[PATCH v10 10/15] arm_mpam: Track the PARTID and internal PARTID limits per class
From: Jinjie Ruan
Date: Mon Oct 19 2026 - 03:37:34 EST
From: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
The number of PARTIDs and PMGs a resource supports is global, and the
number of internal PARTIDs is not tracked at all. Tracking this per
class lets the resctrl glue code find the limits of the classes it will
use, and pick the number of control groups before it is initialised.
Resources that implement PARTID narrowing reduce msc->partid_max,
because they don't have one configuration per PARTID. Record the
internal PARTID limit alongside partid_max in struct mpam_props, and
take the smaller of the values a class's RIS advertise.
Cc: James Morse <james.morse@xxxxxxx>
Cc: Ben Horgan <ben.horgan@xxxxxxx>
Cc: Reinette Chatre <reinette.chatre@xxxxxxxxx>
Cc: Fenghua Yu <fenghuay@xxxxxxxxxx>
Suggested-by: James Morse <james.morse@xxxxxxx>
Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
v9->v10:
- Copy partid_max/intpartid_max on the first aliasing merge into a
zero-initialized parent instead of clamping to zero
---
drivers/resctrl/mpam_devices.c | 34 ++++++++++++++++++++++++---------
drivers/resctrl/mpam_internal.h | 2 ++
2 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index a44d66a5733d..7f88a0170c05 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -793,7 +793,6 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
struct mpam_msc *msc = ris->vmsc->msc;
struct device *dev = &msc->pdev->dev;
struct mpam_props *props = &ris->props;
- struct mpam_class *class = ris->vmsc->comp->class;
lockdep_assert_held(&msc->probe_lock);
lockdep_assert_held(&msc->part_sel_lock);
@@ -938,18 +937,20 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
}
/*
- * RIS with PARTID narrowing don't have enough storage for one
- * configuration per PARTID. If these are in a class we could use,
- * reduce the supported partid_max to match the number of intpartid.
- * If the class is unknown, just ignore it.
+ * A RIS that implements PARTID narrowing has one configuration per
+ * internal PARTID, and several request PARTIDs share it. Record both
+ * limits in the resource properties.
*/
- if (FIELD_GET(MPAMF_IDR_HAS_PARTID_NRW, ris->idr) &&
- class->type != MPAM_CLASS_UNKNOWN) {
+ props->partid_max = msc->partid_max;
+ props->intpartid_max = msc->partid_max;
+
+ if (FIELD_GET(MPAMF_IDR_HAS_PARTID_NRW, ris->idr)) {
u32 nrwidr = mpam_read_partsel_reg(msc, PARTID_NRW_IDR);
- u16 partid_max = FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr);
+ u16 intpartid_max = FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr);
mpam_set_feature(mpam_feat_partid_nrw, props);
- msc->partid_max = min(msc->partid_max, partid_max);
+ props->intpartid_max = min(props->intpartid_max, intpartid_max);
+ msc->partid_max = min(msc->partid_max, intpartid_max);
}
}
@@ -2270,6 +2271,21 @@ static void __props_mismatch(struct mpam_props *parent,
child->num_mbwu_mon);
}
+ /*
+ * Take the smallest, so the result is safe for every RIS in the class.
+ * The first aliasing merge into a zero-initialized parent must copy
+ * the child's value, otherwise min() would clamp the limit to zero.
+ */
+ if (alias && !parent->partid_max)
+ parent->partid_max = child->partid_max;
+ else
+ parent->partid_max = min(parent->partid_max, child->partid_max);
+
+ if (alias && !parent->intpartid_max)
+ parent->intpartid_max = child->intpartid_max;
+ else
+ parent->intpartid_max = min(parent->intpartid_max, child->intpartid_max);
+
if (CAN_MERGE_FEAT(parent, child, mpam_feat_intpri_part, alias)) {
parent->intpri_wd = child->intpri_wd;
} else if (MISMATCHED_FEAT(parent, child, mpam_feat_intpri_part,
diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
index def0e3a65c23..0a2177241615 100644
--- a/drivers/resctrl/mpam_internal.h
+++ b/drivers/resctrl/mpam_internal.h
@@ -203,6 +203,8 @@ struct mpam_props {
u16 dspri_wd;
u16 num_csu_mon;
u16 num_mbwu_mon;
+ u16 partid_max;
+ u16 intpartid_max;
/*
* Kunit tests use memset() to set up feature combinations that should be
--
2.43.0