From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6A76E4A1DE8; Thu, 24 Sep 2026 15:28:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263684; cv=none; b=WE/IPDnWJeTb0LN1XrpQ5oXC5ODQuq4ZFee6U+qP5quJMODny7jCwhF20DkPWmjjBSopN7iP7p5DsJksuMAbOSFjbraQla7cAWMon2uVLhVre78RDyT2F8vBE4B0dFlDRzVONkLr21R4SWyISr/JCY6g8jFqmkDfUkTyvvxFc2g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263684; c=relaxed/simple; bh=IFylef1Uho/v2i1SPiYmwDYqojrNosvB9pyHGcxaKkY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pkYmzj3dpjE2dukF13k0ZMz82qXdhDtw9CZUjFxNiRg4g1A1w2Ws/wr6X5dj7FNerLp/PvGbE5LqF9DaaaxL3Hu4VJwSj53ZSBL4ahVZ1iK/AigjvIitmJm32n9DTfAfRGvCGj3vHBGPwyxI/gtccncl0e5Kix7vpL6QvZfAbvY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=WjtCDEFD; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="WjtCDEFD" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4EDBB175D; Thu, 24 Sep 2026 08:27:58 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A08073F86F; Thu, 24 Sep 2026 08:27:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263681; bh=IFylef1Uho/v2i1SPiYmwDYqojrNosvB9pyHGcxaKkY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WjtCDEFDserCzJfyrsaelesalZ2i48DIR+KCTCb6uaXXGAl5smRXJfVh7NDWNqsoe IplzpuaAnOprPL6+qL7oCWZ3dRxBEavzmz9dJGtegjqT6E4zzOPeprw1PkU3xg6x6W E8ECyaP2wOdHybZau4OPAqWKRLcrYmMI+8HJwOPA= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 01/13] arm_mpam: let low level MSC accessors return an error Date: Thu, 24 Sep 2026 17:27:27 +0200 Message-ID: <20260924152739.2865510-2-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The upcoming MPAM-Fb support does not use MMIO primitives to access an MSC, but employs a shared-memory/doorbell based firmware protocol. Its complexity means that it must be able to handle errors, whereas we always assume an MMIO based MSC access succeeds today. Change the __mpam_read_reg() low level accessor function to return the requested data through a pointer, and return an error code instead. Also change the __mpam_write_reg() accessor function to return an error code. At the moment this is always 0, so all error handling paths are not exercised at the moment. This will change later when alternative MSC access methods like MPAM-Fb are activated. Change all direct users of those MSC wrappers to comply with the new prototypes, though the errors are not propagated all the way up yet. Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron Reviewed-by: Ben Horgan Reviewed-by: Gavin Shan Tested-by: Gavin Shan # on NVIDIA Grace Hopper --- drivers/resctrl/mpam_devices.c | 208 +++++++++++++++++++++------------ 1 file changed, 134 insertions(+), 74 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index dd422c56fbb14..c7686d3799653 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -177,59 +177,68 @@ static void mpam_assert_partid_sizes_fixed(void) WARN_ON_ONCE(!partid_max_published); } =20 -static u32 __mpam_read_reg(struct mpam_msc *msc, u16 reg) +static int __mpam_read_reg(struct mpam_msc *msc, u16 reg, u32 *res) { WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); =20 - return readl_relaxed(msc->mapped_hwpage + reg); + *res =3D readl_relaxed(msc->mapped_hwpage + reg); + + return 0; } =20 -static inline u32 _mpam_read_partsel_reg(struct mpam_msc *msc, u16 reg) +static inline int _mpam_read_partsel_reg(struct mpam_msc *msc, u16 reg, + u32 *res) { lockdep_assert_held_once(&msc->part_sel_lock); - return __mpam_read_reg(msc, reg); + return __mpam_read_reg(msc, reg, res); } =20 -#define mpam_read_partsel_reg(msc, reg) _mpam_read_partsel_reg(msc, MPAMF_= ##reg) +#define mpam_read_partsel_reg(msc, reg, res) _mpam_read_partsel_reg(msc, M= PAMF_##reg, res) =20 -static void __mpam_write_reg(struct mpam_msc *msc, u16 reg, u32 val) +static int __mpam_write_reg(struct mpam_msc *msc, u16 reg, u32 val) { WARN_ON_ONCE(reg + sizeof(u32) > msc->mapped_hwpage_sz); WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); =20 writel_relaxed(val, msc->mapped_hwpage + reg); + + return 0; } =20 -static inline void _mpam_write_partsel_reg(struct mpam_msc *msc, u16 reg, = u32 val) +static inline int _mpam_write_partsel_reg(struct mpam_msc *msc, u16 reg, u= 32 val) { lockdep_assert_held_once(&msc->part_sel_lock); - __mpam_write_reg(msc, reg, val); + return __mpam_write_reg(msc, reg, val); } =20 #define mpam_write_partsel_reg(msc, reg, val) _mpam_write_partsel_reg(msc= , MPAMCFG_##reg, val) =20 -static inline u32 _mpam_read_monsel_reg(struct mpam_msc *msc, u16 reg) +static inline int _mpam_read_monsel_reg(struct mpam_msc *msc, u16 reg, + u32 *res) { mpam_mon_sel_lock_held(msc); - return __mpam_read_reg(msc, reg); + return __mpam_read_reg(msc, reg, res); } =20 -#define mpam_read_monsel_reg(msc, reg) _mpam_read_monsel_reg(msc, MSMON_##= reg) +#define mpam_read_monsel_reg(msc, reg, res) _mpam_read_monsel_reg(msc, MSM= ON_##reg, res) =20 -static inline void _mpam_write_monsel_reg(struct mpam_msc *msc, u16 reg, u= 32 val) +static inline int _mpam_write_monsel_reg(struct mpam_msc *msc, u16 reg, u3= 2 val) { mpam_mon_sel_lock_held(msc); - __mpam_write_reg(msc, reg, val); + return __mpam_write_reg(msc, reg, val); } =20 #define mpam_write_monsel_reg(msc, reg, val) _mpam_write_monsel_reg(msc,= MSMON_##reg, val) =20 static bool mpam_msc_check_aidr(struct mpam_msc *msc) { - u32 aidr =3D __mpam_read_reg(msc, MPAMF_AIDR); - u32 major =3D FIELD_GET(MPAMF_AIDR_ARCH_MAJOR_REV, aidr); - u32 minor =3D FIELD_GET(MPAMF_AIDR_ARCH_MINOR_REV, aidr); + u32 aidr, major, minor; =20 + if (__mpam_read_reg(msc, MPAMF_AIDR, &aidr)) + return false; + + major =3D FIELD_GET(MPAMF_AIDR_ARCH_MAJOR_REV, aidr); + minor =3D FIELD_GET(MPAMF_AIDR_ARCH_MINOR_REV, aidr); /* * v0.0 and >v2.x aren't supported, but anything else should be backward * compatible to v0.1 or v1.0. @@ -242,25 +251,41 @@ static bool mpam_msc_check_aidr(struct mpam_msc *msc) return true; } =20 -static u64 mpam_msc_read_idr(struct mpam_msc *msc) +static int mpam_msc_read_idr(struct mpam_msc *msc, u64 *res) { - u64 idr_high =3D 0, idr_low; + u32 idr_high, idr_low; + int ret; =20 lockdep_assert_held(&msc->part_sel_lock); =20 - idr_low =3D mpam_read_partsel_reg(msc, IDR); - if (FIELD_GET(MPAMF_IDR_EXT, idr_low)) - idr_high =3D mpam_read_partsel_reg(msc, IDR + 4); + ret =3D mpam_read_partsel_reg(msc, IDR, &idr_low); + if (ret) + return ret; + + if (FIELD_GET(MPAMF_IDR_EXT, idr_low)) { + ret =3D mpam_read_partsel_reg(msc, IDR + 4, &idr_high); + if (ret) + return ret; + } else { + idr_high =3D 0; + } + + *res =3D ((u64)idr_high << 32) | idr_low; =20 - return (idr_high << 32) | idr_low; + return 0; } =20 -static void mpam_msc_clear_esr(struct mpam_msc *msc) +static int mpam_msc_clear_esr(struct mpam_msc *msc) { - u64 esr_low =3D __mpam_read_reg(msc, MPAMF_ESR); + u32 esr_low; + int ret; + + ret =3D __mpam_read_reg(msc, MPAMF_ESR, &esr_low); + if (ret) + return ret; =20 if (!esr_low) - return; + return 0; =20 /* * Clearing the high/low bits of MPAMF_ESR can not be atomic. @@ -268,44 +293,59 @@ static void mpam_msc_clear_esr(struct mpam_msc *msc) * lower half prevent hardware from updating either half of the * register. */ - if (msc->has_extd_esr) - __mpam_write_reg(msc, MPAMF_ESR + 4, 0); - __mpam_write_reg(msc, MPAMF_ESR, 0); + if (msc->has_extd_esr) { + ret =3D __mpam_write_reg(msc, MPAMF_ESR + 4, 0); + if (ret) + return ret; + } + + return __mpam_write_reg(msc, MPAMF_ESR, 0); } =20 -static u64 mpam_msc_read_esr(struct mpam_msc *msc) +static int mpam_msc_read_esr(struct mpam_msc *msc, u64 *res) { - u64 esr_high =3D 0, esr_low; + u32 esr_high, esr_low; + int ret; =20 - esr_low =3D __mpam_read_reg(msc, MPAMF_ESR); - if (msc->has_extd_esr) - esr_high =3D __mpam_read_reg(msc, MPAMF_ESR + 4); + ret =3D __mpam_read_reg(msc, MPAMF_ESR, &esr_low); + if (ret) + return ret; =20 - return (esr_high << 32) | esr_low; + if (msc->has_extd_esr) { + ret =3D __mpam_read_reg(msc, MPAMF_ESR + 4, &esr_high); + if (ret) + return ret; + } else { + esr_high =3D 0; + } + + *res =3D ((u64)esr_high << 32) | esr_low; + + return 0; } =20 -static void __mpam_part_sel_raw(u32 partsel, struct mpam_msc *msc) +static int __mpam_part_sel_raw(u32 partsel, struct mpam_msc *msc) { lockdep_assert_held(&msc->part_sel_lock); =20 - mpam_write_partsel_reg(msc, PART_SEL, partsel); + return mpam_write_partsel_reg(msc, PART_SEL, partsel); } =20 -static void __mpam_part_sel(u8 ris_idx, u16 partid, struct mpam_msc *msc) +static int __mpam_part_sel(u8 ris_idx, u16 partid, struct mpam_msc *msc) { u32 partsel =3D FIELD_PREP(MPAMCFG_PART_SEL_RIS, ris_idx) | FIELD_PREP(MPAMCFG_PART_SEL_PARTID_SEL, partid); =20 - __mpam_part_sel_raw(partsel, msc); + return __mpam_part_sel_raw(partsel, msc); } =20 -static void __mpam_intpart_sel(u8 ris_idx, u16 intpartid, struct mpam_msc = *msc) +static int __mpam_intpart_sel(u8 ris_idx, u16 intpartid, struct mpam_msc *= msc) { u32 partsel =3D FIELD_PREP(MPAMCFG_PART_SEL_RIS, ris_idx) | FIELD_PREP(MPAMCFG_PART_SEL_PARTID_SEL, intpartid) | MPAMCFG_PART_SEL_INTERNAL; =20 - __mpam_part_sel_raw(partsel, msc); + return __mpam_part_sel_raw(partsel, msc); } =20 int mpam_register_requestor(u16 partid_max, u8 pmg_max) @@ -774,13 +814,13 @@ static bool mpam_ris_hw_probe_csu_nrdy(struct mpam_ms= c_ris *ris) mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val); =20 _mpam_write_monsel_reg(msc, MSMON_CSU, MSMON___NRDY); - now =3D _mpam_read_monsel_reg(msc, MSMON_CSU); + _mpam_read_monsel_reg(msc, MSMON_CSU, &now); can_set =3D now & MSMON___NRDY; =20 _mpam_write_monsel_reg(msc, MSMON_CSU, 0); /* Configuration change to try and coax hardware into setting nrdy */ mpam_write_monsel_reg(msc, CFG_CSU_FLT, 0x1); - now =3D _mpam_read_monsel_reg(msc, MSMON_CSU); + _mpam_read_monsel_reg(msc, MSMON_CSU, &now); can_clear =3D !(now & MSMON___NRDY); mpam_mon_sel_unlock(msc); =20 @@ -800,7 +840,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) =20 /* Cache Capacity Partitioning */ if (FIELD_GET(MPAMF_IDR_HAS_CCAP_PART, ris->idr)) { - u32 ccap_features =3D mpam_read_partsel_reg(msc, CCAP_IDR); + u32 ccap_features; + + mpam_read_partsel_reg(msc, CCAP_IDR, &ccap_features); =20 props->cmax_wd =3D FIELD_GET(MPAMF_CCAP_IDR_CMAX_WD, ccap_features); if (props->cmax_wd && @@ -823,7 +865,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) =20 /* Cache Portion partitioning */ if (FIELD_GET(MPAMF_IDR_HAS_CPOR_PART, ris->idr)) { - u32 cpor_features =3D mpam_read_partsel_reg(msc, CPOR_IDR); + u32 cpor_features; + + mpam_read_partsel_reg(msc, CPOR_IDR, &cpor_features); =20 props->cpbm_wd =3D FIELD_GET(MPAMF_CPOR_IDR_CPBM_WD, cpor_features); if (props->cpbm_wd) @@ -832,7 +876,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) =20 /* Memory bandwidth partitioning */ if (FIELD_GET(MPAMF_IDR_HAS_MBW_PART, ris->idr)) { - u32 mbw_features =3D mpam_read_partsel_reg(msc, MBW_IDR); + u32 mbw_features; + + mpam_read_partsel_reg(msc, MBW_IDR, &mbw_features); =20 /* portion bitmap resolution */ props->mbw_pbm_bits =3D FIELD_GET(MPAMF_MBW_IDR_BWPBM_WD, mbw_features); @@ -860,7 +906,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) =20 /* Priority partitioning */ if (FIELD_GET(MPAMF_IDR_HAS_PRI_PART, ris->idr)) { - u32 pri_features =3D mpam_read_partsel_reg(msc, PRI_IDR); + u32 pri_features; + + mpam_read_partsel_reg(msc, PRI_IDR, &pri_features); =20 props->intpri_wd =3D FIELD_GET(MPAMF_PRI_IDR_INTPRI_WD, pri_features); if (props->intpri_wd && FIELD_GET(MPAMF_PRI_IDR_HAS_INTPRI, pri_features= )) { @@ -879,7 +927,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) =20 /* Performance Monitoring */ if (FIELD_GET(MPAMF_IDR_HAS_MSMON, ris->idr)) { - u32 msmon_features =3D mpam_read_partsel_reg(msc, MSMON_IDR); + u32 msmon_features; + + mpam_read_partsel_reg(msc, MSMON_IDR, &msmon_features); =20 /* * If the firmware max-nrdy-us property is missing, the @@ -892,7 +942,8 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_CSU, msmon_features)) { u32 csumonidr; =20 - csumonidr =3D mpam_read_partsel_reg(msc, CSUMON_IDR); + mpam_read_partsel_reg(msc, CSUMON_IDR, &csumonidr); + props->num_csu_mon =3D FIELD_GET(MPAMF_CSUMON_IDR_NUM_MON, csumonidr); if (props->num_csu_mon) { bool hw_managed; @@ -915,7 +966,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) } if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_MBWU, msmon_features)) { bool has_long; - u32 mbwumon_idr =3D mpam_read_partsel_reg(msc, MBWUMON_IDR); + u32 mbwumon_idr; + + mpam_read_partsel_reg(msc, MBWUMON_IDR, &mbwumon_idr); =20 props->num_mbwu_mon =3D FIELD_GET(MPAMF_MBWUMON_IDR_NUM_MON, mbwumon_id= r); if (props->num_mbwu_mon) { @@ -945,8 +998,11 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) */ if (FIELD_GET(MPAMF_IDR_HAS_PARTID_NRW, ris->idr) && class->type !=3D MPAM_CLASS_UNKNOWN) { - u32 nrwidr =3D mpam_read_partsel_reg(msc, PARTID_NRW_IDR); - u16 partid_max =3D FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr); + u16 partid_max; + u32 nrwidr; + + mpam_read_partsel_reg(msc, PARTID_NRW_IDR, &nrwidr); + partid_max =3D FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr); =20 mpam_set_feature(mpam_feat_partid_nrw, props); msc->partid_max =3D min(msc->partid_max, partid_max); @@ -970,8 +1026,9 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) =20 /* Grab an IDR value to find out how many RIS there are */ mutex_lock(&msc->part_sel_lock); - idr =3D mpam_msc_read_idr(msc); - msc->iidr =3D mpam_read_partsel_reg(msc, IIDR); + mpam_msc_read_idr(msc, &idr); + mpam_read_partsel_reg(msc, IIDR, &msc->iidr); + mutex_unlock(&msc->part_sel_lock); =20 mpam_enable_quirks(msc); @@ -985,7 +1042,7 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) for (ris_idx =3D 0; ris_idx <=3D msc->ris_max; ris_idx++) { mutex_lock(&msc->part_sel_lock); __mpam_part_sel(ris_idx, 0, msc); - idr =3D mpam_msc_read_idr(msc); + mpam_msc_read_idr(msc, &idr); mutex_unlock(&msc->part_sel_lock); =20 partid_max =3D FIELD_GET(MPAMF_IDR_PARTID_MAX, idr); @@ -1039,24 +1096,24 @@ static u64 mpam_msc_read_mbwu_l(struct mpam_msc *ms= c) { int retry =3D 3; u32 mbwu_l_low; - u64 mbwu_l_high1, mbwu_l_high2; + u32 mbwu_l_high1, mbwu_l_high2; =20 mpam_mon_sel_lock_held(msc); =20 WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); =20 - mbwu_l_high2 =3D __mpam_read_reg(msc, MSMON_MBWU_L + 4); + __mpam_read_reg(msc, MSMON_MBWU_L + 4, &mbwu_l_high2); do { mbwu_l_high1 =3D mbwu_l_high2; - mbwu_l_low =3D __mpam_read_reg(msc, MSMON_MBWU_L); - mbwu_l_high2 =3D __mpam_read_reg(msc, MSMON_MBWU_L + 4); + __mpam_read_reg(msc, MSMON_MBWU_L, &mbwu_l_low); + __mpam_read_reg(msc, MSMON_MBWU_L + 4, &mbwu_l_high2); =20 retry--; } while (mbwu_l_high1 !=3D mbwu_l_high2 && retry > 0); =20 if (mbwu_l_high1 =3D=3D mbwu_l_high2) - return (mbwu_l_high1 << 32) | mbwu_l_low; + return ((u64)mbwu_l_high1 << 32) | mbwu_l_low; =20 pr_warn("Failed to read a stable value\n"); return MSMON___L_NRDY; @@ -1120,14 +1177,14 @@ static void read_msmon_ctl_flt_vals(struct mon_read= *m, u32 *ctl_val, =20 switch (m->type) { case mpam_feat_msmon_csu: - *ctl_val =3D mpam_read_monsel_reg(msc, CFG_CSU_CTL); - *flt_val =3D mpam_read_monsel_reg(msc, CFG_CSU_FLT); + mpam_read_monsel_reg(msc, CFG_CSU_CTL, ctl_val); + mpam_read_monsel_reg(msc, CFG_CSU_FLT, flt_val); break; case mpam_feat_msmon_mbwu_31counter: case mpam_feat_msmon_mbwu_44counter: case mpam_feat_msmon_mbwu_63counter: - *ctl_val =3D mpam_read_monsel_reg(msc, CFG_MBWU_CTL); - *flt_val =3D mpam_read_monsel_reg(msc, CFG_MBWU_FLT); + mpam_read_monsel_reg(msc, CFG_MBWU_CTL, ctl_val); + mpam_read_monsel_reg(msc, CFG_MBWU_FLT, flt_val); break; default: pr_warn("Unexpected monitor type %d\n", m->type); @@ -1205,6 +1262,7 @@ static u64 mpam_msmon_overflow_val(enum mpam_device_f= eatures type, static void __ris_msmon_read(void *arg) { u64 now; + u32 now32; bool nrdy =3D false; bool config_mismatch; bool overflow =3D false; @@ -1267,9 +1325,9 @@ static void __ris_msmon_read(void *arg) =20 switch (m->type) { case mpam_feat_msmon_csu: - now =3D mpam_read_monsel_reg(msc, CSU); - nrdy =3D now & MSMON___NRDY; - now =3D FIELD_GET(MSMON___VALUE, now); + mpam_read_monsel_reg(msc, CSU, &now32); + nrdy =3D now32 & MSMON___NRDY; + now =3D FIELD_GET(MSMON___VALUE, now32); =20 if (mpam_has_quirk(IGNORE_CSU_NRDY, msc) && m->waited_timeout) nrdy =3D false; @@ -1287,9 +1345,9 @@ static void __ris_msmon_read(void *arg) else now =3D FIELD_GET(MSMON___L_VALUE, now); } else { - now =3D mpam_read_monsel_reg(msc, MBWU); - nrdy =3D now & MSMON___NRDY; - now =3D FIELD_GET(MSMON___VALUE, now); + mpam_read_monsel_reg(msc, MBWU, &now32); + nrdy =3D now32 & MSMON___NRDY; + now =3D FIELD_GET(MSMON___VALUE, now32); } =20 if (mpam_has_quirk(T241_MBW_COUNTER_SCALE_64, msc)) @@ -1689,16 +1747,18 @@ static int mpam_save_mbwu_state(void *arg) mon_sel =3D FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, i) | FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); - - cur_flt =3D mpam_read_monsel_reg(msc, CFG_MBWU_FLT); - cur_ctl =3D mpam_read_monsel_reg(msc, CFG_MBWU_CTL); + mpam_read_monsel_reg(msc, CFG_MBWU_FLT, &cur_flt); + mpam_read_monsel_reg(msc, CFG_MBWU_CTL, &cur_ctl); mpam_write_monsel_reg(msc, CFG_MBWU_CTL, 0); =20 if (mpam_ris_has_mbwu_long_counter(ris)) { val =3D mpam_msc_read_mbwu_l(msc); mpam_msc_zero_mbwu_l(msc); } else { - val =3D mpam_read_monsel_reg(msc, MBWU); + u32 val32; + + mpam_read_monsel_reg(msc, MBWU, &val32); + val =3D val32; mpam_write_monsel_reg(msc, MBWU, 0); } =20 @@ -2473,7 +2533,7 @@ static irqreturn_t __mpam_irq_handler(int irq, struct= mpam_msc *msc) &msc->accessibility))) return IRQ_NONE; =20 - reg =3D mpam_msc_read_esr(msc); + mpam_msc_read_esr(msc, ®); =20 errcode =3D FIELD_GET(MPAMF_ESR_ERRCODE, reg); if (!errcode) --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 751FA4A0130; Thu, 24 Sep 2026 15:28:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263691; cv=none; b=nlYsjZ9/rmKs1swM3h10azSCFrKI2iO9dPjr7GYtMVGpCwpo6Gqxx4gTvi2DmUU/YnOS+oEVWpDreO7ubAZL7ITUM6EYNShD0sB/Mx9+aSOTGLxZ64nesThI+CxcSDhQ4JKw9V+goOGmNGjDovviEUh0JdAzfo1U45hMuPh8sn4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263691; c=relaxed/simple; bh=f5djBEtBRz7HuppG85mC4yqvdEzgprnz8z3OIhXuWR8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VQgpDfXQ7Eq7Gjq8NDKCdSb3UWQ9TvP/2NKVXD2zBNpfr33l4u/0NOr2cy7O8zFqgAa+R3bpbUJEkoWmDenr663GgTSzDy13vZpfahvEyZ/ZQIlnvlwq+/RjgRoYR+Gb9za8hUBsXnhV9dbA6aEZc85agyIlxxEMEdi70up5fRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=tTpa6IqN; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="tTpa6IqN" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 433A31A25; Thu, 24 Sep 2026 08:28:05 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 54AC93F86F; Thu, 24 Sep 2026 08:28:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263688; bh=f5djBEtBRz7HuppG85mC4yqvdEzgprnz8z3OIhXuWR8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tTpa6IqNC03QEvWIicOlPWzMgRF7Ed0ksrnwMer4kwhkVz5KPuWDnvVBwWlsr264l cQAVfKNJSws3TTMvG5R63/MQVP/rWMJ/3E9slOVVbGFD+IuS+ZQGQMxQueM5THyCTh aCcfl9uASB6+5E4bUrLN+kdrvR5reoXKiV8TfUyg= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 02/13] arm_mpam: propagate MSC access errors for hw_probe functions Date: Thu, 24 Sep 2026 17:27:28 +0200 Message-ID: <20260924152739.2865510-3-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow the functions probing for MSC hardware and features to return an error, and propagate read and write errors from the lower level up. This uses some "scoped cleanup" functions like scoped_guard() and ACQUIRE() to avoid the complexity of error handling when a lock has been taken. Since the mon_sel_lock is a bit special (even more so in an upcoming patch), we define a new GUARD type for it. Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron Reviewed-by: Ben Horgan Reviewed-by: Gavin Shan Tested-by: Gavin Shan # on NVIDIA Grace Hopper --- drivers/resctrl/mpam_devices.c | 126 +++++++++++++++++++++----------- drivers/resctrl/mpam_internal.h | 4 + 2 files changed, 87 insertions(+), 43 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index c7686d3799653..22069e7f7bb05 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -798,38 +798,46 @@ static bool mpam_ris_hw_probe_csu_nrdy(struct mpam_ms= c_ris *ris) bool can_set, can_clear; struct mpam_msc *msc =3D ris->vmsc->msc; =20 - if (WARN_ON_ONCE(!mpam_mon_sel_lock(msc))) + ACQUIRE(mon_sel_lock, guard)(msc); + if (ACQUIRE_ERR(mon_sel_lock, &guard)) return false; =20 mon_sel =3D FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, 0) | FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); - mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); + if (mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel)) + return false; =20 /* Hardware might ignore nrdy if it's not enabled */ ctl_val =3D MSMON_CFG_CSU_CTL_TYPE_CSU; ctl_val |=3D MSMON_CFG_x_CTL_MATCH_PARTID; ctl_val |=3D MSMON_CFG_x_CTL_MATCH_PMG; ctl_val |=3D MSMON_CFG_x_CTL_EN; - mpam_write_monsel_reg(msc, CFG_CSU_FLT, 0); - mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val); + if (mpam_write_monsel_reg(msc, CFG_CSU_FLT, 0)) + return false; + if (mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val)) + return false; =20 - _mpam_write_monsel_reg(msc, MSMON_CSU, MSMON___NRDY); - _mpam_read_monsel_reg(msc, MSMON_CSU, &now); + if (_mpam_write_monsel_reg(msc, MSMON_CSU, MSMON___NRDY)) + return false; + if (_mpam_read_monsel_reg(msc, MSMON_CSU, &now)) + return false; can_set =3D now & MSMON___NRDY; =20 - _mpam_write_monsel_reg(msc, MSMON_CSU, 0); + if (_mpam_write_monsel_reg(msc, MSMON_CSU, 0)) + return false; /* Configuration change to try and coax hardware into setting nrdy */ - mpam_write_monsel_reg(msc, CFG_CSU_FLT, 0x1); - _mpam_read_monsel_reg(msc, MSMON_CSU, &now); + if (mpam_write_monsel_reg(msc, CFG_CSU_FLT, 0x1)) + return false; + if (_mpam_read_monsel_reg(msc, MSMON_CSU, &now)) + return false; can_clear =3D !(now & MSMON___NRDY); - mpam_mon_sel_unlock(msc); =20 return (!can_set || !can_clear); } =20 -static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) +static int mpam_ris_hw_probe(struct mpam_msc_ris *ris) { - int err; + int fw_has_nrdy_err, err; struct mpam_msc *msc =3D ris->vmsc->msc; struct device *dev =3D &msc->pdev->dev; struct mpam_props *props =3D &ris->props; @@ -842,7 +850,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) if (FIELD_GET(MPAMF_IDR_HAS_CCAP_PART, ris->idr)) { u32 ccap_features; =20 - mpam_read_partsel_reg(msc, CCAP_IDR, &ccap_features); + err =3D mpam_read_partsel_reg(msc, CCAP_IDR, &ccap_features); + if (err) + return err; =20 props->cmax_wd =3D FIELD_GET(MPAMF_CCAP_IDR_CMAX_WD, ccap_features); if (props->cmax_wd && @@ -867,7 +877,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) if (FIELD_GET(MPAMF_IDR_HAS_CPOR_PART, ris->idr)) { u32 cpor_features; =20 - mpam_read_partsel_reg(msc, CPOR_IDR, &cpor_features); + err =3D mpam_read_partsel_reg(msc, CPOR_IDR, &cpor_features); + if (err) + return err; =20 props->cpbm_wd =3D FIELD_GET(MPAMF_CPOR_IDR_CPBM_WD, cpor_features); if (props->cpbm_wd) @@ -877,8 +889,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) /* Memory bandwidth partitioning */ if (FIELD_GET(MPAMF_IDR_HAS_MBW_PART, ris->idr)) { u32 mbw_features; - - mpam_read_partsel_reg(msc, MBW_IDR, &mbw_features); + err =3D mpam_read_partsel_reg(msc, MBW_IDR, &mbw_features); + if (err) + return err; =20 /* portion bitmap resolution */ props->mbw_pbm_bits =3D FIELD_GET(MPAMF_MBW_IDR_BWPBM_WD, mbw_features); @@ -907,8 +920,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) /* Priority partitioning */ if (FIELD_GET(MPAMF_IDR_HAS_PRI_PART, ris->idr)) { u32 pri_features; - - mpam_read_partsel_reg(msc, PRI_IDR, &pri_features); + err =3D mpam_read_partsel_reg(msc, PRI_IDR, &pri_features); + if (err) + return err; =20 props->intpri_wd =3D FIELD_GET(MPAMF_PRI_IDR_INTPRI_WD, pri_features); if (props->intpri_wd && FIELD_GET(MPAMF_PRI_IDR_HAS_INTPRI, pri_features= )) { @@ -929,20 +943,24 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ri= s) if (FIELD_GET(MPAMF_IDR_HAS_MSMON, ris->idr)) { u32 msmon_features; =20 - mpam_read_partsel_reg(msc, MSMON_IDR, &msmon_features); + err =3D mpam_read_partsel_reg(msc, MSMON_IDR, &msmon_features); + if (err) + return err; =20 /* * If the firmware max-nrdy-us property is missing, the * CSU counters can't be used. Should we wait forever? */ - err =3D device_property_read_u32(&msc->pdev->dev, - "arm,not-ready-us", - &msc->nrdy_usec); + fw_has_nrdy_err =3D device_property_read_u32(&msc->pdev->dev, + "arm,not-ready-us", + &msc->nrdy_usec); =20 if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_CSU, msmon_features)) { u32 csumonidr; =20 - mpam_read_partsel_reg(msc, CSUMON_IDR, &csumonidr); + err =3D mpam_read_partsel_reg(msc, CSUMON_IDR, &csumonidr); + if (err) + return err; =20 props->num_csu_mon =3D FIELD_GET(MPAMF_CSUMON_IDR_NUM_MON, csumonidr); if (props->num_csu_mon) { @@ -960,7 +978,7 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) * Accept the missing firmware property if NRDY appears * un-implemented. */ - if (err && hw_managed) + if (fw_has_nrdy_err && hw_managed) dev_err_once(dev, "Counters are not usable because not-ready timeout = was not provided by firmware."); } } @@ -968,7 +986,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) bool has_long; u32 mbwumon_idr; =20 - mpam_read_partsel_reg(msc, MBWUMON_IDR, &mbwumon_idr); + err =3D mpam_read_partsel_reg(msc, MBWUMON_IDR, &mbwumon_idr); + if (err) + return err; =20 props->num_mbwu_mon =3D FIELD_GET(MPAMF_MBWUMON_IDR_NUM_MON, mbwumon_id= r); if (props->num_mbwu_mon) { @@ -1001,16 +1021,22 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *= ris) u16 partid_max; u32 nrwidr; =20 - mpam_read_partsel_reg(msc, PARTID_NRW_IDR, &nrwidr); + err =3D mpam_read_partsel_reg(msc, PARTID_NRW_IDR, &nrwidr); + if (err) + return err; + partid_max =3D FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr); =20 mpam_set_feature(mpam_feat_partid_nrw, props); msc->partid_max =3D min(msc->partid_max, partid_max); } + + return 0; } =20 static int mpam_msc_hw_probe(struct mpam_msc *msc) { + int ret; u64 idr; u16 partid_max; u8 ris_idx, pmg_max; @@ -1025,11 +1051,15 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) } =20 /* Grab an IDR value to find out how many RIS there are */ - mutex_lock(&msc->part_sel_lock); - mpam_msc_read_idr(msc, &idr); - mpam_read_partsel_reg(msc, IIDR, &msc->iidr); + scoped_guard(mutex, &msc->part_sel_lock) { + ret =3D mpam_msc_read_idr(msc, &idr); + if (ret) + return ret; =20 - mutex_unlock(&msc->part_sel_lock); + ret =3D mpam_read_partsel_reg(msc, IIDR, &msc->iidr); + if (ret) + return ret; + } =20 mpam_enable_quirks(msc); =20 @@ -1040,10 +1070,15 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) msc->pmg_max =3D FIELD_GET(MPAMF_IDR_PMG_MAX, idr); =20 for (ris_idx =3D 0; ris_idx <=3D msc->ris_max; ris_idx++) { - mutex_lock(&msc->part_sel_lock); - __mpam_part_sel(ris_idx, 0, msc); - mpam_msc_read_idr(msc, &idr); - mutex_unlock(&msc->part_sel_lock); + scoped_guard(mutex, &msc->part_sel_lock) { + ret =3D __mpam_part_sel(ris_idx, 0, msc); + if (ret) + return ret; + + ret =3D mpam_msc_read_idr(msc, &idr); + if (ret) + return ret; + } =20 partid_max =3D FIELD_GET(MPAMF_IDR_PARTID_MAX, idr); pmg_max =3D FIELD_GET(MPAMF_IDR_PMG_MAX, idr); @@ -1051,17 +1086,22 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) msc->pmg_max =3D min(msc->pmg_max, pmg_max); msc->has_extd_esr =3D FIELD_GET(MPAMF_IDR_HAS_EXTD_ESR, idr); =20 - mutex_lock(&mpam_list_lock); - ris =3D mpam_get_or_create_ris(msc, ris_idx); - mutex_unlock(&mpam_list_lock); - if (IS_ERR(ris)) - return PTR_ERR(ris); + scoped_guard(mutex, &mpam_list_lock) { + ris =3D mpam_get_or_create_ris(msc, ris_idx); + if (IS_ERR(ris)) + return PTR_ERR(ris); + } ris->idr =3D idr; =20 - mutex_lock(&msc->part_sel_lock); - __mpam_part_sel(ris_idx, 0, msc); - mpam_ris_hw_probe(ris); - mutex_unlock(&msc->part_sel_lock); + scoped_guard(mutex, &msc->part_sel_lock) { + ret =3D __mpam_part_sel(ris_idx, 0, msc); + if (ret) + return ret; + + ret =3D mpam_ris_hw_probe(ris); + if (ret) + return ret; + } } =20 /* Clear any stale errors */ diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_interna= l.h index def0e3a65c230..68a6cf2b9cc73 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -162,6 +162,10 @@ static inline void mpam_mon_sel_lock_init(struct mpam_= msc *msc) raw_spin_lock_init(&msc->_mon_sel_lock); } =20 +DEFINE_GUARD(mon_sel, struct mpam_msc *, + mpam_mon_sel_lock(_T), mpam_mon_sel_unlock(_T)); +DEFINE_GUARD_COND(mon_sel, _lock, mpam_mon_sel_lock(_T), _RET); + /* Bits for mpam features bitmaps */ enum mpam_device_features { mpam_feat_cpor_part, --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B67C34A2064; Thu, 24 Sep 2026 15:28:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263699; cv=none; b=MqTaIA+rqikV8yIlVSROtD0nNKMiwxIGPFoCgPd6Nayl0couz1hPZjkl092/GUDItij64v/NzO5xb7GoI/0s0MGv++94mpvLCxSk+zCYTknLWaKhhNkj1c19p87o7T8eJEGhX5Wfx1g+F54p/jI675cK3cUtwsjo6XK3iK42CCg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263699; c=relaxed/simple; bh=mFas1w7I1cXL8LOHpUSEzdVwuRk8NVqBlgDk+CKwI4I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bKODbMAfKwGK5dMmRemoxmChxNv5dL13QQUmbv7eoLitT50RI3eshSRI7q35pgZn21pPV67To8+4D7McqH8IQRnqbSG2rzj4xCOTPAx6qSU049eJnz6hzk9oZwaNdjwS/OJ90V4+Jz2MyVwtrtag7x4j0RtVQR8Afn7Qe1+46No= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=Eqc6Q/eb; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="Eqc6Q/eb" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 672FA1A32; Thu, 24 Sep 2026 08:28:12 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 521473F86F; Thu, 24 Sep 2026 08:28:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263695; bh=mFas1w7I1cXL8LOHpUSEzdVwuRk8NVqBlgDk+CKwI4I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Eqc6Q/ebhVfD9BuM1Na304lMAMpUhgGlhR65dJPXQdJMMmMRPQpIT6vt4n+dmY83e hK/ZkND9HV5dXwdt6FKXpKe8f1RrBI2R3V6NQEuE77EfeJvl88j/fNNLAQKfYjhbQ1 bguOKi5plKLLA28NhJqisqYEVCV7DSExMNI/JECI= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 03/13] arm_mpam: propagate MSC access errors for MBWU counters Date: Thu, 24 Sep 2026 17:27:29 +0200 Message-ID: <20260924152739.2865510-4-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow the mpam_msc_read_mbwu_l() function to return an error, and propagate errors from the lower level up. This also changes the users of this function. Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron Reviewed-by: Ben Horgan Reviewed-by: Gavin Shan Tested-by: Gavin Shan # on NVIDIA Grace Hopper --- drivers/resctrl/mpam_devices.c | 45 +++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index 22069e7f7bb05..f780bcc587c7a 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -1132,8 +1132,9 @@ static bool mpam_ris_has_mbwu_long_counter(struct mpa= m_msc_ris *ris) mpam_has_feature(mpam_feat_msmon_mbwu_44counter, &ris->props)); } =20 -static u64 mpam_msc_read_mbwu_l(struct mpam_msc *msc) +static int mpam_msc_read_mbwu_l(struct mpam_msc *msc, u64 *res) { + int ret; int retry =3D 3; u32 mbwu_l_low; u32 mbwu_l_high1, mbwu_l_high2; @@ -1143,20 +1144,30 @@ static u64 mpam_msc_read_mbwu_l(struct mpam_msc *ms= c) WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); =20 - __mpam_read_reg(msc, MSMON_MBWU_L + 4, &mbwu_l_high2); + ret =3D __mpam_read_reg(msc, MSMON_MBWU_L + 4, &mbwu_l_high2); + if (ret) + return ret; + do { mbwu_l_high1 =3D mbwu_l_high2; - __mpam_read_reg(msc, MSMON_MBWU_L, &mbwu_l_low); - __mpam_read_reg(msc, MSMON_MBWU_L + 4, &mbwu_l_high2); + ret =3D __mpam_read_reg(msc, MSMON_MBWU_L, &mbwu_l_low); + if (ret) + return ret; + ret =3D __mpam_read_reg(msc, MSMON_MBWU_L + 4, &mbwu_l_high2); + if (ret) + return ret; =20 retry--; } while (mbwu_l_high1 !=3D mbwu_l_high2 && retry > 0); =20 - if (mbwu_l_high1 =3D=3D mbwu_l_high2) - return ((u64)mbwu_l_high1 << 32) | mbwu_l_low; + if (mbwu_l_high1 =3D=3D mbwu_l_high2) { + *res =3D ((u64)mbwu_l_high1 << 32) | mbwu_l_low; + } else { + pr_warn("Failed to read a stable value\n"); + *res =3D MSMON___L_NRDY; + } =20 - pr_warn("Failed to read a stable value\n"); - return MSMON___L_NRDY; + return 0; } =20 static void mpam_msc_zero_mbwu_l(struct mpam_msc *msc) @@ -1314,10 +1325,12 @@ static void __ris_msmon_read(void *arg) struct mpam_msc *msc =3D m->ris->vmsc->msc; u32 mon_sel, ctl_val, flt_val, cur_ctl, cur_flt; =20 - if (!mpam_mon_sel_lock(msc)) { + ACQUIRE(mon_sel_lock, guard)(msc); + if (ACQUIRE_ERR(mon_sel_lock, &guard)) { m->err =3D -EIO; return; } + mon_sel =3D FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, ctx->mon) | FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); @@ -1377,7 +1390,9 @@ static void __ris_msmon_read(void *arg) case mpam_feat_msmon_mbwu_44counter: case mpam_feat_msmon_mbwu_63counter: if (m->type !=3D mpam_feat_msmon_mbwu_31counter) { - now =3D mpam_msc_read_mbwu_l(msc); + m->err =3D mpam_msc_read_mbwu_l(msc, &now); + if (m->err) + return; nrdy =3D now & MSMON___L_NRDY; =20 if (m->type =3D=3D mpam_feat_msmon_mbwu_63counter) @@ -1410,7 +1425,6 @@ static void __ris_msmon_read(void *arg) default: m->err =3D -EINVAL; } - mpam_mon_sel_unlock(msc); =20 if (nrdy) m->err =3D -EBUSY; @@ -1771,6 +1785,7 @@ static int mpam_save_mbwu_state(void *arg) { int i; u64 val; + int ret; struct mon_cfg *cfg; u32 cur_flt, cur_ctl, mon_sel; struct mpam_msc_ris *ris =3D arg; @@ -1781,7 +1796,8 @@ static int mpam_save_mbwu_state(void *arg) mbwu_state =3D &ris->mbwu_state[i]; cfg =3D &mbwu_state->cfg; =20 - if (WARN_ON_ONCE(!mpam_mon_sel_lock(msc))) + ACQUIRE(mon_sel_lock, guard)(msc); + if (ACQUIRE_ERR(mon_sel_lock, &guard)) return -EIO; =20 mon_sel =3D FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, i) | @@ -1792,7 +1808,9 @@ static int mpam_save_mbwu_state(void *arg) mpam_write_monsel_reg(msc, CFG_MBWU_CTL, 0); =20 if (mpam_ris_has_mbwu_long_counter(ris)) { - val =3D mpam_msc_read_mbwu_l(msc); + ret =3D mpam_msc_read_mbwu_l(msc, &val); + if (ret) + return ret; mpam_msc_zero_mbwu_l(msc); } else { u32 val32; @@ -1808,7 +1826,6 @@ static int mpam_save_mbwu_state(void *arg) cfg->partid =3D FIELD_GET(MSMON_CFG_x_FLT_PARTID, cur_flt); mbwu_state->correction +=3D val; mbwu_state->enabled =3D FIELD_GET(MSMON_CFG_x_CTL_EN, cur_ctl); - mpam_mon_sel_unlock(msc); } =20 return 0; --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CCF7949E5C2; Thu, 24 Sep 2026 15:28:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263706; cv=none; b=mTxSHFLHfYplCgdCQANQTYCQqkeomAP62OX7LbGHRftBa+R8gkU3TRI3pTmIb8I1JN0l6lFL0W2Fpfw+rRAg70xjLOwFiYzba/zVu1dAAIE5rfJ5MBlSUz76ATYWzqdhXLgQnOnRJLdwJY9JRYtkEQl4E8aWHF8BNskJ8rzm8zI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263706; c=relaxed/simple; bh=lQbsP8ZSYvWNdPXsJJ7VCy9P00wz+YHxs5Fcq8+D5cQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DoutRvmxpxrUTYpzXECO4HlNef77Fkg9TskCXUwp8Iy8XO3C4xTWlUskO2NyALywpPjif6/TYXRB63/d03cREn+zod/q1NTh+6/0kZyv9HQShK1goCn4ZFgulZ1m5F3cm3mnhoQBPgSVA0XNHdEuurXUN/K4dNlMGlRYKq+jO9I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=be9IttSs; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="be9IttSs" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id CC2281BCB; Thu, 24 Sep 2026 08:28:20 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 68C353F86F; Thu, 24 Sep 2026 08:28:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263704; bh=lQbsP8ZSYvWNdPXsJJ7VCy9P00wz+YHxs5Fcq8+D5cQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=be9IttSswjCx8Pug0FCTESdp2JJ1tslvEH3ledEMydmp4SQBy5PwlyWOXH7leNjg9 kKsoRwtXk/cX2rV14K6aXObEkpcwB3JF14pA2sz+xEuNXqAuRruSS5+leqsC8OwYRI KCtBtrJpA3d2Kyjuat0zZZdwYeOvY9fFmDIHp5qI= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 04/13] arm_mpam: propagate MSC access errors for msmon helpers Date: Thu, 24 Sep 2026 17:27:30 +0200 Message-ID: <20260924152739.2865510-5-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow the helper functions for msmon accesses to return an error, and propagate read and write errors from the lower level up. Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron Reviewed-by: Ben Horgan Reviewed-by: Gavin Shan Tested-by: Gavin Shan # on NVIDIA Grace Hopper --- drivers/resctrl/mpam_devices.c | 72 ++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index f780bcc587c7a..bfad65596f172 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -1170,15 +1170,20 @@ static int mpam_msc_read_mbwu_l(struct mpam_msc *ms= c, u64 *res) return 0; } =20 -static void mpam_msc_zero_mbwu_l(struct mpam_msc *msc) +static int mpam_msc_zero_mbwu_l(struct mpam_msc *msc) { + int ret; + mpam_mon_sel_lock_held(msc); =20 WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); =20 - __mpam_write_reg(msc, MSMON_MBWU_L, 0); - __mpam_write_reg(msc, MSMON_MBWU_L + 4, 0); + ret =3D __mpam_write_reg(msc, MSMON_MBWU_L, 0); + if (ret) + return ret; + + return __mpam_write_reg(msc, MSMON_MBWU_L + 4, 0); } =20 static void gen_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val, @@ -1221,24 +1226,28 @@ static void gen_msmon_ctl_flt_vals(struct mon_read = *m, u32 *ctl_val, } } =20 -static void read_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val, - u32 *flt_val) +static int read_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val, + u32 *flt_val) { struct mpam_msc *msc =3D m->ris->vmsc->msc; + int ret; =20 switch (m->type) { case mpam_feat_msmon_csu: - mpam_read_monsel_reg(msc, CFG_CSU_CTL, ctl_val); - mpam_read_monsel_reg(msc, CFG_CSU_FLT, flt_val); - break; + ret =3D mpam_read_monsel_reg(msc, CFG_CSU_CTL, ctl_val); + if (ret) + return ret; + return mpam_read_monsel_reg(msc, CFG_CSU_FLT, flt_val); case mpam_feat_msmon_mbwu_31counter: case mpam_feat_msmon_mbwu_44counter: case mpam_feat_msmon_mbwu_63counter: - mpam_read_monsel_reg(msc, CFG_MBWU_CTL, ctl_val); - mpam_read_monsel_reg(msc, CFG_MBWU_FLT, flt_val); - break; + ret =3D mpam_read_monsel_reg(msc, CFG_MBWU_CTL, ctl_val); + if (ret) + return ret; + return mpam_read_monsel_reg(msc, CFG_MBWU_FLT, flt_val); default: pr_warn("Unexpected monitor type %d\n", m->type); + return -EINVAL; } } =20 @@ -1251,10 +1260,11 @@ static inline void clean_msmon_ctl_val(u32 *cur_ctl) *cur_ctl &=3D ~MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L; } =20 -static void write_msmon_ctl_flt_vals(struct mon_read *m, u32 ctl_val, - u32 flt_val) +static int write_msmon_ctl_flt_vals(struct mon_read *m, u32 ctl_val, + u32 flt_val) { struct mpam_msc *msc =3D m->ris->vmsc->msc; + int ret; =20 /* * Write the ctl_val with the enable bit cleared, reset the counter, @@ -1262,25 +1272,37 @@ static void write_msmon_ctl_flt_vals(struct mon_rea= d *m, u32 ctl_val, */ switch (m->type) { case mpam_feat_msmon_csu: - mpam_write_monsel_reg(msc, CFG_CSU_FLT, flt_val); - mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val); - mpam_write_monsel_reg(msc, CSU, 0); - mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val | MSMON_CFG_x_CTL_EN); - break; + ret =3D mpam_write_monsel_reg(msc, CFG_CSU_FLT, flt_val); + if (ret) + return ret; + ret =3D mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val); + if (ret) + return ret; + ret =3D mpam_write_monsel_reg(msc, CSU, 0); + if (ret) + return ret; + return mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val | MSMON_CFG_x_CTL= _EN); case mpam_feat_msmon_mbwu_31counter: case mpam_feat_msmon_mbwu_44counter: case mpam_feat_msmon_mbwu_63counter: - mpam_write_monsel_reg(msc, CFG_MBWU_FLT, flt_val); - mpam_write_monsel_reg(msc, CFG_MBWU_CTL, ctl_val); - mpam_write_monsel_reg(msc, CFG_MBWU_CTL, ctl_val | MSMON_CFG_x_CTL_EN); + ret =3D mpam_write_monsel_reg(msc, CFG_MBWU_FLT, flt_val); + if (ret) + return ret; + ret =3D mpam_write_monsel_reg(msc, CFG_MBWU_CTL, ctl_val); + if (ret) + return ret; + ret =3D mpam_write_monsel_reg(msc, CFG_MBWU_CTL, + ctl_val | MSMON_CFG_x_CTL_EN); + if (ret) + return ret; /* Counting monitors require NRDY to be reset by software */ if (m->type =3D=3D mpam_feat_msmon_mbwu_31counter) - mpam_write_monsel_reg(msc, MBWU, 0); - else - mpam_msc_zero_mbwu_l(m->ris->vmsc->msc); - break; + return mpam_write_monsel_reg(msc, MBWU, 0); + + return mpam_msc_zero_mbwu_l(m->ris->vmsc->msc); default: pr_warn("Unexpected monitor type %d\n", m->type); + return -EINVAL; } } =20 --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 491A449F112; Thu, 24 Sep 2026 15:28:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263714; cv=none; b=Q3G7eyg1mV9dMl39UHY1sAIFCrf7llqYdaWYZJ6EWkOc3tAyX7u8PGvl8ZTdtXbdjiCrB+u6Ut1hQBPwE2bFoV7h+Ojbu7gzQ7sQ4tF/p6jYuhNB0LqgoXl43s1LSOZkrMaDN0t7aFJ3tNk1NNQhuXDPX22Gjx1HzleCH1koIL4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263714; c=relaxed/simple; bh=JUYW6rzzZKURsfUY87KV0xgd0hseR11dCrFozrEpdjk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bEJDPGPiBUBxiKi4fSX6cWiqZc6BcsWQoqOLjM2VZu3wWi2xBS/BZRnbXmwK0WHwU4Yj+ZPxnBbscp/haFJwCNJn1BeRYMs6wa3vINIZW6Cn/xJgThhWCpdo9dyCO6JF4Z3l/5g82BRSEKhNJfXP3wN4GueUgWecDm+azswuO9g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=P0bX/KuD; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="P0bX/KuD" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2877B1CC4; Thu, 24 Sep 2026 08:28:28 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id CF6BC3F86F; Thu, 24 Sep 2026 08:28:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263711; bh=JUYW6rzzZKURsfUY87KV0xgd0hseR11dCrFozrEpdjk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P0bX/KuDQ2quumQCta2J1vjQ+3dnzgbBwFQy0W1xApuP9BYS9W5QYc4ew6e1QvxWV Hnonv5EkF0TU9e41+L5yH1Slzu8tpyNLlzKXymBTxIuEcoEJ4MXbtAREcvcr+14VAJ dV9ytSuHj8UBSif9gcKjTijar0xre3OfD1ZFmPTU= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 05/13] arm_mpam: propagate MSC access errors for __ris_msmon_read() Date: Thu, 24 Sep 2026 17:27:31 +0200 Message-ID: <20260924152739.2865510-6-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow the function for RIS accesses to return an error, and propagate read and write errors from the lower level up. This function is a bit special, since it can be called via an SMP helper, so the prototype must stay as void. So propagate any errors using the "err" field in the struct passed in as the sole argument to that function. Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron Reviewed-by: Ben Horgan Reviewed-by: Gavin Shan Tested-by: Gavin Shan # on NVIDIA Grace Hopper --- drivers/resctrl/mpam_devices.c | 36 +++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index bfad65596f172..6a514cc9251ec 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -1332,6 +1332,10 @@ static u64 mpam_msmon_overflow_val(enum mpam_device_= features type, return overflow_val; } =20 +/* + * This function might be called via smp_call_function_any(), so propagate + * errors inside the arg struct. + */ static void __ris_msmon_read(void *arg) { u64 now; @@ -1355,7 +1359,9 @@ static void __ris_msmon_read(void *arg) =20 mon_sel =3D FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, ctx->mon) | FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); - mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); + m->err =3D mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); + if (m->err) + return; =20 switch (m->type) { case mpam_feat_msmon_mbwu_31counter: @@ -1375,7 +1381,9 @@ static void __ris_msmon_read(void *arg) * Read the existing configuration to avoid re-writing the same values. * This saves waiting for 'nrdy' on subsequent reads. */ - read_msmon_ctl_flt_vals(m, &cur_ctl, &cur_flt); + m->err =3D read_msmon_ctl_flt_vals(m, &cur_ctl, &cur_flt); + if (m->err) + return; =20 if (mpam_feat_msmon_mbwu_31counter =3D=3D m->type) overflow =3D cur_ctl & MSMON_CFG_x_CTL_OFLOW_STATUS; @@ -1389,18 +1397,24 @@ static void __ris_msmon_read(void *arg) cur_ctl !=3D (ctl_val | MSMON_CFG_x_CTL_EN); =20 if (config_mismatch || reset_on_next_read) { - write_msmon_ctl_flt_vals(m, ctl_val, flt_val); + m->err =3D write_msmon_ctl_flt_vals(m, ctl_val, flt_val); + if (m->err) + return; overflow =3D false; } else if (overflow) { - mpam_write_monsel_reg(msc, CFG_MBWU_CTL, - cur_ctl & - ~(MSMON_CFG_x_CTL_OFLOW_STATUS | - MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L)); + m->err =3D mpam_write_monsel_reg(msc, CFG_MBWU_CTL, + cur_ctl & + ~(MSMON_CFG_x_CTL_OFLOW_STATUS | + MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L)); + if (m->err) + return; } =20 switch (m->type) { case mpam_feat_msmon_csu: - mpam_read_monsel_reg(msc, CSU, &now32); + m->err =3D mpam_read_monsel_reg(msc, CSU, &now32); + if (m->err) + return; nrdy =3D now32 & MSMON___NRDY; now =3D FIELD_GET(MSMON___VALUE, now32); =20 @@ -1422,7 +1436,9 @@ static void __ris_msmon_read(void *arg) else now =3D FIELD_GET(MSMON___L_VALUE, now); } else { - mpam_read_monsel_reg(msc, MBWU, &now32); + m->err =3D mpam_read_monsel_reg(msc, MBWU, &now32); + if (m->err) + return; nrdy =3D now32 & MSMON___NRDY; now =3D FIELD_GET(MSMON___VALUE, now32); } @@ -1796,6 +1812,8 @@ static int mpam_restore_mbwu_state(void *_ris) mwbu_arg.val =3D &val; =20 __ris_msmon_read(&mwbu_arg); + if (mwbu_arg.err && mwbu_arg.err !=3D -EBUSY) + return mwbu_arg.err; } } =20 --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EA40547ACF1; Thu, 24 Sep 2026 15:28:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263720; cv=none; b=TlNckqi9/Ceyh1vPv+ItMmrKDR3LrMhhupfO7eEUGKRhAV0RexaMbCATTWa14GpSvK4N9Plq5Sz4EBdG0Ssz+trwNZ/UePmjErD7P8jMaEqTmwGXBSNqdet7kQWmjzHrLl5T8dOGfD9tA5WbjLe0dKYm6o0aamdZz9Xsb5lWZS4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263720; c=relaxed/simple; bh=FAUJ4f/N3Kj5dER0Hkup0QFcUrEJsrOUZNEavXsQOKI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mi2y9j1W/pzQQdegB7qcdIk4IWnSdsxubwzfKldas5+cpA2zNix6aCJYPydIrznB5L++PBO7AFDKVMZvnZXFoW1hxKyjDHRuBL1VyJqrFeC+ztMBELkFBHHjAcX7wtR4uWNiol5p2IcqEYhqhdB0lOaRBo/Gzbz588UdrRYDZZw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=R+oN1kvy; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="R+oN1kvy" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C18541CDD; Thu, 24 Sep 2026 08:28:34 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 25F3A3F86F; Thu, 24 Sep 2026 08:28:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263718; bh=FAUJ4f/N3Kj5dER0Hkup0QFcUrEJsrOUZNEavXsQOKI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=R+oN1kvyJXrnc2PEXkdylk9CcB39Ko+Kk8jrVC3WkApVU1XdCklST/YHXgB8mjefu 1/+7519da3bcstpai+UAj/9famqkPlyybAT3YZn7/hYCl0Y3nOP3kk1VuZPs08hdI8 82tbwvln8MIzjWT2U+sCSdynk1tiTe55AsZCoDys= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 06/13] arm_mpam: propagate MSC access errors for state saving function Date: Thu, 24 Sep 2026 17:27:32 +0200 Message-ID: <20260924152739.2865510-7-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow the mpam_save_mbwu_state() function to return an error, and propagate read and write errors from the lower level up. Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron Reviewed-by: Ben Horgan Reviewed-by: Gavin Shan Tested-by: Gavin Shan # on NVIDIA Grace Hopper --- drivers/resctrl/mpam_devices.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index 6a514cc9251ec..f1af249744d2e 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -1842,22 +1842,37 @@ static int mpam_save_mbwu_state(void *arg) =20 mon_sel =3D FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, i) | FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); - mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); - mpam_read_monsel_reg(msc, CFG_MBWU_FLT, &cur_flt); - mpam_read_monsel_reg(msc, CFG_MBWU_CTL, &cur_ctl); - mpam_write_monsel_reg(msc, CFG_MBWU_CTL, 0); + ret =3D mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); + if (ret) + return ret; + ret =3D mpam_read_monsel_reg(msc, CFG_MBWU_FLT, &cur_flt); + if (ret) + return ret; + ret =3D mpam_read_monsel_reg(msc, CFG_MBWU_CTL, &cur_ctl); + if (ret) + return ret; + ret =3D mpam_write_monsel_reg(msc, CFG_MBWU_CTL, 0); + if (ret) + return ret; =20 if (mpam_ris_has_mbwu_long_counter(ris)) { ret =3D mpam_msc_read_mbwu_l(msc, &val); if (ret) return ret; - mpam_msc_zero_mbwu_l(msc); + ret =3D mpam_msc_zero_mbwu_l(msc); + if (ret) + return ret; } else { u32 val32; =20 - mpam_read_monsel_reg(msc, MBWU, &val32); + ret =3D mpam_read_monsel_reg(msc, MBWU, &val32); + if (ret) + return ret; val =3D val32; - mpam_write_monsel_reg(msc, MBWU, 0); + + ret =3D mpam_write_monsel_reg(msc, MBWU, 0); + if (ret) + return ret; } =20 cfg->mon =3D i; --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 167A84A263D; Thu, 24 Sep 2026 15:28:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263728; cv=none; b=k3FnPsVjWGgFwaVWKEDMcS76e2MYpagbhLjk1WqXqnltwfORcyLm2zQ+KhWpIt8dVFoev9lbs5eX7eF00C7FL4ykuXNYhVkOVy0qs/Y1sDxD9OfOPr+S5WmnV1ZNVO63OE6LmD0IcwvO3Lw0qSKEiI03opmNjpZ1hPMMPugg4hc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263728; c=relaxed/simple; bh=SNngnAs6y+FNlv7mQoigcO7WVhTh+FzOVYZkavw0miQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WZIdPO5+EcVgwHVrkhKPmKOXDvnf35kawSnCSVh71aE3Ei72QCXOztrZnUOgDkoJov6PA1ndH27TK2hJFhDhqEmPPop0jKr32yJcC8hW0PiPDWm4qp50dGpTyyZjwy+CgeQFtjqVzs3/XUPwc7//e7Xpzg8stcQGB9DnY9PjjwM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=JR71d9+4; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="JR71d9+4" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C7F691CE2; Thu, 24 Sep 2026 08:28:42 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C36583F86F; Thu, 24 Sep 2026 08:28:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263726; bh=SNngnAs6y+FNlv7mQoigcO7WVhTh+FzOVYZkavw0miQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JR71d9+4/sWEf32WC1n3lalKXwLGRDLYZnVavwXgECW2DSe4TuZFCiWtEdBoQ3QWI 8qqIfuXX7lDt2GgG9MyzaYMMyJzRoDtz5syy0dCwNLAwBJONrvH5R5lWitabeW9J8u jwM3Sq700Q054k3N9oTCir2i5v5R1nvcgR80A7aI= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 07/13] arm_mpam: propagate MSC access errors for mpam_reprogram_ris_partid() Date: Thu, 24 Sep 2026 17:27:33 +0200 Message-ID: <20260924152739.2865510-8-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow the mpam_reprogram_ris_partid() function to check for and return errors, and propagate MSC read and write errors from the lower level up. This also covers the callers of this function: mpam_reset_ris() and apply_config(). Signed-off-by: Andre Przywara Reviewed-by: Ben Horgan Reviewed-by: Jonathan Cameron Reviewed-by: Gavin Shan Tested-by: Gavin Shan # on NVIDIA Grace Hopper Reviewed-by: Srivathsa L Rao --- drivers/resctrl/mpam_devices.c | 137 ++++++++++++++++++++++----------- 1 file changed, 94 insertions(+), 43 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index f1af249744d2e..558efab75f911 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -1599,7 +1599,7 @@ void mpam_msmon_reset_mbwu(struct mpam_component *com= p, struct mon_cfg *ctx) } } =20 -static void mpam_reset_msc_bitmap(struct mpam_msc *msc, u16 reg, u16 wd) +static int mpam_reset_msc_bitmap(struct mpam_msc *msc, u16 reg, u16 wd) { u32 num_words, msb; u32 bm =3D ~0; @@ -1608,15 +1608,20 @@ static void mpam_reset_msc_bitmap(struct mpam_msc *= msc, u16 reg, u16 wd) lockdep_assert_held(&msc->part_sel_lock); =20 if (wd =3D=3D 0) - return; + return 0; =20 /* * Write all ~0 to all but the last 32bit-word, which may * have fewer bits... */ num_words =3D DIV_ROUND_UP(wd, 32); - for (i =3D 0; i < num_words - 1; i++, reg +=3D sizeof(bm)) - __mpam_write_reg(msc, reg, bm); + for (i =3D 0; i < num_words - 1; i++, reg +=3D sizeof(bm)) { + int ret; + + ret =3D __mpam_write_reg(msc, reg, bm); + if (ret) + return ret; + } =20 /* * ....and then the last (maybe) partial 32bit word. When wd is a @@ -1624,7 +1629,7 @@ static void mpam_reset_msc_bitmap(struct mpam_msc *ms= c, u16 reg, u16 wd) */ msb =3D (wd - 1) % 32; bm =3D GENMASK(msb, 0); - __mpam_write_reg(msc, reg, bm); + return __mpam_write_reg(msc, reg, bm); } =20 static void mpam_apply_t241_erratum(struct mpam_msc_ris *ris, u16 partid) @@ -1697,40 +1702,59 @@ static u16 mpam_wa_t241_calc_min_from_max(struct mp= am_props *props, } =20 /* Called via IPI. Call while holding an SRCU reference */ -static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, - struct mpam_config *cfg) +static int mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, + struct mpam_config *cfg) { u16 cmax =3D MPAMCFG_CMAX_CMAX; struct mpam_msc *msc =3D ris->vmsc->msc; struct mpam_props *rprops =3D &ris->props; + int ret; =20 - mutex_lock(&msc->part_sel_lock); - __mpam_part_sel(ris->ris_idx, partid, msc); + guard(mutex)(&msc->part_sel_lock); + ret =3D __mpam_part_sel(ris->ris_idx, partid, msc); + if (ret) + return ret; =20 if (mpam_has_feature(mpam_feat_partid_nrw, rprops)) { /* Update the intpartid mapping */ - mpam_write_partsel_reg(msc, INTPARTID, - MPAMCFG_INTPARTID_INTERNAL | partid); + ret =3D mpam_write_partsel_reg(msc, INTPARTID, + MPAMCFG_INTPARTID_INTERNAL | partid); + if (ret) + return ret; =20 /* * Then switch to the 'internal' partid to update the * configuration. */ - __mpam_intpart_sel(ris->ris_idx, partid, msc); + ret =3D __mpam_intpart_sel(ris->ris_idx, partid, msc); + if (ret) + return ret; } =20 if (mpam_has_feature(mpam_feat_cpor_part, rprops)) { - if (mpam_has_feature(mpam_feat_cpor_part, cfg)) - mpam_write_partsel_reg(msc, CPBM, cfg->cpbm); - else - mpam_reset_msc_bitmap(msc, MPAMCFG_CPBM, rprops->cpbm_wd); + if (mpam_has_feature(mpam_feat_cpor_part, cfg)) { + ret =3D mpam_write_partsel_reg(msc, CPBM, cfg->cpbm); + if (ret) + return ret; + } else { + ret =3D mpam_reset_msc_bitmap(msc, MPAMCFG_CPBM, + rprops->cpbm_wd); + if (ret) + return ret; + } } =20 if (mpam_has_feature(mpam_feat_mbw_part, rprops)) { - if (mpam_has_feature(mpam_feat_mbw_part, cfg)) - mpam_write_partsel_reg(msc, MBW_PBM, cfg->mbw_pbm); - else - mpam_reset_msc_bitmap(msc, MPAMCFG_MBW_PBM, rprops->mbw_pbm_bits); + if (mpam_has_feature(mpam_feat_mbw_part, cfg)) { + ret =3D mpam_write_partsel_reg(msc, MBW_PBM, cfg->mbw_pbm); + if (ret) + return ret; + } else { + ret =3D mpam_reset_msc_bitmap(msc, MPAMCFG_MBW_PBM, + rprops->mbw_pbm_bits); + if (ret) + return ret; + } } =20 if (mpam_has_feature(mpam_feat_mbw_min, rprops)) { @@ -1743,27 +1767,47 @@ static void mpam_reprogram_ris_partid(struct mpam_m= sc_ris *ris, u16 partid, val =3D max(val, min); } =20 - mpam_write_partsel_reg(msc, MBW_MIN, val); + ret =3D mpam_write_partsel_reg(msc, MBW_MIN, val); + if (ret) + return ret; } =20 if (mpam_has_feature(mpam_feat_mbw_max, rprops)) { - if (mpam_has_feature(mpam_feat_mbw_max, cfg)) - mpam_write_partsel_reg(msc, MBW_MAX, cfg->mbw_max); - else - mpam_write_partsel_reg(msc, MBW_MAX, MPAMCFG_MBW_MAX_MAX); + if (mpam_has_feature(mpam_feat_mbw_max, cfg)) { + ret =3D mpam_write_partsel_reg(msc, MBW_MAX, cfg->mbw_max); + if (ret) + return ret; + } else { + ret =3D mpam_write_partsel_reg(msc, MBW_MAX, + MPAMCFG_MBW_MAX_MAX); + if (ret) + return ret; + } } =20 - if (mpam_has_feature(mpam_feat_mbw_prop, rprops)) - mpam_write_partsel_reg(msc, MBW_PROP, 0); + if (mpam_has_feature(mpam_feat_mbw_prop, rprops)) { + ret =3D mpam_write_partsel_reg(msc, MBW_PROP, 0); + if (ret) + return ret; + } =20 - if (mpam_has_feature(mpam_feat_cmax_cmax, rprops)) - mpam_write_partsel_reg(msc, CMAX, cmax); + if (mpam_has_feature(mpam_feat_cmax_cmax, rprops)) { + ret =3D mpam_write_partsel_reg(msc, CMAX, cmax); + if (ret) + return ret; + } =20 - if (mpam_has_feature(mpam_feat_cmax_cmin, rprops)) - mpam_write_partsel_reg(msc, CMIN, 0); + if (mpam_has_feature(mpam_feat_cmax_cmin, rprops)) { + ret =3D mpam_write_partsel_reg(msc, CMIN, 0); + if (ret) + return ret; + } =20 - if (mpam_has_feature(mpam_feat_cmax_cassoc, rprops)) - mpam_write_partsel_reg(msc, CASSOC, MPAMCFG_CASSOC_CASSOC); + if (mpam_has_feature(mpam_feat_cmax_cassoc, rprops)) { + ret =3D mpam_write_partsel_reg(msc, CASSOC, MPAMCFG_CASSOC_CASSOC); + if (ret) + return ret; + } =20 if (mpam_has_feature(mpam_feat_intpri_part, rprops) || mpam_has_feature(mpam_feat_dspri_part, rprops)) { @@ -1787,12 +1831,14 @@ static void mpam_reprogram_ris_partid(struct mpam_m= sc_ris *ris, u16 partid, pri_val |=3D FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri); } =20 - mpam_write_partsel_reg(msc, PRI, pri_val); + ret =3D mpam_write_partsel_reg(msc, PRI, pri_val); + if (ret) + return ret; } =20 mpam_quirk_post_config_change(ris, partid, cfg); =20 - mutex_unlock(&msc->part_sel_lock); + return 0; } =20 /* Call with msc cfg_lock held */ @@ -1895,6 +1941,7 @@ static int mpam_reset_ris(void *arg) u16 partid, partid_max; struct mpam_config reset_cfg =3D {}; struct mpam_msc_ris *ris =3D arg; + int ret; =20 if (ris->in_reset_state) return 0; @@ -1902,8 +1949,11 @@ static int mpam_reset_ris(void *arg) spin_lock(&partid_max_lock); partid_max =3D mpam_partid_max; spin_unlock(&partid_max_lock); - for (partid =3D 0; partid <=3D partid_max; partid++) - mpam_reprogram_ris_partid(ris, partid, &reset_cfg); + for (partid =3D 0; partid <=3D partid_max; partid++) { + ret =3D mpam_reprogram_ris_partid(ris, partid, &reset_cfg); + if (ret) + return ret; + } =20 return 0; } @@ -1942,9 +1992,8 @@ static int __write_config(void *arg) { struct mpam_write_config_arg *c =3D arg; =20 - mpam_reprogram_ris_partid(c->ris, c->partid, &c->comp->cfg[c->partid]); - - return 0; + return mpam_reprogram_ris_partid(c->ris, c->partid, + &c->comp->cfg[c->partid]); } =20 static void mpam_reprogram_msc(struct mpam_msc *msc) @@ -3098,6 +3147,7 @@ int mpam_apply_config(struct mpam_component *comp, u1= 6 partid, struct mpam_msc_ris *ris; struct mpam_vmsc *vmsc; struct mpam_msc *msc; + int ret; =20 lockdep_assert_cpus_held(); =20 @@ -3115,14 +3165,15 @@ int mpam_apply_config(struct mpam_component *comp, = u16 partid, srcu_read_lock_held(&mpam_srcu)) { msc =3D vmsc->msc; =20 - mutex_lock(&msc->cfg_lock); + guard(mutex)(&msc->cfg_lock); list_for_each_entry_srcu(ris, &vmsc->ris, vmsc_list, srcu_read_lock_held(&mpam_srcu)) { arg.ris =3D ris; - mpam_touch_msc(msc, __write_config, &arg); + ret =3D mpam_touch_msc(msc, __write_config, &arg); + if (ret) + return ret; ris->in_reset_state =3D false; } - mutex_unlock(&msc->cfg_lock); } =20 return 0; --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E43504A13AF; Thu, 24 Sep 2026 15:28:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263736; cv=none; b=qxkBH0wyV7O7qu0t23hvq+f44O3HfnPJk8J8rQbYmMCNfFy9YC0riM+041kG/OgCAOCioGqfE5YxqePKTbjZopUOeB5JnXYG4crjfvzzIYI7uVXeMWxAyKhG1JohhSDtYs4BEZi2dPqcp5NBJBjnmG0TxGJJKtvemg93AaUBA/E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263736; c=relaxed/simple; bh=tV3gLmdj46JrcPvGnrYdoLxgsZp2pmyHv+oxJsoBQ+8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ury0AwzkN0/G1ZFKzu96uQK4yp3hOpGrMubIq/M5yrLcpIWGpc+CGRhDUVLb+wXITpmmngS6mISXpmmwmg9I1dxqUMTiopqfnKrjojhs0aKklNJSMBkOEL+g21cvqLg1L/PSyFParpFdho0zc13aIKP2SrH+rGdbIveQ5hRszQg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=cDOS9g46; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="cDOS9g46" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A599A1D14; Thu, 24 Sep 2026 08:28:50 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 453173FAB1; Thu, 24 Sep 2026 08:28:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263734; bh=tV3gLmdj46JrcPvGnrYdoLxgsZp2pmyHv+oxJsoBQ+8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cDOS9g46BRU8apeGek0JhfberlQKhWqYvaFTZwJeasB7aACnRBbRDvKfLnRdacIvS FZCRZKDsHwE5e40pup3CBzUaqYqlrrPQShmUnnaWheX324e/iO5yeE9IMlOuSKfoDL fxoRfVgHvKCjSBWJe/7CXh57QsGh0ZoaC41r9kdM= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 08/13] arm_mpam: propagate MSC access errors for interrupt control Date: Thu, 24 Sep 2026 17:27:34 +0200 Message-ID: <20260924152739.2865510-9-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow the functions dealing with interrupt registration and enablement to check for and return errors, and propagate MSC read and write errors from the lower level up. This does not cover the IRQ handler yet, as this needs some more attention. Signed-off-by: Andre Przywara Reviewed-by: Srivathsa L Rao Reviewed-by: Jonathan Cameron --- drivers/resctrl/mpam_devices.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index 558efab75f911..eb26c25b9f970 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -1105,7 +1105,9 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) } =20 /* Clear any stale errors */ - mpam_msc_clear_esr(msc); + ret =3D mpam_msc_clear_esr(msc); + if (ret) + return ret; =20 spin_lock(&partid_max_lock); mpam_partid_max =3D min(mpam_partid_max, msc->partid_max); @@ -2668,9 +2670,7 @@ static int mpam_enable_msc_ecr(void *_msc) { struct mpam_msc *msc =3D _msc; =20 - __mpam_write_reg(msc, MPAMF_ECR, MPAMF_ECR_INTEN); - - return 0; + return __mpam_write_reg(msc, MPAMF_ECR, MPAMF_ECR_INTEN); } =20 /* This can run in mpam_disable(), and the interrupt handler on the same C= PU */ @@ -2678,9 +2678,7 @@ static int mpam_disable_msc_ecr(void *_msc) { struct mpam_msc *msc =3D _msc; =20 - __mpam_write_reg(msc, MPAMF_ECR, 0); - - return 0; + return __mpam_write_reg(msc, MPAMF_ECR, 0); } =20 static irqreturn_t __mpam_irq_handler(int irq, struct mpam_msc *msc) @@ -2777,11 +2775,13 @@ static int mpam_register_irqs(void) return err; } =20 - mutex_lock(&msc->error_irq_lock); - msc->error_irq_req =3D true; - mpam_touch_msc(msc, mpam_enable_msc_ecr, msc); - msc->error_irq_hw_enabled =3D true; - mutex_unlock(&msc->error_irq_lock); + scoped_guard(mutex, &msc->error_irq_lock) { + msc->error_irq_req =3D true; + err =3D mpam_touch_msc(msc, mpam_enable_msc_ecr, msc); + if (err) + return err; + msc->error_irq_hw_enabled =3D true; + } } =20 return 0; @@ -2800,10 +2800,10 @@ static void mpam_unregister_irqs(void) if (irq <=3D 0) continue; =20 - mutex_lock(&msc->error_irq_lock); + guard(mutex)(&msc->error_irq_lock); if (msc->error_irq_hw_enabled) { - mpam_touch_msc(msc, mpam_disable_msc_ecr, msc); - msc->error_irq_hw_enabled =3D false; + if (!mpam_touch_msc(msc, mpam_disable_msc_ecr, msc)) + msc->error_irq_hw_enabled =3D false; } =20 if (msc->error_irq_req) { @@ -2815,7 +2815,6 @@ static void mpam_unregister_irqs(void) } msc->error_irq_req =3D false; } - mutex_unlock(&msc->error_irq_lock); } } =20 --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D049649E5C2; Thu, 24 Sep 2026 15:29:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263744; cv=none; b=p2op7ZV90w9jXz7boRj70/3uAmMsNaCQsSpJlQGpJH/6CRjugXPpEKqabIF/XGf5MdWUTUfZAqyM2zAL3EVV/SVHK+2svpBmXfSFcteUgIzqtPh9pVUZFvirt3Yb+JBdAGbtXr2C+ibJGroa9TXMWY1CwaqJLUMmLxNMvKIpvo4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263744; c=relaxed/simple; bh=ednoOePGVW1sykn3VGIVtNz9LP2Jute7Y1pUUhwMwWA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Nya/V4fjK0jYIGUN07aLq3DhKegtaaouls0mCZuWkBUwNF8CVCl3+Fj8qbmM02FOKsTEcsxXSYbbX/5o3pXUeDZWnreJB4+YYeegRZ3lnv5g7e25/sxcS5sIO+YkVU7QzFDCFJ0SmidTdQWDCr4khdhTNrv3r+7fAdZ517W9g4E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=WWcfxLP5; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="WWcfxLP5" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 927311D6F; Thu, 24 Sep 2026 08:28:58 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A5BB33F86F; Thu, 24 Sep 2026 08:28:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263742; bh=ednoOePGVW1sykn3VGIVtNz9LP2Jute7Y1pUUhwMwWA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WWcfxLP5NuofZdrVkv4ILVBZg8S9mc2XZE5NyvZYhLfRnUsjY5cNWg8rjINAS+xn3 vAlsZfusC0wjQ98GFF2/0oXMqPnNsr4w+Qt5LbzNQ/ltRVucVpljPeCawWLbt5LoEh LW2VY0QF4Y+XSX4PA1BmyyKbJCpzCqf7zX2usDl8= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 09/13] arm_mpam: propagate MSC access errors in mpam_reset_class_locked() Date: Thu, 24 Sep 2026 17:27:35 +0200 Message-ID: <20260924152739.2865510-10-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The mpam_reset_ris() function can return an error, propagate this up through mpam_reset_component_locked() to mpam_reset_class_locked(), which is exported. The external caller is a void function, so cannot really handle the error at the moment, but at least we report everything on the MPAM interface side. Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron --- drivers/resctrl/mpam_devices.c | 24 ++++++++++++++++++------ drivers/resctrl/mpam_internal.h | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index eb26c25b9f970..6d1fda949a05c 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -2994,7 +2994,7 @@ static void mpam_enable_once(void) mpam_partid_max + 1, mpam_pmg_max + 1); } =20 -static void mpam_reset_component_locked(struct mpam_component *comp) +static int mpam_reset_component_locked(struct mpam_component *comp) { struct mpam_vmsc *vmsc; =20 @@ -3008,26 +3008,38 @@ static void mpam_reset_component_locked(struct mpam= _component *comp) srcu_read_lock_held(&mpam_srcu)) { struct mpam_msc *msc =3D vmsc->msc; struct mpam_msc_ris *ris; + int ret; =20 list_for_each_entry_srcu(ris, &vmsc->ris, vmsc_list, srcu_read_lock_held(&mpam_srcu)) { - if (!ris->in_reset_state) - mpam_touch_msc(msc, mpam_reset_ris, ris); + if (!ris->in_reset_state) { + ret =3D mpam_touch_msc(msc, mpam_reset_ris, ris); + if (ret) + return ret; + } ris->in_reset_state =3D true; } } + + return 0; } =20 -void mpam_reset_class_locked(struct mpam_class *class) +int mpam_reset_class_locked(struct mpam_class *class) { struct mpam_component *comp; + int ret; =20 lockdep_assert_cpus_held(); =20 guard(srcu)(&mpam_srcu); list_for_each_entry_srcu(comp, &class->components, class_list, - srcu_read_lock_held(&mpam_srcu)) - mpam_reset_component_locked(comp); + srcu_read_lock_held(&mpam_srcu)) { + ret =3D mpam_reset_component_locked(comp); + if (ret) + return ret; + } + + return 0; } =20 static void mpam_reset_class(struct mpam_class *class) diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_interna= l.h index 68a6cf2b9cc73..09f8168fb4d2c 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -465,7 +465,7 @@ void mpam_enable(struct work_struct *work); void mpam_disable(struct work_struct *work); =20 /* Reset all the RIS in a class under cpus_read_lock() */ -void mpam_reset_class_locked(struct mpam_class *class); +int mpam_reset_class_locked(struct mpam_class *class); =20 int mpam_apply_config(struct mpam_component *comp, u16 partid, struct mpam_config *cfg); --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 192BE4A3D34; Thu, 24 Sep 2026 15:29:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263752; cv=none; b=C8n0S8YLrqcWJWoE9lyvFpLRw1IAAz97BBK7Mgko/V9vDp0hjSyJjHiqGhrwA8fzCBNrmGUYaSoCHNzWYXo3arLvFuT5/wmbTqz2AibP0ogW45K7sMecScR505mWFTfrpcSM395P4JVMqBM6rBRv8XSw+P36YBQDS9ff+Zye5PA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263752; c=relaxed/simple; bh=UHaREaYb2N0OpH2PuUS7Js7AaasyKmsX2ZOw8YFBCrg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t0IaSThf9ftW4L/xQIs207Q2ILhVRi3vPeAFna/+x69bkqherHWnVuNPRY4m/BkHsfdPB08vaNP7GuGnaKydutPLbkfwAz/pME5HYWyOoL74VSmASfjisBnJOAe426XP9pMHLXRCYTfxY734OIGxeKe50NlG7zBPSvyZj6iV4q8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=Hg7uYlHI; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="Hg7uYlHI" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8CFE41D70; Thu, 24 Sep 2026 08:29:05 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 984883F86F; Thu, 24 Sep 2026 08:29:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263748; bh=UHaREaYb2N0OpH2PuUS7Js7AaasyKmsX2ZOw8YFBCrg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Hg7uYlHI+a6ANdyP1oZ2HG4A0Ur3RCfNWeuxWrOcT8WjbL6EpzHZIRUT35wwpxuoz Le3ioB1r5DiLRKgsRA6uYpnSIzaE00PJ9Ru3N8MTxrS2km97fMY+Fu2UCXXfzcphV0 wzWoEcRHq2BZIhkUXuvJpyHqXhF8/J3pIcx57fLE= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 10/13] arm_mpam: prepare mon_sel locking for MPAM-Fb Date: Thu, 24 Sep 2026 17:27:36 +0200 Message-ID: <20260924152739.2865510-11-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The MSC MON_SEL register needs to be accessed from hardirq for the overflow interrupt, and when taking an IPI to access these registers on platforms where MSCs are not accesible from every CPU. This makes an irqsave spinlock the obvious lock to protect these registers. On systems with MPAM-Fb mailbox MSC access it must be able to sleep, meaning a mutex must be used. So MPAM-Fb platforms cannot support an overflow interrupt easily. Clearly these two methods can't exist for one MSC at the same time. Change the mon_sel locking wrapper function to only use a spinlock when the MSC is accessed directly via MMIO. In case of MPAM-Fb, we use a mutex, but only if we are in a sleepable context. If that's not the case, we return an error. This should not happen, as MPAM-Fb by design does not require an MSC access to happen from a specific CPU, so there is no need for any IPIs or preemption disabling to satisfy CPU constraints. And since overflow interrupts are not supported at the moment anyway, we also wouldn't meet the other case. Bailing out early is already happening in rare occasions today. Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron Reviewed-by: Ben Horgan Reviewed-by: Gavin Shan Tested-by: Gavin Shan # on NVIDIA Grace Hopper --- drivers/resctrl/mpam_devices.c | 6 ++++- drivers/resctrl/mpam_internal.h | 43 +++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index 6d1fda949a05c..4c548ec1bd7be 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -2288,7 +2288,6 @@ static struct mpam_msc *do_mpam_msc_drv_probe(struct = platform_device *pdev) if (err) return ERR_PTR(err); =20 - mpam_mon_sel_lock_init(msc); msc->id =3D pdev->id; msc->pdev =3D pdev; INIT_LIST_HEAD_RCU(&msc->all_msc_list); @@ -2309,6 +2308,11 @@ static struct mpam_msc *do_mpam_msc_drv_probe(struct= platform_device *pdev) else msc->iface =3D MPAM_IFACE_PCC; =20 + /* Lock type depends on MSC interface used */ + err =3D mpam_mon_sel_lock_init(dev, msc); + if (err) + return ERR_PTR(err); + if (msc->iface =3D=3D MPAM_IFACE_MMIO) { void __iomem *io; =20 diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_interna= l.h index 09f8168fb4d2c..58f7523bc087b 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -126,6 +126,12 @@ struct mpam_msc { */ raw_spinlock_t _mon_sel_lock; unsigned long _mon_sel_flags; + /* + * mon_sel_mutex is the mutex version of the _mon_sel_lock above. + * Always use the mpam_mon_sel_lock() helpers when taking the lock, + * as this will select the correct lock type automatically. + */ + struct mutex mon_sel_mutex; =20 void __iomem *mapped_hwpage; size_t mapped_hwpage_sz; @@ -139,27 +145,50 @@ struct mpam_msc { /* Returning false here means accesses to mon_sel must fail and report an = error. */ static inline bool __must_check mpam_mon_sel_lock(struct mpam_msc *msc) { - /* Locking will require updating to support a firmware backed interface */ - if (WARN_ON_ONCE(msc->iface !=3D MPAM_IFACE_MMIO)) + if (msc->iface =3D=3D MPAM_IFACE_MMIO) { + raw_spin_lock_irqsave(&msc->_mon_sel_lock, msc->_mon_sel_flags); + + return true; + } + + if (!preemptible()) return false; =20 - raw_spin_lock_irqsave(&msc->_mon_sel_lock, msc->_mon_sel_flags); + mutex_lock(&msc->mon_sel_mutex); + return true; } =20 static inline void mpam_mon_sel_unlock(struct mpam_msc *msc) { - raw_spin_unlock_irqrestore(&msc->_mon_sel_lock, msc->_mon_sel_flags); + if (msc->iface =3D=3D MPAM_IFACE_MMIO) { + raw_spin_unlock_irqrestore(&msc->_mon_sel_lock, + msc->_mon_sel_flags); + + return; + } + + mutex_unlock(&msc->mon_sel_mutex); } =20 static inline void mpam_mon_sel_lock_held(struct mpam_msc *msc) { - lockdep_assert_held_once(&msc->_mon_sel_lock); + if (msc->iface =3D=3D MPAM_IFACE_MMIO) + lockdep_assert_held_once(&msc->_mon_sel_lock); + else + lockdep_assert_held_once(&msc->mon_sel_mutex); } =20 -static inline void mpam_mon_sel_lock_init(struct mpam_msc *msc) +static inline int mpam_mon_sel_lock_init(struct device *dev, + struct mpam_msc *msc) { - raw_spin_lock_init(&msc->_mon_sel_lock); + if (msc->iface =3D=3D MPAM_IFACE_MMIO) { + raw_spin_lock_init(&msc->_mon_sel_lock); + + return 0; + } + + return devm_mutex_init(dev, &msc->mon_sel_mutex); } =20 DEFINE_GUARD(mon_sel, struct mpam_msc *, --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 294834A2A64; Thu, 24 Sep 2026 15:29:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263761; cv=none; b=f+bhJM+4b7DZfA6HXCoAlv5BmmezrOZ16pPHZtX89K40O8LkD/tIFYKLebrB1YNyeC+mctqo2qfy0JH+TQaDBJaLarzykHyjQxGzUUg4h+3yhTqU9+pjjFPgfUunYv1K8EXHGSU0dLqf2NSEze+RZRXrjOVQF62LJR/iREJHq8U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263761; c=relaxed/simple; bh=SP4g3pJyVIp8FPmSVPefsBF0KbrKlUNBm84iksgHW3o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Kcm6SwbdqClXtuSKG/8V1JDbiaBYQVNijgc0S0lxlQ8D/TM4ruoXvwd6ZQfF8vW+wWbPONOcuvnmTlzZQcg/kvp4AshH8N0vtdbFWcuhAhL5sF1EUuqq6C2cA+6DMAXPpvN6j++3X5mVSj74ZPpAiFyDkByA1DuoECDPSN2zQvY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=s4OU1GwG; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="s4OU1GwG" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id EF30A1DB5; Thu, 24 Sep 2026 08:29:14 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7239F3F86F; Thu, 24 Sep 2026 08:29:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263758; bh=SP4g3pJyVIp8FPmSVPefsBF0KbrKlUNBm84iksgHW3o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=s4OU1GwGNS0oZFNyPVtKxp1FMkdGvsuXyb0c1AbYpBSI9NlZHogDXtQZVHOpMc5pK hBOCg952VCQR4q9gvAjzrebDetXCf8LOImr3V6FEns8JkjtytbKRRPCUGchv71/Hdb olGDN/5pGQ9dx4CMtJtXuab2DqeVFEgiLq6OJTMY= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 11/13] arm_mpam: add MPAM-Fb MSC firmware access support Date: Thu, 24 Sep 2026 17:27:37 +0200 Message-ID: <20260924152739.2865510-12-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The Arm MPAM Firmware-backed (Fb) Profile document[1] describes an alternative way of accessing the "Memory System Components" (MSC) in an MPAM enabled system. Normally the MSCs are MMIO mapped, but in some implementations this might not be possible (MSC located outside of the local socket, MSC mapped secure-only) or desirable (direct MMIO access too slow or needs to be mediated through a control processor). MPAM-fb standardises a protocol to abstract MSC accesses, building on the SCMI protocol. Add functions that do an MSC read or write access by redirecting the request through a firmware interface. For now this done via an ACPI PCC shared memory and mailbox combination. Since the protocol used is only a small subset of the full SCMI spec, and the SCMI protocol has no full ACPI support anyway, open-code the (simple) SCMI message generation, for just the fields we need. [1] https://developer.arm.com/documentation/den0144/latest Signed-off-by: Andre Przywara Reviewed-by: Jonathan Cameron Tested-by: Ritwick Sharma # on Arm AGI CPU Reviewed-by: Gavin Shan Reviewed-by: Srivathsa L Rao --- drivers/acpi/arm64/mpam.c | 6 +- drivers/resctrl/Kconfig | 1 + drivers/resctrl/Makefile | 2 +- drivers/resctrl/mpam_devices.c | 65 ++++++++-- drivers/resctrl/mpam_fb.c | 212 ++++++++++++++++++++++++++++++++ drivers/resctrl/mpam_internal.h | 19 +++ include/linux/arm_mpam.h | 2 +- 7 files changed, 291 insertions(+), 16 deletions(-) create mode 100644 drivers/resctrl/mpam_fb.c diff --git a/drivers/acpi/arm64/mpam.c b/drivers/acpi/arm64/mpam.c index 84963a20c3e78..c57bd367922b7 100644 --- a/drivers/acpi/arm64/mpam.c +++ b/drivers/acpi/arm64/mpam.c @@ -220,8 +220,8 @@ static struct platform_device * __init acpi_mpam_parse_= msc(struct acpi_mpam_msc_ struct platform_device *pdev __free(platform_device_put) =3D platform_device_alloc("mpam_msc", tbl_msc->identifier); int next_res =3D 0, next_prop =3D 0, err; - /* pcc, nrdy, affinity and a sentinel */ - struct property_entry props[4] =3D { 0 }; + /* pcc, msc-id, nrdy, affinity and a sentinel */ + struct property_entry props[5] =3D { 0 }; /* mmio, 2xirq, no sentinel. */ struct resource res[3] =3D { 0 }; struct acpi_device *companion; @@ -256,6 +256,8 @@ static struct platform_device * __init acpi_mpam_parse_= msc(struct acpi_mpam_msc_ } else if (iface =3D=3D MPAM_IFACE_PCC) { props[next_prop++] =3D PROPERTY_ENTRY_U32("pcc-channel", tbl_msc->base_address); + props[next_prop++] =3D PROPERTY_ENTRY_U32("mpam-fb-msc-id", + tbl_msc->identifier); } =20 acpi_mpam_parse_irqs(pdev, tbl_msc, res, &next_res); diff --git a/drivers/resctrl/Kconfig b/drivers/resctrl/Kconfig index 672abea3b03cc..9591d792736e5 100644 --- a/drivers/resctrl/Kconfig +++ b/drivers/resctrl/Kconfig @@ -2,6 +2,7 @@ menuconfig ARM64_MPAM_DRIVER bool "MPAM driver" depends on ARM64 && ARM64_MPAM select ACPI_MPAM if ACPI + select MAILBOX help Memory System Resource Partitioning and Monitoring (MPAM) driver for System IP, e.g. caches and memory controllers. diff --git a/drivers/resctrl/Makefile b/drivers/resctrl/Makefile index 4f6d0e81f9b8f..097c036724e97 100644 --- a/drivers/resctrl/Makefile +++ b/drivers/resctrl/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_ARM64_MPAM_DRIVER) +=3D mpam.o -mpam-y +=3D mpam_devices.o +mpam-y +=3D mpam_devices.o mpam_fb.o mpam-$(CONFIG_ARM64_MPAM_RESCTRL_FS) +=3D mpam_resctrl.o =20 ccflags-$(CONFIG_ARM64_MPAM_DRIVER_DEBUG) +=3D -DDEBUG diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index 4c548ec1bd7be..90161696aada0 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,21 @@ static DECLARE_WORK(mpam_broken_work, &mpam_disable); =20 /* When mpam is disabled, the printed reason to aid debugging */ static char *mpam_disable_reason; +static int mpam_disable_errno; +static int mpam_disable_mpam_fb_err; + +void mpam_fb_disable_mpam(int err, int mpam_fb_err) +{ + /* Prevent repeated calls when mpam_disable() does MSC accesses. */ + if (!mpam_is_enabled()) + return; + + mpam_disable_errno =3D err; + mpam_disable_mpam_fb_err =3D mpam_fb_err; + + mpam_disable_reason =3D "MPAM-Fb error"; + schedule_work(&mpam_broken_work); +} =20 /* * Whether resctrl has been setup. Used by cpuhp in preference to @@ -179,8 +195,11 @@ static void mpam_assert_partid_sizes_fixed(void) =20 static int __mpam_read_reg(struct mpam_msc *msc, u16 reg, u32 *res) { - WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); =20 + if (msc->iface =3D=3D MPAM_IFACE_PCC) + return mpam_fb_send_read_request(msc, reg, res); + + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); *res =3D readl_relaxed(msc->mapped_hwpage + reg); =20 return 0; @@ -197,9 +216,12 @@ static inline int _mpam_read_partsel_reg(struct mpam_m= sc *msc, u16 reg, =20 static int __mpam_write_reg(struct mpam_msc *msc, u16 reg, u32 val) { - WARN_ON_ONCE(reg + sizeof(u32) > msc->mapped_hwpage_sz); - WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); =20 + if (msc->iface =3D=3D MPAM_IFACE_PCC) + return mpam_fb_send_write_request(msc, reg, val); + + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); + WARN_ON_ONCE(reg + sizeof(u32) > msc->mapped_hwpage_sz); writel_relaxed(val, msc->mapped_hwpage + reg); =20 return 0; @@ -1143,8 +1165,11 @@ static int mpam_msc_read_mbwu_l(struct mpam_msc *msc= , u64 *res) =20 mpam_mon_sel_lock_held(msc); =20 - WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); - WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); + if (msc->iface =3D=3D MPAM_IFACE_MMIO) { + WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), + &msc->accessibility)); + } =20 ret =3D __mpam_read_reg(msc, MSMON_MBWU_L + 4, &mbwu_l_high2); if (ret) @@ -1178,8 +1203,11 @@ static int mpam_msc_zero_mbwu_l(struct mpam_msc *msc) =20 mpam_mon_sel_lock_held(msc); =20 - WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); - WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); + if (msc->iface =3D=3D MPAM_IFACE_MMIO) { + WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), + &msc->accessibility)); + } =20 ret =3D __mpam_write_reg(msc, MSMON_MBWU_L, 0); if (ret) @@ -1490,11 +1518,16 @@ static int _msmon_read(struct mpam_component *comp,= struct mon_read *arg) srcu_read_lock_held(&mpam_srcu)) { arg->ris =3D ris; =20 - err =3D smp_call_function_any(&msc->accessibility, - __ris_msmon_read, arg, - true); - if (!err && arg->err) + if (msc->iface =3D=3D MPAM_IFACE_MMIO) { + err =3D smp_call_function_any(&msc->accessibility, + __ris_msmon_read, + arg, true); + if (!err) + err =3D arg->err; + } else { + __ris_msmon_read(arg); err =3D arg->err; + } =20 /* * Save one error to be returned to the caller, but @@ -1977,6 +2010,9 @@ static int mpam_get_msc_preferred_cpu(struct mpam_msc= *msc) =20 static int mpam_touch_msc(struct mpam_msc *msc, int (*fn)(void *a), void *= arg) { + if (msc->iface !=3D MPAM_IFACE_MMIO) + return fn(arg); + lockdep_assert_irqs_enabled(); lockdep_assert_cpus_held(); WARN_ON_ONCE(!srcu_read_lock_held((&mpam_srcu))); @@ -3102,7 +3138,12 @@ void mpam_disable(struct work_struct *ignored) mutex_unlock(&mpam_list_lock); mpam_free_garbage(); =20 - pr_err_once("MPAM disabled due to %s\n", mpam_disable_reason); + if (mpam_disable_errno || mpam_disable_mpam_fb_err) + pr_err_once("MPAM disabled due to %s: %s, MPAM-Fb error %d\n", + mpam_disable_reason, errname(mpam_disable_errno), + mpam_disable_mpam_fb_err); + else + pr_err_once("MPAM disabled due to %s\n", mpam_disable_reason); } =20 /* diff --git a/drivers/resctrl/mpam_fb.c b/drivers/resctrl/mpam_fb.c new file mode 100644 index 0000000000000..8298fcedd2be7 --- /dev/null +++ b/drivers/resctrl/mpam_fb.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2024-2026 Arm Ltd. + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mpam_internal.h" + +#define MPAM_MSC_TOKEN_MASK GENMASK_U32(27, 18) +#define MPAM_MSC_PROT_ID_MASK GENMASK_U32(17, 10) + +#define MPAM_FB_PROTOCOL_ID 0x1a + +#define MPAM_PROTOCOL_VERSION_CMD 0x0 +#define MPAM_MSC_READ_CMD 0x4 +#define MPAM_MSC_WRITE_CMD 0x5 + +#define MPAM_FB_PROT_HEADER_LEN sizeof(u32) + +#define MPAM_FB_SUCCESS 0 +#define MPAM_FB_ERR_NOT_SUPPORTED -1 +#define MPAM_FB_ERR_INVALID_PARAMETERS -2 +#define MPAM_FB_ERR_DENIED -3 +#define MPAM_FB_ERR_NOT_FOUND -4 +#define MPAM_FB_ERR_OUT_OF_RANGE -5 +#define MPAM_FB_ERR_BUSY -6 +#define MPAM_FB_ERR_COMMS_ERROR -7 +#define MPAM_FB_ERR_GENERIC_ERROR -8 +#define MPAM_FB_ERR_HW_ERROR -9 +#define MPAM_FB_ERR_PROTOCOL_ERROR -10 +#define MPAM_FB_ERR_IN_USE -11 + +static atomic_t mpam_fb_token =3D ATOMIC_INIT(0); + +static int mpam_fb_to_linux_errno(int mpam_fb_code) +{ + switch (mpam_fb_code) { + case MPAM_FB_ERR_NOT_SUPPORTED: + return -EOPNOTSUPP; + case MPAM_FB_ERR_INVALID_PARAMETERS: + return -EINVAL; + case MPAM_FB_ERR_NOT_FOUND: + return -ENOENT; + case MPAM_FB_ERR_OUT_OF_RANGE: + return -ERANGE; + case MPAM_FB_ERR_BUSY: + return -EBUSY; + default: + return -EINVAL; + } +} + +static void mpam_fb_build_version_message(unsigned int token, + void __iomem *msg_buf) +{ + struct acpi_pcct_ext_pcc_shared_memory __iomem *pcc_shmem =3D msg_buf; + + /* .signature is filled by the platform */ + writel_relaxed(PCC_CMD_COMPLETION_NOTIFY, &pcc_shmem->flags); + writel_relaxed(MPAM_FB_PROT_HEADER_LEN, &pcc_shmem->length); + writel_relaxed(MPAM_PROTOCOL_VERSION_CMD | + FIELD_PREP(MPAM_MSC_TOKEN_MASK, token) | + FIELD_PREP(MPAM_MSC_PROT_ID_MASK, MPAM_FB_PROTOCOL_ID), + &pcc_shmem->command); +} + +static void mpam_fb_build_read_message(int msc_fb_id, int reg, + unsigned int token, + void __iomem *msg_buf) +{ + struct acpi_pcct_ext_pcc_shared_memory __iomem *pcc_shmem =3D msg_buf; + struct mpam_fb_read_payload { + u32 msc_fb_id; + u32 flags; + u32 reg_offset; + } __packed __iomem *payload =3D msg_buf + sizeof(*pcc_shmem); + int msg_size =3D MPAM_FB_PROT_HEADER_LEN + sizeof(*payload); + + /* .signature is filled by the platform */ + writel_relaxed(PCC_CMD_COMPLETION_NOTIFY, &pcc_shmem->flags); + writel_relaxed(msg_size, &pcc_shmem->length); + writel_relaxed(MPAM_MSC_READ_CMD | + FIELD_PREP(MPAM_MSC_TOKEN_MASK, token) | + FIELD_PREP(MPAM_MSC_PROT_ID_MASK, MPAM_FB_PROTOCOL_ID), + &pcc_shmem->command); + + writel_relaxed(msc_fb_id, &payload->msc_fb_id); + writel_relaxed(0, &payload->flags); + writel_relaxed(reg, &payload->reg_offset); +} + +static void mpam_fb_build_write_message(int msc_fb_id, int reg, u32 val, + unsigned int token, + void __iomem *msg_buf) +{ + struct acpi_pcct_ext_pcc_shared_memory __iomem *pcc_shmem =3D msg_buf; + struct mpam_fb_write_payload { + u32 msc_fb_id; + u32 flags; + u32 reg_offset; + u32 value; + } __packed __iomem *payload =3D msg_buf + sizeof(*pcc_shmem); + int msg_size =3D MPAM_FB_PROT_HEADER_LEN + sizeof(*payload); + + /* .signature is filled by the platform */ + writel_relaxed(PCC_CMD_COMPLETION_NOTIFY, &pcc_shmem->flags); + writel_relaxed(msg_size, &pcc_shmem->length); + writel_relaxed(MPAM_MSC_WRITE_CMD | + FIELD_PREP(MPAM_MSC_TOKEN_MASK, token) | + FIELD_PREP(MPAM_MSC_PROT_ID_MASK, MPAM_FB_PROTOCOL_ID), + &pcc_shmem->command); + + writel_relaxed(msc_fb_id, &payload->msc_fb_id); + writel_relaxed(0, &payload->flags); + writel_relaxed(reg, &payload->reg_offset); + writel_relaxed(val, &payload->value); +} + +static int mpam_fb_send_request(struct mpam_msc *msc, u32 msc_fb_id, + u16 reg, u32 *result, int mpam_fb_command) +{ + unsigned int token =3D atomic_inc_return(&mpam_fb_token); + struct acpi_pcct_ext_pcc_shared_memory __iomem *pcc_shmem; + struct mpam_pcc_chan *pcc_chan; + struct pcc_mbox_chan *chan; + void __iomem *payload_ofs; + int mpam_fb_err =3D 0; + u32 status; + int ret; + + pcc_chan =3D msc->pcc_chan; + if (!pcc_chan) + return -ENODEV; + + chan =3D pcc_chan->pcc_chan; + + /* prune token to fit into the 10 bits inside the command register */ + token =3D FIELD_GET(MPAM_MSC_TOKEN_MASK, + FIELD_PREP(MPAM_MSC_TOKEN_MASK, token)); + + mutex_lock(&pcc_chan->pcc_chan_lock); + + switch (mpam_fb_command) { + case MPAM_PROTOCOL_VERSION_CMD: + mpam_fb_build_version_message(token, chan->shmem); + break; + case MPAM_MSC_READ_CMD: + mpam_fb_build_read_message(msc_fb_id, reg, token, chan->shmem); + break; + case MPAM_MSC_WRITE_CMD: + mpam_fb_build_write_message(msc_fb_id, reg, *result, + token, chan->shmem); + break; + default: + dev_err(&msc->pdev->dev, "unsupported MPAM-Fb command %d\n", + mpam_fb_command); + ret =3D -EINVAL; + goto out_err; + } + + ret =3D mbox_send_message(chan->mchan, NULL); + if (ret < 0) + goto out_err; + + pcc_shmem =3D chan->shmem; + payload_ofs =3D chan->shmem + sizeof(*pcc_shmem); + status =3D readl(&pcc_shmem->command); + if (FIELD_GET(MPAM_MSC_TOKEN_MASK, status) !=3D token) { + ret =3D -ETIMEDOUT; + goto out_err; + } + + mpam_fb_err =3D readl(payload_ofs + 0x0); + if (mpam_fb_err < 0) { + ret =3D mpam_fb_to_linux_errno(mpam_fb_err); + goto out_err; + } + + if (mpam_fb_command !=3D MPAM_MSC_WRITE_CMD) + *result =3D readl(payload_ofs + 0x4); + + mutex_unlock(&pcc_chan->pcc_chan_lock); + + return 0; + +out_err: + mutex_unlock(&pcc_chan->pcc_chan_lock); + + mpam_fb_disable_mpam(ret, mpam_fb_err); + + return ret; +} + +int mpam_fb_send_read_request(struct mpam_msc *msc, u16 reg, u32 *result) +{ + return mpam_fb_send_request(msc, msc->fb_id, reg, result, + MPAM_MSC_READ_CMD); +} + +int mpam_fb_send_write_request(struct mpam_msc *msc, u16 reg, u32 value) +{ + return mpam_fb_send_request(msc, msc->fb_id, reg, &value, + MPAM_MSC_WRITE_CMD); +} diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_interna= l.h index 58f7523bc087b..99057d6abee1e 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,15 @@ struct mpam_garbage { struct platform_device *pdev; }; =20 +struct mpam_pcc_chan { + struct list_head pcc_chans; + struct mbox_client pcc_cl; + struct pcc_mbox_chan *pcc_chan; + struct mutex pcc_chan_lock; /* only one message at a time */ + struct kref refcount; + int subspace_id; +}; + struct mpam_msc { /* member of mpam_all_msc */ struct list_head all_msc_list; @@ -66,6 +76,8 @@ struct mpam_msc { =20 /* Not modified after mpam_is_enabled() becomes true */ enum mpam_msc_iface iface; + struct mpam_pcc_chan *pcc_chan; + int fb_id; u32 nrdy_usec; cpumask_t accessibility; bool has_extd_esr; @@ -493,6 +505,9 @@ extern u8 mpam_pmg_max; void mpam_enable(struct work_struct *work); void mpam_disable(struct work_struct *work); =20 +/* helper function to call from outside mpam_devices.c */ +void mpam_fb_disable_mpam(int err, int mpam_fb_err); + /* Reset all the RIS in a class under cpus_read_lock() */ int mpam_reset_class_locked(struct mpam_class *class); =20 @@ -520,6 +535,10 @@ static inline void mpam_resctrl_offline_cpu(unsigned i= nt cpu) { } static inline void mpam_resctrl_teardown_class(struct mpam_class *class) {= } #endif /* CONFIG_RESCTRL_FS */ =20 +/* MPAM-Fb Firmware-backed protocol wrappers */ +int mpam_fb_send_read_request(struct mpam_msc *msc, u16 reg, u32 *result); +int mpam_fb_send_write_request(struct mpam_msc *msc, u16 reg, u32 value); + /* * MPAM MSCs have the following register layout. See: * Arm Memory System Resource Partitioning and Monitoring (MPAM) System diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index f92a36187a527..002f56e153626 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -12,7 +12,7 @@ struct mpam_msc; =20 enum mpam_msc_iface { MPAM_IFACE_MMIO, /* a real MPAM MSC */ - MPAM_IFACE_PCC, /* a fake MPAM MSC */ + MPAM_IFACE_PCC, /* using the MPAM-Fb firmware redirection */ }; =20 enum mpam_class_types { --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 847714A4854; Thu, 24 Sep 2026 15:29:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263768; cv=none; b=uuy6lj58MylXXfcgY4q8IEmlCGyJRp0wVWaeAuYbGpDDOWdnyAmhY/mA2Pz1bmdcSL9KbAb1k6BaQ04HjqQZZaBxYRbEgl/Ky5/COy437Jp63clCGop9gEW70YfSAU9l46/uuTEd1LQEx5CCNobRYhEeyJ3q/lk13tgNcIMqm3Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263768; c=relaxed/simple; bh=hiYDOsrFTqYrHghNF5qpN7Ez9iCF+l3+Mk6RkjCoBOg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jdz+otHIg9aysFNZWJSp+VWTIFBWpuJj3HfguxeFsdD/Kke7RQ2TSiwg0PuD2+FGNrLFancS4v+WTRbKGIvvRNOGU6ivP5333jEPUrvovgtJpWVyXoyl8Al3UFZLCR2yc7KmkXXynZePfSNaKP4Ee+arhbANpcFH0SE1JI9aj9c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=N6p60/aj; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="N6p60/aj" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3417C1E2F; Thu, 24 Sep 2026 08:29:22 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0B95F3F86F; Thu, 24 Sep 2026 08:29:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263765; bh=hiYDOsrFTqYrHghNF5qpN7Ez9iCF+l3+Mk6RkjCoBOg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N6p60/ajuKHsLs0uGMl2YBmLNBTH6evUyExuhPImEomU1uBi9CPKJ98/wfd37eJQl Vd/8YfVfzsr5Jx6HatviI0C4jIT5L3ePnSLg8FXrYp1rf+ie3Q+sLabA4kx1DqqwoC C8/TF7s1R/V9dz2+5wpL4ZU8Z6v4MJe8AGjVHoIo= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 12/13] arm_mpam: change MPAM-Fb error IRQ to use a threaded IRQ handler Date: Thu, 24 Sep 2026 17:27:38 +0200 Message-ID: <20260924152739.2865510-13-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When an MPAM MSC gets into an error condition, it can trigger an error IRQ. We cannot really do much about those errors, but we at least query and log the error, then disable MPAM functionality. This error report relies on reading the MSC's error status register (ESR) in the current hard-IRQ handler, which is not possible for MPAM-Fb based MSC accesses, since they involve mailbox routines that might sleep. The same is true for clearing the interrupt at the source, which requires a (potentially sleeping) MSC access as well. Change the error IRQ handler to be a threaded interrupt, but keep the handling in the hard-IRQ part for MMIO MSCs. This is needed since the CPU affinity check in the MSC accessors requires a non-preemptible context. When the MSC is using an MPAM-Fb based access, we push the work into the threaded part of the handler, where the accessors are allowed to sleep. Also forbid per-CPU interrupts (PPIs) for MPAM-Fb, as we cannot use a threaded IRQ here. The actual IRQ handler learns how to deal with errors. We cannot really handle them, but we can try our best to disable the IRQ anyway. Should the level IRQ line deactivation fail on the device side, we mask the IRQ on the irqchip level, to prevent an interrupt storm. Signed-off-by: Andre Przywara Reviewed-by: Gavin Shan Reviewed-by: Srivathsa L Rao Reviewed-by: Jonathan Cameron --- drivers/resctrl/mpam_devices.c | 77 ++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index 90161696aada0..ce20dc44d5d40 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -2721,24 +2721,42 @@ static int mpam_disable_msc_ecr(void *_msc) return __mpam_write_reg(msc, MPAMF_ECR, 0); } =20 +/* + * This will run as the threaded IRQ handler part when using MPAM-Fb, but + * as the sole hard-IRQ handler for MMIO based accesses. + */ static irqreturn_t __mpam_irq_handler(int irq, struct mpam_msc *msc) { u64 reg; + int ret; u16 partid; u8 errcode, pmg, ris; =20 - if (WARN_ON_ONCE(!msc) || + if (WARN_ON_ONCE(!msc)) + return IRQ_NONE; + + if (msc->iface =3D=3D MPAM_IFACE_MMIO && WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility))) return IRQ_NONE; =20 - mpam_msc_read_esr(msc, ®); + ret =3D mpam_msc_read_esr(msc, ®); + if (ret) { + pr_err_ratelimited("unknown error irq from msc:%u\n", msc->id); + + /* Try out best here ... */ + goto out_disable; + } =20 errcode =3D FIELD_GET(MPAMF_ESR_ERRCODE, reg); if (!errcode) return IRQ_NONE; =20 - /* Clear level triggered irq */ + /* + * Clear the level triggered IRQ. If that fails, we cannot do anything + * about it, so ignore any errors. We will disable the IRQ either on + * the device side or on the irqchip level next anyway. + */ mpam_msc_clear_esr(msc); =20 partid =3D FIELD_GET(MPAMF_ESR_PARTID_MON, reg); @@ -2749,16 +2767,24 @@ static irqreturn_t __mpam_irq_handler(int irq, stru= ct mpam_msc *msc) msc->id, mpam_errcode_names[errcode], partid, pmg, ris); =20 - /* Disable this interrupt. */ - mpam_disable_msc_ecr(msc); +out_disable: + /* + * Disable this interrupt on the device side. If that fails, disable + * the IRQ on the irqchip level, as we must prevent further handler + * invocations. We only take the interrupt once anyway, as we + * are going to free the IRQ next, in mpam_disable(). + */ + ret =3D mpam_disable_msc_ecr(msc); + if (ret) + disable_irq_nosync(irq); =20 - /* Are we racing with the thread disabling MPAM? */ + /* Check whether we are racing with the thread disabling MPAM. */ if (!mpam_is_enabled()) return IRQ_HANDLED; =20 /* - * Schedule the teardown work. Don't use a threaded IRQ as we can't - * unregister the interrupt from the threaded part of the handler. + * Schedule the teardown work. We have to defer it as we can't + * unregister the interrupt from the threaded part of a handler. */ mpam_disable_reason =3D "hardware error interrupt"; schedule_work(&mpam_broken_work); @@ -2773,10 +2799,30 @@ static irqreturn_t mpam_ppi_handler(int irq, void *= dev_id) return __mpam_irq_handler(irq, msc); } =20 -static irqreturn_t mpam_spi_handler(int irq, void *dev_id) +/* + * MMIO based MSC accesses must run in non-preemptible context, as they + * might have affinity requirements to check. + * MPAM-Fb based MSC accesses must NOT run in hard-IRQ context, as they + * can sleep. + * So split the IRQ handling up, depending on the MSC access type. + */ +static irqreturn_t mpam_shared_hard_irq(int irq, void *dev_id) { struct mpam_msc *msc =3D dev_id; =20 + if (msc->iface =3D=3D MPAM_IFACE_MMIO) + return __mpam_irq_handler(irq, msc); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t mpam_shared_thread_irq(int irq, void *dev_id) +{ + struct mpam_msc *msc =3D dev_id; + + if (msc->iface =3D=3D MPAM_IFACE_MMIO) + return IRQ_HANDLED; + return __mpam_irq_handler(irq, msc); } =20 @@ -2797,6 +2843,11 @@ static int mpam_register_irqs(void) /* The MPAM spec says the interrupt can be SPI, PPI or LPI */ /* We anticipate sharing the interrupt with other MSCs */ if (irq_is_percpu(irq)) { + if (msc->iface !=3D MPAM_IFACE_MMIO) { + dev_err(&msc->pdev->dev, + "Only MMIO MSCs can use per-CPU interrupts\n"); + return -EINVAL; + } err =3D request_percpu_irq(irq, &mpam_ppi_handler, "mpam:msc:error", msc->error_dev_id); @@ -2808,9 +2859,11 @@ static int mpam_register_irqs(void) &_enable_percpu_irq, &irq, true); } else { - err =3D devm_request_irq(&msc->pdev->dev, irq, - &mpam_spi_handler, IRQF_SHARED, - "mpam:msc:error", msc); + err =3D devm_request_threaded_irq(&msc->pdev->dev, irq, + &mpam_shared_hard_irq, + &mpam_shared_thread_irq, + IRQF_SHARED | IRQF_ONESHOT, + "mpam:msc:error", msc); if (err) return err; } --=20 2.43.0 From nobody Fri Sep 25 14:31:22 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 701454A4F0B; Thu, 24 Sep 2026 15:29:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263775; cv=none; b=DCvKPUu8pO3o/FmAE4tTIhI29Gj3+jq/1kV4YZmiIs9DoobdsQnsBhQ65r2WJ5Fwd2QHo2GeAUVyeI/nn90/WU7ZzRqDjytMOyW800dhTtkgdJ3Q/WFPLC2ExJfliSpkfxxBt398nuQixqbnw1TbkCq8jj2u4jF6I9fqAPdPr3o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263775; c=relaxed/simple; bh=YOtj1b3IF2JPdmr6iRY0wBQb2u6zimKxycYRZwrP7Cs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P02qYCyAyqjSwRbOcQVijk1zGSxhABbdnzzFoB1pG6ZP98+oWbA/okUoLGQOvwCR3xWvDGv3EatxZFJimNAbXzolfsBe/RSkSTkb6VRe7ZNlBqiQrqTPkzJJ+wMC2zQssWC75ERWlf+4Irbs89ZL2Z0XBksokg11xeKQQmZ96o0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=pei0UWqP; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="pei0UWqP" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 30AE11E32; Thu, 24 Sep 2026 08:29:29 -0700 (PDT) Received: from e142021.arm.com (unknown [10.57.8.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3C01D3F86F; Thu, 24 Sep 2026 08:29:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1790263772; bh=YOtj1b3IF2JPdmr6iRY0wBQb2u6zimKxycYRZwrP7Cs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pei0UWqPxStZ81rDTu1EBCTr5VTGBysCdRWbhuZbRh7SpqFH+oGqol8adwfLxAiuH 39ULzwgMhuRBdDVkvii/fAJjqg9f2fn7Dj2swn+RMABVG4D0438evzn09fOqSgZ09/ 8BzoTY+mmuxQr7vt55+OJyQ9Q+3QEq+i3CZNhk4s= From: Andre Przywara To: Lorenzo Pieralisi , Hanjun Guo , Sudeep Holla , Catalin Marinas , Will Deacon , "Rafael J . Wysocki" , Len Brown , James Morse , Ben Horgan , Reinette Chatre , Fenghua Yu Cc: Jonathan Cameron , Srivathsa L Rao , Ganapatrao Kulkarni , Trilok Soni , Srinivas Ramana , Niyas Sait , Lee Trager , Ritwick Sharma , Gavin Shan , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v11 13/13] arm_mpam: detect and enable MPAM-Fb PCC support Date: Thu, 24 Sep 2026 17:27:39 +0200 Message-ID: <20260924152739.2865510-14-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924152739.2865510-1-andre.przywara@arm.com> References: <20260924152739.2865510-1-andre.przywara@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The Arm MPAM-Fb specification [1] describes a protocol to access MSC registers through a firmware interface. This requires a shared memory region to hold the message, and a mailbox to trigger the access. For ACPI this is wrapped as a PCC channel, described using existing ACPI abstractions. Add code to parse those PCC table descriptions associated with an MSC, and store the parsed information in the MSC struct. There can be multiple PCC channels, and each channel can serve multiple MSCs, so we need to keep track of the channel usage, using a list and a refcount. This will be used by the MPAM-Fb access wrapper code. [1] https://developer.arm.com/documentation/den0144/latest Signed-off-by: Andre Przywara Tested-by: Ritwick Sharma # on Arm AGI CPU Reviewed-by: Jonathan Cameron Tested-by: Srivathsa L Rao Reviewed-by: Srivathsa L Rao Reviewed-by: Gavin Shan --- drivers/resctrl/Kconfig | 1 + drivers/resctrl/mpam_devices.c | 119 +++++++++++++++++++++++++++++++- drivers/resctrl/mpam_fb.c | 41 +++++++++++ drivers/resctrl/mpam_internal.h | 2 + 4 files changed, 161 insertions(+), 2 deletions(-) diff --git a/drivers/resctrl/Kconfig b/drivers/resctrl/Kconfig index 9591d792736e5..f5ff9b1f6c48e 100644 --- a/drivers/resctrl/Kconfig +++ b/drivers/resctrl/Kconfig @@ -2,6 +2,7 @@ menuconfig ARM64_MPAM_DRIVER bool "MPAM driver" depends on ARM64 && ARM64_MPAM select ACPI_MPAM if ACPI + select PCC if ACPI select MAILBOX help Memory System Resource Partitioning and Monitoring (MPAM) driver for diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index ce20dc44d5d40..ca7e0fe75f24f 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -20,14 +20,19 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include =20 +#include +#include + #include "mpam_internal.h" =20 /* Values for the T241 errata workaround */ @@ -50,6 +55,87 @@ static LIST_HEAD(mpam_all_msc); =20 struct srcu_struct mpam_srcu; =20 +/* PCC channels might be serving multiple MSCs, so keep a refcounted list.= */ +static DEFINE_MUTEX(pcc_chan_list_lock); +static LIST_HEAD(pcc_chan_list); + +static void mpam_pcc_chan_release(struct kref *ref) +{ + struct mpam_pcc_chan *cur =3D container_of(ref, struct mpam_pcc_chan, + refcount); + + pcc_mbox_free_channel(cur->pcc_chan); + list_del(&cur->pcc_chans); + mutex_destroy(&cur->pcc_chan_lock); + kfree(cur); +} + +static struct mpam_pcc_chan *mpam_pcc_chan_get(struct device *dev, + int subspace_id) +{ + struct mpam_pcc_chan *cur; + + guard(mutex)(&pcc_chan_list_lock); + + list_for_each_entry(cur, &pcc_chan_list, pcc_chans) { + if (cur->subspace_id =3D=3D subspace_id) { + kref_get(&cur->refcount); + + return cur; + } + } + + cur =3D kzalloc_obj(*cur); + if (!cur) + return ERR_PTR(-ENOMEM); + + cur->pcc_cl.tx_block =3D true; + + cur->pcc_chan =3D pcc_mbox_request_channel(&cur->pcc_cl, subspace_id); + if (IS_ERR(cur->pcc_chan)) { + long err =3D PTR_ERR(cur->pcc_chan); + + kfree(cur); + return ERR_PTR(err); + } + + /* + * Timeout based on the "nominal latency" in us, from the + * PCC ACPI table. tx_tout is in ms. + * Add some margin here to be on the safe side. + */ + cur->pcc_cl.tx_tout =3D DIV_ROUND_UP(cur->pcc_chan->latency * 5, 1000); + + mutex_init(&cur->pcc_chan_lock); + + cur->subspace_id =3D subspace_id; + kref_init(&cur->refcount); + + list_add_tail(&cur->pcc_chans, &pcc_chan_list); + + return cur; +} + +static int mpam_pcc_chan_put(struct mpam_pcc_chan *pcc_chan) +{ + struct mpam_pcc_chan *cur, *tmp; + + if (!pcc_chan) + return 0; + + guard(mutex)(&pcc_chan_list_lock); + + list_for_each_entry_safe(cur, tmp, &pcc_chan_list, pcc_chans) { + if (cur =3D=3D pcc_chan) { + kref_put(&cur->refcount, mpam_pcc_chan_release); + + return 0; + } + } + + return -ENOENT; +} + /* * Number of MSCs that have been probed. Once all MSCs have been probed MP= AM * can be enabled. @@ -2272,6 +2358,8 @@ static void mpam_msc_destroy(struct mpam_msc *msc) list_for_each_entry_safe(ris, tmp, &msc->ris, msc_list) mpam_ris_destroy(ris); =20 + mpam_pcc_chan_put(msc->pcc_chan); + list_del_rcu(&msc->all_msc_list); platform_set_drvdata(pdev, NULL); =20 @@ -2295,7 +2383,7 @@ static void mpam_msc_drv_remove(struct platform_devic= e *pdev) static struct mpam_msc *do_mpam_msc_drv_probe(struct platform_device *pdev) { int err; - u32 tmp; + u32 pcc_subspace_id; struct mpam_msc *msc; struct resource *msc_res; struct device *dev =3D &pdev->dev; @@ -2339,7 +2427,7 @@ static struct mpam_msc *do_mpam_msc_drv_probe(struct = platform_device *pdev) if (err) return ERR_PTR(err); =20 - if (device_property_read_u32(&pdev->dev, "pcc-channel", &tmp)) + if (device_property_read_u32(dev, "pcc-channel", &pcc_subspace_id)) msc->iface =3D MPAM_IFACE_MMIO; else msc->iface =3D MPAM_IFACE_PCC; @@ -2360,6 +2448,33 @@ static struct mpam_msc *do_mpam_msc_drv_probe(struct= platform_device *pdev) } msc->mapped_hwpage_sz =3D msc_res->end - msc_res->start; msc->mapped_hwpage =3D io; + } else if (msc->iface =3D=3D MPAM_IFACE_PCC) { + u32 mpam_fb_msc_id; + + msc->pcc_chan =3D mpam_pcc_chan_get(dev, pcc_subspace_id); + if (IS_ERR(msc->pcc_chan)) { + pr_err("Failed to request MSC PCC channel\n"); + return ERR_CAST(msc->pcc_chan); + } + + err =3D mpam_fb_check_shared_buffer_size(msc); + if (err) { + mpam_pcc_chan_put(msc->pcc_chan); + + return ERR_PTR(err); + } + + err =3D mpam_fb_check_protocol_version(msc); + if (err) { + mpam_pcc_chan_put(msc->pcc_chan); + + return ERR_PTR(err); + } + + if (device_property_read_u32(&pdev->dev, "mpam-fb-msc-id", + &mpam_fb_msc_id)) + mpam_fb_msc_id =3D msc->id; + msc->fb_id =3D mpam_fb_msc_id; } else { return ERR_PTR(-EINVAL); } diff --git a/drivers/resctrl/mpam_fb.c b/drivers/resctrl/mpam_fb.c index 8298fcedd2be7..d90888944abbd 100644 --- a/drivers/resctrl/mpam_fb.c +++ b/drivers/resctrl/mpam_fb.c @@ -20,10 +20,15 @@ #define MPAM_FB_PROTOCOL_ID 0x1a =20 #define MPAM_PROTOCOL_VERSION_CMD 0x0 +#define MPAM_FB_VERSION_MAJOR_MASK GENMASK_U32(31, 16) +#define MPAM_FB_VERSION_MINOR_MASK GENMASK_U32(15, 0) + #define MPAM_MSC_READ_CMD 0x4 #define MPAM_MSC_WRITE_CMD 0x5 =20 #define MPAM_FB_PROT_HEADER_LEN sizeof(u32) +/* The longest message is MPAM_MSC_WRITE, with 4 parameters. */ +#define MPAM_FB_MAX_MSG_SIZE (4 * sizeof(u32)) =20 #define MPAM_FB_SUCCESS 0 #define MPAM_FB_ERR_NOT_SUPPORTED -1 @@ -210,3 +215,39 @@ int mpam_fb_send_write_request(struct mpam_msc *msc, u= 16 reg, u32 value) return mpam_fb_send_request(msc, msc->fb_id, reg, &value, MPAM_MSC_WRITE_CMD); } + +/* We only support MPAM-Fb protocol version 1.x */ +int mpam_fb_check_protocol_version(struct mpam_msc *msc) +{ + u32 version; + int ret; + + ret =3D mpam_fb_send_request(msc, 0, 0, &version, + MPAM_PROTOCOL_VERSION_CMD); + if (ret) + return ret; + + if (FIELD_GET(MPAM_FB_VERSION_MAJOR_MASK, version) !=3D 1) { + pr_err("Incompatible MPAM-Fb protocol version %d.%d\n", + FIELD_GET(MPAM_FB_VERSION_MAJOR_MASK, version), + FIELD_GET(MPAM_FB_VERSION_MINOR_MASK, version)); + + return -EINVAL; + } + + return 0; +} + +int mpam_fb_check_shared_buffer_size(struct mpam_msc *msc) +{ + int min_buffer_size =3D MPAM_FB_MAX_MSG_SIZE + + sizeof(struct acpi_pcct_ext_pcc_shared_memory); + + if (msc->pcc_chan->pcc_chan->shmem_size < min_buffer_size) { + pr_err("MPAM-Fb PCC channel size too small.\n"); + + return -ENOMEM; + } + + return 0; +} diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_interna= l.h index 99057d6abee1e..ee7c3953a9b6c 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -538,6 +538,8 @@ static inline void mpam_resctrl_teardown_class(struct m= pam_class *class) { } /* MPAM-Fb Firmware-backed protocol wrappers */ int mpam_fb_send_read_request(struct mpam_msc *msc, u16 reg, u32 *result); int mpam_fb_send_write_request(struct mpam_msc *msc, u16 reg, u32 value); +int mpam_fb_check_protocol_version(struct mpam_msc *msc); +int mpam_fb_check_shared_buffer_size(struct mpam_msc *msc); =20 /* * MPAM MSCs have the following register layout. See: --=20 2.43.0