[Intel-gfx] [PATCH 1/4] drm/i915/fbdev: Use an ordinary worker to avoid async deadlock
Daniel Vetter
daniel at ffwll.ch
Fri Oct 19 08:23:54 UTC 2018
On Mon, Oct 15, 2018 at 12:17:39PM +0100, Chris Wilson wrote:
> We try to avoid a deadlock of synchronizing the async fbdev task by
> skipping the synchronisation from the async worker, but that prevents us
> from using an async worker for the device probe. As we have our own
> barrier and do not rely on the global async flush, we can simply replace
> the async task with an explicit worker.
>
> References: 366e39b4d2c5 ("drm/i915: Tear down fbdev if initialization fails")
> Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Does this now mean that fbdev setup lags behind module load? Afaiui that
will annoy userspace, which assumes that once the kms driver is loaded,
fbdev works. Or at least I have vague memories of pains in this area.
-Daniel
> ---
> drivers/gpu/drm/i915/intel_drv.h | 3 +--
> drivers/gpu/drm/i915/intel_fbdev.c | 35 +++++++++++++++---------------
> 2 files changed, 18 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 3dea7a1bda7f..15bbf604724d 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -25,7 +25,6 @@
> #ifndef __INTEL_DRV_H__
> #define __INTEL_DRV_H__
>
> -#include <linux/async.h>
> #include <linux/i2c.h>
> #include <linux/hdmi.h>
> #include <linux/sched/clock.h>
> @@ -207,8 +206,8 @@ struct intel_fbdev {
> struct intel_framebuffer *fb;
> struct i915_vma *vma;
> unsigned long vma_flags;
> - async_cookie_t cookie;
> int preferred_bpp;
> + struct work_struct work;
> };
>
> struct intel_encoder {
> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> index 2480c7d6edee..265cc947aede 100644
> --- a/drivers/gpu/drm/i915/intel_fbdev.c
> +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> @@ -24,7 +24,6 @@
> * David Airlie
> */
>
> -#include <linux/async.h>
> #include <linux/module.h>
> #include <linux/kernel.h>
> #include <linux/console.h>
> @@ -666,6 +665,16 @@ static void intel_fbdev_suspend_worker(struct work_struct *work)
> true);
> }
>
> +static void intel_fbdev_initial_config(struct work_struct *work)
> +{
> + struct intel_fbdev *ifbdev = container_of(work, typeof(*ifbdev), work);
> +
> + /* Due to peculiar init order wrt to hpd handling this is separate. */
> + if (drm_fb_helper_initial_config(&ifbdev->helper,
> + ifbdev->preferred_bpp))
> + intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
> +}
> +
> int intel_fbdev_init(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = to_i915(dev);
> @@ -679,6 +688,8 @@ int intel_fbdev_init(struct drm_device *dev)
> if (ifbdev == NULL)
> return -ENOMEM;
>
> + INIT_WORK(&ifbdev->work, intel_fbdev_initial_config);
> +
> drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
>
> if (!intel_fbdev_init_bios(dev, ifbdev))
> @@ -698,16 +709,6 @@ int intel_fbdev_init(struct drm_device *dev)
> return 0;
> }
>
> -static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
> -{
> - struct intel_fbdev *ifbdev = data;
> -
> - /* Due to peculiar init order wrt to hpd handling this is separate. */
> - if (drm_fb_helper_initial_config(&ifbdev->helper,
> - ifbdev->preferred_bpp))
> - intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
> -}
> -
> void intel_fbdev_initial_config_async(struct drm_device *dev)
> {
> struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
> @@ -715,17 +716,16 @@ void intel_fbdev_initial_config_async(struct drm_device *dev)
> if (!ifbdev)
> return;
>
> - ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
> + schedule_work(&ifbdev->work);
> }
>
> static void intel_fbdev_sync(struct intel_fbdev *ifbdev)
> {
> - if (!ifbdev->cookie)
> + if (!READ_ONCE(ifbdev->work.func))
> return;
>
> - /* Only serialises with all preceding async calls, hence +1 */
> - async_synchronize_cookie(ifbdev->cookie + 1);
> - ifbdev->cookie = 0;
> + flush_work(&ifbdev->work);
> + ifbdev->work.func = NULL;
> }
>
> void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
> @@ -736,8 +736,7 @@ void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
> return;
>
> cancel_work_sync(&dev_priv->fbdev_suspend_work);
> - if (!current_is_async())
> - intel_fbdev_sync(ifbdev);
> + intel_fbdev_sync(ifbdev);
>
> drm_fb_helper_unregister_fbi(&ifbdev->helper);
> }
> --
> 2.19.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the Intel-gfx
mailing list