diff --git a/drivers/platform/arm64/mpam/mpam_devices.c b/drivers/platform/arm64/mpam/mpam_devices.c
index 6b326506c359..4b43dfef1cdc 100644
--- a/drivers/platform/arm64/mpam/mpam_devices.c
+++ b/drivers/platform/arm64/mpam/mpam_devices.c
@@ -1531,6 +1531,7 @@ static void mpam_quirk_post_config_change(struct mpam_msc_ris *ris, u16 partid,
 static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
 				      struct mpam_config *cfg)
 {
+	u16 intpartid = 0;
 	u32 pri_val = 0;
 	u16 cmax = MPAMCFG_CMAX_CMAX;
 	u16 bwa_fract = MPAMCFG_MBW_MAX_MAX;
@@ -1543,9 +1544,13 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
 	__mpam_part_sel(ris->ris_idx, partid, msc);
 
 	if (mpam_has_feature(mpam_feat_partid_nrw, rprops)) {
+		if (mpam_has_feature(mpam_feat_partid_nrw, cfg))
+			intpartid = cfg->cpartid;
+
 		mpam_write_partsel_reg(msc, INTPARTID,
-				       MPAMCFG_INTPARTID_INTERNAL | partid);
-		__mpam_intpart_sel(ris->ris_idx, partid, msc);
+				       MPAMCFG_INTPARTID_INTERNAL | intpartid);
+
+		__mpam_intpart_sel(ris->ris_idx, intpartid, msc);
 	}
 
 	if (mpam_has_feature(mpam_feat_cpor_part, rprops)) {
@@ -3084,6 +3089,7 @@ static mpam_features_t mpam_update_config(struct mpam_config *cfg,
 {
 	mpam_features_t changes = 0;
 
+	maybe_update_config(cfg, mpam_feat_partid_nrw, newcfg, cpartid, changes);
 	maybe_update_config(cfg, mpam_feat_cpor_part, newcfg, cpbm, changes);
 	maybe_update_config(cfg, mpam_feat_mbw_part, newcfg, mbw_pbm, changes);
 	maybe_update_config(cfg, mpam_feat_mbw_max, newcfg, mbw_max, changes);
diff --git a/drivers/platform/arm64/mpam/mpam_internal.h b/drivers/platform/arm64/mpam/mpam_internal.h
index 5af6ed60272e..965f4fea3012 100644
--- a/drivers/platform/arm64/mpam/mpam_internal.h
+++ b/drivers/platform/arm64/mpam/mpam_internal.h
@@ -300,6 +300,13 @@ struct mpam_config {
 	u16	mbw_max;
 	u16	mbw_min;
 
+	/*
+	 * Control partition; resource regulation context for stateful controls
+	 * Valid if features has mpam_feat_partid_nrw.
+	 * For MSCs that implement PARTID Narrowing, this is intPARTID.
+	 */
+	u16	cpartid;
+
 	struct mpam_garbage	garbage;
 };
 
diff --git a/drivers/platform/arm64/mpam/mpam_resctrl.c b/drivers/platform/arm64/mpam/mpam_resctrl.c
index eb1ef5d2bc57..f1d0d9f59771 100644
--- a/drivers/platform/arm64/mpam/mpam_resctrl.c
+++ b/drivers/platform/arm64/mpam/mpam_resctrl.c
@@ -205,7 +205,8 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored)
 
 static void mpam_resctrl_partid_range(u32 closid, enum resctrl_conf_type type,
 				      const struct rdt_resource *r,
-				      u16 *min_partid, u16 *max_partid)
+				      u16 *min_partid, u16 *max_partid,
+				      u16 *cpartid)
 {
 	u16 base_partid = closid;
 	u16 span = 1;
@@ -222,6 +223,9 @@ static void mpam_resctrl_partid_range(u32 closid, enum resctrl_conf_type type,
 	*min_partid = base_partid * partid_per_closid;
 	if (max_partid)
 		*max_partid = *min_partid + (span * partid_per_closid - 1);
+
+	if (cpartid)
+		*cpartid = base_partid;
 }
 
 static void mpam_resctrl_hwid(u32 closid, u32 rmid,
@@ -318,7 +322,7 @@ bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
 	u32 tsk_closid = FIELD_GET(MPAM1_EL1_PARTID_D, regval);
 
 	mpam_resctrl_partid_range(closid, CDP_NONE, NULL,
-				  &min_partid, &max_partid);
+				  &min_partid, &max_partid, NULL);
 	return tsk_closid >= min_partid && tsk_closid <= max_partid;
 }
 
@@ -1147,7 +1151,7 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
 	dom = container_of(d, struct mpam_resctrl_dom, resctrl_ctrl_dom);
 	cprops = &res->class->props;
 
-	mpam_resctrl_partid_range(closid, type, r, &partid, NULL);
+	mpam_resctrl_partid_range(closid, type, r, &partid, NULL, NULL);
 	cfg = &dom->comp->cfg[partid];
 
 	switch (r->rid) {
@@ -1205,13 +1209,15 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_ctrl_domain *d,
 	dom = container_of(d, struct mpam_resctrl_dom, resctrl_ctrl_dom);
 	cprops = &res->class->props;
 
-	mpam_resctrl_partid_range(closid, t, r, &min_partid, &max_partid);
+	cfg.features = 0;
+	mpam_set_feature(mpam_feat_partid_nrw, &cfg);
+	mpam_resctrl_partid_range(closid, t, r, &min_partid, &max_partid,
+				  &cfg.cpartid);
 	if (!r->alloc_capable ||
 	    min_partid > mpam_partid_max ||
 	    max_partid > mpam_partid_max)
 		return -EINVAL;
 
-	cfg.features = 0;
 	switch (r->rid) {
 	case RDT_RESOURCE_L2:
 	case RDT_RESOURCE_L3:
