Patch "drm/nouveau: Intercept ACPI_VIDEO_NOTIFY_PROBE" has been added to the 4.9-stable tree
Subsystems (4)
This is a note to let you know that I've just added the patch titled
drm/nouveau: Intercept ACPI_VIDEO_NOTIFY_PROBE
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
drm-nouveau-intercept-acpi_video_notify_probe.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Thu Jun 15 14:56:50 CEST 2017
From: Hans de Goede <[email protected]>
Date: Wed, 9 Nov 2016 18:17:44 +0100
Subject: drm/nouveau: Intercept ACPI_VIDEO_NOTIFY_PROBE
From: Hans de Goede <[email protected]>
[ Upstream commit 3a6536c51d5db3adf58dcd466a3aee6233b58544 ]
Various notebooks with nvidia GPUs generate an ACPI_VIDEO_NOTIFY_PROBE acpi-video event when an external device gets plugged in (and again on modesets on that connector), the default behavior in the acpi-video driver for this is to send a KEY_SWITCHVIDEOMODE evdev event, which causes e.g. gnome-settings-daemon to ask us to rescan the connectors (good), but also causes g-s-d to switch to mirror mode on a newly plugged monitor rather then using the monitor to extend the desktop (bad) as KEY_SWITCHVIDEOMODE is supposed to switch between extend the desktop vs mirror mode.
More troublesome are the repeated ACPI_VIDEO_NOTIFY_PROBE events on changing the mode on the connector, which cause g-s-d to switch between mirror/extend mode, which causes a new ACPI_VIDEO_NOTIFY_PROBE event and we end up with an endless loop.
This commit fixes this by adding an acpi notifier block handler to nouveau_display.c to intercept ACPI_VIDEO_NOTIFY_PROBE and:
1) Wake-up runtime suspended GPUs and call drm_helper_hpd_irq_event() on them, this is necessary in some cases for the GPU to detect connector hotplug events while runtime suspended
2) Return NOTIFY_BAD to stop acpi-video from emitting a bogus KEY_SWITCHVIDEOMODE key-press event
There already is another acpi notifier block handler registered in drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c, but that is not suitable since that one gets unregistered on runtime suspend, and we also want to intercept ACPI_VIDEO_NOTIFY_PROBE when runtime suspended.
--- drivers/gpu/drm/nouveau/nouveau_display.c | 59 ++++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_drv.h | 6 +++ 2 files changed, 65 insertions(+)
drivers/gpu/drm/nouveau/nouveau_display.c +59 -0
@@ -24,6 +24,7 @@* */ +#include <acpi/video.h> #include <drm/drmP.h> #include <drm/drm_crtc_helper.h>
@@ -358,6 +359,55 @@ static struct nouveau_drm_prop_enum_list } \ } while(0) +#ifdef CONFIG_ACPI + +/* +* Hans de Goede: This define belongs in acpi/video.h, I've submitted a patch +* to the acpi subsys to move it there from drivers/acpi/acpi_video.c . +* This should be dropped once that is merged. +*/ +#ifndef ACPI_VIDEO_NOTIFY_PROBE +#define ACPI_VIDEO_NOTIFY_PROBE 0x81 +#endif + +static void +nouveau_display_acpi_work (struct work_struct *work) +{ +struct nouveau_drm *drm =container_of (work,typeof (*drm), acpi_work); + +pm_runtime_get_sync (drm->dev->dev); + +drm_helper_hpd_irq_event (drm->dev); + +pm_runtime_mark_last_busy (drm->dev->dev); +pm_runtime_put_sync (drm->dev->dev); +} + +static int +nouveau_display_acpi_ntfy (struct notifier_block *nb,unsigned long val, +void *data) +{ +struct nouveau_drm *drm =container_of (nb,typeof (*drm), acpi_nb); +struct acpi_bus_event *info = data; + +if (!strcmp (info->device_class,ACPI_VIDEO_CLASS )) { +if (info->type ==ACPI_VIDEO_NOTIFY_PROBE ) { +/* +* This may be the only indication we receive of a +* connector hotplug on a runtime suspended GPU, +* schedule acpi_work to check. +*/ +schedule_work (&drm->acpi_work); + +/* acpi-video should not generate keypresses for this */ +return NOTIFY_BAD ; + } + } + +return NOTIFY_DONE ; +} +#endif +int nouveau_display_init (struct drm_device *dev) {
@@ -537,6 +587,12 @@ nouveau_display_create(struct drm_device }nouveau_backlight_init (dev); +#ifdef CONFIG_ACPI +INIT_WORK (&drm->acpi_work, nouveau_display_acpi_work); + drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy; +register_acpi_notifier (&drm->acpi_nb); +#endif +return 0 ; vblank_err:
@@ -552,6 +608,9 @@ nouveau_display_destroy(struct drm_devic {struct nouveau_display *disp =nouveau_display (dev); +#ifdef CONFIG_ACPI +unregister_acpi_notifier (&nouveau_drm (dev)->acpi_nb); +#endif nouveau_backlight_exit (dev);nouveau_display_vblank_fini (dev);
drivers/gpu/drm/nouveau/nouveau_drv.h +6 -0
@@ -37,6 +37,8 @@* - implemented limited ABI16/NVIF interop */ +#include <linux/notifier.h> +#include <nvif/client.h> #include <nvif/device.h> #include <nvif/ioctl.h>
@@ -161,6 +163,10 @@ struct nouveau_drm {struct nvbios vbios;struct nouveau_display *display;struct backlight_device *backlight; +#ifdef CONFIG_ACPI +struct notifier_block acpi_nb; +struct work_struct acpi_work; +#endif /* power management */ struct nouveau_hwmon *hwmon;
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/drm-nouveau-intercept-acpi_video_notify_probe.patch queue-4.9/drm-nouveau-handle-fbcon-suspend-resume-in-seperate-worker.patch queue-4.9/drm-nouveau-rename-acpi_work-to-hpd_work.patch