
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8T2RT -------------------------------- 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 | 2 ++ include/linux/resctrl_types.h | 1 + 6 files changed, 106 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 400afaba0ecd..533c891bc0c5 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 1b19d74dd75c..278da1e7836c 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -69,6 +69,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) { @@ -86,6 +87,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; } @@ -100,6 +104,9 @@ const char *resctrl_arch_set_feat_lab(enum resctrl_feat_type feat, case FEAT_MIN: return "MIN"; + case FEAT_INTPRI: + return "PRI"; + default: break; } @@ -780,6 +787,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; @@ -806,6 +814,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 @@ -837,6 +848,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) @@ -850,6 +862,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; @@ -968,6 +983,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; @@ -984,6 +1003,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: @@ -992,11 +1015,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; } @@ -1014,6 +1042,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; } @@ -1059,6 +1089,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; @@ -1077,7 +1112,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 787595f2cf7d..61e498ce808a 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->rid == RDT_RESOURCE_MBA) { + if (s->feat_type == FEAT_INTPRI) { + if (!prio_validate(data->buf, &bw_val, r)) + return -EINVAL; + + } else if (r->rid == RDT_RESOURCE_MBA) { + /* 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 ca2ad398b8b5..0dbee80f7211 100644 --- a/include/linux/resctrl.h +++ b/include/linux/resctrl.h @@ -140,6 +140,7 @@ struct resctrl_cache { unsigned int shareable_bits; bool arch_has_sparse_bitmasks; bool arch_has_per_cpu_cfg; + unsigned int intpri_wd; }; /** @@ -175,6 +176,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 1ccfe08b118b..7a33a4c119c3 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -77,6 +77,7 @@ enum resctrl_feat_type { FEAT_PBM, FEAT_MAX, FEAT_MIN, + FEAT_INTPRI, FEAT_NUM_TYPES, }; -- 2.25.1