* [PATCH RFC v2 01/10] arm_mpam: Fix the RIS index range check in mpam_ris_create_locked
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 02/10] arm_mpam: Fix MSC MMIO window size off-by-one with resource_size() Yin Li
` (8 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
The RIS selector field is defined as MPAMCFG_PART_SEL_RIS (bits 27:24),
which is 4 bits wide and gives valid indices 0..15. MPAM_MSC_MAX_NUM_RIS
is defined as 16, so the check should use >= to reject index 16 and
above. The previous > check incorrectly accepted index 16 as valid.
Fixes: 01fb4b822472 ("arm_mpam: Add the class and component structures for firmware described ris")
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
---
drivers/resctrl/mpam_devices.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index dd422c56fbb1..6da217abf689 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -552,7 +552,7 @@ static int mpam_ris_create_locked(struct mpam_msc *msc, u8 ris_idx,
lockdep_assert_held(&mpam_list_lock);
- if (ris_idx > MPAM_MSC_MAX_NUM_RIS)
+ if (ris_idx >= MPAM_MSC_MAX_NUM_RIS)
return -EINVAL;
if (test_and_set_bit(ris_idx, &msc->ris_idxs))
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH RFC v2 02/10] arm_mpam: Fix MSC MMIO window size off-by-one with resource_size()
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 01/10] arm_mpam: Fix the RIS index range check in mpam_ris_create_locked Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 03/10] dt-bindings: arm: Add MPAM MSC binding Yin Li
` (7 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree, kernel test robot
struct resource uses an inclusive end address, so the window size is
end - start + 1. do_mpam_msc_drv_probe() computed it as end - start,
which is one byte too small.
mapped_hwpage_sz is used by the register access bounds checks, which
have the form "offset + width > mapped_hwpage_sz". With the size one
byte too small, an access to the last register in the window is
incorrectly flagged as out of bounds: for a 0x1000 window, a 4-byte
access at offset 0xFFC (bytes 0xFFC..0xFFF, legal) computes
0xFFC + 4 = 0x1000 > 0xFFF and falsely warns.
Use resource_size() so the size is correct. The ">" bounds checks are
correct as-is once the size is accurate and are left unchanged.
Fixes: f04046f2577a ("arm_mpam: Add probe/remove for mpam msc driver and kbuild boiler plate")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202609030809.ObirDhR3-lkp@intel.com/
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Ben Horgan <ben.horgan@arm.com>
---
drivers/resctrl/mpam_devices.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 6da217abf689..c68135ee0ffc 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -2095,7 +2095,7 @@ static struct mpam_msc *do_mpam_msc_drv_probe(struct platform_device *pdev)
dev_err_once(dev, "Failed to map MSC base address\n");
return ERR_CAST(io);
}
- msc->mapped_hwpage_sz = msc_res->end - msc_res->start;
+ msc->mapped_hwpage_sz = resource_size(msc_res);
msc->mapped_hwpage = io;
} else {
return ERR_PTR(-EINVAL);
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH RFC v2 03/10] dt-bindings: arm: Add MPAM MSC binding
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 01/10] arm_mpam: Fix the RIS index range check in mpam_ris_create_locked Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 02/10] arm_mpam: Fix MSC MMIO window size off-by-one with resource_size() Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 14:41 ` Andre Przywara
2026-09-14 9:37 ` [PATCH RFC v2 04/10] cacheinfo: Expose the code to generate a cache-id from a device_node Yin Li
` (6 subsequent siblings)
9 siblings, 1 reply; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
From: Rob Herring <robh@kernel.org>
The binding is designed around the assumption that an MSC will be a
sub-block of something else such as a memory controller, cache controller,
or IOMMU. However, it's certainly possible a design does not have that
association or has a mixture of both, so the binding illustrates how we can
support that with RIS child nodes.
A key part of MPAM is we need to know about all of the MSCs in the system
before it can be enabled. This drives the need for the genericish
'arm,mpam-msc' compatible. Though we can't assume an MSC is accessible
until a h/w specific driver potentially enables the h/w.
Cc: James Morse <james.morse@arm.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
---
.../devicetree/bindings/arm/arm,mpam-msc.yaml | 199 +++++++++++++++++++++
1 file changed, 199 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
new file mode 100644
index 000000000000..53a6fdbbf05f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
@@ -0,0 +1,199 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/arm,mpam-msc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Arm Memory System Resource Partitioning and Monitoring (MPAM)
+
+description: |
+ The Arm MPAM specification can be found here:
+
+ https://developer.arm.com/documentation/ddi0598/latest
+
+maintainers:
+ - Rob Herring <robh@kernel.org>
+
+properties:
+ compatible:
+ items:
+ - const: arm,mpam-msc # Further details are discoverable
+ - const: arm,mpam-memory-controller-msc
+
+ reg:
+ maxItems: 1
+ description: A memory region containing registers as defined in the MPAM
+ specification.
+
+ interrupts:
+ minItems: 1
+ items:
+ - description: error (optional)
+ - description: overflow (optional, only for monitoring)
+
+ interrupt-names:
+ oneOf:
+ - items:
+ - enum: [ error, overflow ]
+ - items:
+ - const: error
+ - const: overflow
+
+ arm,not-ready-us:
+ description: The maximum time in microseconds for monitoring data to be
+ accurate after a settings change. For more information, see the
+ Not-Ready (NRDY) bit description in the MPAM specification.
+
+ numa-node-id: true # see NUMA binding
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+patternProperties:
+ '^ris@[0-9a-f]+$':
+ type: object
+ additionalProperties: false
+ description:
+ RIS nodes for each resource instance in an MSC. These nodes are required
+ for each resource instance implementing known MPAM controls
+
+ properties:
+ compatible:
+ enum:
+ - arm,mpam-cache
+ # Memory bandwidth
+ - arm,mpam-memory
+
+ reg:
+ minimum: 0
+ maximum: 0xf
+
+ cpus:
+ description:
+ Phandle(s) to the CPU node(s) this RIS belongs to. By default, the parent
+ device's affinity is used.
+
+ arm,mpam-device:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ By default, the MPAM enabled device associated with a RIS is the MSC's
+ parent node. It is possible for each RIS to be associated with different
+ devices in which case 'arm,mpam-device' should be used.
+
+ required:
+ - compatible
+ - reg
+
+required:
+ - compatible
+ - reg
+
+dependencies:
+ interrupts: [ interrupt-names ]
+
+additionalProperties: false
+
+examples:
+ - |
+ L3: cache-controller@30000000 {
+ compatible = "arm,dsu-l3-cache", "cache";
+ cache-level = <3>;
+ cache-unified;
+
+ ranges = <0x0 0x30000000 0x800000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ msc@10000 {
+ compatible = "arm,mpam-msc";
+
+ reg = <0x10000 0x2000>;
+ interrupts = <1>, <2>;
+ interrupt-names = "error", "overflow";
+ arm,not-ready-us = <1>;
+ /* CPU affinity implied by parent cache node */
+ };
+ };
+
+ mem: memory-controller@20000 {
+ compatible = "foo,a-memory-controller";
+ reg = <0x20000 0x1000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ msc@21000 {
+ compatible = "arm,mpam-memory-controller-msc", "arm,mpam-msc";
+ reg = <0x21000 0x1000>;
+ interrupts = <3>;
+ interrupt-names = "error";
+ arm,not-ready-us = <1>;
+ numa-node-id = <1>;
+ };
+ };
+
+ iommu@40000 {
+ reg = <0x40000 0x1000>;
+
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ msc@41000 {
+ compatible = "arm,mpam-msc";
+ reg = <0 0x1000>;
+ interrupts = <5>, <6>;
+ interrupt-names = "error", "overflow";
+ arm,not-ready-us = <1>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ris@2 {
+ compatible = "arm,mpam-cache";
+ reg = <0>;
+ // TODO: How to map to device(s)?
+ };
+ };
+ };
+
+ msc@80000 {
+ compatible = "foo,a-standalone-msc";
+ reg = <0x80000 0x1000>;
+
+ clocks = <&clks 123>;
+
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ msc@10000 {
+ compatible = "arm,mpam-msc";
+
+ reg = <0x10000 0x2000>;
+ interrupts = <7>;
+ interrupt-names = "overflow";
+ arm,not-ready-us = <1>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ris@0 {
+ compatible = "arm,mpam-cache";
+ reg = <0>;
+ arm,mpam-device = <&L2_0>;
+ };
+
+ ris@1 {
+ compatible = "arm,mpam-memory";
+ reg = <1>;
+ arm,mpam-device = <&mem>;
+ };
+ };
+ };
+
+...
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC v2 03/10] dt-bindings: arm: Add MPAM MSC binding
2026-09-14 9:37 ` [PATCH RFC v2 03/10] dt-bindings: arm: Add MPAM MSC binding Yin Li
@ 2026-09-14 14:41 ` Andre Przywara
2026-09-14 14:50 ` Andre Przywara
0 siblings, 1 reply; 18+ messages in thread
From: Andre Przywara @ 2026-09-14 14:41 UTC (permalink / raw)
To: Yin Li, James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Drew Fustini, Ilpo Järvinen, Shaopeng Tan, trilok.soni,
aiqun.yu, ganapatrao.kulkarni, Srivathsa L Rao, Huang Yiwei,
linux-arm-kernel, linux-arm-msm, linux-kernel, driver-core,
devicetree
Hi,
On 9/14/26 11:37, Yin Li wrote:
> From: Rob Herring <robh@kernel.org>
>
> The binding is designed around the assumption that an MSC will be a
> sub-block of something else such as a memory controller, cache controller,
> or IOMMU. However, it's certainly possible a design does not have that
> association or has a mixture of both, so the binding illustrates how we can
> support that with RIS child nodes.
>
> A key part of MPAM is we need to know about all of the MSCs in the system
> before it can be enabled. This drives the need for the genericish
> 'arm,mpam-msc' compatible. Though we can't assume an MSC is accessible
> until a h/w specific driver potentially enables the h/w.
>
> Cc: James Morse <james.morse@arm.com>
> Signed-off-by: Rob Herring <robh@kernel.org>
> Signed-off-by: James Morse <james.morse@arm.com>
> Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
> ---
> .../devicetree/bindings/arm/arm,mpam-msc.yaml | 199 +++++++++++++++++++++
> 1 file changed, 199 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
> new file mode 100644
> index 000000000000..53a6fdbbf05f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
> @@ -0,0 +1,199 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/arm,mpam-msc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Arm Memory System Resource Partitioning and Monitoring (MPAM)
> +
> +description: |
> + The Arm MPAM specification can be found here:
> +
> + https://developer.arm.com/documentation/ddi0598/latest
> +
> +maintainers:
> + - Rob Herring <robh@kernel.org>
> +
> +properties:
> + compatible:
> + items:
> + - const: arm,mpam-msc # Further details are discoverable
> + - const: arm,mpam-memory-controller-msc
But that doesn't match the examples below, does it? Don't we want to
allow just "arm,mpam-msc", but also the memory controller string, with
"arm,mpam-msc" as a fallback?
I guess the pattern should then look similar to interrupt-names below?
> +
> + reg:
> + maxItems: 1
> + description: A memory region containing registers as defined in the MPAM
> + specification.
> +
> + interrupts:
> + minItems: 1
> + items:
> + - description: error (optional)
> + - description: overflow (optional, only for monitoring)
> +
> + interrupt-names:
> + oneOf:
> + - items:
> + - enum: [ error, overflow ]
> + - items:
> + - const: error
> + - const: overflow
> +
> + arm,not-ready-us:
> + description: The maximum time in microseconds for monitoring data to be
> + accurate after a settings change. For more information, see the
> + Not-Ready (NRDY) bit description in the MPAM specification.
> +
> + numa-node-id: true # see NUMA binding
> +
> + '#address-cells':
> + const: 1
> +
> + '#size-cells':
> + const: 0
> +
> +patternProperties:
> + '^ris@[0-9a-f]+$':
> + type: object
> + additionalProperties: false
> + description:
> + RIS nodes for each resource instance in an MSC. These nodes are required
> + for each resource instance implementing known MPAM controls
> +
> + properties:
> + compatible:
> + enum:
> + - arm,mpam-cache
> + # Memory bandwidth
> + - arm,mpam-memory
> +
> + reg:
> + minimum: 0
> + maximum: 0xf
> +
> + cpus:
> + description:
> + Phandle(s) to the CPU node(s) this RIS belongs to. By default, the parent
> + device's affinity is used.
> +
> + arm,mpam-device:
> + $ref: /schemas/types.yaml#/definitions/phandle
> + description:
> + By default, the MPAM enabled device associated with a RIS is the MSC's
> + parent node. It is possible for each RIS to be associated with different
> + devices in which case 'arm,mpam-device' should be used.
> +
> + required:
> + - compatible
> + - reg
> +
> +required:
> + - compatible
> + - reg
> +
> +dependencies:
> + interrupts: [ interrupt-names ]
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + L3: cache-controller@30000000 {
> + compatible = "arm,dsu-l3-cache", "cache";
> + cache-level = <3>;
> + cache-unified;
> +
> + ranges = <0x0 0x30000000 0x800000>;
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + msc@10000 {
> + compatible = "arm,mpam-msc";
> +
> + reg = <0x10000 0x2000>;
> + interrupts = <1>, <2>;
> + interrupt-names = "error", "overflow";
> + arm,not-ready-us = <1>;
> + /* CPU affinity implied by parent cache node */
> + };
> + };
> +
> + mem: memory-controller@20000 {
> + compatible = "foo,a-memory-controller";
> + reg = <0x20000 0x1000>;
> +
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;
> +
> + msc@21000 {
> + compatible = "arm,mpam-memory-controller-msc", "arm,mpam-msc";
> + reg = <0x21000 0x1000>;
> + interrupts = <3>;
> + interrupt-names = "error";
> + arm,not-ready-us = <1>;
> + numa-node-id = <1>;
> + };
> + };
> +
> + iommu@40000 {
> + reg = <0x40000 0x1000>;
> +
> + ranges;
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + msc@41000 {
> + compatible = "arm,mpam-msc";
> + reg = <0 0x1000>;
> + interrupts = <5>, <6>;
> + interrupt-names = "error", "overflow";
> + arm,not-ready-us = <1>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + ris@2 {
> + compatible = "arm,mpam-cache";
> + reg = <0>;
> + // TODO: How to map to device(s)?
Maybe we should remove this example, if it isn't ready yet?
Cheers,
Andre
> + };
> + };
> + };
> +
> + msc@80000 {
> + compatible = "foo,a-standalone-msc";
> + reg = <0x80000 0x1000>;
> +
> + clocks = <&clks 123>;
> +
> + ranges;
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + msc@10000 {
> + compatible = "arm,mpam-msc";
> +
> + reg = <0x10000 0x2000>;
> + interrupts = <7>;
> + interrupt-names = "overflow";
> + arm,not-ready-us = <1>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + ris@0 {
> + compatible = "arm,mpam-cache";
> + reg = <0>;
> + arm,mpam-device = <&L2_0>;
> + };
> +
> + ris@1 {
> + compatible = "arm,mpam-memory";
> + reg = <1>;
> + arm,mpam-device = <&mem>;
> + };
> + };
> + };
> +
> +...
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC v2 03/10] dt-bindings: arm: Add MPAM MSC binding
2026-09-14 14:41 ` Andre Przywara
@ 2026-09-14 14:50 ` Andre Przywara
2026-09-15 2:49 ` Yin Li
0 siblings, 1 reply; 18+ messages in thread
From: Andre Przywara @ 2026-09-14 14:50 UTC (permalink / raw)
To: Yin Li, James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Drew Fustini, Ilpo Järvinen, Shaopeng Tan, trilok.soni,
aiqun.yu, ganapatrao.kulkarni, Srivathsa L Rao, Huang Yiwei,
linux-arm-kernel, linux-arm-msm, linux-kernel, driver-core,
devicetree
Hi,
On 9/14/26 16:41, Andre Przywara wrote:
> Hi,
>
> On 9/14/26 11:37, Yin Li wrote:
>> From: Rob Herring <robh@kernel.org>
>>
>> The binding is designed around the assumption that an MSC will be a
>> sub-block of something else such as a memory controller, cache
>> controller,
>> or IOMMU. However, it's certainly possible a design does not have that
>> association or has a mixture of both, so the binding illustrates how
>> we can
>> support that with RIS child nodes.
>>
>> A key part of MPAM is we need to know about all of the MSCs in the system
>> before it can be enabled. This drives the need for the genericish
>> 'arm,mpam-msc' compatible. Though we can't assume an MSC is accessible
>> until a h/w specific driver potentially enables the h/w.
>>
>> Cc: James Morse <james.morse@arm.com>
>> Signed-off-by: Rob Herring <robh@kernel.org>
>> Signed-off-by: James Morse <james.morse@arm.com>
>> Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
>> ---
>> .../devicetree/bindings/arm/arm,mpam-msc.yaml | 199 +++++++++++
>> ++++++++++
>> 1 file changed, 199 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
>> b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
>> new file mode 100644
>> index 000000000000..53a6fdbbf05f
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
>> @@ -0,0 +1,199 @@
>> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/arm/arm,mpam-msc.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Arm Memory System Resource Partitioning and Monitoring (MPAM)
>> +
>> +description: |
>> + The Arm MPAM specification can be found here:
>> +
>> + https://developer.arm.com/documentation/ddi0598/latest
>> +
>> +maintainers:
>> + - Rob Herring <robh@kernel.org>
>> +
>> +properties:
>> + compatible:
>> + items:
>> + - const: arm,mpam-msc # Further details are
>> discoverable
>> + - const: arm,mpam-memory-controller-msc
>
> But that doesn't match the examples below, does it? Don't we want to
> allow just "arm,mpam-msc", but also the memory controller string, with
> "arm,mpam-msc" as a fallback?
> I guess the pattern should then look similar to interrupt-names below?
Just seeing that you fix this and other things up in patch 08/10 later.
I think it's confusing to have this split now for a v2 still. I wouldn't
be aware of previous review of this original patch, so it doesn't really
matter. Please squash them.
So I think you should merge 07/10 and 08/10 into their original patches,
otherwise reviewers might just get confused.
But you might wait for a bit with a repost, to see if there are more
generic comments on DT support.
Cheers,
Andre
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFC v2 03/10] dt-bindings: arm: Add MPAM MSC binding
2026-09-14 14:50 ` Andre Przywara
@ 2026-09-15 2:49 ` Yin Li
0 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-15 2:49 UTC (permalink / raw)
To: Andre Przywara, James Morse, Rob Herring, Shanker Donthineni,
Ben Horgan, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Drew Fustini, Ilpo Järvinen, Shaopeng Tan, trilok.soni,
aiqun.yu, ganapatrao.kulkarni, Srivathsa L Rao, Huang Yiwei,
linux-arm-kernel, linux-arm-msm, linux-kernel, driver-core,
devicetree
On 9/14/2026 10:50 PM, Andre Przywara wrote:
> Hi,
>
> On 9/14/26 16:41, Andre Przywara wrote:
>> Hi,
>>
>> On 9/14/26 11:37, Yin Li wrote:
>>> From: Rob Herring <robh@kernel.org>
>>>
>>> The binding is designed around the assumption that an MSC will be a
>>> sub-block of something else such as a memory controller, cache
>>> controller,
>>> or IOMMU. However, it's certainly possible a design does not have that
>>> association or has a mixture of both, so the binding illustrates how
>>> we can
>>> support that with RIS child nodes.
>>>
>>> A key part of MPAM is we need to know about all of the MSCs in the
>>> system
>>> before it can be enabled. This drives the need for the genericish
>>> 'arm,mpam-msc' compatible. Though we can't assume an MSC is accessible
>>> until a h/w specific driver potentially enables the h/w.
>>>
>>> Cc: James Morse <james.morse@arm.com>
>>> Signed-off-by: Rob Herring <robh@kernel.org>
>>> Signed-off-by: James Morse <james.morse@arm.com>
>>> Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
>>> ---
>>> .../devicetree/bindings/arm/arm,mpam-msc.yaml | 199 ++++++++++
>>> + ++++++++++
>>> 1 file changed, 199 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
>>> b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
>>> new file mode 100644
>>> index 000000000000..53a6fdbbf05f
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
>>> @@ -0,0 +1,199 @@
>>> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/arm/arm,mpam-msc.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: Arm Memory System Resource Partitioning and Monitoring (MPAM)
>>> +
>>> +description: |
>>> + The Arm MPAM specification can be found here:
>>> +
>>> + https://developer.arm.com/documentation/ddi0598/latest
>>> +
>>> +maintainers:
>>> + - Rob Herring <robh@kernel.org>
>>> +
>>> +properties:
>>> + compatible:
>>> + items:
>>> + - const: arm,mpam-msc # Further details are
>>> discoverable
>>> + - const: arm,mpam-memory-controller-msc
>>
>> But that doesn't match the examples below, does it? Don't we want to
>> allow just "arm,mpam-msc", but also the memory controller string, with
>> "arm,mpam-msc" as a fallback?
>> I guess the pattern should then look similar to interrupt-names below?
>
> Just seeing that you fix this and other things up in patch 08/10 later.
> I think it's confusing to have this split now for a v2 still. I wouldn't
> be aware of previous review of this original patch, so it doesn't really
> matter. Please squash them.
>
> So I think you should merge 07/10 and 08/10 into their original patches,
> otherwise reviewers might just get confused.
>
> But you might wait for a bit with a repost, to see if there are more
> generic comments on DT support.
>
Hi Andre,
Good catch on the compatible issue in 03/10: you're right, "items"
requires both strings to be present, whereas we want to allow standalone
"arm,mpam-msc" or the two-item combination. This is fixed in 08/10 using
"oneOf"; the iommu example with the TODO is also fixed there.
On squashing: sorry for the confusion and agreed on both points. Since
this is still an RFC and the original authors haven't commented yet,
I've kept the fixes as separate patches to make it easier for them to
review. I'll squash them in the next version.
Thanks for your quick review!
Yin
> Cheers,
> Andre
>
>
--
Thx and BRs,
Yin
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH RFC v2 04/10] cacheinfo: Expose the code to generate a cache-id from a device_node
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
` (2 preceding siblings ...)
2026-09-14 9:37 ` [PATCH RFC v2 03/10] dt-bindings: arm: Add MPAM MSC binding Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 12:26 ` Andre Przywara
2026-09-14 9:37 ` [PATCH RFC v2 05/10] arm_mpam: Add device tree support for MSC probing Yin Li
` (5 subsequent siblings)
9 siblings, 1 reply; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
From: James Morse <james.morse@arm.com>
The MPAM driver identifies caches by id for use with resctrl. It
needs to know the cache-id when probe-ing, but the value isn't set
in cacheinfo until device_initcall(). Even after device_initcall(),
the cache-id is only available if at least one CPU associated with
the cache is online.
Instead of making the driver wait, expose the code that generates the
cache-id. The parts of the MPAM driver that run early can use this to
set up the resctrl structures before cacheinfo is ready in
device_initcall().
Signed-off-by: James Morse <james.morse@arm.com>
[ Yin Li: fix context conflicts in cacheinfo.c and cacheinfo.h; guard the
cache_of_calculate_id() declaration with CONFIG_OF to prevent build
errors when CONFIG_OF is not set ]
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
---
drivers/base/cacheinfo.c | 17 ++++++++++++-----
include/linux/cacheinfo.h | 3 +++
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 9f9c72727a05..f75e7f64038b 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -226,8 +226,7 @@ static bool match_cache_node(struct device_node *cpu,
#define arch_compact_of_hwid(_x) (_x)
#endif
-static void cache_of_set_id(struct cacheinfo *this_leaf,
- struct device_node *cache_node)
+u32 cache_of_calculate_id(struct device_node *cache_node)
{
struct device_node *cpu;
u32 min_id = ~0;
@@ -238,15 +237,23 @@ static void cache_of_set_id(struct cacheinfo *this_leaf,
id = arch_compact_of_hwid(id);
if (FIELD_GET(GENMASK_ULL(63, 32), id)) {
of_node_put(cpu);
- return;
+ return ~0;
}
if (match_cache_node(cpu, cache_node))
min_id = min(min_id, id);
}
- if (min_id != ~0) {
- this_leaf->id = min_id;
+ return min_id;
+}
+
+static void cache_of_set_id(struct cacheinfo *this_leaf,
+ struct device_node *cache_node)
+{
+ u32 id = cache_of_calculate_id(cache_node);
+
+ if (id != ~0) {
+ this_leaf->id = id;
this_leaf->attributes |= CACHE_ID;
}
}
diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
index fc879ac4cc4f..c33bb3c8bd63 100644
--- a/include/linux/cacheinfo.h
+++ b/include/linux/cacheinfo.h
@@ -113,6 +113,9 @@ int acpi_get_cache_info(unsigned int cpu,
#endif
const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf);
+#ifdef CONFIG_OF
+u32 cache_of_calculate_id(struct device_node *np);
+#endif
/*
* Get the cacheinfo structure for the cache associated with @cpu at
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC v2 04/10] cacheinfo: Expose the code to generate a cache-id from a device_node
2026-09-14 9:37 ` [PATCH RFC v2 04/10] cacheinfo: Expose the code to generate a cache-id from a device_node Yin Li
@ 2026-09-14 12:26 ` Andre Przywara
2026-09-15 6:49 ` Yin Li
0 siblings, 1 reply; 18+ messages in thread
From: Andre Przywara @ 2026-09-14 12:26 UTC (permalink / raw)
To: Yin Li, James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Drew Fustini, Ilpo Järvinen, Shaopeng Tan, trilok.soni,
aiqun.yu, ganapatrao.kulkarni, Srivathsa L Rao, Huang Yiwei,
linux-arm-kernel, linux-arm-msm, linux-kernel, driver-core,
devicetree
Hi,
On 9/14/26 11:37, Yin Li wrote:
> From: James Morse <james.morse@arm.com>
>
> The MPAM driver identifies caches by id for use with resctrl. It
> needs to know the cache-id when probe-ing, but the value isn't set
> in cacheinfo until device_initcall(). Even after device_initcall(),
> the cache-id is only available if at least one CPU associated with
> the cache is online.
>
> Instead of making the driver wait, expose the code that generates the
> cache-id. The parts of the MPAM driver that run early can use this to
> set up the resctrl structures before cacheinfo is ready in
> device_initcall().
>
> Signed-off-by: James Morse <james.morse@arm.com>
> [ Yin Li: fix context conflicts in cacheinfo.c and cacheinfo.h; guard the
> cache_of_calculate_id() declaration with CONFIG_OF to prevent build
> errors when CONFIG_OF is not set ]
You can shorten that part in square brackets: doing adjustments due to
rebasing is surely implied, and you can shorten the rest, like:
[ Yin Li: guard cache_of_calculate_id() prototype ]
Speaking of which ...
> Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
> ---
> drivers/base/cacheinfo.c | 17 ++++++++++++-----
> include/linux/cacheinfo.h | 3 +++
> 2 files changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
> index 9f9c72727a05..f75e7f64038b 100644
> --- a/drivers/base/cacheinfo.c
> +++ b/drivers/base/cacheinfo.c
> @@ -226,8 +226,7 @@ static bool match_cache_node(struct device_node *cpu,
> #define arch_compact_of_hwid(_x) (_x)
> #endif
>
> -static void cache_of_set_id(struct cacheinfo *this_leaf,
> - struct device_node *cache_node)
> +u32 cache_of_calculate_id(struct device_node *cache_node)
> {
> struct device_node *cpu;
> u32 min_id = ~0;
> @@ -238,15 +237,23 @@ static void cache_of_set_id(struct cacheinfo *this_leaf,
> id = arch_compact_of_hwid(id);
> if (FIELD_GET(GENMASK_ULL(63, 32), id)) {
> of_node_put(cpu);
> - return;
> + return ~0;
> }
>
> if (match_cache_node(cpu, cache_node))
> min_id = min(min_id, id);
> }
>
> - if (min_id != ~0) {
> - this_leaf->id = min_id;
> + return min_id;
> +}
> +
> +static void cache_of_set_id(struct cacheinfo *this_leaf,
> + struct device_node *cache_node)
> +{
> + u32 id = cache_of_calculate_id(cache_node);
> +
> + if (id != ~0) {
> + this_leaf->id = id;
> this_leaf->attributes |= CACHE_ID;
> }
> }
> diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
> index fc879ac4cc4f..c33bb3c8bd63 100644
> --- a/include/linux/cacheinfo.h
> +++ b/include/linux/cacheinfo.h
> @@ -113,6 +113,9 @@ int acpi_get_cache_info(unsigned int cpu,
> #endif
>
> const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf);
> +#ifdef CONFIG_OF
Why is that, exactly? First IIUC it's quite uncommon to use #ifdef
guards around prototypes (unless they are stubbed without the symbol
defined). Using types protected by those symbols if certainly another
reason, and it looks like this would be the case here, but I had no
trouble building the kernel for x86, where CONFIG_OF is not defined.
So can you share a .config example (or give a hint) as to where this
fails building?
And if it does, wouldn't it be better to always include <linux/of.h> in
that file instead? I think I see a similar pattern elsewhere
(rfkill-gpio.c, sound/ac97/bus.c).
Cheers,
Andre
> +u32 cache_of_calculate_id(struct device_node *np);
> +#endif
>
> /*
> * Get the cacheinfo structure for the cache associated with @cpu at
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC v2 04/10] cacheinfo: Expose the code to generate a cache-id from a device_node
2026-09-14 12:26 ` Andre Przywara
@ 2026-09-15 6:49 ` Yin Li
2026-09-15 7:59 ` Andre Przywara
0 siblings, 1 reply; 18+ messages in thread
From: Yin Li @ 2026-09-15 6:49 UTC (permalink / raw)
To: Andre Przywara, James Morse, Rob Herring, Shanker Donthineni,
Ben Horgan, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Drew Fustini, Ilpo Järvinen, Shaopeng Tan, trilok.soni,
aiqun.yu, ganapatrao.kulkarni, Srivathsa L Rao, Huang Yiwei,
linux-arm-kernel, linux-arm-msm, linux-kernel, driver-core,
devicetree
On 9/14/2026 8:26 PM, Andre Przywara wrote:
> Hi,
>
> On 9/14/26 11:37, Yin Li wrote:
>> From: James Morse <james.morse@arm.com>
>>
>> The MPAM driver identifies caches by id for use with resctrl. It
>> needs to know the cache-id when probe-ing, but the value isn't set
>> in cacheinfo until device_initcall(). Even after device_initcall(),
>> the cache-id is only available if at least one CPU associated with
>> the cache is online.
>>
>> Instead of making the driver wait, expose the code that generates the
>> cache-id. The parts of the MPAM driver that run early can use this to
>> set up the resctrl structures before cacheinfo is ready in
>> device_initcall().
>>
>> Signed-off-by: James Morse <james.morse@arm.com>
>> [ Yin Li: fix context conflicts in cacheinfo.c and cacheinfo.h; guard the
>> cache_of_calculate_id() declaration with CONFIG_OF to prevent build
>> errors when CONFIG_OF is not set ]
>
> You can shorten that part in square brackets: doing adjustments due to
> rebasing is surely implied, and you can shorten the rest, like:
> [ Yin Li: guard cache_of_calculate_id() prototype ]
>
> Speaking of which ...
>
>> Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
>> ---
>> drivers/base/cacheinfo.c | 17 ++++++++++++-----
>> include/linux/cacheinfo.h | 3 +++
>> 2 files changed, 15 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
>> index 9f9c72727a05..f75e7f64038b 100644
>> --- a/drivers/base/cacheinfo.c
>> +++ b/drivers/base/cacheinfo.c
>> @@ -226,8 +226,7 @@ static bool match_cache_node(struct device_node *cpu,
>> #define arch_compact_of_hwid(_x) (_x)
>> #endif
>> -static void cache_of_set_id(struct cacheinfo *this_leaf,
>> - struct device_node *cache_node)
>> +u32 cache_of_calculate_id(struct device_node *cache_node)
>> {
>> struct device_node *cpu;
>> u32 min_id = ~0;
>> @@ -238,15 +237,23 @@ static void cache_of_set_id(struct cacheinfo
>> *this_leaf,
>> id = arch_compact_of_hwid(id);
>> if (FIELD_GET(GENMASK_ULL(63, 32), id)) {
>> of_node_put(cpu);
>> - return;
>> + return ~0;
>> }
>> if (match_cache_node(cpu, cache_node))
>> min_id = min(min_id, id);
>> }
>> - if (min_id != ~0) {
>> - this_leaf->id = min_id;
>> + return min_id;
>> +}
>> +
>> +static void cache_of_set_id(struct cacheinfo *this_leaf,
>> + struct device_node *cache_node)
>> +{
>> + u32 id = cache_of_calculate_id(cache_node);
>> +
>> + if (id != ~0) {
>> + this_leaf->id = id;
>> this_leaf->attributes |= CACHE_ID;
>> }
>> }
>> diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
>> index fc879ac4cc4f..c33bb3c8bd63 100644
>> --- a/include/linux/cacheinfo.h
>> +++ b/include/linux/cacheinfo.h
>> @@ -113,6 +113,9 @@ int acpi_get_cache_info(unsigned int cpu,
>> #endif
>> const struct attribute_group *cache_get_priv_group(struct cacheinfo
>> *this_leaf);
>> +#ifdef CONFIG_OF
>
> Why is that, exactly? First IIUC it's quite uncommon to use #ifdef
> guards around prototypes (unless they are stubbed without the symbol
> defined). Using types protected by those symbols if certainly another
> reason, and it looks like this would be the case here, but I had no
> trouble building the kernel for x86, where CONFIG_OF is not defined.
> So can you share a .config example (or give a hint) as to where this
> fails building?
> And if it does, wouldn't it be better to always include <linux/of.h> in
> that file instead? I think I see a similar pattern elsewhere (rfkill-
> gpio.c, sound/ac97/bus.c).
>
Hi Andre,
On the #ifdef CONFIG_OF: I also verified that removing the guard doesn't
break the build. However, since the implementation in cacheinfo.c is
itself guarded by #ifdef CONFIG_OF, exposing the prototype
unconditionally could cause a link error on CONFIG_OF=n builds if called
from outside the ARM64/MPAM path. A more idiomatic approach might be to
use a stub to keep the header consistent with the implementation:
#ifdef CONFIG_OF
u32 cache_of_calculate_id(struct device_node *np);
#else
static inline u32 cache_of_calculate_id(struct device_node *np)
{
return ~0U;
}
#endif
Would that work for you? Otherwise I'm happy to just drop the guard in
the next version.
Thanks,
Yin
> Cheers,
> Andre
>
>
>> +u32 cache_of_calculate_id(struct device_node *np);
>> +#endif
>> /*
>> * Get the cacheinfo structure for the cache associated with @cpu at
>>
>
--
Thx and BRs,
Yin
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC v2 04/10] cacheinfo: Expose the code to generate a cache-id from a device_node
2026-09-15 6:49 ` Yin Li
@ 2026-09-15 7:59 ` Andre Przywara
2026-09-16 2:29 ` Yin Li
0 siblings, 1 reply; 18+ messages in thread
From: Andre Przywara @ 2026-09-15 7:59 UTC (permalink / raw)
To: Yin Li, James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Drew Fustini, Ilpo Järvinen, Shaopeng Tan, trilok.soni,
aiqun.yu, ganapatrao.kulkarni, Srivathsa L Rao, Huang Yiwei,
linux-arm-kernel, linux-arm-msm, linux-kernel, driver-core,
devicetree
Hi Yin,
thanks for the reply!
On 9/15/26 08:49, Yin Li wrote:
>
>
> On 9/14/2026 8:26 PM, Andre Przywara wrote:
>> Hi,
>>
>> On 9/14/26 11:37, Yin Li wrote:
>>> From: James Morse <james.morse@arm.com>
>>>
>>> The MPAM driver identifies caches by id for use with resctrl. It
>>> needs to know the cache-id when probe-ing, but the value isn't set
>>> in cacheinfo until device_initcall(). Even after device_initcall(),
>>> the cache-id is only available if at least one CPU associated with
>>> the cache is online.
>>>
>>> Instead of making the driver wait, expose the code that generates the
>>> cache-id. The parts of the MPAM driver that run early can use this to
>>> set up the resctrl structures before cacheinfo is ready in
>>> device_initcall().
>>>
>>> Signed-off-by: James Morse <james.morse@arm.com>
>>> [ Yin Li: fix context conflicts in cacheinfo.c and cacheinfo.h; guard
>>> the
>>> cache_of_calculate_id() declaration with CONFIG_OF to prevent build
>>> errors when CONFIG_OF is not set ]
>>
>> You can shorten that part in square brackets: doing adjustments due to
>> rebasing is surely implied, and you can shorten the rest, like:
>> [ Yin Li: guard cache_of_calculate_id() prototype ]
>>
>> Speaking of which ...
>>
>>> Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
>>> ---
>>> drivers/base/cacheinfo.c | 17 ++++++++++++-----
>>> include/linux/cacheinfo.h | 3 +++
>>> 2 files changed, 15 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
>>> index 9f9c72727a05..f75e7f64038b 100644
>>> --- a/drivers/base/cacheinfo.c
>>> +++ b/drivers/base/cacheinfo.c
>>> @@ -226,8 +226,7 @@ static bool match_cache_node(struct device_node
>>> *cpu,
>>> #define arch_compact_of_hwid(_x) (_x)
>>> #endif
>>> -static void cache_of_set_id(struct cacheinfo *this_leaf,
>>> - struct device_node *cache_node)
>>> +u32 cache_of_calculate_id(struct device_node *cache_node)
>>> {
>>> struct device_node *cpu;
>>> u32 min_id = ~0;
>>> @@ -238,15 +237,23 @@ static void cache_of_set_id(struct cacheinfo
>>> *this_leaf,
>>> id = arch_compact_of_hwid(id);
>>> if (FIELD_GET(GENMASK_ULL(63, 32), id)) {
>>> of_node_put(cpu);
>>> - return;
>>> + return ~0;
>>> }
>>> if (match_cache_node(cpu, cache_node))
>>> min_id = min(min_id, id);
>>> }
>>> - if (min_id != ~0) {
>>> - this_leaf->id = min_id;
>>> + return min_id;
>>> +}
>>> +
>>> +static void cache_of_set_id(struct cacheinfo *this_leaf,
>>> + struct device_node *cache_node)
>>> +{
>>> + u32 id = cache_of_calculate_id(cache_node);
>>> +
>>> + if (id != ~0) {
>>> + this_leaf->id = id;
>>> this_leaf->attributes |= CACHE_ID;
>>> }
>>> }
>>> diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
>>> index fc879ac4cc4f..c33bb3c8bd63 100644
>>> --- a/include/linux/cacheinfo.h
>>> +++ b/include/linux/cacheinfo.h
>>> @@ -113,6 +113,9 @@ int acpi_get_cache_info(unsigned int cpu,
>>> #endif
>>> const struct attribute_group *cache_get_priv_group(struct cacheinfo
>>> *this_leaf);
>>> +#ifdef CONFIG_OF
>>
>> Why is that, exactly? First IIUC it's quite uncommon to use #ifdef
>> guards around prototypes (unless they are stubbed without the symbol
>> defined). Using types protected by those symbols if certainly another
>> reason, and it looks like this would be the case here, but I had no
>> trouble building the kernel for x86, where CONFIG_OF is not defined.
>> So can you share a .config example (or give a hint) as to where this
>> fails building?
>> And if it does, wouldn't it be better to always include <linux/of.h>
>> in that file instead? I think I see a similar pattern elsewhere
>> (rfkill- gpio.c, sound/ac97/bus.c).
>>
>
> Hi Andre,
>
> On the #ifdef CONFIG_OF: I also verified that removing the guard doesn't
> break the build. However, since the implementation in cacheinfo.c is
> itself guarded by #ifdef CONFIG_OF, exposing the prototype
> unconditionally could cause a link error on CONFIG_OF=n builds if called
How so? Just exposing a prototype wouldn't be a problem, as long as you
don't try to call that function. And that would be caught by the linker,
and then you have a different problem anyway (the caller).
The only reason to protect the prototype would be if a type used in the
parameters is not defined. And on the face of it "struct device_node" is
an OF specific type, declared in include/linux/of.h, but as mentioned, I
can't produce a compiler error, and even if so, would prefer to include
of.h instead.
> from outside the ARM64/MPAM path. A more idiomatic approach might be to
> use a stub to keep the header consistent with the implementation:
>
> #ifdef CONFIG_OF
> u32 cache_of_calculate_id(struct device_node *np);
> #else
> static inline u32 cache_of_calculate_id(struct device_node *np)
> {
> return ~0U;
> }
> #endif
>
> Would that work for you?
That's not necessary and doesn't solve the problem: the struct
device_node would be present in both branches, so that doesn't help. And
given there are no preprocessor protections for OF or ACPI in the whole
of mpam_devices.c, that's a non-issue, I'd say.
> Otherwise I'm happy to just drop the guard in
> the next version.
So can you say whether you have a .config that does not build? Or was
that issue just pointed out by some picky AI review tool?
Otherwise I would drop the guards, and wait for the kernel test robot or
Arnd's infamous randconfig builds to show up the exact problem.
Cheers,
Andre
>>
>>> +u32 cache_of_calculate_id(struct device_node *np);
>>> +#endif
>>> /*
>>> * Get the cacheinfo structure for the cache associated with @cpu at
>>>
>>
>
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC v2 04/10] cacheinfo: Expose the code to generate a cache-id from a device_node
2026-09-15 7:59 ` Andre Przywara
@ 2026-09-16 2:29 ` Yin Li
0 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-16 2:29 UTC (permalink / raw)
To: Andre Przywara, James Morse, Rob Herring, Shanker Donthineni,
Ben Horgan, Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Drew Fustini, Ilpo Järvinen, Shaopeng Tan, trilok.soni,
aiqun.yu, ganapatrao.kulkarni, Srivathsa L Rao, Huang Yiwei,
linux-arm-kernel, linux-arm-msm, linux-kernel, driver-core,
devicetree
On 9/15/2026 3:59 PM, Andre Przywara wrote:
> Hi Yin,
>
> thanks for the reply!
>
> On 9/15/26 08:49, Yin Li wrote:
>>
>>
>> On 9/14/2026 8:26 PM, Andre Przywara wrote:
>>> Hi,
>>>
>>> On 9/14/26 11:37, Yin Li wrote:
>>>> From: James Morse <james.morse@arm.com>
>>>>
>>>> The MPAM driver identifies caches by id for use with resctrl. It
>>>> needs to know the cache-id when probe-ing, but the value isn't set
>>>> in cacheinfo until device_initcall(). Even after device_initcall(),
>>>> the cache-id is only available if at least one CPU associated with
>>>> the cache is online.
>>>>
>>>> Instead of making the driver wait, expose the code that generates the
>>>> cache-id. The parts of the MPAM driver that run early can use this to
>>>> set up the resctrl structures before cacheinfo is ready in
>>>> device_initcall().
>>>>
>>>> Signed-off-by: James Morse <james.morse@arm.com>
>>>> [ Yin Li: fix context conflicts in cacheinfo.c and cacheinfo.h;
>>>> guard the
>>>> cache_of_calculate_id() declaration with CONFIG_OF to prevent build
>>>> errors when CONFIG_OF is not set ]
>>>
>>> You can shorten that part in square brackets: doing adjustments due
>>> to rebasing is surely implied, and you can shorten the rest, like:
>>> [ Yin Li: guard cache_of_calculate_id() prototype ]
>>>
>>> Speaking of which ...
>>>
>>>> Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
>>>> ---
>>>> drivers/base/cacheinfo.c | 17 ++++++++++++-----
>>>> include/linux/cacheinfo.h | 3 +++
>>>> 2 files changed, 15 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
>>>> index 9f9c72727a05..f75e7f64038b 100644
>>>> --- a/drivers/base/cacheinfo.c
>>>> +++ b/drivers/base/cacheinfo.c
>>>> @@ -226,8 +226,7 @@ static bool match_cache_node(struct device_node
>>>> *cpu,
>>>> #define arch_compact_of_hwid(_x) (_x)
>>>> #endif
>>>> -static void cache_of_set_id(struct cacheinfo *this_leaf,
>>>> - struct device_node *cache_node)
>>>> +u32 cache_of_calculate_id(struct device_node *cache_node)
>>>> {
>>>> struct device_node *cpu;
>>>> u32 min_id = ~0;
>>>> @@ -238,15 +237,23 @@ static void cache_of_set_id(struct cacheinfo
>>>> *this_leaf,
>>>> id = arch_compact_of_hwid(id);
>>>> if (FIELD_GET(GENMASK_ULL(63, 32), id)) {
>>>> of_node_put(cpu);
>>>> - return;
>>>> + return ~0;
>>>> }
>>>> if (match_cache_node(cpu, cache_node))
>>>> min_id = min(min_id, id);
>>>> }
>>>> - if (min_id != ~0) {
>>>> - this_leaf->id = min_id;
>>>> + return min_id;
>>>> +}
>>>> +
>>>> +static void cache_of_set_id(struct cacheinfo *this_leaf,
>>>> + struct device_node *cache_node)
>>>> +{
>>>> + u32 id = cache_of_calculate_id(cache_node);
>>>> +
>>>> + if (id != ~0) {
>>>> + this_leaf->id = id;
>>>> this_leaf->attributes |= CACHE_ID;
>>>> }
>>>> }
>>>> diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
>>>> index fc879ac4cc4f..c33bb3c8bd63 100644
>>>> --- a/include/linux/cacheinfo.h
>>>> +++ b/include/linux/cacheinfo.h
>>>> @@ -113,6 +113,9 @@ int acpi_get_cache_info(unsigned int cpu,
>>>> #endif
>>>> const struct attribute_group *cache_get_priv_group(struct
>>>> cacheinfo *this_leaf);
>>>> +#ifdef CONFIG_OF
>>>
>>> Why is that, exactly? First IIUC it's quite uncommon to use #ifdef
>>> guards around prototypes (unless they are stubbed without the symbol
>>> defined). Using types protected by those symbols if certainly another
>>> reason, and it looks like this would be the case here, but I had no
>>> trouble building the kernel for x86, where CONFIG_OF is not defined.
>>> So can you share a .config example (or give a hint) as to where this
>>> fails building?
>>> And if it does, wouldn't it be better to always include <linux/of.h>
>>> in that file instead? I think I see a similar pattern elsewhere
>>> (rfkill- gpio.c, sound/ac97/bus.c).
>>>
>>
>> Hi Andre,
>>
>> On the #ifdef CONFIG_OF: I also verified that removing the guard doesn't
>> break the build. However, since the implementation in cacheinfo.c is
>> itself guarded by #ifdef CONFIG_OF, exposing the prototype
>> unconditionally could cause a link error on CONFIG_OF=n builds if called
>
> How so? Just exposing a prototype wouldn't be a problem, as long as you
> don't try to call that function. And that would be caught by the linker,
> and then you have a different problem anyway (the caller).
>
> The only reason to protect the prototype would be if a type used in the
> parameters is not defined. And on the face of it "struct device_node" is
> an OF specific type, declared in include/linux/of.h, but as mentioned, I
> can't produce a compiler error, and even if so, would prefer to include
> of.h instead.
>
Hi Andre,
Thanks for the review.
I'll drop the #ifdef guard in the next version.
Just to clarify: MPAM depends on ARM64, which selects OF, so CONFIG_OF
is always set in any configuration that enables MPAM. I had kept the
guard as a precaution for potential callers outside that dependency
chain, though I take your point that this would be a caller-side issue
rather than something to address in the header.
>> from outside the ARM64/MPAM path. A more idiomatic approach might be to
>> use a stub to keep the header consistent with the implementation:
>>
>> #ifdef CONFIG_OF
>> u32 cache_of_calculate_id(struct device_node *np);
>> #else
>> static inline u32 cache_of_calculate_id(struct device_node *np)
>> {
>> return ~0U;
>> }
>> #endif
>>
>> Would that work for you?
>
> That's not necessary and doesn't solve the problem: the struct
> device_node would be present in both branches, so that doesn't help. And
> given there are no preprocessor protections for OF or ACPI in the whole
> of mpam_devices.c, that's a non-issue, I'd say.
>
>> Otherwise I'm happy to just drop the guard in
>> the next version.
>
> So can you say whether you have a .config that does not build? Or was
> that issue just pointed out by some picky AI review tool?
> Otherwise I would drop the guards, and wait for the kernel test robot or
> Arnd's infamous randconfig builds to show up the exact problem.
>
For context: I did experiment with wrapping all the OF-specific code in
mpam_devices.c with #ifdef CONFIG_OF, but dropped it for the same reason
— the MPAM driver depends on ARM64 which selects OF. I then kept only
the header guard as a precaution for potential external users, but as
you point out, that's not necessary either.
Thanks,
Yin
> Cheers,
> Andre
>
>>>
>>>> +u32 cache_of_calculate_id(struct device_node *np);
>>>> +#endif
>>>> /*
>>>> * Get the cacheinfo structure for the cache associated with @cpu at
>>>>
>>>
>>
>
--
Thx and BRs,
Yin
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH RFC v2 05/10] arm_mpam: Add device tree support for MSC probing
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
` (3 preceding siblings ...)
2026-09-14 9:37 ` [PATCH RFC v2 04/10] cacheinfo: Expose the code to generate a cache-id from a device_node Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 06/10] arm_mpam: Add support for memory controller MSC on DT platforms Yin Li
` (4 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
From: James Morse <james.morse@arm.com>
The MPAM driver currently discovers MSCs only via ACPI. Add a device
tree path so MSCs can be probed on DT-based platforms: parse MSC nodes
from the device tree, compute cache-id and affinity from the cache
nodes and create the RIS entries.
Signed-off-by: James Morse <james.morse@arm.com>
[ Yin Li: fix context conflicts; drop the ACPI-only stub of
mpam_get_cpumask_from_cache_id(); use of_node_get() for the cache
parent to avoid a refcount underflow; reject out-of-range ris_idx
after of_property_read_reg() before narrowing to u8; use u32 instead
of unsigned long for cache-id values and compare against ~0U ]
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
---
drivers/resctrl/mpam_devices.c | 256 +++++++++++++++++++++++++++++++++++++---
drivers/resctrl/mpam_internal.h | 2 +-
2 files changed, 240 insertions(+), 18 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index c68135ee0ffc..7a5b27e87759 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -20,6 +20,9 @@
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/printk.h>
#include <linux/srcu.h>
@@ -161,6 +164,171 @@ static void mpam_free_garbage(void)
}
}
+/* Called recursively to walk the list of caches from a particular CPU */
+static void __mpam_get_cpumask_from_cache_id(int cpu, struct device_node *cache_node,
+ u32 cache_id,
+ u32 cache_level,
+ cpumask_t *affinity)
+{
+ int err;
+ u32 iter_level;
+ u32 iter_cache_id;
+ struct device_node *iter_node __free(device_node) = of_find_next_cache_node(cache_node);
+
+ if (!iter_node)
+ return;
+
+ err = of_property_read_u32(iter_node, "cache-level", &iter_level);
+ if (err)
+ return;
+
+ /*
+ * get_cpu_cacheinfo_id() isn't ready until sometime
+ * during device_initcall(). Use cache_of_calculate_id().
+ */
+ iter_cache_id = cache_of_calculate_id(iter_node);
+ if (iter_cache_id == ~0U)
+ return;
+
+ if (iter_level == cache_level && iter_cache_id == cache_id)
+ cpumask_set_cpu(cpu, affinity);
+
+ if (iter_level < cache_level)
+ __mpam_get_cpumask_from_cache_id(cpu, iter_node, cache_id,
+ cache_level, affinity);
+}
+
+/*
+ * The cacheinfo structures are only populated when CPUs are online.
+ * This helper walks the device tree to include offline CPUs too.
+ */
+int mpam_get_cpumask_from_cache_id(u32 cache_id, u32 cache_level,
+ cpumask_t *affinity)
+{
+ int cpu;
+
+ if (!acpi_disabled)
+ return acpi_pptt_get_cpumask_from_cache_id(cache_id, affinity);
+
+ for_each_possible_cpu(cpu) {
+ struct device_node *cpu_node __free(device_node) = of_get_cpu_node(cpu, NULL);
+ if (!cpu_node) {
+ pr_err("Failed to find cpu%d device node\n", cpu);
+ return -ENOENT;
+ }
+
+ __mpam_get_cpumask_from_cache_id(cpu, cpu_node, cache_id,
+ cache_level, affinity);
+ }
+
+ return 0;
+}
+
+static int get_cpumask_from_cache(struct device_node *cache,
+ cpumask_t *affinity)
+{
+ int err;
+ u32 cache_level;
+ u32 cache_id;
+
+ err = of_property_read_u32(cache, "cache-level", &cache_level);
+ if (err) {
+ pr_err("Failed to read cache-level from cache node\n");
+ return -ENOENT;
+ }
+
+ cache_id = cache_of_calculate_id(cache);
+ if (cache_id == ~0U) {
+ pr_err("Failed to calculate cache-id from cache node\n");
+ return -ENOENT;
+ }
+
+ return mpam_get_cpumask_from_cache_id(cache_id, cache_level, affinity);
+}
+
+static int mpam_dt_count_msc(void)
+{
+ int count = 0;
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "arm,mpam-msc") {
+ if (of_device_is_available(np))
+ count++;
+ }
+
+ return count;
+}
+
+static int mpam_dt_parse_resource(struct mpam_msc *msc, struct device_node *np,
+ u8 ris_idx)
+{
+ int err = 0;
+ u32 level = 0;
+ u32 cache_id;
+ struct device *dev = &msc->pdev->dev;
+ struct device_node *cache __free(device_node) = NULL;
+ struct device_node *parent __free(device_node) = of_get_parent(np);
+
+ if (of_device_is_compatible(np, "arm,mpam-cache")) {
+ cache = of_parse_phandle(np, "arm,mpam-device", 0);
+ if (!cache) {
+ dev_err_once(dev, "Failed to read phandle\n");
+ return -EINVAL;
+ }
+ } else if (of_device_is_compatible(parent, "cache")) {
+ cache = of_node_get(parent);
+ } else {
+ /* For now, only caches are supported */
+ cache = NULL;
+ return err;
+ }
+
+ err = of_property_read_u32(cache, "cache-level", &level);
+ if (err) {
+ dev_err_once(dev, "Failed to read cache-level\n");
+ return err;
+ }
+
+ cache_id = cache_of_calculate_id(cache);
+ if (cache_id == ~0U) {
+ dev_err_once(dev, "Failed to calculate cache-id\n");
+ return -ENOENT;
+ }
+
+ return mpam_ris_create(msc, ris_idx, MPAM_CLASS_CACHE, level, cache_id);
+}
+
+static int mpam_dt_parse_resources(struct mpam_msc *msc, void *ignored)
+{
+ u64 ris_idx = 0;
+ int err, num_ris = 0;
+ struct device_node *np;
+
+ np = msc->pdev->dev.of_node;
+ for_each_available_child_of_node_scoped(np, iter) {
+ err = of_property_read_reg(iter, 0, &ris_idx, NULL);
+ if (!err) {
+ /*
+ * ris_idx is read as u64 but indexes a 4-bit RIS selector
+ * (0..MPAM_MSC_MAX_NUM_RIS). Reject out-of-range values here,
+ * before it is narrowed to u8, so a large value cannot be
+ * truncated into a valid-looking index.
+ */
+ if (ris_idx >= MPAM_MSC_MAX_NUM_RIS)
+ return -EINVAL;
+ num_ris++;
+ err = mpam_dt_parse_resource(msc, iter, ris_idx);
+ if (err)
+ return err;
+ }
+ }
+
+ if (!num_ris)
+ err = mpam_dt_parse_resource(msc, np, 0);
+
+ return err;
+}
+
/*
* Once mpam is enabled, new requestors cannot further reduce the available
* partid. Assert that the size is fixed, and new requestors will be turned
@@ -481,16 +649,6 @@ mpam_vmsc_find(struct mpam_component *comp, struct mpam_msc *msc)
return mpam_vmsc_alloc(comp, msc);
}
-/*
- * The cacheinfo structures are only populated when CPUs are online.
- * This helper walks the acpi tables to include offline CPUs too.
- */
-int mpam_get_cpumask_from_cache_id(unsigned long cache_id, u32 cache_level,
- cpumask_t *affinity)
-{
- return acpi_pptt_get_cpumask_from_cache_id(cache_id, affinity);
-}
-
/*
* cpumask_of_node() only knows about online CPUs. This can't tell us whether
* a class is represented on all possible CPUs.
@@ -1987,15 +2145,34 @@ static int mpam_msc_setup_error_irq(struct mpam_msc *msc)
*/
static void update_msc_accessibility(struct mpam_msc *msc)
{
+ struct device *dev = &msc->pdev->dev;
+ struct device_node *parent;
u32 affinity_id;
int err;
- err = device_property_read_u32(&msc->pdev->dev, "cpu_affinity",
- &affinity_id);
- if (err)
+ if (!acpi_disabled) {
+ err = device_property_read_u32(&msc->pdev->dev, "cpu_affinity",
+ &affinity_id);
+ if (err)
+ cpumask_copy(&msc->accessibility, cpu_possible_mask);
+ else
+ acpi_pptt_get_cpus_from_container(affinity_id,
+ &msc->accessibility);
+
+ return;
+ }
+
+ /* Where an MSC can be accessed from depends on the path to of_node. */
+ parent = of_get_parent(msc->pdev->dev.of_node);
+ if (parent == of_root) {
cpumask_copy(&msc->accessibility, cpu_possible_mask);
- else
- acpi_pptt_get_cpus_from_container(affinity_id, &msc->accessibility);
+ } else {
+ if (of_device_is_compatible(parent, "cache"))
+ get_cpumask_from_cache(parent, &msc->accessibility);
+ else
+ dev_err_once(dev, "Cannot determine accessibility of MSC.\n");
+ }
+ of_node_put(parent);
}
/*
@@ -2123,7 +2300,10 @@ static int mpam_msc_drv_probe(struct platform_device *pdev)
return PTR_ERR(msc);
/* Create RIS entries described by firmware */
- err = acpi_mpam_parse_resources(msc, plat_data);
+ if (!acpi_disabled)
+ err = acpi_mpam_parse_resources(msc, plat_data);
+ else
+ err = mpam_dt_parse_resources(msc, plat_data);
if (err) {
mpam_msc_drv_remove(pdev);
return err;
@@ -2136,15 +2316,51 @@ static int mpam_msc_drv_probe(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id mpam_of_match[] = {
+ { .compatible = "arm,mpam-msc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mpam_of_match);
+
static struct platform_driver mpam_msc_driver = {
.driver = {
.name = "mpam_msc",
.suppress_bind_attrs = true,
+ .of_match_table = of_match_ptr(mpam_of_match),
},
.probe = mpam_msc_drv_probe,
.remove = mpam_msc_drv_remove,
};
+/*
+ * MSCs that are declared by the firmware as being part of a cache may not
+ * be created automatically as platform devices, since there is no
+ * dedicated cache driver.
+ *
+ * Deal with theo MSCs here.
+ */
+static void mpam_dt_create_foundling_msc(void)
+{
+ struct platform_device *pdev;
+ struct device_node *cache;
+
+ for_each_compatible_node(cache, NULL, "cache") {
+ struct device_node *cache_device;
+
+ if (of_node_check_flag(cache, OF_POPULATED))
+ continue;
+
+ cache_device = of_find_matching_node_and_match(cache, mpam_of_match, NULL);
+ if (!cache_device)
+ continue;
+ of_node_put(cache_device);
+
+ pdev = of_platform_device_create(cache, "cache", NULL);
+ if (!pdev)
+ pr_err_once("Failed to create MSC devices under caches\n");
+ }
+}
+
/* Any of these features mean the BWA_WD field is valid. */
static bool mpam_has_bwa_wd_feature(struct mpam_props *props)
{
@@ -2963,12 +3179,18 @@ static int __init mpam_msc_driver_init(void)
init_srcu_struct(&mpam_srcu);
- fw_num_msc = acpi_mpam_count_msc();
+ if (!acpi_disabled)
+ fw_num_msc = acpi_mpam_count_msc();
+ else
+ fw_num_msc = mpam_dt_count_msc();
if (fw_num_msc <= 0) {
pr_err("No MSC devices found in firmware\n");
return -EINVAL;
}
+ if (acpi_disabled)
+ mpam_dt_create_foundling_msc();
+
return platform_driver_register(&mpam_msc_driver);
}
diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
index def0e3a65c23..aa45d00bcd07 100644
--- a/drivers/resctrl/mpam_internal.h
+++ b/drivers/resctrl/mpam_internal.h
@@ -470,7 +470,7 @@ int mpam_msmon_read(struct mpam_component *comp, struct mon_cfg *ctx,
enum mpam_device_features, u64 *val);
void mpam_msmon_reset_mbwu(struct mpam_component *comp, struct mon_cfg *ctx);
-int mpam_get_cpumask_from_cache_id(unsigned long cache_id, u32 cache_level,
+int mpam_get_cpumask_from_cache_id(u32 cache_id, u32 cache_level,
cpumask_t *affinity);
#ifdef CONFIG_RESCTRL_FS
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH RFC v2 06/10] arm_mpam: Add support for memory controller MSC on DT platforms
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
` (4 preceding siblings ...)
2026-09-14 9:37 ` [PATCH RFC v2 05/10] arm_mpam: Add device tree support for MSC probing Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 07/10] arm_mpam: Fix mpam_dt_create_foundling_msc() to create MSC platform devices Yin Li
` (3 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
From: Shanker Donthineni <sdonthineni@nvidia.com>
The MPAM DT path only handles cache MSCs. Memory-controller MSCs
cannot be probed yet.
Add support to discover memory-controller MSCs from the device tree:
derive the component id from the NUMA node and create a 'memory' class
RIS, and treat a memory parent as accessible from all CPUs.
Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
[ morse: split out of a bigger patch, added affinity piece ]
Signed-off-by: James Morse <james.morse@arm.com>
[ Yin Li: fix context offset conflicts; use of_node_get() for the memory
parent to avoid a refcount underflow; use u32 instead of unsigned long
for component_id and compare against ~0U ]
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
---
drivers/resctrl/mpam_devices.c | 55 ++++++++++++++++++++++++++++++------------
1 file changed, 40 insertions(+), 15 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 7a5b27e87759..480e38cfa86d 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -263,10 +263,12 @@ static int mpam_dt_parse_resource(struct mpam_msc *msc, struct device_node *np,
u8 ris_idx)
{
int err = 0;
- u32 level = 0;
- u32 cache_id;
+ u32 class_id = 0;
+ u32 component_id = 0;
struct device *dev = &msc->pdev->dev;
+ enum mpam_class_types type = MPAM_CLASS_UNKNOWN;
struct device_node *cache __free(device_node) = NULL;
+ struct device_node *memory __free(device_node) = NULL;
struct device_node *parent __free(device_node) = of_get_parent(np);
if (of_device_is_compatible(np, "arm,mpam-cache")) {
@@ -275,27 +277,48 @@ static int mpam_dt_parse_resource(struct mpam_msc *msc, struct device_node *np,
dev_err_once(dev, "Failed to read phandle\n");
return -EINVAL;
}
+ type = MPAM_CLASS_CACHE;
+
} else if (of_device_is_compatible(parent, "cache")) {
cache = of_node_get(parent);
+ type = MPAM_CLASS_CACHE;
+ } else if (of_device_is_compatible(np, "arm,mpam-memory")) {
+ memory = of_parse_phandle(np, "arm,mpam-device", 0);
+ if (!memory) {
+ dev_err_once(dev, "Failed to read phandle\n");
+ return -EINVAL;
+ }
+ type = MPAM_CLASS_MEMORY;
+ } else if (of_device_is_compatible(np, "arm,mpam-memory-controller-msc")) {
+ memory = of_node_get(parent);
+ type = MPAM_CLASS_MEMORY;
} else {
- /* For now, only caches are supported */
- cache = NULL;
- return err;
- }
-
- err = of_property_read_u32(cache, "cache-level", &level);
- if (err) {
- dev_err_once(dev, "Failed to read cache-level\n");
+ /*
+ * For now, only caches and memory controllers are
+ * supported.
+ */
return err;
}
- cache_id = cache_of_calculate_id(cache);
- if (cache_id == ~0U) {
- dev_err_once(dev, "Failed to calculate cache-id\n");
- return -ENOENT;
+ /* Determine the class and component ids, based on type. */
+ if (type == MPAM_CLASS_CACHE) {
+ err = of_property_read_u32(cache, "cache-level", &class_id);
+ if (err) {
+ dev_err_once(dev, "Failed to read cache-level\n");
+ return err;
+ }
+ component_id = cache_of_calculate_id(cache);
+ if (component_id == ~0U) {
+ dev_err_once(dev, "Failed to calculate cache-id\n");
+ return -ENOENT;
+ }
+ } else if (type == MPAM_CLASS_MEMORY) {
+ err = of_node_to_nid(np);
+ component_id = (err == NUMA_NO_NODE) ? 0 : err;
+ class_id = MPAM_CLASS_ID_DEFAULT;
}
- return mpam_ris_create(msc, ris_idx, MPAM_CLASS_CACHE, level, cache_id);
+ return mpam_ris_create(msc, ris_idx, type, class_id, component_id);
}
static int mpam_dt_parse_resources(struct mpam_msc *msc, void *ignored)
@@ -2169,6 +2192,8 @@ static void update_msc_accessibility(struct mpam_msc *msc)
} else {
if (of_device_is_compatible(parent, "cache"))
get_cpumask_from_cache(parent, &msc->accessibility);
+ else if (of_device_is_compatible(parent, "memory"))
+ cpumask_copy(&msc->accessibility, cpu_possible_mask);
else
dev_err_once(dev, "Cannot determine accessibility of MSC.\n");
}
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH RFC v2 07/10] arm_mpam: Fix mpam_dt_create_foundling_msc() to create MSC platform devices
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
` (5 preceding siblings ...)
2026-09-14 9:37 ` [PATCH RFC v2 06/10] arm_mpam: Add support for memory controller MSC on DT platforms Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 08/10] dt-bindings: arm: Fix MPAM MSC binding schema and examples Yin Li
` (2 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
The original code created a platform device for the cache node itself
rather than for the MSC, so the MSC was never created. Instead, walk
the cache's children using for_each_child_of_node_scoped() and create
the platform device for the MSC child node, skipping cache parents
that firmware has marked disabled.
Co-developed-by: Huang Yiwei <huang.yiwei@oss.qualcomm.com>
Signed-off-by: Huang Yiwei <huang.yiwei@oss.qualcomm.com>
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
---
drivers/resctrl/mpam_devices.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 480e38cfa86d..7ef3ed55b066 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -2366,23 +2366,20 @@ static struct platform_driver mpam_msc_driver = {
*/
static void mpam_dt_create_foundling_msc(void)
{
- struct platform_device *pdev;
- struct device_node *cache;
-
- for_each_compatible_node(cache, NULL, "cache") {
- struct device_node *cache_device;
-
- if (of_node_check_flag(cache, OF_POPULATED))
- continue;
-
- cache_device = of_find_matching_node_and_match(cache, mpam_of_match, NULL);
- if (!cache_device)
+ for_each_compatible_node_scoped(cache, NULL, "cache") {
+ if (!of_device_is_available(cache))
continue;
- of_node_put(cache_device);
- pdev = of_platform_device_create(cache, "cache", NULL);
- if (!pdev)
- pr_err_once("Failed to create MSC devices under caches\n");
+ for_each_child_of_node_scoped(cache, child) {
+ if (!of_match_node(mpam_of_match, child))
+ continue;
+ if (!of_device_is_available(child))
+ continue;
+ if (of_node_check_flag(child, OF_POPULATED))
+ continue;
+ if (!of_platform_device_create(child, NULL, NULL))
+ pr_err("Failed to create MSC device for %pOF\n", child);
+ }
}
}
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH RFC v2 08/10] dt-bindings: arm: Fix MPAM MSC binding schema and examples
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
` (6 preceding siblings ...)
2026-09-14 9:37 ` [PATCH RFC v2 07/10] arm_mpam: Fix mpam_dt_create_foundling_msc() to create MSC platform devices Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 9:37 ` [PATCH RFC v2 09/10] arm_mpam: Support MSC accessibility derivation from RIS nodes Yin Li
2026-09-14 9:37 ` [PATCH DNM RFC v2 10/10] arm64: dts: qcom: kaanapali: Add MPAM MSC nodes for the L2 caches Yin Li
9 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
Fix multiple issues in the MPAM MSC device tree binding:
Schema fixes:
- Move maintainers field before description to follow standard field order
- Change compatible from fixed items list to oneOf to allow both standalone
arm,mpam-msc and the two-item arm,mpam-memory-controller-msc +
arm,mpam-msc combination
- Constrain numa-node-id as uint32 with description instead of
unconstrained
- Add phandle-array type constraint to cpus property
- Fix bracket spacing to pass yamllint
Example fixes:
- Replace arm,dsu-l3-cache with foo,a-l3-cache (no upstream schema exists)
- Fix msc@41000 reg address from 0x0 to 0x41000 to match unit-address
- Fix ris@2 reg value from 0 to 2 to match unit-address
- Add arm,mpam-device phandle reference and remove TODO comment
- Remove unnecessary blank lines for consistency
Co-developed-by: Huang Yiwei <huang.yiwei@oss.qualcomm.com>
Signed-off-by: Huang Yiwei <huang.yiwei@oss.qualcomm.com>
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
---
.../devicetree/bindings/arm/arm,mpam-msc.yaml | 39 ++++++++++++----------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
index 53a6fdbbf05f..3c7b13a23ff2 100644
--- a/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
+++ b/Documentation/devicetree/bindings/arm/arm,mpam-msc.yaml
@@ -6,19 +6,21 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Arm Memory System Resource Partitioning and Monitoring (MPAM)
+maintainers:
+ - Rob Herring <robh@kernel.org>
+
description: |
The Arm MPAM specification can be found here:
https://developer.arm.com/documentation/ddi0598/latest
-maintainers:
- - Rob Herring <robh@kernel.org>
-
properties:
compatible:
- items:
+ oneOf:
- const: arm,mpam-msc # Further details are discoverable
- - const: arm,mpam-memory-controller-msc
+ - items:
+ - const: arm,mpam-memory-controller-msc
+ - const: arm,mpam-msc
reg:
maxItems: 1
@@ -34,7 +36,7 @@ properties:
interrupt-names:
oneOf:
- items:
- - enum: [ error, overflow ]
+ - enum: [error, overflow]
- items:
- const: error
- const: overflow
@@ -44,7 +46,9 @@ properties:
accurate after a settings change. For more information, see the
Not-Ready (NRDY) bit description in the MPAM specification.
- numa-node-id: true # see NUMA binding
+ numa-node-id:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: NUMA node identifier for the memory resource this MSC controls.
'#address-cells':
const: 1
@@ -72,16 +76,17 @@ patternProperties:
maximum: 0xf
cpus:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
description:
- Phandle(s) to the CPU node(s) this RIS belongs to. By default, the parent
- device's affinity is used.
+ Phandle(s) to the CPU node(s) this RIS belongs to. By default, the
+ parent device's affinity is used.
arm,mpam-device:
$ref: /schemas/types.yaml#/definitions/phandle
description:
By default, the MPAM enabled device associated with a RIS is the MSC's
- parent node. It is possible for each RIS to be associated with different
- devices in which case 'arm,mpam-device' should be used.
+ parent node. It is possible for each RIS to be associated with
+ different devices in which case 'arm,mpam-device' should be used.
required:
- compatible
@@ -92,14 +97,14 @@ required:
- reg
dependencies:
- interrupts: [ interrupt-names ]
+ interrupts: [interrupt-names]
additionalProperties: false
examples:
- |
L3: cache-controller@30000000 {
- compatible = "arm,dsu-l3-cache", "cache";
+ compatible = "foo,a-l3-cache", "cache";
cache-level = <3>;
cache-unified;
@@ -109,7 +114,6 @@ examples:
msc@10000 {
compatible = "arm,mpam-msc";
-
reg = <0x10000 0x2000>;
interrupts = <1>, <2>;
interrupt-names = "error", "overflow";
@@ -145,7 +149,7 @@ examples:
msc@41000 {
compatible = "arm,mpam-msc";
- reg = <0 0x1000>;
+ reg = <0x41000 0x1000>;
interrupts = <5>, <6>;
interrupt-names = "error", "overflow";
arm,not-ready-us = <1>;
@@ -155,8 +159,8 @@ examples:
ris@2 {
compatible = "arm,mpam-cache";
- reg = <0>;
- // TODO: How to map to device(s)?
+ reg = <2>;
+ arm,mpam-device = <&L3>;
};
};
};
@@ -173,7 +177,6 @@ examples:
msc@10000 {
compatible = "arm,mpam-msc";
-
reg = <0x10000 0x2000>;
interrupts = <7>;
interrupt-names = "overflow";
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH RFC v2 09/10] arm_mpam: Support MSC accessibility derivation from RIS nodes
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
` (7 preceding siblings ...)
2026-09-14 9:37 ` [PATCH RFC v2 08/10] dt-bindings: arm: Fix MPAM MSC binding schema and examples Yin Li
@ 2026-09-14 9:37 ` Yin Li
2026-09-14 9:37 ` [PATCH DNM RFC v2 10/10] arm64: dts: qcom: kaanapali: Add MPAM MSC nodes for the L2 caches Yin Li
9 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
The DT accessibility derivation only handled MSCs whose parent node is
a cache or memory device. When the MSC is placed under a generic
container (e.g. directly under /soc), the parent gives no affinity hint
and there is no fallback.
Add a per-RIS fallback path for when the parent node is not a
recognised cache or memory device. For each available RIS child node,
affinity is resolved in two steps: first from an explicit 'cpus'
phandle-array on the RIS node, then from the 'arm,mpam-device' phandle.
The final accessibility mask is the union of all RIS masks; if any RIS
fails to resolve, the mask is cleared and the MSC fails to probe rather
than come up with a partial affinity.
Factor the DT-specific logic into mpam_dt_update_msc_accessibility() so
that update_msc_accessibility() dispatches cleanly between ACPI and DT
paths.
Co-developed-by: Huang Yiwei <huang.yiwei@oss.qualcomm.com>
Signed-off-by: Huang Yiwei <huang.yiwei@oss.qualcomm.com>
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
---
drivers/resctrl/mpam_devices.c | 146 ++++++++++++++++++++++++++++++++++++-----
1 file changed, 131 insertions(+), 15 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 7ef3ed55b066..ede1b157ab57 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -2159,6 +2159,136 @@ static int mpam_msc_setup_error_irq(struct mpam_msc *msc)
return 0;
}
+/*
+ * Resolve a RIS to its CPU affinity from its 'cpus' phandle-array.
+ * Returns -ENODEV when 'cpus' is absent (the caller may use another source),
+ * -EINVAL when any phandle is invalid, or 0 on full success.
+ */
+static int get_cpumask_from_ris_cpus(struct device_node *ris_np,
+ cpumask_t *affinity)
+{
+ int i, cpu_phandle_count;
+
+ cpu_phandle_count = of_count_phandle_with_args(ris_np, "cpus", NULL);
+ if (cpu_phandle_count <= 0)
+ return -ENODEV;
+
+ for (i = 0; i < cpu_phandle_count; i++) {
+ struct device_node *phandle_np __free(device_node) =
+ of_parse_phandle(ris_np, "cpus", i);
+ int cpu, matched = -1;
+
+ if (phandle_np) {
+ for_each_possible_cpu(cpu) {
+ struct device_node *cpu_node __free(device_node) =
+ of_get_cpu_node(cpu, NULL);
+
+ if (phandle_np == cpu_node) {
+ matched = cpu;
+ break;
+ }
+ }
+ }
+
+ if (matched < 0) {
+ pr_warn("MPAM: RIS %pOF cpus[%d] (%pOF) is not a possible CPU\n",
+ ris_np, i, phandle_np);
+ return -EINVAL;
+ }
+
+ cpumask_set_cpu(matched, affinity);
+ }
+
+ return 0;
+}
+
+/*
+ * Resolve a RIS to its CPU affinity from its 'arm,mpam-device' phandle.
+ * Returns -EINVAL when 'arm,mpam-device' is absent or the phandle is invalid.
+ * 0 on full success.
+ */
+static int get_cpumask_from_ris_phandle(struct device_node *ris,
+ cpumask_t *affinity)
+{
+ struct device_node *mpam_device __free(device_node) =
+ of_parse_phandle(ris, "arm,mpam-device", 0);
+
+ if (!mpam_device) {
+ pr_warn("MPAM: RIS %pOF has neither 'cpus' nor 'arm,mpam-device'\n",
+ ris);
+ return -EINVAL;
+ }
+
+ if (of_device_is_compatible(mpam_device, "cache"))
+ return get_cpumask_from_cache(mpam_device, affinity);
+
+ if (of_device_is_compatible(mpam_device, "memory")) {
+ cpumask_or(affinity, affinity, cpu_possible_mask);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int get_cpumask_from_ris(struct device_node *ris, cpumask_t *affinity)
+{
+ int err;
+
+ err = get_cpumask_from_ris_cpus(ris, affinity);
+ if (err != -ENODEV)
+ return err;
+
+ return get_cpumask_from_ris_phandle(ris, affinity);
+}
+
+/*
+ * Returns -ENODEV when the parent is just a container (not a recognised device),
+ * so the caller falls back to the per-RIS description.
+ */
+static int get_cpumask_from_parent(struct mpam_msc *msc, cpumask_t *affinity)
+{
+ struct device_node *parent __free(device_node) =
+ of_get_parent(msc->pdev->dev.of_node);
+
+ if (parent == of_root) {
+ cpumask_copy(affinity, cpu_possible_mask);
+ return 0;
+ }
+
+ if (of_device_is_compatible(parent, "cache"))
+ return get_cpumask_from_cache(parent, affinity);
+
+ if (of_device_is_compatible(parent, "memory")) {
+ cpumask_copy(affinity, cpu_possible_mask);
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+/*
+ * An MSC's CPU affinity is described either by its parent node or, when the
+ * parent is just a container, per-RIS inside the MSC. In the per-RIS case the
+ * accessibility is the union of the RIS affinities: every RIS must resolve, so
+ * a single failure clears the mask and stops and the MSC fails to probe rather
+ * than come up with a partial affinity.
+ */
+static void mpam_dt_update_msc_accessibility(struct mpam_msc *msc)
+{
+ cpumask_t *affinity = &msc->accessibility;
+
+ cpumask_clear(affinity);
+
+ if (get_cpumask_from_parent(msc, affinity) == -ENODEV) {
+ for_each_available_child_of_node_scoped(msc->pdev->dev.of_node, ris) {
+ if (get_cpumask_from_ris(ris, affinity)) {
+ cpumask_clear(affinity);
+ break;
+ }
+ }
+ }
+}
+
/*
* An MSC can control traffic from a set of CPUs, but may only be accessible
* from a (hopefully wider) set of CPUs. The common reason for this is power
@@ -2168,8 +2298,6 @@ static int mpam_msc_setup_error_irq(struct mpam_msc *msc)
*/
static void update_msc_accessibility(struct mpam_msc *msc)
{
- struct device *dev = &msc->pdev->dev;
- struct device_node *parent;
u32 affinity_id;
int err;
@@ -2185,19 +2313,7 @@ static void update_msc_accessibility(struct mpam_msc *msc)
return;
}
- /* Where an MSC can be accessed from depends on the path to of_node. */
- parent = of_get_parent(msc->pdev->dev.of_node);
- if (parent == of_root) {
- cpumask_copy(&msc->accessibility, cpu_possible_mask);
- } else {
- if (of_device_is_compatible(parent, "cache"))
- get_cpumask_from_cache(parent, &msc->accessibility);
- else if (of_device_is_compatible(parent, "memory"))
- cpumask_copy(&msc->accessibility, cpu_possible_mask);
- else
- dev_err_once(dev, "Cannot determine accessibility of MSC.\n");
- }
- of_node_put(parent);
+ mpam_dt_update_msc_accessibility(msc);
}
/*
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH DNM RFC v2 10/10] arm64: dts: qcom: kaanapali: Add MPAM MSC nodes for the L2 caches
2026-09-14 9:37 [PATCH RFC v2 00/10] arm-mpam: Add basic device tree support for resctrl Yin Li
` (8 preceding siblings ...)
2026-09-14 9:37 ` [PATCH RFC v2 09/10] arm_mpam: Support MSC accessibility derivation from RIS nodes Yin Li
@ 2026-09-14 9:37 ` Yin Li
9 siblings, 0 replies; 18+ messages in thread
From: Yin Li @ 2026-09-14 9:37 UTC (permalink / raw)
To: James Morse, Rob Herring, Shanker Donthineni, Ben Horgan,
Krzysztof Kozlowski, Conor Dooley, Catalin Marinas,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Reinette Chatre, Fenghua Yu, Jonathan Cameron, Bjorn Andersson,
Konrad Dybcio, Gavin Shan
Cc: Yin Li, Andre Przywara, Drew Fustini, Ilpo Järvinen,
Shaopeng Tan, trilok.soni, aiqun.yu, ganapatrao.kulkarni,
Srivathsa L Rao, Huang Yiwei, linux-arm-kernel, linux-arm-msm,
linux-kernel, driver-core, devicetree
Add an MPAM MSC device node for each L2 cache. Each MSC is nested
directly under its L2 cache node so that the cache node is the MSC's
parent device and its CPU affinity is derived from that cache.
The L2 cache nodes are placed directly under the root node. The root is
the root of the physical address space, so each cache node only needs an
identity 'ranges' property for its nested MSC's 'reg' to be resolved to
a physical address. The two caches use distinct node names (l2-cache-0
and l2-cache-1) since a cache node has no MMIO unit-address of its own.
The nodes are disabled by default. Production firmware does not expose
MSC register access to the OS, so these nodes can only be enabled on a
local test setup where firmware permits direct MMIO access to the MSCs.
This DTS is therefore only an example for other platform DT authors and
is not intended to be merged.
Co-developed-by: Huang Yiwei <huang.yiwei@oss.qualcomm.com>
Signed-off-by: Huang Yiwei <huang.yiwei@oss.qualcomm.com>
Signed-off-by: Yin Li <yin.li@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/kaanapali.dtsi | 50 +++++++++++++++++++++++++--------
1 file changed, 38 insertions(+), 12 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/kaanapali.dtsi b/arch/arm64/boot/dts/qcom/kaanapali.dtsi
index 131fd2a16c54..b1dcb1e9c570 100644
--- a/arch/arm64/boot/dts/qcom/kaanapali.dtsi
+++ b/arch/arm64/boot/dts/qcom/kaanapali.dtsi
@@ -48,12 +48,6 @@ cpu0: cpu@0 {
power-domains = <&cpu_pd0>, <&scmi_perf 0>;
power-domain-names = "psci", "perf";
#cooling-cells = <2>;
-
- l2_0: l2-cache {
- compatible = "cache";
- cache-level = <2>;
- cache-unified;
- };
};
cpu1: cpu@100 {
@@ -120,12 +114,6 @@ cpu6: cpu@10000 {
power-domains = <&cpu_pd6>, <&scmi_perf 1>;
power-domain-names = "psci", "perf";
#cooling-cells = <2>;
-
- l2_1: l2-cache {
- compatible = "cache";
- cache-level = <2>;
- cache-unified;
- };
};
cpu7: cpu@10100 {
@@ -531,6 +519,44 @@ soccp_smp2p_in: slave-kernel {
};
};
+ l2_0: l2-cache-0 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0xc00000>;
+ ranges;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ msc@19870000 {
+ compatible = "arm,mpam-msc";
+ reg = <0x0 0x19870000 0x0 0x10000>;
+ arm,not-ready-us = <1>;
+ status = "disabled";
+ };
+
+ };
+
+ l2_1: l2-cache-1 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0xc00000>;
+ ranges;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ msc@1a870000 {
+ compatible = "arm,mpam-msc";
+ reg = <0x0 0x1a870000 0x0 0x10000>;
+ arm,not-ready-us = <1>;
+ status = "disabled";
+ };
+
+ };
+
soc: soc@0 {
compatible = "simple-bus";
--
2.34.1
^ permalink raw reply [flat|nested] 18+ messages in thread