diff mbox series

arm_mpam: resctrl: Update only requested configuration

Message ID 20240819220752.201815-1-sdonthineni@nvidia.com (mailing list archive)
State New, archived
Headers show
Series arm_mpam: resctrl: Update only requested configuration | expand

Commit Message

Shanker Donthineni Aug. 19, 2024, 10:07 p.m. UTC
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@nvidia.com>
---
 drivers/platform/arm64/mpam/mpam_resctrl.c | 49 ++++------------------
 1 file changed, 7 insertions(+), 42 deletions(-)
diff mbox series

Patch

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;