Re: [PATCH] drm/xe/memirq: Size report pages from static engine mask

"Wang, X" <[email protected]>
Newsgroups org.freedesktop.lists.intel-xe
Message-ID <[email protected]>

On 6/15/2026 15:26, Summers, Stuart wrote:
> On Fri, 2026-06-12 at 17:16 -0700, Xin Wang wrote:
>> xe_memirq_init() is called from xe_tile_init(), before HW engines are
> Can we move this to xe_gt_init_early() instead? This is dependent on
> the fuses of course which need to come later, so I'm thinking we have
> an xe_xe_hw_engines_init_prefuse() or something that uses the engines
> defined in xe_pci.c to come up with an early count.
Re: moving this to xe_gt_init_early() -- I actually tried that approach 
before
sending this version. It doesn't work as-is: too much of the state this 
depends
on isn't ready yet at that point in the init sequence (the fuses/engine 
info
aren't reliable that early), so xe_hw_engine_max_instance() can't be called
safely from there yet. Getting it to work would require a broader 
refactor of
the init/early_init sequencing first, which felt out of scope for this fix.
Happy to revisit once/if that refactor happens.
> Maybe I'm overthinking that though... It would be nice to have
> everything in one for_each macro, but then the macro would need to
> comprehend whether the fuses were read already or not...
>
> One downside of this approach is we're allocating more space than we
> really need to since we might not be supporting the full engine set
> you're querying. Maybe we re-allocate after the engine initialization
> is done?
>
> Or maybe we move the memirq init later in the load sequence? That might
> have consequences for VF load though - would need Michal's input there.
>
> One minor comment below as well..
>
>> initialized. hwe_max_count() uses for_each_hw_engine() to size the
>> memirq BO, but at this point hwe->name is still NULL so the iterator
>> yields nothing and the BO is allocated with a single page, which is
>> insufficient on platforms where engine instances do not start at 0.
>>
>> Cc: Michal Wajdeczko <[email protected]>
>> Signed-off-by: Xin Wang <[email protected]>
>> ---
>>   drivers/gpu/drm/xe/xe_hw_engine.c | 26 ++++++++++++++++++++++++++
>>   drivers/gpu/drm/xe/xe_hw_engine.h |  1 +
>>   drivers/gpu/drm/xe/xe_memirq.c    |  6 ++----
>>   3 files changed, 29 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c
>> b/drivers/gpu/drm/xe/xe_hw_engine.c
>> index 98265293f2dc..16ff37756ddb 100644
>> --- a/drivers/gpu/drm/xe/xe_hw_engine.c
>> +++ b/drivers/gpu/drm/xe/xe_hw_engine.c
>> @@ -1018,6 +1018,32 @@ u32 xe_hw_engine_mask_per_class(struct xe_gt
>> *gt,
>>          return mask;
>>   }
>>   
>> +/**
>> + * xe_hw_engine_max_instance - Get the maximum HW engine instance
>> for a GT.
>> + * @gt: the &xe_gt
>> + *
>> + * Compute the highest HW engine instance present on @gt based on
>> the static
>> + * engine mask. Unlike iterating with for_each_hw_engine(), this
>> relies only on
>> + * @gt->info.engine_mask (set during early PCI probe) and the static
>> engine
>> + * descriptor table, so it is valid even before hw engines are
>> initialized
>> + * (e.g. when sizing the `Memory Based Interrupts`_ report pages).
>> + *
>> + * Return: The maximum engine instance value on @gt.
>> + */
>> +unsigned int xe_hw_engine_max_instance(struct xe_gt *gt)
>> +{
>> +       unsigned int max_instance = 0;
>> +       enum xe_hw_engine_id id;
>> +
>> +       for (id = 0; id < XE_NUM_HW_ENGINES; ++id) {
>> +               if (gt->info.engine_mask & BIT(id))
>> +                       max_instance = max(max_instance,
>> +                                          (unsigned
>> int)engine_infos[id].instance);
> We can drop the cast here since the variable is uint also.
I don't think we can drop it. `instance` is declared as an 8-bit bitfield
of type `unsigned int` in `struct engine_info`, but per the C integer
promotion rules, an unsigned bitfield narrower than `int` whose
full value range fits in `int` gets promoted to plain (signed) `int`
in an expression, not to `unsigned int`. So without the cast,
`engine_infos[id].instance` actually evaluates as `int`, while
`max_instance` is `unsigned int`. The kernel's `max()` macro does
a strict typecheck between its two arguments, so dropping the cast
would trip that check (build warning/error, and likely a sparse
complaint too). I'll keep it as-is unless there's a cleaner way to 
express it.
> Thanks,
> Stuart
>
>> +       }
>> +
>> +       return max_instance;
>> +}
>> +
>>   bool xe_hw_engine_is_reserved(struct xe_hw_engine *hwe)
>>   {
>>          struct xe_gt *gt = hwe->gt;
>> diff --git a/drivers/gpu/drm/xe/xe_hw_engine.h
>> b/drivers/gpu/drm/xe/xe_hw_engine.h
>> index c3ee37f8cfc0..838abf7092a5 100644
>> --- a/drivers/gpu/drm/xe/xe_hw_engine.h
>> +++ b/drivers/gpu/drm/xe/xe_hw_engine.h
>> @@ -55,6 +55,7 @@ void xe_hw_engine_handle_irq(struct xe_hw_engine
>> *hwe, u16 intr_vec);
>>   void xe_hw_engine_enable_ring(struct xe_hw_engine *hwe);
>>   u32 xe_hw_engine_mask_per_class(struct xe_gt *gt,
>>                                  enum xe_engine_class engine_class);
>> +unsigned int xe_hw_engine_max_instance(struct xe_gt *gt);
>>   struct xe_hw_engine_snapshot *
>>   xe_hw_engine_snapshot_capture(struct xe_hw_engine *hwe, struct
>> xe_exec_queue *q);
>>   void xe_hw_engine_snapshot_free(struct xe_hw_engine_snapshot
>> *snapshot);
>> diff --git a/drivers/gpu/drm/xe/xe_memirq.c
>> b/drivers/gpu/drm/xe/xe_memirq.c
>> index 9dfe965cb46e..5a87ac42351d 100644
>> --- a/drivers/gpu/drm/xe/xe_memirq.c
>> +++ b/drivers/gpu/drm/xe/xe_memirq.c
>> @@ -175,13 +175,11 @@ static inline bool
>> hw_reports_to_instance_zero(struct xe_memirq *memirq)
>>   static unsigned int hwe_max_count(struct xe_tile *tile)
>>   {
>>          unsigned int max_instance = 0;
>> -       unsigned int gtid, hweid;
>> -       struct xe_hw_engine *hwe;
>> +       unsigned int gtid;
>>          struct xe_gt *gt;
>>   
>>          for_each_gt_on_tile(gt, tile, gtid)
>> -               for_each_hw_engine(hwe, gt, hweid)
>> -                       max_instance = max(max_instance, hwe-
>>> instance);
>> +               max_instance = max(max_instance,
>> xe_hw_engine_max_instance(gt));
>>   
>>          return max_instance + 1;
>>   }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.