These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / drm_probe_helper.c
index 6350387..f8b5fcf 100644 (file)
@@ -93,6 +93,40 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
        return 1;
 }
 
+#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
+/**
+ * drm_kms_helper_poll_enable_locked - re-enable output polling.
+ * @dev: drm_device
+ *
+ * This function re-enables the output polling work without
+ * locking the mode_config mutex.
+ *
+ * This is like drm_kms_helper_poll_enable() however it is to be
+ * called from a context where the mode_config mutex is locked
+ * already.
+ */
+void drm_kms_helper_poll_enable_locked(struct drm_device *dev)
+{
+       bool poll = false;
+       struct drm_connector *connector;
+
+       WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
+       if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
+               return;
+
+       drm_for_each_connector(connector, dev) {
+               if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
+                                        DRM_CONNECTOR_POLL_DISCONNECT))
+                       poll = true;
+       }
+
+       if (poll)
+               schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
+}
+EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked);
+
+
 static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
                                                              uint32_t maxX, uint32_t maxY, bool merge_type_bits)
 {
@@ -153,7 +187,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
 
        /* Re-enable polling in case the global poll config changed. */
        if (drm_kms_helper_poll != dev->mode_config.poll_running)
-               drm_kms_helper_poll_enable(dev);
+               drm_kms_helper_poll_enable_locked(dev);
 
        dev->mode_config.poll_running = drm_kms_helper_poll;
 
@@ -195,7 +229,8 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
                mode_flags |= DRM_MODE_FLAG_3D_MASK;
 
        list_for_each_entry(mode, &connector->modes, head) {
-               mode->status = drm_mode_validate_basic(mode);
+               if (mode->status == MODE_OK)
+                       mode->status = drm_mode_validate_basic(mode);
 
                if (mode->status == MODE_OK)
                        mode->status = drm_mode_validate_size(mode, maxX, maxY);
@@ -295,7 +330,6 @@ void drm_kms_helper_hotplug_event(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
 
-#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
 static void output_poll_execute(struct work_struct *work)
 {
        struct delayed_work *delayed_work = to_delayed_work(work);
@@ -312,7 +346,7 @@ static void output_poll_execute(struct work_struct *work)
                goto out;
 
        mutex_lock(&dev->mode_config.mutex);
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_for_each_connector(connector, dev) {
 
                /* Ignore forced connectors. */
                if (connector->force)
@@ -323,8 +357,6 @@ static void output_poll_execute(struct work_struct *work)
                if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
                        continue;
 
-               repoll = true;
-
                old_status = connector->status;
                /* if we are connected and don't want to poll for disconnect
                   skip it */
@@ -332,6 +364,8 @@ static void output_poll_execute(struct work_struct *work)
                    !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
                        continue;
 
+               repoll = true;
+
                connector->status = connector->funcs->detect(connector, false);
                if (old_status != connector->status) {
                        const char *old, *new;
@@ -407,20 +441,9 @@ EXPORT_SYMBOL(drm_kms_helper_poll_disable);
  */
 void drm_kms_helper_poll_enable(struct drm_device *dev)
 {
-       bool poll = false;
-       struct drm_connector *connector;
-
-       if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
-               return;
-
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
-                                        DRM_CONNECTOR_POLL_DISCONNECT))
-                       poll = true;
-       }
-
-       if (poll)
-               schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
+       mutex_lock(&dev->mode_config.mutex);
+       drm_kms_helper_poll_enable_locked(dev);
+       mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_enable);
 
@@ -495,7 +518,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
                return false;
 
        mutex_lock(&dev->mode_config.mutex);
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       drm_for_each_connector(connector, dev) {
 
                /* Only handle HPD capable connectors. */
                if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))