[PATCH 4.9 27/44] drm/nouveau/drm/nouveau: Fix bogus drm_kms_helper_poll_enable() placement

From: Greg Kroah-Hartman
Date: Thu Sep 27 2018 - 05:29:37 EST


4.9-stable review patch. If anyone has any objections, please let me know.

------------------

From: Lyude Paul <lyude@xxxxxxxxxx>

commit d77ef138ff572409ab93d492e5e6c826ee6fb21d upstream.

Turns out this part is my fault for not noticing when reviewing
9a2eba337cace ("drm/nouveau: Fix drm poll_helper handling"). Currently
we call drm_kms_helper_poll_enable() from nouveau_display_hpd_work().
This makes basically no sense however, because that means we're calling
drm_kms_helper_poll_enable() every time we schedule the hotplug
detection work. This is also against the advice mentioned in
drm_kms_helper_poll_enable()'s documentation:

Note that calls to enable and disable polling must be strictly ordered,
which is automatically the case when they're only call from
suspend/resume callbacks.

Of course, hotplugs can't really be ordered. They could even happen
immediately after we called drm_kms_helper_poll_disable() in
nouveau_display_fini(), which can lead to all sorts of issues.

Additionally; enabling polling /after/ we call
drm_helper_hpd_irq_event() could also mean that we'd miss a hotplug
event anyway, since drm_helper_hpd_irq_event() wouldn't bother trying to
probe connectors so long as polling is disabled.

So; simply move this back into nouveau_display_init() again. The race
condition that both of these patches attempted to work around has
already been fixed properly in

d61a5c106351 ("drm/nouveau: Fix deadlock on runtime suspend")

Fixes: 9a2eba337cace ("drm/nouveau: Fix drm poll_helper handling")
Signed-off-by: Lyude Paul <lyude@xxxxxxxxxx>
Acked-by: Karol Herbst <kherbst@xxxxxxxxxx>
Acked-by: Daniel Vetter <daniel@xxxxxxxx>
Cc: Lukas Wunner <lukas@xxxxxxxxx>
Cc: Peter Ujfalusi <peter.ujfalusi@xxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Ben Skeggs <bskeggs@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
drivers/gpu/drm/nouveau/nouveau_display.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -367,8 +367,6 @@ nouveau_display_hpd_work(struct work_str
pm_runtime_get_sync(drm->dev->dev);

drm_helper_hpd_irq_event(drm->dev);
- /* enable polling for external displays */
- drm_kms_helper_poll_enable(drm->dev);

pm_runtime_mark_last_busy(drm->dev->dev);
pm_runtime_put_sync(drm->dev->dev);
@@ -422,6 +420,11 @@ nouveau_display_init(struct drm_device *
if (ret)
return ret;

+ /* enable connector detection and polling for connectors without HPD
+ * support
+ */
+ drm_kms_helper_poll_enable(dev);
+
/* enable hotplug interrupts */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct nouveau_connector *conn = nouveau_connector(connector);