[Intel-gfx] [PATCH v2] drm/i915/d12+: Disable DMC firmware flip queue handlers
Imre Deak
imre.deak at intel.com
Fri May 13 08:00:27 UTC 2022
On Thu, May 12, 2022 at 03:37:14PM -0700, Lucas De Marchi wrote:
> On Thu, May 12, 2022 at 10:47:46PM +0300, Imre Deak wrote:
> > On Thu, May 12, 2022 at 10:56:11AM -0700, Lucas De Marchi wrote:
> > > On Thu, May 12, 2022 at 12:37:05PM +0300, Imre Deak wrote:
> > > > Based on a bspec update the DMC firmware's flip queue handling events
> > > > need to be disabled before enabling DC5/6. i915 doesn't use the flip
> > > > queue feature atm, so disable it already after loading the firmware.
> > > > This removes some overhead of the event handler which runs at a 1 kHz
> > > > frequency.
> > > >
> > > > Bspec: 49193, 72486, 72487
> > > >
> > > > v2:
> > > > - Fix the DMC pipe A register offsets for GEN12.
> > > > - Disable the events on DG2 only on pipe A..D .
> > > >
> > > > Signed-off-by: Imre Deak <imre.deak at intel.com>
> > > > Reviewed-by: Anusha Srivatsa <anusha.srivatsa at intel.com> # v1
> > > > ---
> > > > drivers/gpu/drm/i915/display/intel_dmc.c | 89 ++++++++++++++++++-
> > > > drivers/gpu/drm/i915/display/intel_dmc_regs.h | 41 +++++++++
> > > > 2 files changed, 129 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
> > > > index 257cf662f9f4b..0ede8c86c6ccb 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dmc.c
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dmc.c
> > > > @@ -244,9 +244,14 @@ struct stepping_info {
> > > > char substepping;
> > > > };
> > > >
> > > > +static bool intel_dmc_has_fw_payload(struct drm_i915_private *i915, int dmc_id)
> > >
> > > in several places, including this file, we are trying to keep the
> > > convention of not using intel_ prefix for non-exported functions.
> > >
> > > has_dmc_id_fw() here would read better IMO.
> >
> > Ok.
> >
> > > > +{
> > > > + return i915->dmc.dmc_info[dmc_id].payload;
> > > > +}
> > > > +
> > > > bool intel_dmc_has_payload(struct drm_i915_private *i915)
> > > > {
> > > > - return i915->dmc.dmc_info[DMC_FW_MAIN].payload;
> > > > + return intel_dmc_has_fw_payload(i915, DMC_FW_MAIN);
> > > > }
> > > >
> > > > static const struct stepping_info *
> > > > @@ -268,6 +273,81 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
> > > > intel_de_posting_read(dev_priv, DC_STATE_DEBUG);
> > > > }
> > > >
> > > > +static void
> > > > +disable_simple_flip_queue_event(struct drm_i915_private *i915,
> > > > + i915_reg_t ctl_reg, i915_reg_t htp_reg)
> > > > +{
> > > > + u32 event_ctl;
> > > > + u32 event_htp;
> > > > +
> > > > + event_ctl = intel_de_read(i915, ctl_reg);
> > > > + event_htp = intel_de_read(i915, htp_reg);
> > > > + if (event_ctl != (DMC_EVT_CTL_ENABLE |
> > > > + DMC_EVT_CTL_RECURRING |
> > > > + REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK,
> > > > + DMC_EVT_CTL_TYPE_EDGE_0_1) |
> > > > + REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK,
> > > > + DMC_EVT_CTL_EVENT_ID_CLK_MSEC)) ||
> > > > + !event_htp) {
> > > > + drm_dbg_kms(&i915->drm,
> > > > + "Unexpected DMC event configuration (control %08x htp %08x)\n",
> > > > + event_ctl, event_htp);
> > > > + return;
> > > > + }
> > >
> > > why are we doing this if we just want to disable? If we will always keep
> > > it disabled, then just writing the right values would be simpler.
> >
> > The requirement to disable flip queues explicitly came only now,
> > somewhat as a surprise. Future firmware versions will disable it by
> > default, but it's not clear at which point and how the ABI will change
> > then. So I'd like to keep the above check for any such ABI change in
> > place at least until those plans get clarified to us.
>
> humn... It seems weird to log "Unexpected DMC event... " if we are
> expecting that in future it will be disabled. But since it's a debug
> message only, it's not a big thing.
>
> Later are you expecting to separate the an if condition like below?
>
> if (!(event_ctl & DMC_EVT_CTL_ENABLE)) {
> drm_dbg_kms(&i915->drm, "Skip flip queue disabling: already disabled\n");
> return;
> }
I think after noticing via the above debug message that a given
platform/fw revision changed the MMIO list so that it doesn't enable the
flip queue events, we should adjust the platform/fw revision checks to
not call the disabling function for those.
> > > > +
> > > > + intel_de_write(i915, ctl_reg,
> > > > + REG_FIELD_PREP(DMC_EVT_CTL_TYPE_MASK,
> > > > + DMC_EVT_CTL_TYPE_EDGE_0_1) |
> > > > + REG_FIELD_PREP(DMC_EVT_CTL_EVENT_ID_MASK,
> > > > + DMC_EVT_CTL_EVENT_ID_FALSE));
> > > > + intel_de_write(i915, htp_reg, 0);
> > >
> > > matches bspec 72487 and 72486. It looks like we are missing a disable
> > > sequence for ADL-P though. Is it a missing documentation or function
> > > below should be updated to do nothing on ADL-P?
> >
> > First I thought ADL-P doesn't use the same 1 kHz event as the other
> > platforms, hence no disable sequence is defined by bspec. But looking
> > again it also seems to use that just with a different event ID
> > ('1KHZ_FLIPQ' vs. 'CLK_MSEC', see bspec 67608). I filed a bspec ticket
> > and will add the disabling for ADLP as well once that gets clarified.
>
> ok
>
> > > > +}
> > > > +
> > > > +static bool
> > > > +get_simple_flip_queue_event_regs(struct drm_i915_private *i915, int dmc_id,
> > > > + i915_reg_t *ctl_reg, i915_reg_t *htp_reg)
> > > > +{
> > > > + switch (dmc_id) {
> > > > + case DMC_FW_MAIN:
> > > > + if (DISPLAY_VER(i915) == 12) {
> > >
> > > Shouldn't this be >= 12? but see comment above about ADL-P
> >
> > It's only D12 platforms that use one event handler running on the main
> > DMC for this, all later platforms use one event handler running on each
> > pipe DMC, and no flip queue handler running on the main DMC.
>
> ok, this is the PIPEMDC_* vs DMC_* on Display 13 vs 12.
>
>
> > > > + *ctl_reg = DMC_EVT_CTL(i915, dmc_id, 3);
> > > > + *htp_reg = DMC_EVT_HTP(i915, dmc_id, 3);
> > >
> > > For DG2 the sequence in bspec is:
> > >
> > > 1. Disable flip queue
> > > 2. PIPEDMC_EVT_CTL_2_A/B/C/D = 0x00030100
> > > 3. PIPEDMC_EVT_HTP_2_A/B/C/D = 0x00000000
> > >
> > > where did you get that for main dmc you need to write to CTL_3/HTP_3?
> >
> > Bspec/72486, and checking the fixed MMIOs in the TGL/RKL firmwares (for
> > the above 1kHz events).
>
> yeah, looks good. Kind of same issue I had reading the spec in the
> question above. That answers it.
>
> > > > +
> > > > + return true;
> > > > + }
> > > > + break;
> > > > + case DMC_FW_PIPEA ... DMC_FW_PIPED:
> > > > + if (IS_DG2(i915)) {
> > > > + *ctl_reg = DMC_EVT_CTL(i915, dmc_id, 2);
> > > > + *htp_reg = DMC_EVT_HTP(i915, dmc_id, 2);
> > > > +
> > > > + return true;
> > > > + }
> > > > + break;
> > > > + }
> > > > +
> > > > + return false;
> > > > +}
> > > > +
> > > > +static void
> > > > +disable_all_simple_flip_queue_events(struct drm_i915_private *i915)
> > > > +{
> > > > + int dmc_id;
> > > > +
> > > > + for (dmc_id = 0; dmc_id < DMC_FW_MAX; dmc_id++) {
> > > > + i915_reg_t ctl_reg;
> > > > + i915_reg_t htp_reg;
> > > > +
> > > > + if (!intel_dmc_has_fw_payload(i915, dmc_id))
> > > > + continue;
> > > > +
> > > > + if (!get_simple_flip_queue_event_regs(i915, dmc_id, &ctl_reg, &htp_reg))
> > > > + continue;
> > > > +
> > > > + disable_simple_flip_queue_event(i915, ctl_reg, htp_reg);
> > > > + }
> > > > +}
> > >
> > > it seems we are mixing "flip queue" and "simple flip queue". Maybe just
> > > remove "simple" as it doesn't add much information?
> >
> > The other variant is called batch flip queue, but can rename this to
> > flip_queue.
>
> My preference is to drop "simple", but feel free to keep it if you want.
>
> > > > +
> > > > /**
> > > > * intel_dmc_load_program() - write the firmware from memory to register.
> > > > * @dev_priv: i915 drm device.
> > > > @@ -308,6 +388,13 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv)
> > > > dev_priv->dmc.dc_state = 0;
> > > >
> > > > gen9_set_dc_state_debugmask(dev_priv);
> > > > +
> > > > + /*
> > > > + * Flip queue events need to be disabled before enabling DC5/6.
> > > > + * i915 doesn't use the flip queue feature, so disable it already
> > > > + * here.
> > > > + */
> > > > + disable_all_simple_flip_queue_events(dev_priv);
> > > > }
> > > >
> > > > void assert_dmc_loaded(struct drm_i915_private *i915)
> > > > diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
> > > > index d65e698832eb5..43d780148b196 100644
> > > > --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h
> > > > +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h
> > > > @@ -10,6 +10,47 @@
> > > >
> > > > #define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4)
> > > > #define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0
> > > > +
> > > > +#define _PIPEDMC_REG_MMIO_BASE_A_GEN13 0x5f000
> > > > +#define _PIPEDMC_REG_MMIO_BASE_A_GEN12 0x92000
> > >
> > > no _GEN12/_GEN13 suffix
> >
> > Why not? Is _ADLP/_TGL ok?
>
> We are not supposed to add GEN<x> anymore as that doesn't make sense for
> our gpus anymore. Versions are separated per IP like display, graphics,
> media. We went on an effort to rename everything last year. We still
> have some, but we should avoid adding more.
>
> yes, using the first platform that uses the register keeps with what's
> being used in i915_drv.h
Ok. Looks like flags use a suffix and regs/bases a prefix, so will use
ADLP_*/TGL_*.
> > > > +
> > > > +#define _PIPEDMC_REG_MMIO_BASE(i915, dmc_id) \
> > > > + ((DISPLAY_VER(i915) >= 13 ? _PIPEDMC_REG_MMIO_BASE_A_GEN13 : \
> > > > + _PIPEDMC_REG_MMIO_BASE_A_GEN12) + \
> > > > + 0x400 * ((dmc_id) - 1))
> > > > +
> > > > +#define _MAINDMC_REG_MMIO_BASE 0x8f000
> > > > +
> > > > +#define _DMC_REG_MMIO_BASE(i915, dmc_id) \
> > > > + ((dmc_id) == DMC_FW_MAIN ? _MAINDMC_REG_MMIO_BASE : \
> > > > + _PIPEDMC_REG_MMIO_BASE(i915, dmc_id))
> > > > +
> > > > +#define _DMC_REG(i915, dmc_id, reg) \
> > > > + ((reg) - _MAINDMC_REG_MMIO_BASE + _DMC_REG_MMIO_BASE(i915, dmc_id))
> > > > +
> > > > +#define _MAINDMC_EVT_HTP_0 0x8f004
> > > > +
> > > > +#define DMC_EVT_HTP(i915, dmc_id, handler) \
> > > > + _MMIO(_DMC_REG(i915, dmc_id, _MAINDMC_EVT_HTP_0) + 4 * (handler))
> > > > +
> > > > +#define _MAINDMC_EVT_CTL_0 0x8f034
> > >
> > > if we were to follow the spec names, we'd rather name
> > > _DMC_* for main fw
> > > _PIPEDMC_* for others.
> >
> > Ok.
> >
> > > > +
> > > > +#define DMC_EVT_CTL(i915, dmc_id, handler) \
> > > > + _MMIO(_DMC_REG(i915, dmc_id, _MAINDMC_EVT_CTL_0) + 4 * (handler))
> > >
> > > s/handler/offset/?
> >
> > There are a number of event handlers each main/pipe DMC can run,
> > each of which is configured via its control and HTP register. 'handler'
> > refers to such handler instances.
>
> makes sense, it was my lack of understanding on this part of the spec.
>
> > > It seems we have to massage the macros everywhere to handle pipe vs
> > > main. Given get_simple_flip_queue_event_regs() already handle them
> > > separate, I think it would be simpler to just split the macros on DMC_*
> > > vs PIPEDMC_*, which would be more inline with the spec too.
> >
> > There are cases where it's practical being able to loop through all main
> > and pipe DMC registers in one go, for instance for clearing all
> > event control and HTP registers when reloading the firmware.
>
> humn, I have the impression in most cases the code is cleaner handling
> the MAIN DMC separate from the loop on the pipe DMCs. But if you want to
> keep them together on the macro, I'm fine.
I meant for instance the still to-be-added init from bspec/49193
"Sequence to reload DMC Firmware". It could be just
for_each_dmc_id
for_each_handler
init_evt_ctl(dmc_id, handler)
init_evt_htp(dmc_id, handler)
instead of having two separate loops for both the MAIN DMC and pipe DMCs.
> > > Maybe the most important question:
> > >
> > > with this patch + the patch to load DMC on DG2, do we get the DC5
> > > transition to work? It'd be good to submit both together so we can
> > > ensure it does.
> >
> > I think disabling flip queues is the correct thing even w/o considering
> > DC5. But yes, on DG2 it happens to fix that. The idea was to merge this
> > patch first to get separate CI results and follow up with a change to
> > enable DC5 on DG2.
>
> The problem from my pov is avoid merging something just to realize later
> there is something wrong we didn't find in the review and having to fix
> it up on top.
We did a bunch of both manual and full CI run testing on DG2 with this
patch and enabling DC5. I can send a trybot patchset with both and check
that result too before merging this one.
> Anyway, code here looks correct. Feel free to add
>
> Reviewed-by: Lucas De Marchi <lucas.demarchi at intel.com>
>
> on the next version.
Thanks.
> thanks
> Lucas De Marchi
>
> >
> > > Lucas De Marchi
> > >
> > > > +
> > > > +#define DMC_EVT_CTL_ENABLE REG_BIT(31)
> > > > +#define DMC_EVT_CTL_RECURRING REG_BIT(30)
> > > > +#define DMC_EVT_CTL_TYPE_MASK REG_GENMASK(17, 16)
> > > > +#define DMC_EVT_CTL_TYPE_LEVEL_0 0
> > > > +#define DMC_EVT_CTL_TYPE_LEVEL_1 1
> > > > +#define DMC_EVT_CTL_TYPE_EDGE_1_0 2
> > > > +#define DMC_EVT_CTL_TYPE_EDGE_0_1 3
> > > > +
> > > > +#define DMC_EVT_CTL_EVENT_ID_MASK REG_GENMASK(15, 8)
> > > > +#define DMC_EVT_CTL_EVENT_ID_FALSE 0x01
> > > > +/* An event handler scheduled to run at a 1 kHz frequency. */
> > > > +#define DMC_EVT_CTL_EVENT_ID_CLK_MSEC 0xbf
> > > > +
> > > > #define DMC_HTP_ADDR_SKL 0x00500034
> > > > #define DMC_SSP_BASE _MMIO(0x8F074)
> > > > #define DMC_HTP_SKL _MMIO(0x8F004)
> > > > --
> > > > 2.30.2
> > > >
More information about the Intel-gfx
mailing list