@@ -1531,6 +1531,7 @@ static void mpam_quirk_post_config_change(struct mpam_msc_ris *ris, u16 partid,
static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
struct mpam_config *cfg)
{
+ u16 intpartid = 0;
u32 pri_val = 0;
u16 cmax = MPAMCFG_CMAX_CMAX;
u16 bwa_fract = MPAMCFG_MBW_MAX_MAX;
@@ -1543,9 +1544,13 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
__mpam_part_sel(ris->ris_idx, partid, msc);
if (mpam_has_feature(mpam_feat_partid_nrw, rprops)) {
+ if (mpam_has_feature(mpam_feat_partid_nrw, cfg))
+ intpartid = cfg->cpartid;
+
mpam_write_partsel_reg(msc, INTPARTID,
- MPAMCFG_INTPARTID_INTERNAL | partid);
- __mpam_intpart_sel(ris->ris_idx, partid, msc);
+ MPAMCFG_INTPARTID_INTERNAL | intpartid);
+
+ __mpam_intpart_sel(ris->ris_idx, intpartid, msc);
}
if (mpam_has_feature(mpam_feat_cpor_part, rprops)) {
@@ -3084,6 +3089,7 @@ static mpam_features_t mpam_update_config(struct mpam_config *cfg,
{
mpam_features_t changes = 0;
+ maybe_update_config(cfg, mpam_feat_partid_nrw, newcfg, cpartid, changes);
maybe_update_config(cfg, mpam_feat_cpor_part, newcfg, cpbm, changes);
maybe_update_config(cfg, mpam_feat_mbw_part, newcfg, mbw_pbm, changes);
maybe_update_config(cfg, mpam_feat_mbw_max, newcfg, mbw_max, changes);
@@ -300,6 +300,13 @@ struct mpam_config {
u16 mbw_max;
u16 mbw_min;
+ /*
+ * Control partition; resource regulation context for stateful controls
+ * Valid if features has mpam_feat_partid_nrw.
+ * For MSCs that implement PARTID Narrowing, this is intPARTID.
+ */
+ u16 cpartid;
+
struct mpam_garbage garbage;
};
@@ -205,7 +205,8 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored)
static void mpam_resctrl_partid_range(u32 closid, enum resctrl_conf_type type,
const struct rdt_resource *r,
- u16 *min_partid, u16 *max_partid)
+ u16 *min_partid, u16 *max_partid,
+ u16 *cpartid)
{
u16 base_partid = closid;
u16 span = 1;
@@ -222,6 +223,9 @@ static void mpam_resctrl_partid_range(u32 closid, enum resctrl_conf_type type,
*min_partid = base_partid * partid_per_closid;
if (max_partid)
*max_partid = *min_partid + (span * partid_per_closid - 1);
+
+ if (cpartid)
+ *cpartid = base_partid;
}
static void mpam_resctrl_hwid(u32 closid, u32 rmid,
@@ -318,7 +322,7 @@ bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
u32 tsk_closid = FIELD_GET(MPAM1_EL1_PARTID_D, regval);
mpam_resctrl_partid_range(closid, CDP_NONE, NULL,
- &min_partid, &max_partid);
+ &min_partid, &max_partid, NULL);
return tsk_closid >= min_partid && tsk_closid <= max_partid;
}
@@ -1147,7 +1151,7 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
dom = container_of(d, struct mpam_resctrl_dom, resctrl_ctrl_dom);
cprops = &res->class->props;
- mpam_resctrl_partid_range(closid, type, r, &partid, NULL);
+ mpam_resctrl_partid_range(closid, type, r, &partid, NULL, NULL);
cfg = &dom->comp->cfg[partid];
switch (r->rid) {
@@ -1205,13 +1209,15 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
dom = container_of(d, struct mpam_resctrl_dom, resctrl_ctrl_dom);
cprops = &res->class->props;
- mpam_resctrl_partid_range(closid, t, r, &min_partid, &max_partid);
+ cfg.features = 0;
+ mpam_set_feature(mpam_feat_partid_nrw, &cfg);
+ mpam_resctrl_partid_range(closid, t, r, &min_partid, &max_partid,
+ &cfg.cpartid);
if (!r->alloc_capable ||
min_partid > mpam_partid_max ||
max_partid > mpam_partid_max)
return -EINVAL;
- cfg.features = 0;
switch (r->rid) {
case RDT_RESOURCE_L2:
case RDT_RESOURCE_L3:
Currently, MPAM PARTIDs are assigned 1:1 to resctrl control groups. This means that an MSC that implements PARTID Narrowing can simply program the PARTID value for intPARTID where needed. In order to enable multiple PARTIDs to be assigned to a single control group in a flexible manner, the PARTID value cannot be used directly for the intPARTID, so in the mpam_devices backend, Narrowing MSCs need an explicit identifier for the control / resource regulation group. Add a field cpartid to struct mpam_config to hold this identifier, and wire up the resctrl glue code to pass a suitable value. In common with the handling of other parameters, make programming of MPAMCFG_INTPARTID unconditional when applying control updates. When no cpartid is supplied, e.g., during driver startup, intPARTID is programmed with 0. (There is no architectural reset value for MPAMCFG_INTPARTID even for PARTID 0, but the architecture can be interpreted as suggesting intPARTID 0 as the default, so this is as good a choice as any.) Control updates through resctrl will always supply a cpartid, identifying the affected resctrl control partition. Signed-off-by: Dave Martin <Dave.Martin@arm.com> --- drivers/platform/arm64/mpam/mpam_devices.c | 10 ++++++++-- drivers/platform/arm64/mpam/mpam_internal.h | 7 +++++++ drivers/platform/arm64/mpam/mpam_resctrl.c | 16 +++++++++++----- 3 files changed, 26 insertions(+), 7 deletions(-)