From: Lyude Paul <lyude@redhat.com>
To: nouveau@lists.freedesktop.org
Cc: Ben Skeggs <bskeggs@redhat.com>, David Airlie <airlied@linux.ie>,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] drm/nouveau: Prevent redundant connector probes from ACPI
Date: Mon, 30 Jul 2018 20:58:35 -0400 [thread overview]
Message-ID: <20180731005835.21032-2-lyude@redhat.com> (raw)
In-Reply-To: <20180731005835.21032-1-lyude@redhat.com>
On the Lenovo P50 I've been working on, ACPI notifications for hotplugs
always seem happen even while the GPU has it's hotplugs enabled. This
means that we're uselessly scheduling two connector probes every time we
get a hotplug.
Since we can't unregister the acpi handler without causing userspace to
start getting mysterious keypresses from the ACPI_VIDEO_REPROBE events
that are meant for us, simply add a member to nouveau_drm that can be
used to enable/disable our ACPI event handler from being able to
schedule connector probes on it's own.
Signed-off-by: Lyude Paul <lyude@redhat.com>
---
drivers/gpu/drm/nouveau/nouveau_display.c | 40 +++++++++++++++--------
drivers/gpu/drm/nouveau/nouveau_display.h | 4 +--
drivers/gpu/drm/nouveau/nouveau_drm.c | 4 +--
drivers/gpu/drm/nouveau/nouveau_drv.h | 1 +
4 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index b2a93e3fa67b..b80226c87487 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -382,13 +382,16 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
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 hpd_work to check.
- */
- NV_DEBUG(drm, "ACPI requested connector probe\n");
- schedule_work(&drm->hpd_work);
+ if (READ_ONCE(drm->acpi_hpd_enabled)) {
+ /*
+ * This may be the only indication we receive
+ * of a connector hotplug on a runtime
+ * suspended GPU, schedule hpd_work to check.
+ */
+ NV_DEBUG(drm,
+ "ACPI requested connector probe\n");
+ schedule_work(&drm->hpd_work);
+ }
/* acpi-video should not generate keypresses for this */
return NOTIFY_BAD;
@@ -400,7 +403,7 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
#endif
int
-nouveau_display_init(struct drm_device *dev)
+nouveau_display_init(struct drm_device *dev, bool runtime)
{
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
@@ -420,13 +423,20 @@ nouveau_display_init(struct drm_device *dev)
}
drm_connector_list_iter_end(&conn_iter);
+ /* disable ACPI hotplug handling to prevent duplicate connector
+ * probes
+ * FIXME: make sure that WRITE_ONCE() implies a store barrier
+ * beforehand
+ */
+ WRITE_ONCE(drm->acpi_hpd_enabled, false);
+
/* enable flip completion events */
nvif_notify_get(&drm->flip);
return ret;
}
void
-nouveau_display_fini(struct drm_device *dev, bool suspend)
+nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime)
{
struct nouveau_display *disp = nouveau_display(dev);
struct nouveau_drm *drm = nouveau_drm(dev);
@@ -443,6 +453,10 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
/* disable flip completion events */
nvif_notify_put(&drm->flip);
+ /* let ACPI handle hotplugs since we won't have them enabled */
+ if (runtime)
+ WRITE_ONCE(drm->acpi_hpd_enabled, true);
+
/* disable hotplug interrupts */
drm_connector_list_iter_begin(dev, &conn_iter);
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
@@ -619,11 +633,11 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime)
}
}
- nouveau_display_fini(dev, true);
+ nouveau_display_fini(dev, true, runtime);
return 0;
}
- nouveau_display_fini(dev, true);
+ nouveau_display_fini(dev, true, runtime);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct nouveau_framebuffer *nouveau_fb;
@@ -656,7 +670,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
int ret;
if (drm_drv_uses_atomic_modeset(dev)) {
- nouveau_display_init(dev);
+ nouveau_display_init(dev, runtime);
if (disp->suspend) {
drm_atomic_helper_resume(dev, disp->suspend);
disp->suspend = NULL;
@@ -689,7 +703,7 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
NV_ERROR(drm, "Could not pin/map cursor.\n");
}
- nouveau_display_init(dev);
+ nouveau_display_init(dev, runtime);
/* Force CLUT to get re-loaded during modeset */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 54aa7c3fa42d..473411120225 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -61,8 +61,8 @@ nouveau_display(struct drm_device *dev)
int nouveau_display_create(struct drm_device *dev);
void nouveau_display_destroy(struct drm_device *dev);
-int nouveau_display_init(struct drm_device *dev);
-void nouveau_display_fini(struct drm_device *dev, bool suspend);
+int nouveau_display_init(struct drm_device *dev, bool runtime);
+void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime);
int nouveau_display_suspend(struct drm_device *dev, bool runtime);
void nouveau_display_resume(struct drm_device *dev, bool runtime);
int nouveau_display_vblank_enable(struct drm_device *, unsigned int);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index c7ec86d6c3c9..65dc5b5cf6ce 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -574,7 +574,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
goto fail_dispctor;
if (dev->mode_config.num_crtc) {
- ret = nouveau_display_init(dev);
+ ret = nouveau_display_init(dev, false);
if (ret)
goto fail_dispinit;
}
@@ -629,7 +629,7 @@ nouveau_drm_unload(struct drm_device *dev)
nouveau_debugfs_fini(drm);
if (dev->mode_config.num_crtc)
- nouveau_display_fini(dev, false);
+ nouveau_display_fini(dev, false, false);
nouveau_display_destroy(dev);
nouveau_bios_takedown(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 6e1acaec3400..22e70e72ec8b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -201,6 +201,7 @@ struct nouveau_drm {
int fbcon_new_state;
#ifdef CONFIG_ACPI
struct notifier_block acpi_nb;
+ bool acpi_hpd_enabled;
#endif
/* power management */
--
2.17.1
next prev parent reply other threads:[~2018-07-31 0:58 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-31 0:58 [PATCH 1/2] drm/nouveau: Print debug message on ACPI probe event Lyude Paul
2018-07-31 0:58 ` Lyude Paul [this message]
2018-07-31 10:33 ` [PATCH 2/2] drm/nouveau: Prevent redundant connector probes from ACPI kbuild test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180731005835.21032-2-lyude@redhat.com \
--to=lyude@redhat.com \
--cc=airlied@linux.ie \
--cc=bskeggs@redhat.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nouveau@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome