[PATCH v3 08/29] arm_mpam: Add the class and component structures for firmware described ris

Ben Horgan ben.horgan at arm.com
Thu Nov 6 09:43:20 PST 2025


Hi Jonathan,

On 10/24/25 17:47, Jonathan Cameron wrote:
> n Fri, 17 Oct 2025 18:56:24 +0000
> James Morse <james.morse at arm.com> wrote:
> 
>> An MSC is a container of resources, each identified by their RIS index.
>> Some RIS are described by firmware to provide their position in the system.
>> Others are discovered when the driver probes the hardware.
>>
>> To configure a resource it needs to be found by its class, e.g. 'L2'.
>> There are two kinds of grouping, a class is a set of components, which
>> are visible to user-space as there are likely to be multiple instances
>> of the L2 cache. (e.g. one per cluster or package)
>>
>> Add support for creating and destroying structures to allow a hierarchy
>> of resources to be created.
>>
>> CC: Ben Horgan <ben.horgan at arm.com>
>> Tested-by: Fenghua Yu <fenghuay at nvidia.com>
>> Signed-off-by: James Morse <james.morse at arm.com>
> A few minor things inline.  Mostly code ordering related to make
> it easier to review!
> 
>> ---
>>  drivers/resctrl/mpam_devices.c  | 390 +++++++++++++++++++++++++++++++-
>>  drivers/resctrl/mpam_internal.h |  93 ++++++++
>>  include/linux/arm_mpam.h        |   8 +-
>>  3 files changed, 483 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
>> index d18eeec95f79..8685e50f08c6 100644
>> --- a/drivers/resctrl/mpam_devices.c
>> +++ b/drivers/resctrl/mpam_devices.c
>> @@ -30,7 +30,7 @@
>>  static DEFINE_MUTEX(mpam_list_lock);
>>  static LIST_HEAD(mpam_all_msc);
>>  
>> -static struct srcu_struct mpam_srcu;
>> +struct srcu_struct mpam_srcu;
> 
> Meh. Others may be fussier about this but I'd rather you just
> added the extern when this was first introduced and didn't
> have this churn here.

I've dropped the static earlier now.

> 
> 
>> +static void mpam_vmsc_destroy(struct mpam_vmsc *vmsc)
>> +{
>> +	struct mpam_component *comp = vmsc->comp;
>> +
>> +	lockdep_assert_held(&mpam_list_lock);
>> +
>> +	list_del_rcu(&vmsc->comp_list);
>> +	add_to_garbage(vmsc);
>> +
>> +	if (list_empty(&comp->vmsc))
>> +		mpam_comp_destroy(comp);
>> +}
>> +
>> +static void mpam_ris_destroy(struct mpam_msc_ris *ris)
> I'd rather see the create / destroy next to each other if possible.
> Makes it easier to check this unwinds the creat path.

I've done this.

> 
>> +{
>> +	struct mpam_vmsc *vmsc = ris->vmsc;
>> +	struct mpam_msc *msc = vmsc->msc;
>> +	struct mpam_component *comp = vmsc->comp;
>> +	struct mpam_class *class = comp->class;
>> +
>> +	lockdep_assert_held(&mpam_list_lock);
>> +
>> +	/*
>> +	 * It is assumed affinities don't overlap. If they do the class becomes
>> +	 * unusable immediately.
>> +	 */
>> +	cpumask_andnot(&comp->affinity, &comp->affinity, &ris->affinity);
>> +	cpumask_andnot(&class->affinity, &class->affinity, &ris->affinity);
>> +	clear_bit(ris->ris_idx, &msc->ris_idxs);
>> +	list_del_rcu(&ris->vmsc_list);
>> +	list_del_rcu(&ris->msc_list);
> Can you reorder these so that they are reverse of what happens in create path?
> Makes not real difference other than slightly easier to check everything is done.
> Right now I'm failing to spot where this was added to ris->msc_list in the
> create path.

Yes, it is cleaner like that.

> 
> 
>> +	add_to_garbage(ris);
>> +
>> +	if (list_empty(&vmsc->ris))
>> +		mpam_vmsc_destroy(vmsc);
>> +}
>> +
> 
>> +
>> +/*
>> + * The cacheinfo structures are only populated when CPUs are online.
>> + * This helper walks the device tree to include offline CPUs too.
> 
> Comment stale?  It does walk a tree of devices but I'm not sure that's
> what people will read device tree as meaning.

Dropped.

> 
>> + */
>> +int mpam_get_cpumask_from_cache_id(unsigned long cache_id, u32 cache_level,
>> +				   cpumask_t *affinity)
>> +{
>> +	return acpi_pptt_get_cpumask_from_cache_id(cache_id, affinity);
>> +}
> 
>> +
>> +static int mpam_ris_create_locked(struct mpam_msc *msc, u8 ris_idx,
>> +				  enum mpam_class_types type, u8 class_id,
>> +				  int component_id)
>> +{
> ...
> 
>> +	ris = devm_kzalloc(&msc->pdev->dev, sizeof(*ris), GFP_KERNEL);
>> +	if (!ris)
>> +		return -ENOMEM;
>> +	init_garbage(&ris->garbage);
>> +	ris->garbage.pdev = pdev;
> I wonder if it's cleaner to just pass the pdev (sometimes null) in
> as a parameter to init_garbage()

Maybe... but I've left it as is for now.

>> +
>> +	class = mpam_class_find(class_id, type);
>> +	if (IS_ERR(class))
>> +		return PTR_ERR(class);
> 
> 
> 
>> diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
>> index 6ac75f3613c3..1a5d96660382 100644
>> --- a/drivers/resctrl/mpam_internal.h
>> +++ b/drivers/resctrl/mpam_internal.h
> 
>> +/*
>> + * Structures protected by SRCU may not be freed for a surprising amount of
>> + * time (especially if perf is running). To ensure the MPAM error interrupt can
>> + * tear down all the structures, build a list of objects that can be gargbage
> 
> Spell check.  garbage

Ack.

> 
>> + * collected once synchronize_srcu() has returned.
>> + * If pdev is non-NULL, use devm_kfree().
>> + */
>> +struct mpam_garbage {
>> +	/* member of mpam_garbage */
>> +	struct llist_node	llist;
>> +
>> +	void			*to_free;
>> +	struct platform_device	*pdev;
>> +};
> 

Thanks,

Ben




More information about the linux-arm-kernel mailing list