Re: [Intel-gfx] [PATCH v5 7/7] drm/i915: Implement fbdev emulation as in-kernel client

2023-11-01 Thread Thomas Zimmermann

Hi

Am 01.11.23 um 10:25 schrieb Ville Syrjälä:

On Wed, Nov 01, 2023 at 09:33:41AM +0100, Thomas Zimmermann wrote:

Hi

Am 25.10.23 um 13:36 schrieb Hogander, Jouni:
[...]

+
+   if (!drm_drv_uses_atomic_modeset(dev))
+   drm_helper_disable_unused_functions(dev);


Can you please explain why this is needed here?


This disables some parts of the mode-setting pipeline and is required
for drivers with non-atomic commits.  AFAICT atomic mode setting is not
supported on some very old Intel chips. [1]  I'll leave a short comment
on the code.


We don't expose the atomic uapi because the watermark code is
kinda sketchy for the old chips, but internally i915 is 100% atomic.


Great, thanks. I'll drop that code then.

Best regards
Thomas





[1]
https://elixir.bootlin.com/linux/v6.6/source/drivers/gpu/drm/i915/intel_device_info.c#L399

Best regard
Thomas




+
+   ret = drm_fb_helper_initial_config(fb_helper);
+   if (ret)
+   goto err_drm_fb_helper_fini;
+
+   vga_switcheroo_client_fb_set(pdev, fb_helper->info);
   
  return 0;

+
+err_drm_fb_helper_fini:
+   drm_fb_helper_fini(fb_helper);
+err_drm_err:
+   drm_err(dev, "Failed to setup i915 fbdev emulation
(ret=%d)\n", ret);
+   return ret;
   }
   
   static const struct drm_client_funcs intel_fbdev_client_funcs = {

@@ -703,22 +729,23 @@ static const struct drm_client_funcs
intel_fbdev_client_funcs = {
  .hotplug= intel_fbdev_client_hotplug,
   };
   
-int intel_fbdev_init(struct drm_device *dev)

+void intel_fbdev_setup(struct drm_i915_private *dev_priv)


Use i915 rather than dev_priv.

BR,

Jouni Högander


   {
-   struct drm_i915_private *dev_priv = to_i915(dev);
+   struct drm_device *dev = _priv->drm;
  struct intel_fbdev *ifbdev;
  int ret;
   
-   if (drm_WARN_ON(dev, !HAS_DISPLAY(dev_priv)))

-   return -ENODEV;
+   if (!HAS_DISPLAY(dev_priv))
+   return;
   
  ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL);

  if (!ifbdev)
-   return -ENOMEM;
-
-   mutex_init(>hpd_lock);
+   return;
  drm_fb_helper_prepare(dev, >helper, 32,
_fb_helper_funcs);
   
+   dev_priv->display.fbdev.fbdev = ifbdev;

+   INIT_WORK(_priv->display.fbdev.suspend_work,
intel_fbdev_suspend_worker);
+   mutex_init(>hpd_lock);
  if (intel_fbdev_init_bios(dev, ifbdev))
  ifbdev->helper.preferred_bpp = ifbdev->preferred_bpp;
  else
@@ -726,68 +753,19 @@ int intel_fbdev_init(struct drm_device *dev)
   
  ret = drm_client_init(dev, >helper.client, "i915-

fbdev",
    _fbdev_client_funcs);
-   if (ret)
+   if (ret) {
+   drm_err(dev, "Failed to register client: %d\n", ret);
  goto err_drm_fb_helper_unprepare;
+   }
   
-   ret = drm_fb_helper_init(dev, >helper);

-   if (ret)
-   goto err_drm_client_release;
-
-   dev_priv->display.fbdev.fbdev = ifbdev;
-   INIT_WORK(_priv->display.fbdev.suspend_work,
intel_fbdev_suspend_worker);
+   drm_client_register(>helper.client);
   
-   return 0;

+   return;
   
-err_drm_client_release:

-   drm_client_release(>helper.client);
   err_drm_fb_helper_unprepare:
  drm_fb_helper_unprepare(>helper);
+   mutex_destroy(>hpd_lock);
  kfree(ifbdev);
-   return ret;
-}
-
-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(>helper))
-   intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
-}
-
-void intel_fbdev_initial_config_async(struct drm_i915_private
*dev_priv)
-{
-   struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
-
-   if (!ifbdev)
-   return;
-
-   ifbdev->cookie = async_schedule(intel_fbdev_initial_config,
ifbdev);
-}
-
-void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
-{
-   struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
-
-   if (!ifbdev)
-   return;
-
-   intel_fbdev_set_suspend(_priv->drm,
FBINFO_STATE_SUSPENDED, true);
-
-   if (!current_is_async())
-   intel_fbdev_sync(ifbdev);
-
-   drm_fb_helper_unregister_info(>helper);
-}
-
-void intel_fbdev_fini(struct drm_i915_private *dev_priv)
-{
-   struct intel_fbdev *ifbdev = fetch_and_zero(_priv-

display.fbdev.fbdev);

-
-   if (!ifbdev)
-   return;
-
-   intel_fbdev_destroy(ifbdev);
   }
   
   struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev

*fbdev)
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.h
b/drivers/gpu/drm/i915/display/intel_fbdev.h
index 8c953f102ba22..08de2d5b34338 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.h
+++ 

Re: [Intel-gfx] [PATCH v5 7/7] drm/i915: Implement fbdev emulation as in-kernel client

2023-11-01 Thread Ville Syrjälä
On Wed, Nov 01, 2023 at 09:33:41AM +0100, Thomas Zimmermann wrote:
> Hi
> 
> Am 25.10.23 um 13:36 schrieb Hogander, Jouni:
> [...]
> >> +
> >> +   if (!drm_drv_uses_atomic_modeset(dev))
> >> +   drm_helper_disable_unused_functions(dev);
> > 
> > Can you please explain why this is needed here?
> 
> This disables some parts of the mode-setting pipeline and is required 
> for drivers with non-atomic commits.  AFAICT atomic mode setting is not 
> supported on some very old Intel chips. [1]  I'll leave a short comment 
> on the code.

We don't expose the atomic uapi because the watermark code is
kinda sketchy for the old chips, but internally i915 is 100% atomic.

> 
> [1] 
> https://elixir.bootlin.com/linux/v6.6/source/drivers/gpu/drm/i915/intel_device_info.c#L399
> 
> Best regard
> Thomas
> 
> > 
> >> +
> >> +   ret = drm_fb_helper_initial_config(fb_helper);
> >> +   if (ret)
> >> +   goto err_drm_fb_helper_fini;
> >> +
> >> +   vga_switcheroo_client_fb_set(pdev, fb_helper->info);
> >>   
> >>  return 0;
> >> +
> >> +err_drm_fb_helper_fini:
> >> +   drm_fb_helper_fini(fb_helper);
> >> +err_drm_err:
> >> +   drm_err(dev, "Failed to setup i915 fbdev emulation
> >> (ret=%d)\n", ret);
> >> +   return ret;
> >>   }
> >>   
> >>   static const struct drm_client_funcs intel_fbdev_client_funcs = {
> >> @@ -703,22 +729,23 @@ static const struct drm_client_funcs
> >> intel_fbdev_client_funcs = {
> >>  .hotplug= intel_fbdev_client_hotplug,
> >>   };
> >>   
> >> -int intel_fbdev_init(struct drm_device *dev)
> >> +void intel_fbdev_setup(struct drm_i915_private *dev_priv)
> > 
> > Use i915 rather than dev_priv.
> > 
> > BR,
> > 
> > Jouni Högander
> > 
> >>   {
> >> -   struct drm_i915_private *dev_priv = to_i915(dev);
> >> +   struct drm_device *dev = _priv->drm;
> >>  struct intel_fbdev *ifbdev;
> >>  int ret;
> >>   
> >> -   if (drm_WARN_ON(dev, !HAS_DISPLAY(dev_priv)))
> >> -   return -ENODEV;
> >> +   if (!HAS_DISPLAY(dev_priv))
> >> +   return;
> >>   
> >>  ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL);
> >>  if (!ifbdev)
> >> -   return -ENOMEM;
> >> -
> >> -   mutex_init(>hpd_lock);
> >> +   return;
> >>  drm_fb_helper_prepare(dev, >helper, 32,
> >> _fb_helper_funcs);
> >>   
> >> +   dev_priv->display.fbdev.fbdev = ifbdev;
> >> +   INIT_WORK(_priv->display.fbdev.suspend_work,
> >> intel_fbdev_suspend_worker);
> >> +   mutex_init(>hpd_lock);
> >>  if (intel_fbdev_init_bios(dev, ifbdev))
> >>  ifbdev->helper.preferred_bpp = ifbdev->preferred_bpp;
> >>  else
> >> @@ -726,68 +753,19 @@ int intel_fbdev_init(struct drm_device *dev)
> >>   
> >>  ret = drm_client_init(dev, >helper.client, "i915-
> >> fbdev",
> >>    _fbdev_client_funcs);
> >> -   if (ret)
> >> +   if (ret) {
> >> +   drm_err(dev, "Failed to register client: %d\n", ret);
> >>  goto err_drm_fb_helper_unprepare;
> >> +   }
> >>   
> >> -   ret = drm_fb_helper_init(dev, >helper);
> >> -   if (ret)
> >> -   goto err_drm_client_release;
> >> -
> >> -   dev_priv->display.fbdev.fbdev = ifbdev;
> >> -   INIT_WORK(_priv->display.fbdev.suspend_work,
> >> intel_fbdev_suspend_worker);
> >> +   drm_client_register(>helper.client);
> >>   
> >> -   return 0;
> >> +   return;
> >>   
> >> -err_drm_client_release:
> >> -   drm_client_release(>helper.client);
> >>   err_drm_fb_helper_unprepare:
> >>  drm_fb_helper_unprepare(>helper);
> >> +   mutex_destroy(>hpd_lock);
> >>  kfree(ifbdev);
> >> -   return ret;
> >> -}
> >> -
> >> -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(>helper))
> >> -   intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
> >> -}
> >> -
> >> -void intel_fbdev_initial_config_async(struct drm_i915_private
> >> *dev_priv)
> >> -{
> >> -   struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
> >> -
> >> -   if (!ifbdev)
> >> -   return;
> >> -
> >> -   ifbdev->cookie = async_schedule(intel_fbdev_initial_config,
> >> ifbdev);
> >> -}
> >> -
> >> -void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
> >> -{
> >> -   struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
> >> -
> >> -   if (!ifbdev)
> >> -   return;
> >> -
> >> -   intel_fbdev_set_suspend(_priv->drm,
> >> FBINFO_STATE_SUSPENDED, true);
> >> -
> >> -   if (!current_is_async())
> >> -   intel_fbdev_sync(ifbdev);
> >> -
> >> -   drm_fb_helper_unregister_info(>helper);
> >> -}
> >> -
> >> -void 

Re: [Intel-gfx] [PATCH v5 7/7] drm/i915: Implement fbdev emulation as in-kernel client

2023-11-01 Thread Thomas Zimmermann

Hi

Am 25.10.23 um 13:36 schrieb Hogander, Jouni:
[...]

+
+   if (!drm_drv_uses_atomic_modeset(dev))
+   drm_helper_disable_unused_functions(dev);


Can you please explain why this is needed here?


This disables some parts of the mode-setting pipeline and is required 
for drivers with non-atomic commits.  AFAICT atomic mode setting is not 
supported on some very old Intel chips. [1]  I'll leave a short comment 
on the code.


[1] 
https://elixir.bootlin.com/linux/v6.6/source/drivers/gpu/drm/i915/intel_device_info.c#L399


Best regard
Thomas




+
+   ret = drm_fb_helper_initial_config(fb_helper);
+   if (ret)
+   goto err_drm_fb_helper_fini;
+
+   vga_switcheroo_client_fb_set(pdev, fb_helper->info);
  
 return 0;

+
+err_drm_fb_helper_fini:
+   drm_fb_helper_fini(fb_helper);
+err_drm_err:
+   drm_err(dev, "Failed to setup i915 fbdev emulation
(ret=%d)\n", ret);
+   return ret;
  }
  
  static const struct drm_client_funcs intel_fbdev_client_funcs = {

@@ -703,22 +729,23 @@ static const struct drm_client_funcs
intel_fbdev_client_funcs = {
 .hotplug= intel_fbdev_client_hotplug,
  };
  
-int intel_fbdev_init(struct drm_device *dev)

+void intel_fbdev_setup(struct drm_i915_private *dev_priv)


Use i915 rather than dev_priv.

BR,

Jouni Högander


  {
-   struct drm_i915_private *dev_priv = to_i915(dev);
+   struct drm_device *dev = _priv->drm;
 struct intel_fbdev *ifbdev;
 int ret;
  
-   if (drm_WARN_ON(dev, !HAS_DISPLAY(dev_priv)))

-   return -ENODEV;
+   if (!HAS_DISPLAY(dev_priv))
+   return;
  
 ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL);

 if (!ifbdev)
-   return -ENOMEM;
-
-   mutex_init(>hpd_lock);
+   return;
 drm_fb_helper_prepare(dev, >helper, 32,
_fb_helper_funcs);
  
+   dev_priv->display.fbdev.fbdev = ifbdev;

+   INIT_WORK(_priv->display.fbdev.suspend_work,
intel_fbdev_suspend_worker);
+   mutex_init(>hpd_lock);
 if (intel_fbdev_init_bios(dev, ifbdev))
 ifbdev->helper.preferred_bpp = ifbdev->preferred_bpp;
 else
@@ -726,68 +753,19 @@ int intel_fbdev_init(struct drm_device *dev)
  
 ret = drm_client_init(dev, >helper.client, "i915-

fbdev",
   _fbdev_client_funcs);
-   if (ret)
+   if (ret) {
+   drm_err(dev, "Failed to register client: %d\n", ret);
 goto err_drm_fb_helper_unprepare;
+   }
  
-   ret = drm_fb_helper_init(dev, >helper);

-   if (ret)
-   goto err_drm_client_release;
-
-   dev_priv->display.fbdev.fbdev = ifbdev;
-   INIT_WORK(_priv->display.fbdev.suspend_work,
intel_fbdev_suspend_worker);
+   drm_client_register(>helper.client);
  
-   return 0;

+   return;
  
-err_drm_client_release:

-   drm_client_release(>helper.client);
  err_drm_fb_helper_unprepare:
 drm_fb_helper_unprepare(>helper);
+   mutex_destroy(>hpd_lock);
 kfree(ifbdev);
-   return ret;
-}
-
-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(>helper))
-   intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
-}
-
-void intel_fbdev_initial_config_async(struct drm_i915_private
*dev_priv)
-{
-   struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
-
-   if (!ifbdev)
-   return;
-
-   ifbdev->cookie = async_schedule(intel_fbdev_initial_config,
ifbdev);
-}
-
-void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
-{
-   struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
-
-   if (!ifbdev)
-   return;
-
-   intel_fbdev_set_suspend(_priv->drm,
FBINFO_STATE_SUSPENDED, true);
-
-   if (!current_is_async())
-   intel_fbdev_sync(ifbdev);
-
-   drm_fb_helper_unregister_info(>helper);
-}
-
-void intel_fbdev_fini(struct drm_i915_private *dev_priv)
-{
-   struct intel_fbdev *ifbdev = fetch_and_zero(_priv-

display.fbdev.fbdev);

-
-   if (!ifbdev)
-   return;
-
-   intel_fbdev_destroy(ifbdev);
  }
  
  struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev

*fbdev)
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.h
b/drivers/gpu/drm/i915/display/intel_fbdev.h
index 8c953f102ba22..08de2d5b34338 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.h
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.h
@@ -14,27 +14,11 @@ struct intel_fbdev;
  struct intel_framebuffer;
  
  #ifdef CONFIG_DRM_FBDEV_EMULATION

-int intel_fbdev_init(struct drm_device *dev);
-void intel_fbdev_initial_config_async(struct drm_i915_private
*dev_priv);
-void intel_fbdev_unregister(struct drm_i915_private *dev_priv);
-void intel_fbdev_fini(struct 

Re: [Intel-gfx] [PATCH v5 7/7] drm/i915: Implement fbdev emulation as in-kernel client

2023-10-25 Thread Hogander, Jouni
Hi Thomas, couple of minor comments and a question below.

On Wed, 2023-09-27 at 12:26 +0200, Thomas Zimmermann wrote:
> Replace all code that initializes or releases fbdev emulation
> throughout the driver. Instead initialize the fbdev client by a
> single call to i915_fbdev_setup() after i915 has registered its

intel_fbdev_setup

> DRM device. Just like similar code in other drivers, i915 fbdev
> emulation now acts as a regular DRM client.
> 
> The fbdev client setup consists of the initial preparation and the
> hot-plugging of the display. The latter creates the fbdev device
> and sets up the fbdev framebuffer. The setup performs display
> hot-plugging once. If no display can be detected, DRM probe helpers
> re-run the detection on each hotplug event.
> 
> A call to drm_dev_unregister() releases the client automatically.
> No further action is required within i915. If the fbdev framebuffer
> has been fully set up, struct fb_ops.fb_destroy implements the
> release. For partially initialized emulation, the fbdev client
> reverts the initial setup.
> 
> v3:
> * as before, silently ignore devices without displays
> v2:
> * let drm_client_register() handle initial hotplug
> * fix driver name in error message (Jani)
> * fix non-fbdev build (kernel test robot)
> 
> Signed-off-by: Thomas Zimmermann 
> ---
>  drivers/gpu/drm/i915/display/intel_display.c  |   1 -
>  .../drm/i915/display/intel_display_driver.c   |  18 --
>  drivers/gpu/drm/i915/display/intel_fbdev.c    | 180 
> --
>  drivers/gpu/drm/i915/display/intel_fbdev.h    |  20 +-
>  drivers/gpu/drm/i915/i915_driver.c    |   2 +
>  5 files changed, 83 insertions(+), 138 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> b/drivers/gpu/drm/i915/display/intel_display.c
> index edbcf5968804d..7efa8d2787c39 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -81,7 +81,6 @@
>  #include "intel_dvo.h"
>  #include "intel_fb.h"
>  #include "intel_fbc.h"
> -#include "intel_fbdev.h"
>  #include "intel_fdi.h"
>  #include "intel_fifo_underrun.h"
>  #include "intel_frontbuffer.h"
> diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c
> b/drivers/gpu/drm/i915/display/intel_display_driver.c
> index ffdcddd1943e0..213a4ee93ffc2 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_driver.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
> @@ -364,10 +364,6 @@ int intel_display_driver_probe(struct
> drm_i915_private *i915)
>  
> intel_overlay_setup(i915);
>  
> -   ret = intel_fbdev_init(>drm);
> -   if (ret)
> -   return ret;
> -
> /* Only enable hotplug handling once the fbdev is fully set
> up. */
> intel_hpd_init(i915);
> intel_hpd_poll_disable(i915);
> @@ -392,16 +388,6 @@ void intel_display_driver_register(struct
> drm_i915_private *i915)
>  
> intel_display_debugfs_register(i915);
>  
> -   /*
> -    * Some ports require correctly set-up hpd registers for
> -    * detection to work properly (leading to ghost connected
> -    * connector status), e.g. VGA on gm45.  Hence we can only
> set
> -    * up the initial fbdev config after hpd irqs are fully
> -    * enabled. We do it last so that the async config cannot run
> -    * before the connectors are registered.
> -    */
> -   intel_fbdev_initial_config_async(i915);
> -
> /*
>  * We need to coordinate the hotplugs with the asynchronous
>  * fbdev configuration, for which we use the
> @@ -445,9 +431,6 @@ void intel_display_driver_remove_noirq(struct
> drm_i915_private *i915)
>  */
> intel_hpd_poll_fini(i915);
>  
> -   /* poll work can call into fbdev, hence clean that up
> afterwards */
> -   intel_fbdev_fini(i915);
> -
> intel_unregister_dsm_handler();
>  
> /* flush any delayed tasks or pending work */
> @@ -484,7 +467,6 @@ void intel_display_driver_unregister(struct
> drm_i915_private *i915)
> if (!HAS_DISPLAY(i915))
> return;
>  
> -   intel_fbdev_unregister(i915);
> intel_audio_deinit(i915);
>  
> /*
> diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c
> b/drivers/gpu/drm/i915/display/intel_fbdev.c
> index 39de61d4e7906..100a4aaf1b7e4 100644
> --- a/drivers/gpu/drm/i915/display/intel_fbdev.c
> +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
> @@ -24,7 +24,6 @@
>   * David Airlie
>   */
>  
> -#include 
>  #include 
>  #include 
>  #include 
> @@ -39,6 +38,7 @@
>  #include 
>  
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -58,7 +58,6 @@ struct intel_fbdev {
> struct intel_framebuffer *fb;
> struct i915_vma *vma;
> unsigned long vma_flags;
> -   async_cookie_t cookie;
> int preferred_bpp;
>  
> /* Whether or not fbdev hpd processing is temporarily
> suspended */