On Mon, Feb 27, 2023 at 07:25:21PM +0200, Jani Nikula wrote:
> sizeof(struct intel_dmc) > 1024 bytes, allocated on all platforms as
> part of struct drm_i915_private, whether they have DMC or not.
> 
> Allocate struct intel_dmc dynamically, and hide all the dmc details
> behind an opaque pointer in intel_dmc.c.
> 
> Care must be taken to take into account all cases: DMC not supported on
> the platform, DMC supported but not initialized, and DMC initialized but
> not loaded. For the second case, we need to move the wakeref out of
> struct intel_dmc.
> 
> Cc: Imre Deak <[email protected]>
> Signed-off-by: Jani Nikula <[email protected]>
> ---
>  .../gpu/drm/i915/display/intel_display_core.h |  8 ++-
>  drivers/gpu/drm/i915/display/intel_dmc.c      | 50 +++++++++++++++++--
>  drivers/gpu/drm/i915/display/intel_dmc.h      | 34 +------------
>  .../drm/i915/display/intel_modeset_setup.c    |  1 +
>  4 files changed, 53 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h 
> b/drivers/gpu/drm/i915/display/intel_display_core.h
> index 631a7b17899e..fdab7bb93a7d 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> @@ -19,7 +19,6 @@
>  #include "intel_cdclk.h"
>  #include "intel_display_limits.h"
>  #include "intel_display_power.h"
> -#include "intel_dmc.h"
>  #include "intel_dpll_mgr.h"
>  #include "intel_fbc.h"
>  #include "intel_global_state.h"
> @@ -40,6 +39,7 @@ struct intel_cdclk_vals;
>  struct intel_color_funcs;
>  struct intel_crtc;
>  struct intel_crtc_state;
> +struct intel_dmc;
>  struct intel_dpll_funcs;
>  struct intel_dpll_mgr;
>  struct intel_fbdev;
> @@ -340,6 +340,11 @@ struct intel_display {
>               spinlock_t phy_lock;
>       } dkl;
>  
> +     struct {
> +             struct intel_dmc *dmc;
> +             intel_wakeref_t wakeref;
> +     } dmc;
> +
>       struct {
>               /* VLV/CHV/BXT/GLK DSI MMIO register base address */
>               u32 mmio_base;
> @@ -467,7 +472,6 @@ struct intel_display {
>  
>       /* Grouping using named structs. Keep sorted. */
>       struct intel_audio audio;
> -     struct intel_dmc dmc;
>       struct intel_dpll dpll;
>       struct intel_fbc *fbc[I915_MAX_FBCS];
>       struct intel_frontbuffer_tracking fb_tracking;
> diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c 
> b/drivers/gpu/drm/i915/display/intel_dmc.c
> index 0b54b9b96249..8deebd4b62fb 100644
> --- a/drivers/gpu/drm/i915/display/intel_dmc.c
> +++ b/drivers/gpu/drm/i915/display/intel_dmc.c
> @@ -38,9 +38,37 @@
>   * low-power state and comes back to normal.
>   */
>  
> +enum intel_dmc_id {
> +     DMC_FW_MAIN = 0,
> +     DMC_FW_PIPEA,
> +     DMC_FW_PIPEB,
> +     DMC_FW_PIPEC,
> +     DMC_FW_PIPED,
> +     DMC_FW_MAX
> +};
> +
> +struct intel_dmc {
> +     struct drm_i915_private *i915;
> +     struct work_struct work;
> +     const char *fw_path;
> +     u32 max_fw_size; /* bytes */
> +     u32 version;
> +     struct dmc_fw_info {
> +             u32 mmio_count;
> +             i915_reg_t mmioaddr[20];
> +             u32 mmiodata[20];
> +             u32 dmc_offset;
> +             u32 start_mmioaddr;
> +             u32 dmc_fw_size; /*dwords */
> +             u32 *payload;
> +             bool present;
> +     } dmc_info[DMC_FW_MAX];
> +};
> +
> +/* Note: This may be NULL. */
>  static struct intel_dmc *i915_to_dmc(struct drm_i915_private *i915)
>  {
> -     return &i915->display.dmc;
> +     return i915->display.dmc.dmc;
>  }
>  
>  #define DMC_VERSION(major, minor)    ((major) << 16 | (minor))
> @@ -937,7 +965,10 @@ void intel_dmc_init(struct drm_i915_private *dev_priv)
>       if (!HAS_DMC(dev_priv))
>               return;
>  
> -     dmc = i915_to_dmc(dev_priv);
> +     dmc = kzalloc(sizeof(*dmc), GFP_KERNEL);
> +     if (!dmc)
> +             return;

I missed this in my review: the above implies the same thing as the
firmware not being loaded for other reasons, so it would still require
calling intel_dmc_runtime_pm_get() as it's done in those cases.

> +
>       dmc->i915 = dev_priv;
>  
>       INIT_WORK(&dmc->work, dmc_load_work_fn);
> @@ -991,10 +1022,9 @@ void intel_dmc_init(struct drm_i915_private *dev_priv)
>  
>       if (dev_priv->params.dmc_firmware_path) {
>               if (strlen(dev_priv->params.dmc_firmware_path) == 0) {
> -                     dmc->fw_path = NULL;
>                       drm_info(&dev_priv->drm,
>                                "Disabling DMC firmware and runtime PM\n");
> -                     return;
> +                     goto out;
>               }
>  
>               dmc->fw_path = dev_priv->params.dmc_firmware_path;
> @@ -1003,11 +1033,18 @@ void intel_dmc_init(struct drm_i915_private *dev_priv)
>       if (!dmc->fw_path) {
>               drm_dbg_kms(&dev_priv->drm,
>                           "No known DMC firmware for platform, disabling 
> runtime PM\n");
> -             return;
> +             goto out;
>       }
>  
> +     dev_priv->display.dmc.dmc = dmc;
> +
>       drm_dbg_kms(&dev_priv->drm, "Loading %s\n", dmc->fw_path);
>       schedule_work(&dmc->work);
> +
> +     return;
> +
> +out:
> +     kfree(dmc);
>  }
>  
>  /**
> @@ -1074,6 +1111,9 @@ void intel_dmc_fini(struct drm_i915_private *dev_priv)
>       if (dmc) {
>               for_each_dmc_id(dmc_id)
>                       kfree(dmc->dmc_info[dmc_id].payload);
> +
> +             kfree(dmc);
> +             dev_priv->display.dmc.dmc = NULL;
>       }
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h 
> b/drivers/gpu/drm/i915/display/intel_dmc.h
> index b74635497aa7..fd607afff2ef 100644
> --- a/drivers/gpu/drm/i915/display/intel_dmc.h
> +++ b/drivers/gpu/drm/i915/display/intel_dmc.h
> @@ -6,44 +6,12 @@
>  #ifndef __INTEL_DMC_H__
>  #define __INTEL_DMC_H__
>  
> -#include "i915_reg_defs.h"
> -#include "intel_wakeref.h"
> -#include <linux/workqueue.h>
> +#include <linux/types.h>
>  
>  struct drm_i915_error_state_buf;
>  struct drm_i915_private;
> -
>  enum pipe;
>  
> -enum intel_dmc_id {
> -     DMC_FW_MAIN = 0,
> -     DMC_FW_PIPEA,
> -     DMC_FW_PIPEB,
> -     DMC_FW_PIPEC,
> -     DMC_FW_PIPED,
> -     DMC_FW_MAX
> -};
> -
> -struct intel_dmc {
> -     struct drm_i915_private *i915;
> -     struct work_struct work;
> -     const char *fw_path;
> -     u32 max_fw_size; /* bytes */
> -     u32 version;
> -     struct dmc_fw_info {
> -             u32 mmio_count;
> -             i915_reg_t mmioaddr[20];
> -             u32 mmiodata[20];
> -             u32 dmc_offset;
> -             u32 start_mmioaddr;
> -             u32 dmc_fw_size; /*dwords */
> -             u32 *payload;
> -             bool present;
> -     } dmc_info[DMC_FW_MAX];
> -
> -     intel_wakeref_t wakeref;
> -};
> -
>  void intel_dmc_init(struct drm_i915_private *i915);
>  void intel_dmc_load_program(struct drm_i915_private *i915);
>  void intel_dmc_disable_program(struct drm_i915_private *i915);
> diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c 
> b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> index 60f71e6f0491..0f7b414eb472 100644
> --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
> @@ -22,6 +22,7 @@
>  #include "intel_display.h"
>  #include "intel_display_power.h"
>  #include "intel_display_types.h"
> +#include "intel_dmc.h"
>  #include "intel_fifo_underrun.h"
>  #include "intel_modeset_setup.h"
>  #include "intel_pch_display.h"
> -- 
> 2.39.1
> 

Reply via email to