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: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
3dec0095f7
commit
67e77c5ae8
2 changed files with 17 additions and 0 deletions
|
@ -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)
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue