@@ -315,7 +315,7 @@ typedef struct drm_i915_private {
u32 pch_irq_mask;
u32 hotplug_supported_mask;
- struct work_struct hotplug_work;
+ struct delayed_work hotplug_delayed_work;
int tex_lru_log_granularity;
int allow_batchbuffer;
@@ -300,8 +300,9 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,
*/
static void i915_hotplug_work_func(struct work_struct *work)
{
- drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
- hotplug_work);
+ struct delayed_work *delayed_work = to_delayed_work(work);
+ drm_i915_private_t *dev_priv = container_of(delayed_work, drm_i915_private_t,
+ hotplug_delayed_work);
struct drm_device *dev = dev_priv->dev;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_encoder *encoder;
@@ -528,7 +529,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
/* check event from PCH */
if (de_iir & DE_PCH_EVENT_IVB) {
if (pch_iir & SDE_HOTPLUG_MASK_CPT)
- queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+ queue_delayed_work(dev_priv->wq, &dev_priv->hotplug_delayed_work, HZ/4);
pch_irq_handler(dev);
}
@@ -627,7 +628,7 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
/* check event from PCH */
if (de_iir & DE_PCH_EVENT) {
if (pch_iir & hotplug_mask)
- queue_work(dev_priv->wq, &dev_priv->hotplug_work);
+ queue_delayed_work(dev_priv->wq, &dev_priv->hotplug_delayed_work, HZ/4);
pch_irq_handler(dev);
}
@@ -1279,8 +1280,8 @@ static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n",
hotplug_status);
if (hotplug_status & dev_priv->hotplug_supported_mask)
- queue_work(dev_priv->wq,
- &dev_priv->hotplug_work);
+ queue_delayed_work(dev_priv->wq,
+ &dev_priv->hotplug_delayed_work, HZ/4);
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
@@ -1742,7 +1743,7 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
atomic_set(&dev_priv->irq_received, 0);
- INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+ INIT_DELAYED_WORK(&dev_priv->hotplug_delayed_work, i915_hotplug_work_func);
INIT_WORK(&dev_priv->error_work, i915_error_work_func);
if (IS_GEN6(dev) || IS_IVYBRIDGE(dev))
INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
@@ -1906,7 +1907,7 @@ static void i915_driver_irq_preinstall(struct drm_device * dev)
atomic_set(&dev_priv->irq_received, 0);
- INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+ INIT_DELAYED_WORK(&dev_priv->hotplug_delayed_work, i915_hotplug_work_func);
INIT_WORK(&dev_priv->error_work, i915_error_work_func);
if (I915_HAS_HOTPLUG(dev)) {
@@ -8361,7 +8361,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
/* Disable the irq before mode object teardown, for the irq might
* enqueue unpin/hotplug work. */
drm_irq_uninstall(dev);
- cancel_work_sync(&dev_priv->hotplug_work);
+ cancel_delayed_work_sync(&dev_priv->hotplug_delayed_work);
/* flush any delayed tasks or pending work */
flush_scheduled_work();
If the connector is inserted or removed slowly, the hotplug line may well change state before the data lines do. So, assume the user isn't trying to fool us and give them 250ms to get the connector plugged or unplugged. v2: use queue_delayed_work instead of msleep Signed-off-by: Keith Packard <keithp@keithp.com> --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_irq.c | 17 +++++++++-------- drivers/gpu/drm/i915/intel_display.c | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-)