drm/i915: unload: fix error_work races
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 20 Aug 2010 16:18:48 +0000 (18:18 +0200)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 8 Sep 2010 09:13:24 +0000 (10:13 +0100)
This is the first patch to clean up module unload races due to
outstanding timers/work. Preparatory step: Thou shalt not destroy
the workqueue when new work might still get enqued.

Now error_work gets queued by the hangcheck timer and only (atomically)
reads the chip wedged status. So cancel it right after the hangcheck
timer is killed. But the hangcheck is armed by interrupts, so move
everything after irqs are disabled.

Also change a del_timer to a del_timer_sync in the ums gem code, the
hangcheck timer is self-rearming.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_gem.c

index 9d67b485303005771a090ea7a3c1e1c6f8b74e9e..736cca8a03d487652e2a1fd408478973a348f9fa 100644 (file)
@@ -2256,9 +2256,6 @@ int i915_driver_unload(struct drm_device *dev)
        i915_mch_dev = NULL;
        spin_unlock(&mchdev_lock);
 
-       destroy_workqueue(dev_priv->wq);
-       del_timer_sync(&dev_priv->hangcheck_timer);
-
        io_mapping_free(dev_priv->mm.gtt_mapping);
        if (dev_priv->mm.gtt_mtrr >= 0) {
                mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
@@ -2283,6 +2280,9 @@ int i915_driver_unload(struct drm_device *dev)
                vga_client_register(dev->pdev, NULL, NULL, NULL);
        }
 
+       del_timer_sync(&dev_priv->hangcheck_timer);
+       cancel_work_sync(&dev_priv->error_work);
+
        if (dev->pdev->msi_enabled)
                pci_disable_msi(dev->pdev);
 
@@ -2307,6 +2307,8 @@ int i915_driver_unload(struct drm_device *dev)
 
        intel_teardown_mchbar(dev);
 
+       destroy_workqueue(dev_priv->wq);
+
        pci_dev_put(dev_priv->bridge_dev);
        kfree(dev->dev_private);
 
index 16fca1d1799a4211474a91e7fc52b605eceafbfc..4cccdce5f80f565b9faf821a0ab33f281a06826a 100644 (file)
@@ -4408,7 +4408,7 @@ i915_gem_idle(struct drm_device *dev)
         * And not confound mm.suspended!
         */
        dev_priv->mm.suspended = 1;
-       del_timer(&dev_priv->hangcheck_timer);
+       del_timer_sync(&dev_priv->hangcheck_timer);
 
        i915_kernel_lost_context(dev);
        i915_gem_cleanup_ringbuffer(dev);