
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- The Priority Partition feature controls the priority of requests attributed to the target PARTID. In addition to the MATA msc implementing priority features, the L3 controller can also have the same features. Here the *MBPRI* and *L3PRI* interface are provided in the schemata file to allow users to configure and query QoS partition settings. Before transmitting the priority value to msc, it needs to check whether the setting from user is validate or not. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 35 ++++++++++++-------- drivers/platform/mpam/mpam_internal.h | 6 ++++ drivers/platform/mpam/mpam_resctrl.c | 47 +++++++++++++++++++++++++-- fs/resctrl/ctrlmondata.c | 33 ++++++++++++++++++- include/linux/resctrl.h | 4 +++ include/linux/resctrl_types.h | 2 ++ 6 files changed, 109 insertions(+), 18 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index e4ee2cd73cc8..e9d03f2abdc3 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -1193,12 +1193,11 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, struct mpam_config *cfg) { u32 pri_val = 0; + u16 intpri, dspri; u16 cmax = MPAMCFG_CMAX_CMAX; struct mpam_msc *msc = ris->msc; u16 bwa_fract = MPAMCFG_MBW_MAX_MAX; struct mpam_props *rprops = &ris->props; - u16 dspri = GENMASK(rprops->dspri_wd, 0); - u16 intpri = GENMASK(rprops->intpri_wd, 0); spin_lock(&msc->part_sel_lock); __mpam_part_sel(ris->ris_idx, partid, msc); @@ -1250,21 +1249,29 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, if (mpam_has_feature(mpam_feat_ccap_part, rprops)) mpam_write_partsel_reg(msc, CMAX, cmax); - if (mpam_has_feature(mpam_feat_intpri_part, rprops) || - mpam_has_feature(mpam_feat_dspri_part, rprops)) { - /* aces high? */ - if (!mpam_has_feature(mpam_feat_intpri_part_0_low, rprops)) - intpri = 0; - if (!mpam_has_feature(mpam_feat_dspri_part_0_low, rprops)) - dspri = 0; - - if (mpam_has_feature(mpam_feat_intpri_part, rprops)) + if (mpam_has_feature(mpam_feat_intpri_part_0_low, rprops)) + intpri = GENMASK(rprops->intpri_wd - 1, 0); + else + intpri = 0; + + if (mpam_has_feature(mpam_feat_intpri_part, rprops)) { + if (mpam_has_feature(mpam_feat_intpri_part, cfg)) + pri_val |= FIELD_PREP(MPAMCFG_PRI_INTPRI, cfg->intpri); + else pri_val |= FIELD_PREP(MPAMCFG_PRI_INTPRI, intpri); - if (mpam_has_feature(mpam_feat_dspri_part, rprops)) - pri_val |= FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri); + } + if (mpam_has_feature(mpam_feat_dspri_part_0_low, rprops)) + dspri = GENMASK(rprops->dspri_wd - 1, 0); + else + dspri = 0; + + if (mpam_has_feature(mpam_feat_dspri_part, rprops)) + pri_val |= FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri); + + if (mpam_has_feature(mpam_feat_intpri_part, rprops) || + mpam_has_feature(mpam_feat_dspri_part, rprops)) mpam_write_partsel_reg(msc, PRI, pri_val); - } spin_unlock(&msc->part_sel_lock); } diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index b094095abe49..2b0bc33e5efa 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -166,6 +166,12 @@ struct mpam_config { u32 mbw_pbm; u16 mbw_max; u16 mbw_min; + + /* + * dspri is downstream priority, intpri is internal priority. + */ + u16 dspri; + u16 intpri; }; struct mpam_component diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 8c62e3b29f24..16857f5929c1 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -70,6 +70,7 @@ bool resctrl_arch_mon_capable(void) } static bool min_capable[RDT_NUM_RESOURCES]; +static bool intpri_capable[RDT_NUM_RESOURCES]; bool resctrl_arch_feat_capable(enum resctrl_res_level level, enum resctrl_feat_type feat) { @@ -87,6 +88,9 @@ bool resctrl_arch_feat_capable(enum resctrl_res_level level, case FEAT_MIN: return min_capable[level]; + case FEAT_INTPRI: + return intpri_capable[level]; + default: break; } @@ -101,6 +105,9 @@ const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, case FEAT_MIN: return "MIN"; + case FEAT_INTPRI: + return "PRI"; + default: break; } @@ -824,6 +831,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) /* TODO: Scaling is not yet supported */ r->cache.cbm_len = class->props.cpbm_wd; r->cache.arch_has_sparse_bitmasks = true; + r->cache.intpri_wd = class->props.intpri_wd; /* mpam_devices will reject empty bitmaps */ r->cache.min_cbm_bits = 1; @@ -850,6 +858,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) if (mpam_has_feature(mpam_feat_cmin, &class->props)) min_capable[r->rid] = true; + if (mpam_has_feature(mpam_feat_intpri_part, &class->props)) + intpri_capable[r->rid] = true; + /* * MBWU counters may be 'local' or 'total' depending on where * they are in the topology. Counters on caches are assumed to @@ -881,6 +892,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) r->membw.delay_linear = true; r->membw.throttle_mode = THREAD_THROTTLE_UNDEFINED; r->membw.bw_gran = get_mba_granularity(cprops); + r->membw.intpri_wd = class->props.intpri_wd; /* Round up to at least 1% */ if (!r->membw.bw_gran) @@ -894,6 +906,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) if (mpam_has_feature(mpam_feat_mbw_min, cprops)) min_capable[r->rid] = true; + if (mpam_has_feature(mpam_feat_intpri_part, cprops)) + intpri_capable[r->rid] = true; + if (has_mbwu && class->type == MPAM_CLASS_MEMORY) { mbm_total_class = class; r->mon_capable = true; @@ -1012,6 +1027,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (feat == FEAT_MIN)) { configured_by = mpam_feat_cmin; break; + } else if (mpam_has_feature(mpam_feat_intpri_part, cprops) && + (feat == FEAT_INTPRI)) { + configured_by = mpam_feat_intpri_part; + break; } return -EINVAL; @@ -1028,6 +1047,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (feat == FEAT_MIN)) { configured_by = mpam_feat_mbw_min; break; + } else if (mpam_has_feature(mpam_feat_intpri_part, cprops) && + (feat == FEAT_INTPRI)) { + configured_by = mpam_feat_intpri_part; + break; } fallthrough; default: @@ -1036,11 +1059,16 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r) || !mpam_has_feature(configured_by, cfg)) { - if (configured_by == mpam_feat_cmin) + if ((configured_by == mpam_feat_cmin) || + (configured_by == mpam_feat_mbw_min)) return 0; - if (configured_by == mpam_feat_mbw_min) - return 0; + if (configured_by == mpam_feat_intpri_part) { + if (!mpam_has_feature(mpam_feat_intpri_part_0_low, cprops)) + return 0; + + return (u32)GENMASK(cprops->intpri_wd - 1, 0); + } return r->default_ctrl; } @@ -1058,6 +1086,8 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, return mbw_max_to_percent(cfg->mbw_max, cprops->bwa_wd); case mpam_feat_mbw_min: return mbw_max_to_percent(cfg->mbw_min, cprops->bwa_wd); + case mpam_feat_intpri_part: + return cfg->intpri; default: return -EINVAL; } @@ -1103,6 +1133,11 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.ca_min = percent_to_mbw_max(cfg_val, cprops->cmax_wd); mpam_set_feature(mpam_feat_cmin, &cfg); break; + } else if (mpam_has_feature(mpam_feat_intpri_part, cprops) && + (f == FEAT_INTPRI)) { + cfg.intpri = cfg_val; + mpam_set_feature(mpam_feat_intpri_part, &cfg); + break; } return -EINVAL; @@ -1121,7 +1156,13 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.mbw_min = percent_to_mbw_max(cfg_val, cprops->bwa_wd); mpam_set_feature(mpam_feat_mbw_min, &cfg); break; + } else if (mpam_has_feature(mpam_feat_intpri_part, cprops) && + (f == FEAT_INTPRI)) { + cfg.intpri = cfg_val; + mpam_set_feature(mpam_feat_intpri_part, &cfg); + break; } + fallthrough; default: return -EINVAL; diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index 4a74b71daed8..a4a971c34db8 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -86,6 +86,32 @@ static bool deci_validate(char *buf, unsigned long *data, struct rdt_resource *r return true; } +static bool prio_validate(char *buf, unsigned long *data, struct rdt_resource *r) +{ + unsigned long prio, prio_max; + int ret; + + ret = kstrtoul(buf, 10, &prio); + if (ret) { + rdt_last_cmd_printf("Non-decimal digit in PRIO value %s\n", buf); + return false; + } + + if (r->fflags & RFTYPE_RES_CACHE) + prio_max = GENMASK(r->cache.intpri_wd - 1, 0); + else + prio_max = GENMASK(r->membw.intpri_wd - 1, 0); + + if (prio > prio_max) { + rdt_last_cmd_printf("PRIO value %ld out of range [0,%ld]\n", + prio, prio_max); + return false; + } + + *data = prio; + return true; +} + static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, struct rdt_domain *d) { @@ -100,7 +126,12 @@ static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, return -EINVAL; } - if (r->fflags & RFTYPE_RES_MB) { + if (s->feat_type == FEAT_INTPRI) { + if (!prio_validate(data->buf, &bw_val, r)) + return -EINVAL; + + } else if (r->fflags & RFTYPE_RES_MB) { + /* For FEAT_MAX and FEAT_MIN */ if (!bw_validate(data->buf, &bw_val, r)) return -EINVAL; diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h index 1a4d8612c62b..34b246105c78 100644 --- a/include/linux/resctrl.h +++ b/include/linux/resctrl.h @@ -133,6 +133,7 @@ struct rdt_domain { * @arch_has_sparse_bitmasks: True if a bitmask like f00f is valid. * @arch_has_per_cpu_cfg: True if QOS_CFG register for this cache * level has CPU scope. + * @intpri_wd: Number of implemented bits in the priority partition. */ struct resctrl_cache { unsigned int cbm_len; @@ -140,6 +141,7 @@ struct resctrl_cache { unsigned int shareable_bits; bool arch_has_sparse_bitmasks; bool arch_has_per_cpu_cfg; + unsigned int intpri_wd; }; /** @@ -166,6 +168,7 @@ enum membw_throttle_mode { * different memory bandwidths * @mba_sc: True if MBA software controller(mba_sc) is enabled * @mb_map: Mapping of memory B/W percentage to memory B/W delay + * @intpri_wd: Number of implemented bits in the priority partition. */ struct resctrl_membw { u32 min_bw; @@ -175,6 +178,7 @@ struct resctrl_membw { enum membw_throttle_mode throttle_mode; bool mba_sc; u32 *mb_map; + u32 intpri_wd; }; /** diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h index 322839157983..b28de448323f 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -79,11 +79,13 @@ enum resctrl_conf_type { * resource allocation. * @FEAT_MAX: Controls the maximum fraction of the resource capacity. * @FEAT_MIN: Controls the minimum fraction of the resource capacity. + * @FEAT_INTPRI:Controls the priority for the resource. */ enum resctrl_feat_type { FEAT_PBM, FEAT_MAX, FEAT_MIN, + FEAT_INTPRI, FEAT_NUM_TYPES, }; -- 2.25.1