mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-27 01:11:06 +00:00
eb62d9cc04
Fixes #2736
98 lines
3.1 KiB
Diff
98 lines
3.1 KiB
Diff
--- a/drivers/gpu/drm/i915/intel_hotplug.c
|
|
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
|
|
@@ -336,11 +336,10 @@
|
|
/*
|
|
* Handle hotplug events outside the interrupt handler proper.
|
|
*/
|
|
-static void i915_hotplug_work_func(struct work_struct *work)
|
|
+static void i915_hotplug_work_func_x(struct work_struct *work,
|
|
+ struct drm_i915_private *dev_priv,
|
|
+ struct drm_device *dev)
|
|
{
|
|
- struct drm_i915_private *dev_priv =
|
|
- container_of(work, struct drm_i915_private, hotplug.hotplug_work);
|
|
- struct drm_device *dev = &dev_priv->drm;
|
|
struct intel_connector *intel_connector;
|
|
struct intel_encoder *intel_encoder;
|
|
struct drm_connector *connector;
|
|
@@ -353,7 +352,7 @@
|
|
|
|
spin_lock_irq(&dev_priv->irq_lock);
|
|
|
|
- hpd_event_bits = dev_priv->hotplug.event_bits;
|
|
+ hpd_event_bits = dev_priv->hotplug.event_bits | dev_priv->hotplug.recheck_event_bits;
|
|
dev_priv->hotplug.event_bits = 0;
|
|
|
|
/* Disable hotplug on connectors that hit an irq storm. */
|
|
@@ -379,8 +378,40 @@
|
|
drm_connector_list_iter_end(&conn_iter);
|
|
mutex_unlock(&dev->mode_config.mutex);
|
|
|
|
- if (changed)
|
|
+ if (changed) {
|
|
+ dev_priv->hotplug.recheck_event_bits = 0;
|
|
drm_kms_helper_hotplug_event(dev);
|
|
+ } else {
|
|
+ if (hpd_event_bits && !dev_priv->hotplug.recheck_event_bits) {
|
|
+ unsigned long delay = msecs_to_jiffies(2000);
|
|
+ schedule_delayed_work(&dev_priv->hotplug.recheck_hotplug, delay);
|
|
+ }
|
|
+
|
|
+ if (hpd_event_bits != dev_priv->hotplug.recheck_event_bits)
|
|
+ dev_priv->hotplug.recheck_event_bits |= hpd_event_bits;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void i915_hotplug_work_func(struct work_struct *work)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv =
|
|
+ container_of(work, struct drm_i915_private, hotplug.hotplug_work);
|
|
+ struct drm_device *dev = &dev_priv->drm;
|
|
+
|
|
+ i915_hotplug_work_func_x(work, dev_priv, dev);
|
|
+}
|
|
+
|
|
+static void i915_hotplug_recheck_func(struct work_struct *work)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv =
|
|
+ container_of(work, typeof(*dev_priv),
|
|
+ hotplug.recheck_hotplug.work);
|
|
+ struct drm_device *dev = &dev_priv->drm;
|
|
+
|
|
+ i915_hotplug_work_func_x(work, dev_priv, dev);
|
|
+
|
|
+ /* re-try just once */
|
|
+ dev_priv->hotplug.recheck_event_bits = 0;
|
|
}
|
|
|
|
|
|
@@ -604,6 +635,8 @@
|
|
INIT_WORK(&dev_priv->hotplug.poll_init_work, i915_hpd_poll_init_work);
|
|
INIT_DELAYED_WORK(&dev_priv->hotplug.reenable_work,
|
|
intel_hpd_irq_storm_reenable_work);
|
|
+ INIT_DELAYED_WORK(&dev_priv->hotplug.recheck_hotplug,
|
|
+ i915_hotplug_recheck_func);
|
|
}
|
|
|
|
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
|
|
@@ -620,6 +653,7 @@
|
|
cancel_work_sync(&dev_priv->hotplug.hotplug_work);
|
|
cancel_work_sync(&dev_priv->hotplug.poll_init_work);
|
|
cancel_delayed_work_sync(&dev_priv->hotplug.reenable_work);
|
|
+ cancel_delayed_work_sync(&dev_priv->hotplug.recheck_hotplug);
|
|
}
|
|
|
|
bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin)
|
|
--- a/drivers/gpu/drm/i915/i915_drv.h
|
|
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
|
@@ -278,7 +278,9 @@
|
|
} state;
|
|
} stats[HPD_NUM_PINS];
|
|
u32 event_bits;
|
|
+ u32 recheck_event_bits;
|
|
struct delayed_work reenable_work;
|
|
+ struct delayed_work recheck_hotplug;
|
|
|
|
struct intel_digital_port *irq_port[I915_MAX_PORTS];
|
|
u32 long_port_mask;
|