Re: [PATCH] Avoid i915 flip unpin/HPD event handler deadlock.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Aug 30, 2013 at 06:30:55PM -0700, Stuart Abercrombie wrote:
> Both of these were taking the mode_config mutex but executed from the
> same work queue.  If intel_crtc_page_flip happened to flush a work queue
> containing an HPD event handler work item, deadlock resulted, since the
> mutex required by the HPD handler was taken before the flush.  Instead
> use a separate work queue for the flip unpin work.
> 
> Signed-off-by: sabercrombie@xxxxxxxxxxxx
> Reviewed-by: marcheu@xxxxxxxxxxxx

It would be possible to rearrange the flip to drop the lock around the
flush (which is a regression from the kernel/workqueue.c refacting...).
However, this looks much simpler. In the long run being strict on
calling flush_workqueue() unlocked is likely to be safer though.

Reviewed-by; Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>

> ---
>  drivers/gpu/drm/i915/i915_dma.c      | 21 ++++++++++++++++++++-
>  drivers/gpu/drm/i915/i915_drv.h      |  1 +
>  drivers/gpu/drm/i915/intel_display.c |  4 ++--
>  3 files changed, 23 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 4f129bb..9215360 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1558,6 +1558,22 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  		goto out_mtrrfree;
>  	}
>  
> +	/* intel_crtc_page_flip runs with the mode_config mutex having been
> +	 * taken in the DRM layer.  It synchronously waits for pending unpin
> +	 * work items while holding this mutex.  Therefore this queue cannot
> +	 * contain work items that take this mutex, such as HPD event
> +	 * handling, or we deadlock.  There is also no reason for flipping to
> +	 * wait on such events.  Therefore put flip unpinning in its own
> +	 * work queue.
> +	 */
> +	dev_priv->flip_unpin_wq = alloc_ordered_workqueue("i915", 0);
> +	if (dev_priv->flip_unpin_wq == NULL) {
> +		DRM_ERROR("Failed to create flip unpin workqueue.\n");
> +		destroy_workqueue(dev_priv->wq);
> +		ret = -ENOMEM;
> +		goto out_mtrrfree;
> +	}
> +
>  	/* This must be called before any calls to HAS_PCH_* */
>  	intel_detect_pch(dev);
>  
> @@ -1628,6 +1644,7 @@ out_gem_unload:
>  	intel_teardown_gmbus(dev);
>  	intel_teardown_mchbar(dev);
>  	destroy_workqueue(dev_priv->wq);
> +	destroy_workqueue(dev_priv->flip_unpin_wq);

To be consistent, flip_wq then wq. In case we get ordering issues later.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux