The resctrl has helper functions for updating CPOR and MBW configuration updates. While the existing resctrl_arch_update_one() effectively updates the specified configuration as intended, it inadvertently overrides other configurations with default values. Example bandwdith value is not applied: root# cat /sys/fs/resctrl/schemata MB:1=100 L3:1=fff root# echo -e "L3:1=fff\nMB:1=50" > /sys/fs/resctrl/schemata root# cat /sys/fs/resctrl/schemata MB:1=100 L3:1=fff Fix the potential loss of accuracy during the conversion of MBW_MAX from percentage to fixed-point representation, and vice versa. The updated functions provide fixed-point values that closely align with the values specified in the MPAM specification, Table 9-3 for Fraction Widths And Hex Representation. Before this fix: root# echo -e "MB:1=1" > /sys/fs/resctrl/schemata root# cat /sys/fs/resctrl/schemata MB:1=000 L3:1=fff root# echo -e "MB:1=2" > /sys/fs/resctrl/schemata root# cat /sys/fs/resctrl/schemata MB:1=001 L3:1=fff root# echo -e "MB:1=3" > /sys/fs/resctrl/schemata root@pset# cat /sys/fs/resctrl/schemata MB:1=001 L3:1=fff With this patch: root# echo -e "MB:1=1" > /sys/fs/resctrl/schemata root# cat /sys/fs/resctrl/schemata MB:1=001 L3:1=fff root# echo -e "MB:1=2" > /sys/fs/resctrl/schemata root# cat /sys/fs/resctrl/schemata MB:1=002 L3:1=fff root# echo -e "MB:1=3" > /sys/fs/resctrl/schemata root@pset# cat /sys/fs/resctrl/schemata MB:1=003 L3:1=fff Signed-off-by: Shanker Donthineni <sdonthineni@xxxxxxxxxx> --- drivers/platform/arm64/mpam/mpam_resctrl.c | 49 ++++------------------ 1 file changed, 7 insertions(+), 42 deletions(-) diff --git a/drivers/platform/arm64/mpam/mpam_resctrl.c b/drivers/platform/arm64/mpam/mpam_resctrl.c index 258a39e90f2e..f4da24cad600 100644 --- a/drivers/platform/arm64/mpam/mpam_resctrl.c +++ b/drivers/platform/arm64/mpam/mpam_resctrl.c @@ -574,23 +574,7 @@ static u32 mbw_pbm_to_percent(const unsigned long mbw_pbm, struct mpam_props *cp static u32 mbw_max_to_percent(u16 mbw_max, struct mpam_props *cprops) { - int bit; - u8 num_bits = 0; - u32 divisor = 2, value = 0; - - for (bit = 16; bit > (16 - cprops->bwa_wd); bit--) { - if (mbw_max & BIT(bit - 1)) { - num_bits++; - value += MAX_MBA_BW / divisor; - } - divisor <<= 1; - } - - /* Lest user-space get confused... */ - if (num_bits == cprops->bwa_wd) - return 100; - - return value; + return DIV_ROUND_CLOSEST((mbw_max + 1) * 100, 65536); } static u32 percent_to_mbw_pbm(u8 pc, struct mpam_props *cprops) @@ -605,31 +589,7 @@ static u32 percent_to_mbw_pbm(u8 pc, struct mpam_props *cprops) static u16 percent_to_mbw_max(u8 pc, struct mpam_props *cprops) { - u8 bit; - u32 divisor = 2, value = 0, milli_pc; - - /* - * To ensure 100% sets all the bits, we need to the contribution - * of bits worth less than 1%. Scale everything up by 1000. - */ - milli_pc = pc * 1000; - - for (bit = 16; bit > (16 - cprops->bwa_wd); bit--) { - if (milli_pc >= MAX_MBA_BW * 1000 / divisor) { - milli_pc -= MAX_MBA_BW * 1000 / divisor; - value |= BIT(bit - 1); - } - divisor <<= 1; - - if (!milli_pc) - break; - } - - /* Mask out unimplemented bits */ - if (cprops->bwa_wd <= 16) - value &= GENMASK(15, 16 - cprops->bwa_wd); - - return value; + return (((pc * 65536) / 100) - 1); } /* Find the L3 component that holds this CPU */ @@ -1167,6 +1127,9 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d, if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r)) return -EINVAL; + /* Update with requested configuration only */ + cfg = dom->comp->cfg[partid]; + switch (r->rid) { case RDT_RESOURCE_L2: case RDT_RESOURCE_L3: @@ -1182,6 +1145,8 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d, } else if (mpam_has_feature(mpam_feat_mbw_max, cprops)) { cfg.mbw_max = percent_to_mbw_max(cfg_val, cprops); mpam_set_feature(mpam_feat_mbw_max, &cfg); + /* Resctrl doesn't support MBW_MIN yet, use default value */ + mpam_clear_feature(mpam_feat_mbw_min, &cfg.features); break; } fallthrough; -- 2.25.1