Commit 67e77c5a authored by Daniel Vetter's avatar Daniel Vetter Committed by Chris Wilson

drm/i915: unload: fix unpin_work related races

Kill any outstanding unpin_work when destroying the corresponding
crtc. Then flush the workqueue before the gem teardown, in case
any unpin work is still outstanding.
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 3dec0095
...@@ -2292,6 +2292,9 @@ int i915_driver_unload(struct drm_device *dev) ...@@ -2292,6 +2292,9 @@ int i915_driver_unload(struct drm_device *dev)
intel_opregion_free(dev, 0); intel_opregion_free(dev, 0);
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
/* Flush any outstanding unpin_work. */
flush_workqueue(dev_priv->wq);
i915_gem_free_all_phys_object(dev); i915_gem_free_all_phys_object(dev);
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
......
...@@ -4850,8 +4850,22 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) ...@@ -4850,8 +4850,22 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
static void intel_crtc_destroy(struct drm_crtc *crtc) static void intel_crtc_destroy(struct drm_crtc *crtc)
{ {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct intel_unpin_work *work;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
work = intel_crtc->unpin_work;
intel_crtc->unpin_work = NULL;
spin_unlock_irqrestore(&dev->event_lock, flags);
if (work) {
cancel_work_sync(&work->work);
kfree(work);
}
drm_crtc_cleanup(crtc); drm_crtc_cleanup(crtc);
kfree(intel_crtc); kfree(intel_crtc);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment