From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 88BD5C44506 for ; Fri, 10 Jul 2026 14:45:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=2MgB8u7Zm/HvNUsB09hHXQScvv5t1UcCuZUbDulKh74=; b=S1muJQFK7cuVn9M+cYQF8J4eYh DouS1SCCT07w1Pc4upe9Z8E6H2nBKedXVODoV/BrDhbJKsz1AimdA3hn5IG+hlfG5/B6rUXDxFTfK RhKhM3wCPPqivjm499qW5YSwbClAPPAI3sQJYfY3mOMbDRe6MCuw44iIJze9Engj75BMsJhJTrZdO 2Fvy8CKh3lMZHmZgBTo8tLQEE+PeNWpgLciBdgW5nPIAmxhKPyDn5hWW12d0OBnand/Hry3eXDjFt +TY+PFmWMMLx5WjFLynG4FFy3q6ANUVHRLrEekpfpRlpqSxgFgj9Y5sDB++wbkqs7qh7RgVy6YC6E tIdRZv+Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wiCTy-000000056ej-2GU5; Fri, 10 Jul 2026 14:45:38 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wiCTv-000000056dq-3Aou for linux-arm-kernel@lists.infradead.org; Fri, 10 Jul 2026 14:45:37 +0000 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 498AB1BC0; Fri, 10 Jul 2026 07:45:30 -0700 (PDT) Received: from e142021.munich.arm.com (e142021.arm.com [10.41.150.148]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 794993F7B4; Fri, 10 Jul 2026 07:45:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1783694734; bh=463AiPpg8bN0YaCAhKvsVnF4tFZr9fK0cCTAjKjeLXk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oGq0BOzjQXJ/DdpqtP0spb7M3ShpR5x8YCDvOznrw5fDfzP4eq2Vln0aolx3YIyY0 +gySuRUq7BhZuN5JNLQffxqr1XsFprxweEKLG8VGvtSO9GxGUQwOrnoJKasjL7i3XP w4TkcCgret214mFvzHJpTXd/0IvF627mI3V7iZmg= 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 , linux-acpi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 01/16] arm_mpam: let low level MSC read accessors return an error Date: Fri, 10 Jul 2026 16:45:05 +0200 Message-ID: <20260710144520.917375-2-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260710144520.917375-1-andre.przywara@arm.com> References: <20260710144520.917375-1-andre.przywara@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260710_074535_876733_CAE3D496 X-CRM114-Status: GOOD ( 18.25 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 is must be able to handle errors, whereas we always assume an 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. At the moment this is always 0, but this will change with alternative MSC access methods. Change all users of those MSC read wrappers to comply with the new prototype, though at the moment without propagating any errors. Signed-off-by: Andre Przywara --- drivers/resctrl/mpam_devices.c | 129 ++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 51 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index b69f99488111..df14b4513382 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -177,20 +177,23 @@ static void mpam_assert_partid_sizes_fixed(void) WARN_ON_ONCE(!partid_max_published); } -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)); - return readl_relaxed(msc->mapped_hwpage + reg); + *res = readl_relaxed(msc->mapped_hwpage + reg); + + return 0; } -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); } -#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, MPAMF_##reg, res) static void __mpam_write_reg(struct mpam_msc *msc, u16 reg, u32 val) { @@ -208,13 +211,14 @@ static inline void _mpam_write_partsel_reg(struct mpam_msc *msc, u16 reg, u32 va #define mpam_write_partsel_reg(msc, reg, val) _mpam_write_partsel_reg(msc, MPAMCFG_##reg, val) -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); } -#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, MSMON_##reg, res) static inline void _mpam_write_monsel_reg(struct mpam_msc *msc, u16 reg, u32 val) { @@ -226,10 +230,11 @@ static inline void _mpam_write_monsel_reg(struct mpam_msc *msc, u16 reg, u32 val static bool mpam_msc_check_aidr(struct mpam_msc *msc) { - u32 aidr = __mpam_read_reg(msc, MPAMF_AIDR); - u32 major = FIELD_GET(MPAMF_AIDR_ARCH_MAJOR_REV, aidr); - u32 minor = FIELD_GET(MPAMF_AIDR_ARCH_MINOR_REV, aidr); + u32 aidr, major, minor; + __mpam_read_reg(msc, MPAMF_AIDR, &aidr); + major = FIELD_GET(MPAMF_AIDR_ARCH_MAJOR_REV, aidr); + minor = 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. @@ -244,20 +249,22 @@ static bool mpam_msc_check_aidr(struct mpam_msc *msc) static u64 mpam_msc_read_idr(struct mpam_msc *msc) { - u64 idr_high = 0, idr_low; + u32 idr_high = 0, idr_low; lockdep_assert_held(&msc->part_sel_lock); - idr_low = mpam_read_partsel_reg(msc, IDR); + mpam_read_partsel_reg(msc, IDR, &idr_low); if (FIELD_GET(MPAMF_IDR_EXT, idr_low)) - idr_high = mpam_read_partsel_reg(msc, IDR + 4); + mpam_read_partsel_reg(msc, IDR + 4, &idr_high); - return (idr_high << 32) | idr_low; + return ((u64)idr_high << 32) | idr_low; } static void mpam_msc_clear_esr(struct mpam_msc *msc) { - u64 esr_low = __mpam_read_reg(msc, MPAMF_ESR); + u32 esr_low; + + __mpam_read_reg(msc, MPAMF_ESR, &esr_low); if (!esr_low) return; @@ -275,13 +282,13 @@ static void mpam_msc_clear_esr(struct mpam_msc *msc) static u64 mpam_msc_read_esr(struct mpam_msc *msc) { - u64 esr_high = 0, esr_low; + u32 esr_high = 0, esr_low; - esr_low = __mpam_read_reg(msc, MPAMF_ESR); + __mpam_read_reg(msc, MPAMF_ESR, &esr_low); if (msc->has_extd_esr) - esr_high = __mpam_read_reg(msc, MPAMF_ESR + 4); + __mpam_read_reg(msc, MPAMF_ESR + 4, &esr_high); - return (esr_high << 32) | esr_low; + return ((u64)esr_high << 32) | esr_low; } static void __mpam_part_sel_raw(u32 partsel, struct mpam_msc *msc) @@ -774,13 +781,13 @@ static bool mpam_ris_hw_probe_csu_nrdy(struct mpam_msc_ris *ris) mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val); _mpam_write_monsel_reg(msc, MSMON_CSU, MSMON___NRDY); - now = _mpam_read_monsel_reg(msc, MSMON_CSU); + _mpam_read_monsel_reg(msc, MSMON_CSU, &now); can_set = now & MSMON___NRDY; _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 = _mpam_read_monsel_reg(msc, MSMON_CSU); + _mpam_read_monsel_reg(msc, MSMON_CSU, &now); can_clear = !(now & MSMON___NRDY); mpam_mon_sel_unlock(msc); @@ -800,7 +807,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) /* Cache Capacity Partitioning */ if (FIELD_GET(MPAMF_IDR_HAS_CCAP_PART, ris->idr)) { - u32 ccap_features = mpam_read_partsel_reg(msc, CCAP_IDR); + u32 ccap_features; + + mpam_read_partsel_reg(msc, CCAP_IDR, &ccap_features); props->cmax_wd = FIELD_GET(MPAMF_CCAP_IDR_CMAX_WD, ccap_features); if (props->cmax_wd && @@ -823,7 +832,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) /* Cache Portion partitioning */ if (FIELD_GET(MPAMF_IDR_HAS_CPOR_PART, ris->idr)) { - u32 cpor_features = mpam_read_partsel_reg(msc, CPOR_IDR); + u32 cpor_features; + + mpam_read_partsel_reg(msc, CPOR_IDR, &cpor_features); props->cpbm_wd = FIELD_GET(MPAMF_CPOR_IDR_CPBM_WD, cpor_features); if (props->cpbm_wd) @@ -832,7 +843,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); + u32 mbw_features; + + mpam_read_partsel_reg(msc, MBW_IDR, &mbw_features); /* portion bitmap resolution */ props->mbw_pbm_bits = FIELD_GET(MPAMF_MBW_IDR_BWPBM_WD, mbw_features); @@ -860,7 +873,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); + u32 pri_features; + + mpam_read_partsel_reg(msc, PRI_IDR, &pri_features); props->intpri_wd = FIELD_GET(MPAMF_PRI_IDR_INTPRI_WD, pri_features); if (props->intpri_wd && FIELD_GET(MPAMF_PRI_IDR_HAS_INTPRI, pri_features)) { @@ -879,7 +894,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) /* Performance Monitoring */ if (FIELD_GET(MPAMF_IDR_HAS_MSMON, ris->idr)) { - u32 msmon_features = mpam_read_partsel_reg(msc, MSMON_IDR); + u32 msmon_features; + + mpam_read_partsel_reg(msc, MSMON_IDR, &msmon_features); /* * If the firmware max-nrdy-us property is missing, the @@ -892,7 +909,8 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_CSU, msmon_features)) { u32 csumonidr; - csumonidr = mpam_read_partsel_reg(msc, CSUMON_IDR); + mpam_read_partsel_reg(msc, CSUMON_IDR, &csumonidr); + props->num_csu_mon = FIELD_GET(MPAMF_CSUMON_IDR_NUM_MON, csumonidr); if (props->num_csu_mon) { bool hw_managed; @@ -915,7 +933,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 = mpam_read_partsel_reg(msc, MBWUMON_IDR); + u32 mbwumon_idr; + + mpam_read_partsel_reg(msc, MBWUMON_IDR, &mbwumon_idr); props->num_mbwu_mon = FIELD_GET(MPAMF_MBWUMON_IDR_NUM_MON, mbwumon_idr); if (props->num_mbwu_mon) { @@ -945,8 +965,11 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) */ if (FIELD_GET(MPAMF_IDR_HAS_PARTID_NRW, ris->idr) && class->type != MPAM_CLASS_UNKNOWN) { - u32 nrwidr = mpam_read_partsel_reg(msc, PARTID_NRW_IDR); - u16 partid_max = 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 = FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr); mpam_set_feature(mpam_feat_partid_nrw, props); msc->partid_max = min(msc->partid_max, partid_max); @@ -971,7 +994,8 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) /* Grab an IDR value to find out how many RIS there are */ mutex_lock(&msc->part_sel_lock); idr = mpam_msc_read_idr(msc); - msc->iidr = mpam_read_partsel_reg(msc, IIDR); + mpam_read_partsel_reg(msc, IIDR, &msc->iidr); + mutex_unlock(&msc->part_sel_lock); mpam_enable_quirks(msc); @@ -1039,24 +1063,24 @@ static u64 mpam_msc_read_mbwu_l(struct mpam_msc *msc) { int retry = 3; u32 mbwu_l_low; - u64 mbwu_l_high1, mbwu_l_high2; + u32 mbwu_l_high1, mbwu_l_high2; mpam_mon_sel_lock_held(msc); WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); - mbwu_l_high2 = __mpam_read_reg(msc, MSMON_MBWU_L + 4); + __mpam_read_reg(msc, MSMON_MBWU_L + 4, &mbwu_l_high2); do { mbwu_l_high1 = mbwu_l_high2; - mbwu_l_low = __mpam_read_reg(msc, MSMON_MBWU_L); - mbwu_l_high2 = __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); retry--; } while (mbwu_l_high1 != mbwu_l_high2 && retry > 0); if (mbwu_l_high1 == mbwu_l_high2) - return (mbwu_l_high1 << 32) | mbwu_l_low; + return ((u64)mbwu_l_high1 << 32) | mbwu_l_low; pr_warn("Failed to read a stable value\n"); return MSMON___L_NRDY; @@ -1120,14 +1144,14 @@ static void read_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val, switch (m->type) { case mpam_feat_msmon_csu: - *ctl_val = mpam_read_monsel_reg(msc, CFG_CSU_CTL); - *flt_val = 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 = mpam_read_monsel_reg(msc, CFG_MBWU_CTL); - *flt_val = 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); @@ -1206,6 +1230,7 @@ static u64 mpam_msmon_overflow_val(enum mpam_device_features type, static void __ris_msmon_read(void *arg) { u64 now; + u32 now32; bool nrdy = false; bool config_mismatch; bool overflow = false; @@ -1268,9 +1293,9 @@ static void __ris_msmon_read(void *arg) switch (m->type) { case mpam_feat_msmon_csu: - now = mpam_read_monsel_reg(msc, CSU); - nrdy = now & MSMON___NRDY; - now = FIELD_GET(MSMON___VALUE, now); + mpam_read_monsel_reg(msc, CSU, &now32); + nrdy = now32 & MSMON___NRDY; + now = FIELD_GET(MSMON___VALUE, now32); if (mpam_has_quirk(IGNORE_CSU_NRDY, msc) && m->waited_timeout) nrdy = false; @@ -1288,9 +1313,9 @@ static void __ris_msmon_read(void *arg) else now = FIELD_GET(MSMON___L_VALUE, now); } else { - now = mpam_read_monsel_reg(msc, MBWU); - nrdy = now & MSMON___NRDY; - now = FIELD_GET(MSMON___VALUE, now); + mpam_read_monsel_reg(msc, MBWU, &now32); + nrdy = now32 & MSMON___NRDY; + now = FIELD_GET(MSMON___VALUE, now32); } if (mpam_has_quirk(T241_MBW_COUNTER_SCALE_64, msc) && @@ -1685,16 +1710,18 @@ static int mpam_save_mbwu_state(void *arg) mon_sel = 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 = mpam_read_monsel_reg(msc, CFG_MBWU_FLT); - cur_ctl = 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); if (mpam_ris_has_mbwu_long_counter(ris)) { val = mpam_msc_read_mbwu_l(msc); mpam_msc_zero_mbwu_l(msc); } else { - val = mpam_read_monsel_reg(msc, MBWU); + u32 val32; + + mpam_read_monsel_reg(msc, MBWU, &val32); + val = val32; mpam_write_monsel_reg(msc, MBWU, 0); } -- 2.43.0