Introduce narrow PARTID (partid_nrw) feature support, which enables many-to-one mapping of request PARTIDs (reqPARTID) to internal PARTIDs (intPARTID). This expands monitoring capability by allowing a single control group to track more task types through multiple reqPARTIDs per intPARTID, bypassing the PMG limit in some extent. intPARTID: Internal PARTID used for control group configuration. Configurations are synchronized to all reqPARTIDs mapped to the same intPARTID. Count is indicated by MPAMF_PARTID_NRW_IDR.INTPARTID_MAX, or defaults to PARTID count if narrow PARTID is unsupported. reqPARTID: Request PARTID used to expand monitoring groups. Enables a single control group to monitor more task types by multiple reqPARTIDs within one intPARTID, overcoming the PMG count limitation. Control group and monitoring limits are calculated as: n = min(intPARTID, PARTID) /* control groups (closids) */ l = min(reqPARTID, PARTID) /* total reqPARTIDs */ m = l // n /* reqPARTIDs per control group */ Where: intPARTID: intPARTIDs on narrow-PARTID-capable MSCs reqPARTID: reqPARTIDs on narrow-PARTID-capable MSCs PARTID: PARTIDs on non-narrow-PARTID-capable MSCs Example: L3 cache (256 PARTIDs, without narrow PARTID feature) + MATA (32 intPARTIDs, 256 reqPARTIDs): n = min( 32, 256) = 32 intPARTIDs l = min(256, 256) = 256 reqPARTIDs m = 256 / 32 = 8 reqPARTIDs per intPARTID Implementation notes: * Handle mixed MSC systems (some support narrow PARTID, some don't) by taking minimum values across all MSCs. * resctrl_arch_get_num_closid() now returns intPARTID count (was PARTID). Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/resctrl/mpam_devices.c | 30 ++++++++++++++++++++---------- drivers/resctrl/mpam_internal.h | 2 ++ drivers/resctrl/mpam_resctrl.c | 4 ++-- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index 9182c8fcf003..c5b3812e86ab 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -63,6 +63,7 @@ static DEFINE_MUTEX(mpam_cpuhp_state_lock); * Generating traffic outside this range will result in screaming interrupts. */ u16 mpam_partid_max; +u16 mpam_intpartid_max; u8 mpam_pmg_max; static bool partid_max_init, partid_max_published; static DEFINE_SPINLOCK(partid_max_lock); @@ -288,10 +289,12 @@ int mpam_register_requestor(u16 partid_max, u8 pmg_max) { guard(spinlock)(&partid_max_lock); if (!partid_max_init) { + mpam_intpartid_max = partid_max; mpam_partid_max = partid_max; mpam_pmg_max = pmg_max; partid_max_init = true; } else if (!partid_max_published) { + mpam_intpartid_max = min(mpam_intpartid_max, partid_max); mpam_partid_max = min(mpam_partid_max, partid_max); mpam_pmg_max = min(mpam_pmg_max, pmg_max); } else { @@ -931,7 +934,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) u16 partid_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); + msc->intpartid_max = min(msc->partid_max, partid_max); + } else { + msc->intpartid_max = msc->partid_max; } } @@ -995,6 +1000,7 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) spin_lock(&partid_max_lock); mpam_partid_max = min(mpam_partid_max, msc->partid_max); + mpam_intpartid_max = min(mpam_intpartid_max, msc->intpartid_max); mpam_pmg_max = min(mpam_pmg_max, msc->pmg_max); spin_unlock(&partid_max_lock); @@ -1720,7 +1726,7 @@ static int mpam_reset_ris(void *arg) mpam_init_reset_cfg(&reset_cfg); spin_lock(&partid_max_lock); - partid_max = mpam_partid_max; + partid_max = mpam_intpartid_max; spin_unlock(&partid_max_lock); for (partid = 0; partid <= partid_max; partid++) mpam_reprogram_ris_partid(ris, partid, &reset_cfg); @@ -1776,7 +1782,7 @@ static void mpam_reprogram_msc(struct mpam_msc *msc) struct mpam_write_config_arg arg; /* - * No lock for mpam_partid_max as partid_max_published has been + * No lock for mpam_intpartid_max as partid_max_published has been * set by mpam_enabled(), so the values can no longer change. */ mpam_assert_partid_sizes_fixed(); @@ -1793,7 +1799,7 @@ static void mpam_reprogram_msc(struct mpam_msc *msc) arg.comp = ris->vmsc->comp; arg.ris = ris; reset = true; - for (partid = 0; partid <= mpam_partid_max; partid++) { + for (partid = 0; partid <= mpam_intpartid_max; partid++) { cfg = &ris->vmsc->comp->cfg[partid]; if (!bitmap_empty(cfg->features, MPAM_FEATURE_LAST)) reset = false; @@ -2616,7 +2622,7 @@ static void mpam_reset_component_cfg(struct mpam_component *comp) if (!comp->cfg) return; - for (i = 0; i <= mpam_partid_max; i++) { + for (i = 0; i <= mpam_intpartid_max; i++) { comp->cfg[i] = (struct mpam_config) {}; if (cprops->cpbm_wd) comp->cfg[i].cpbm = GENMASK(cprops->cpbm_wd - 1, 0); @@ -2636,7 +2642,7 @@ static int __allocate_component_cfg(struct mpam_component *comp) if (comp->cfg) return 0; - comp->cfg = kzalloc_objs(*comp->cfg, mpam_partid_max + 1); + comp->cfg = kzalloc_objs(*comp->cfg, mpam_intpartid_max + 1); if (!comp->cfg) return -ENOMEM; @@ -2703,7 +2709,7 @@ static void mpam_enable_once(void) int err; /* - * Once the cpuhp callbacks have been changed, mpam_partid_max can no + * Once the cpuhp callbacks have been changed, mpam_intpartid_max can no * longer change. */ spin_lock(&partid_max_lock); @@ -2752,9 +2758,13 @@ static void mpam_enable_once(void) mpam_register_cpuhp_callbacks(mpam_cpu_online, mpam_cpu_offline, "mpam:online"); - /* Use printk() to avoid the pr_fmt adding the function name. */ - printk(KERN_INFO "MPAM enabled with %u PARTIDs and %u PMGs\n", - mpam_partid_max + 1, mpam_pmg_max + 1); + if (mpam_partid_max == mpam_intpartid_max) + /* Use printk() to avoid the pr_fmt adding the function name. */ + printk(KERN_INFO "MPAM enabled with %u PARTIDs and %u PMGs\n", + mpam_partid_max + 1, mpam_pmg_max + 1); + else + printk(KERN_INFO "MPAM enabled with %u reqPARTIDs, %u intPARTIDs and %u PMGs\n", + mpam_partid_max + 1, mpam_intpartid_max + 1, mpam_pmg_max + 1); } static void mpam_reset_component_locked(struct mpam_component *comp) diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h index 195ab821cc52..0b19742d8660 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -81,6 +81,7 @@ struct mpam_msc { */ struct mutex probe_lock; bool probed; + u16 intpartid_max; u16 partid_max; u8 pmg_max; unsigned long ris_idxs; @@ -457,6 +458,7 @@ extern struct list_head mpam_classes; /* System wide partid/pmg values */ extern u16 mpam_partid_max; +extern u16 mpam_intpartid_max; extern u8 mpam_pmg_max; /* Scheduled work callback to enable mpam once all MSC have been probed */ diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c index 19b306017845..222ea1d199e1 100644 --- a/drivers/resctrl/mpam_resctrl.c +++ b/drivers/resctrl/mpam_resctrl.c @@ -206,7 +206,7 @@ int resctrl_arch_set_cdp_enabled(enum resctrl_res_level rid, bool enable) mpam_resctrl_controls[RDT_RESOURCE_MBA].resctrl_res.alloc_capable = true; if (enable) { - if (mpam_partid_max < 1) + if (mpam_intpartid_max < 1) return -EINVAL; partid_d = resctrl_get_config_index(RESCTRL_RESERVED_CLOSID, CDP_DATA); @@ -237,7 +237,7 @@ static bool mpam_resctrl_hide_cdp(enum resctrl_res_level rid) */ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored) { - return mpam_partid_max + 1; + return mpam_intpartid_max + 1; } u32 resctrl_arch_system_num_rmid_idx(void) -- 2.25.1