On Thu, 16 Feb 2023, Imre Deak <imre.deak@xxxxxxxxx> wrote: > On Thu, Feb 16, 2023 at 06:17:39PM +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 <imre.deak@xxxxxxxxx> >> Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx> >> --- >> .../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 b870f7f47f2b..ff51149c5fcb 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 1d156ac2eb4c..8428d08e0c3d 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; > > Couldn't driver loading fail in this case instead (simplifying the > dmc==NULL checks elsewhere)? We could fail driver load, yes, but it still wouldn't simplify the NULL checks because you could use i915.dmc_firmware_path="" to disable the firmware, and what's the point in keeping the 1k memory allocated in that case? BR, Jani. > >> + >> 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 5359b9663a07..42bfd56fcbe4 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_modeset_setup.h" >> #include "intel_pch_display.h" >> #include "intel_pm.h" >> -- >> 2.34.1 >> -- Jani Nikula, Intel Open Source Graphics Center