All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukas Wunner <lukas-JFq808J9C/izQB+pC5nmwQ@public.gmane.org>
To: Peter Wu <peter-VTkQYDcBqhK7DlmcbJSQ7g@public.gmane.org>
Cc: Dave Airlie <airlied-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
	Chris Wilson
	<chris-Y6uKTt2uX1cEflXRtASbqLVCufUGDwFn@public.gmane.org>,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
	nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Subject: Re: [PATCH] drm/nouveau/fbcon: fix deadlock with FBIOPUT_CON2FBMAP
Date: Tue, 12 Jul 2016 21:16:22 +0200	[thread overview]
Message-ID: <20160712191622.GA5476@wunner.de> (raw)
In-Reply-To: <20160712164934.1390-1-peter-VTkQYDcBqhK7DlmcbJSQ7g@public.gmane.org>

On Tue, Jul 12, 2016 at 06:49:34PM +0200, Peter Wu wrote:
> The FBIOPUT_CON2FBMAP ioctl takes a console_lock(). When this is called
> while nouveau was runtime suspended, a deadlock would occur due to
> nouveau_fbcon_set_suspend also trying to obtain console_lock().
> 
> Fix this by delaying the drm_fb_helper_set_suspend call. Based on the
> i915 code (which was done for performance reasons though).
> 
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Signed-off-by: Peter Wu <peter@lekensteyn.nl>
> ---
> Tested on top of v4.7-rc5, the deadlock is gone.

Hm, how did you trigger this deadlock?

Thanks,

Lukas

> ---
>  drivers/gpu/drm/nouveau/nouveau_drm.c   |  4 +--
>  drivers/gpu/drm/nouveau/nouveau_drv.h   |  1 +
>  drivers/gpu/drm/nouveau/nouveau_fbcon.c | 54 ++++++++++++++++++++++++++++-----
>  drivers/gpu/drm/nouveau/nouveau_fbcon.h |  2 +-
>  4 files changed, 50 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
> index 11f8dd9..f9a2c10 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
> @@ -552,7 +552,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
>  
>  	if (dev->mode_config.num_crtc) {
>  		NV_INFO(drm, "suspending console...\n");
> -		nouveau_fbcon_set_suspend(dev, 1);
> +		nouveau_fbcon_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
>  		NV_INFO(drm, "suspending display...\n");
>  		ret = nouveau_display_suspend(dev, runtime);
>  		if (ret)
> @@ -635,7 +635,7 @@ nouveau_do_resume(struct drm_device *dev, bool runtime)
>  		NV_INFO(drm, "resuming display...\n");
>  		nouveau_display_resume(dev, runtime);
>  		NV_INFO(drm, "resuming console...\n");
> -		nouveau_fbcon_set_suspend(dev, 0);
> +		nouveau_fbcon_set_suspend(dev, FBINFO_STATE_RUNNING, false);
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
> index 822a021..a743d19 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drv.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
> @@ -147,6 +147,7 @@ struct nouveau_drm {
>  	struct nouveau_channel *channel;
>  	struct nvkm_gpuobj *notify;
>  	struct nouveau_fbdev *fbcon;
> +	struct work_struct fbdev_suspend_work;
>  	struct nvif_object nvsw;
>  	struct nvif_object ntfy;
>  	struct nvif_notify flip;
> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
> index d1f248f..089156a 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
> @@ -492,19 +492,53 @@ static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
>  	.fb_probe = nouveau_fbcon_create,
>  };
>  
> +static void nouveau_fbcon_suspend_worker(struct work_struct *work)
> +{
> +	nouveau_fbcon_set_suspend(container_of(work,
> +					       struct nouveau_drm,
> +					       fbdev_suspend_work)->dev,
> +				  FBINFO_STATE_RUNNING,
> +				  true);
> +}
> +
>  void
> -nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
> +nouveau_fbcon_set_suspend(struct drm_device *dev, int state, bool synchronous)
>  {
>  	struct nouveau_drm *drm = nouveau_drm(dev);
> -	if (drm->fbcon) {
> -		console_lock();
> -		if (state == FBINFO_STATE_RUNNING)
> -			nouveau_fbcon_accel_restore(dev);
> -		drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
> +	if (!drm->fbcon)
> +		return;
> +
> +	if (synchronous) {
> +		/* Flush any pending work to turn the console on, and then
> +		 * wait to turn it off. It must be synchronous as we are
> +		 * about to suspend or unload the driver.
> +		 *
> +		 * Note that from within the work-handler, we cannot flush
> +		 * ourselves, so only flush outstanding work upon suspend!
> +		 */
>  		if (state != FBINFO_STATE_RUNNING)
> -			nouveau_fbcon_accel_save_disable(dev);
> -		console_unlock();
> +			flush_work(&drm->fbdev_suspend_work);
> +		console_lock();
> +	} else {
> +		/*
> +		 * The console lock can be pretty contented on resume due
> +		 * to all the printk activity.  Try to keep it out of the hot
> +		 * path of resume if possible.  This also prevents a deadlock
> +		 * with FBIOPUT_CON2FBMAP.
> +		 */
> +		WARN_ON(state != FBINFO_STATE_RUNNING);
> +		if (!console_trylock()) {
> +			schedule_work(&drm->fbdev_suspend_work);
> +			return;
> +		}
>  	}
> +
> +	if (state == FBINFO_STATE_RUNNING)
> +		nouveau_fbcon_accel_restore(dev);
> +	drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
> +	if (state != FBINFO_STATE_RUNNING)
> +		nouveau_fbcon_accel_save_disable(dev);
> +	console_unlock();
>  }
>  
>  int
> @@ -526,6 +560,8 @@ nouveau_fbcon_init(struct drm_device *dev)
>  	fbcon->dev = dev;
>  	drm->fbcon = fbcon;
>  
> +	INIT_WORK(&drm->fbdev_suspend_work, nouveau_fbcon_suspend_worker);
> +
>  	drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
>  
>  	ret = drm_fb_helper_init(dev, &fbcon->helper,
> @@ -571,6 +607,8 @@ nouveau_fbcon_fini(struct drm_device *dev)
>  	if (!drm->fbcon)
>  		return;
>  
> +	flush_work(&drm->fbdev_suspend_work);
> +
>  	nouveau_fbcon_accel_fini(dev);
>  	nouveau_fbcon_destroy(dev, drm->fbcon);
>  	kfree(drm->fbcon);
> diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
> index ca77ad0..34b2504 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
> @@ -66,7 +66,7 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info);
>  
>  int nouveau_fbcon_init(struct drm_device *dev);
>  void nouveau_fbcon_fini(struct drm_device *dev);
> -void nouveau_fbcon_set_suspend(struct drm_device *dev, int state);
> +void nouveau_fbcon_set_suspend(struct drm_device *dev, int state, bool synchronous);
>  void nouveau_fbcon_accel_save_disable(struct drm_device *dev);
>  void nouveau_fbcon_accel_restore(struct drm_device *dev);
>  
> -- 
> 2.8.3
> 
> _______________________________________________
> Nouveau mailing list
> Nouveau@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/nouveau
_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

  parent reply	other threads:[~2016-07-12 19:16 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-12 16:49 [PATCH] drm/nouveau/fbcon: fix deadlock with FBIOPUT_CON2FBMAP Peter Wu
     [not found] ` <20160712164934.1390-1-peter-VTkQYDcBqhK7DlmcbJSQ7g@public.gmane.org>
2016-07-12 19:16   ` Lukas Wunner [this message]
     [not found]     ` <20160712191622.GA5476-JFq808J9C/izQB+pC5nmwQ@public.gmane.org>
2016-07-12 20:18       ` Peter Wu
2016-07-13  9:54   ` Daniel Vetter
     [not found]     ` <20160713095449.GZ23520-dv86pmgwkMBes7Z6vYuT8azUEOm+Xw19@public.gmane.org>
2016-07-13 12:40       ` Peter Wu
2016-07-13 14:57         ` Daniel Vetter
     [not found]           ` <20160713145718.GP23520-dv86pmgwkMBes7Z6vYuT8azUEOm+Xw19@public.gmane.org>
2016-07-15 11:10             ` Peter Wu
2016-07-18  6:48               ` Daniel Vetter
2016-07-13 17:17 ` Chris Wilson
     [not found]   ` <20160713171747.GM6157-aII6DKEyn0pWYbfKqPwjAkR8Iwp7RQ6xAL8bYrjMMd8@public.gmane.org>
2016-07-15 11:26     ` Peter Wu
2016-07-15 11:34       ` Chris Wilson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160712191622.GA5476@wunner.de \
    --to=lukas-jfq808j9c/izqb+pc5nmwq@public.gmane.org \
    --cc=airlied-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    --cc=chris-Y6uKTt2uX1cEflXRtASbqLVCufUGDwFn@public.gmane.org \
    --cc=dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=peter-VTkQYDcBqhK7DlmcbJSQ7g@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.