[PATCH v2] drm/fb-helper: Call drm_fb_helper_hotplug_event() when releasing drm master

Daniel Vetter daniel at ffwll.ch
Mon Nov 8 16:00:50 UTC 2021


On Mon, Nov 08, 2021 at 04:34:53PM +0100, Jocelyn Falempe wrote:
> When using Xorg/Logind and an external monitor connected with an MST dock.
> After disconnecting the external monitor, switching to VT may not work,
> the (internal) monitor sill display Xorg, and you can't see what you are
> typing in the VT.
> 
> This is related to commit e2809c7db818 ("drm/fb_helper: move deferred fb
> checking into restore mode (v2)")
> 
> When switching to VT, with Xorg and logind, if there
> are pending hotplug event (like MST unplugged), the hotplug path
> may not be fulfilled, because logind may drop the master a bit later.
> It leads to the console not showing up on the monitor.
> 
> So when dropping the drm master, call the delayed hotplug function if
> needed.
> 
> v2: rewrote the patch by calling the hotplug function after dropping master
> 
> Signed-off-by: Jocelyn Falempe <jfalempe at redhat.com>

Lastclose console restore is a very gross hack, and generally doesn't work
well.

The way this is supposed to work is:
- userspace drops drm master (because drm master always wins)
- userspace switches the console back to text mode (which will restore the
  console)

I guess we could also do this from dropmaster once more (like from
lastclose), but that really feels like papering over userspace bugs. And
given what a massive mess this entire area is already, I'm not eager to
add more hacks here.

So ... can't we fix userspace?

Ofc if it's a regression then that's different, but then I think we need a
bit clearer implementation. I'm not clear on why you clear the callback
(plus the locking looks busted).
-Daniel

> ---
>  drivers/gpu/drm/drm_auth.c      | 7 +++++++
>  drivers/gpu/drm/drm_fb_helper.c | 6 +++---
>  include/drm/drm_fb_helper.h     | 4 +++-
>  3 files changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
> index 60a6b21474b1..73acf1994d49 100644
> --- a/drivers/gpu/drm/drm_auth.c
> +++ b/drivers/gpu/drm/drm_auth.c
> @@ -35,6 +35,7 @@
>  #include <drm/drm_file.h>
>  #include <drm/drm_lease.h>
>  #include <drm/drm_print.h>
> +#include <drm/drm_fb_helper.h>
>  
>  #include "drm_internal.h"
>  #include "drm_legacy.h"
> @@ -321,6 +322,12 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
>  	}
>  
>  	drm_drop_master(dev, file_priv);
> +
> +	mutex_unlock(&dev->master_mutex);
> +	if (dev->fb_helper && dev->fb_helper->delayed_hotplug)
> +		dev->fb_helper->delayed_hotplug(dev->fb_helper);
> +	return ret;
> +
>  out_unlock:
>  	mutex_unlock(&dev->master_mutex);
>  	return ret;
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 8e7a124d6c5a..e8d8cc3f47c3 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -252,9 +252,9 @@ __drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,
>  		ret = drm_client_modeset_commit(&fb_helper->client);
>  	}
>  
> -	do_delayed = fb_helper->delayed_hotplug;
> +	do_delayed = (fb_helper->delayed_hotplug != NULL);
>  	if (do_delayed)
> -		fb_helper->delayed_hotplug = false;
> +		fb_helper->delayed_hotplug = NULL;
>  	mutex_unlock(&fb_helper->lock);
>  
>  	if (do_delayed)
> @@ -1966,7 +1966,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
>  	}
>  
>  	if (!fb_helper->fb || !drm_master_internal_acquire(fb_helper->dev)) {
> -		fb_helper->delayed_hotplug = true;
> +		fb_helper->delayed_hotplug = drm_fb_helper_hotplug_event;
>  		mutex_unlock(&fb_helper->lock);
>  		return err;
>  	}
> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
> index 3af4624368d8..c2131d1a0e23 100644
> --- a/include/drm/drm_fb_helper.h
> +++ b/include/drm/drm_fb_helper.h
> @@ -160,8 +160,10 @@ struct drm_fb_helper {
>  	 * A hotplug was received while fbdev wasn't in control of the DRM
>  	 * device, i.e. another KMS master was active. The output configuration
>  	 * needs to be reprobe when fbdev is in control again.
> +	 * NULL, or a pointer to the hotplug function, so it can be called
> +	 * by the drm drop function directly.
>  	 */
> -	bool delayed_hotplug;
> +	int (*delayed_hotplug)(struct drm_fb_helper *helper);
>  
>  	/**
>  	 * @deferred_setup:
> -- 
> 2.33.1
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list