Instead of reusing the polling code for hdp handling, split them up.
This has a few consequences:
- Don't touch HDP capable connectors in the poll loop.
- Only touch HDP capable connectors in drm_helper_hpd_irq_event.
- Run the HDP handling directly instead of going through a work item -
  all callers already call drm_helper_hpd_irq_event from process
  context without holding the mode_config mutex.

The ultimate goal is that drivers grow some smarts about which
connectors have received a hotplug event and only call the detect code
of that connector. But that's a second step.

Signed-Off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/drm_crtc_helper.c |   39 ++++++++++++++++++++++++++++--------
 1 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 909a85c..b1d643d 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -942,9 +942,9 @@ static void output_poll_execute(struct work_struct *work)
        mutex_lock(&dev->mode_config.mutex);
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {

-               /* if this is HPD or polled don't check it -
-                  TV out for instance */
-               if (!connector->polled)
+               /* Ignore HDP capable connectors and connectors where we don't
+                * want any hotplug detection at all for polling. */
+               if (!connector->polled || connector->polled == 
DRM_CONNECTOR_POLL_HPD)
                        continue;

                else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | 
DRM_CONNECTOR_POLL_DISCONNECT))
@@ -954,8 +954,7 @@ static void output_poll_execute(struct work_struct *work)
                /* if we are connected and don't want to poll for disconnect
                   skip it */
                if (old_status == connector_status_connected &&
-                   !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT) &&
-                   !(connector->polled & DRM_CONNECTOR_POLL_HPD))
+                   !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
                        continue;

                connector->status = connector->funcs->detect(connector, false);
@@ -1019,12 +1018,34 @@ EXPORT_SYMBOL(drm_kms_helper_poll_fini);

 void drm_helper_hpd_irq_event(struct drm_device *dev)
 {
+       struct drm_connector *connector;
+       enum drm_connector_status old_status;
+       bool changed = false;
+
        if (!dev->mode_config.poll_enabled)
                return;

-       /* kill timer and schedule immediate execution, this doesn't block */
-       cancel_delayed_work(&dev->mode_config.output_poll_work);
-       if (drm_kms_helper_poll)
-               queue_delayed_work(system_nrt_wq, 
&dev->mode_config.output_poll_work, 0);
+       mutex_lock(&dev->mode_config.mutex);
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+
+               /* Only handle HPD capable connectors. */
+               if (connector->polled != DRM_CONNECTOR_POLL_HPD)
+                       continue;
+
+               old_status = connector->status;
+
+               connector->status = connector->funcs->detect(connector, false);
+               DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to 
%d\n",
+                             connector->base.id,
+                             drm_get_connector_name(connector),
+                             old_status, connector->status);
+               if (old_status != connector->status)
+                       changed = true;
+       }
+
+       mutex_unlock(&dev->mode_config.mutex);
+
+       if (changed)
+               drm_kms_helper_hotplug_event(dev);
 }
 EXPORT_SYMBOL(drm_helper_hpd_irq_event);
-- 
1.7.7.6

Reply via email to