Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 0/6] iommu/arm-smmu: Add interconnect bandwidth voting support
@ 2026-05-26 14:42 Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 1/6] dt-bindings: iommu: arm,smmu: Document interconnects property Bibek Kumar Patro
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Bibek Kumar Patro @ 2026-05-26 14:42 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-kernel, iommu, devicetree, linux-kernel, linux-arm-msm,
	Bibek Kumar Patro

On some Qualcomm SoCs the SMMU register space is gated behind an
interconnect fabric that requires an active bandwidth vote before
registers can be accessed. In the common case this vote is held
implicitly by other clients (e.g. the GMU device holds a GEM_NOC
vote whenever the GPU is active), so the SMMU works without any
explicit vote from the driver.

However, during certain power transitions — specifically sleep/wakeup
sequences — the interconnect vote can be dropped before the SMMU is
powered down. If the SMMU is then accessed (e.g. during runtime
resume) while the vote is absent, register reads fail intermittently.
The precise ordering makes this difficult to reproduce consistently.

This series adds support for an optional interconnect path in the
arm-smmu driver. When an 'interconnects' property is present in the
SMMU device node, the driver acquires the path and votes for bandwidth
before any register access, releasing the vote on runtime suspend and
on error paths. Platforms that do not describe an interconnect path
are unaffected.

Changes in v2:
- dt-bindings: Cleaned up 'interconnects' property description —
  removed "Optional" prefix and driver implementation details as
  flagged by Krzysztof Kozlowski.
- dt-bindings: Added allOf conditional using 'items' to restrict the
  'interconnects' property to Adreno SMMU nodes only (qcom,adreno-smmu
  with qcom,qcs615-smmu-500, qcom,qcs8300-smmu-500,
  qcom,sa8775p-smmu-500 or qcom,sc7280-smmu-500 compatible), so
  non-Adreno SMMU nodes on the same SoC cannot use this property.
- Added DTS patches for kodiak, lemans, monaco and talos to add
  the GEM_NOC interconnect path for the adreno_smmu node on each
  platform.
Link to v1:
https://lore.kernel.org/all/20260516-smmu_interconnect_addition-v1-0-f889d933f5c1@oss.qualcomm.com/

Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
---
Bibek Kumar Patro (6):
      dt-bindings: iommu: arm,smmu: Document interconnects property
      iommu/arm-smmu: Add interconnect bandwidth voting support
      arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU
      arm64: dts: qcom: lemans: Add GEM_NOC interconnect for adreno SMMU
      arm64: dts: qcom: monaco: Add GEM_NOC interconnect for adreno SMMU
      arm64: dts: qcom: talos: Add GEM_NOC interconnect for adreno SMMU

 .../devicetree/bindings/iommu/arm,smmu.yaml        | 27 ++++++++++
 arch/arm64/boot/dts/qcom/kodiak.dtsi               |  2 +
 arch/arm64/boot/dts/qcom/lemans.dtsi               |  2 +
 arch/arm64/boot/dts/qcom/monaco.dtsi               |  2 +
 arch/arm64/boot/dts/qcom/talos.dtsi                |  2 +
 drivers/iommu/arm/arm-smmu/arm-smmu.c              | 57 +++++++++++++++++++++-
 drivers/iommu/arm/arm-smmu/arm-smmu.h              |  2 +
 7 files changed, 92 insertions(+), 2 deletions(-)
---
base-commit: c1ecb239fa3456529a32255359fc78b69eb9d847
change-id: 20260516-smmu_interconnect_addition-d9567535e9d7

Best regards,
-- 
Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2 1/6] dt-bindings: iommu: arm,smmu: Document interconnects property
  2026-05-26 14:42 [PATCH v2 0/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
@ 2026-05-26 14:42 ` Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 2/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Bibek Kumar Patro @ 2026-05-26 14:42 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-kernel, iommu, devicetree, linux-kernel, linux-arm-msm,
	Bibek Kumar Patro

Some SoC implementations require a bandwidth vote on an interconnect
path before the SMMU register space is accessible. Add the optional
'interconnects' property to the binding to allow platform DT nodes
to describe this path.

Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
---
 .../devicetree/bindings/iommu/arm,smmu.yaml        | 27 ++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
index 06fb5c8e7547cb7a92823adc2772b94f747376a6..3a677ff1a18fcdf5c0ca9ec8a017d41f9eb5ff09 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
@@ -243,6 +243,13 @@ properties:
     minItems: 1
     maxItems: 3
 
+  interconnects:
+    maxItems: 1
+    description:
+      Interconnect path to the SMMU register space. Required on SoCs
+      where the SMMU registers are only accessible after a bandwidth
+      vote has been placed on the interconnect fabric.
+
   nvidia,memory-controller:
     description: |
       A phandle to the memory controller on NVIDIA Tegra186 and later SoCs.
@@ -602,6 +609,26 @@ allOf:
         clock-names: false
         clocks: false
 
+  - if:
+      properties:
+        compatible:
+          items:
+            - enum:
+                - qcom,qcs615-smmu-500
+                - qcom,qcs8300-smmu-500
+                - qcom,sa8775p-smmu-500
+                - qcom,sc7280-smmu-500
+            - const: qcom,adreno-smmu
+            - const: qcom,smmu-500
+            - const: arm,mmu-500
+    then:
+      properties:
+        interconnects:
+          maxItems: 1
+    else:
+      properties:
+        interconnects: false
+
   - if:
       properties:
         compatible:

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/6] iommu/arm-smmu: Add interconnect bandwidth voting support
  2026-05-26 14:42 [PATCH v2 0/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 1/6] dt-bindings: iommu: arm,smmu: Document interconnects property Bibek Kumar Patro
@ 2026-05-26 14:42 ` Bibek Kumar Patro
  2026-05-26 16:21   ` sashiko-bot
  2026-05-26 14:42 ` [PATCH v2 3/6] arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU Bibek Kumar Patro
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 8+ messages in thread
From: Bibek Kumar Patro @ 2026-05-26 14:42 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-kernel, iommu, devicetree, linux-kernel, linux-arm-msm,
	Bibek Kumar Patro

On some SoCs the SMMU registers require an active interconnect
bandwidth vote to be accessible. While other clients typically
satisfy this requirement implicitly, certain corner cases (e.g.
during sleep/wakeup transitions) can leave the SMMU without a
vote, causing intermittent register access failures.

Add support for an optional interconnect path to the arm-smmu
driver and vote for bandwidth while the SMMU is active. The path
is acquired from DT if present and ignored otherwise.

The bandwidth vote is enabled before accessing SMMU registers
during probe and runtime resume, and released during runtime
suspend and on error paths.

Generally, from an architectural perspective, GEM_NOC and DDR are
expected to have an active vote whenever the adreno_smmu block is
powered on. In most common use cases, this requirement is implicitly
satisfied because other GPU-related clients (for example, the GMU
device) already hold a GEM_NOC vote when adreno_smmu is enabled.

However, there are certain corner cases, such as during sleep/wakeup
transitions, where the GEM_NOC vote can be removed before adreno_smmu
is powered down. If adreno_smmu is then accessed while the interconnect
vote is missing, it can lead to the observed failures. Because of the
precise ordering involved, this scenario is difficult to reproduce
consistently.
(also GDSC is involved in adreno usecases can have an independent vote)

Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 57 +++++++++++++++++++++++++++++++++--
 drivers/iommu/arm/arm-smmu/arm-smmu.h |  2 ++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 0bd21d206eb3e75c3b9fb1364cdc92e82c5aa499..07c7e44ec6a5bd1488f00f87d859a20495e46601 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -53,6 +53,11 @@
 #define MSI_IOVA_BASE			0x8000000
 #define MSI_IOVA_LENGTH			0x100000
 
+/* Interconnect bandwidth vote values for the SMMU register access path */
+#define ARM_SMMU_ICC_AVG_BW		0
+#define ARM_SMMU_ICC_PEAK_BW_HIGH	1000
+#define ARM_SMMU_ICC_PEAK_BW_LOW	0
+
 static int force_stage;
 module_param(force_stage, int, S_IRUGO);
 MODULE_PARM_DESC(force_stage,
@@ -86,6 +91,36 @@ static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu)
 	}
 }
 
+static int arm_smmu_icc_get(struct arm_smmu_device *smmu)
+{
+	smmu->icc_path = devm_of_icc_get(smmu->dev, NULL);
+	if (IS_ERR(smmu->icc_path)) {
+		int err = PTR_ERR(smmu->icc_path);
+
+		if (err == -ENODEV) {
+			smmu->icc_path = NULL;
+			return 0;
+		}
+		return dev_err_probe(smmu->dev, err,
+				     "failed to get interconnect path\n");
+	}
+	return 0;
+}
+
+static void arm_smmu_icc_enable(struct arm_smmu_device *smmu)
+{
+	if (smmu->icc_path)
+		WARN_ON(icc_set_bw(smmu->icc_path, ARM_SMMU_ICC_AVG_BW,
+				   ARM_SMMU_ICC_PEAK_BW_HIGH));
+}
+
+static void arm_smmu_icc_disable(struct arm_smmu_device *smmu)
+{
+	if (smmu->icc_path)
+		WARN_ON(icc_set_bw(smmu->icc_path, ARM_SMMU_ICC_AVG_BW,
+				   ARM_SMMU_ICC_PEAK_BW_LOW));
+}
+
 static void arm_smmu_rpm_use_autosuspend(struct arm_smmu_device *smmu)
 {
 	/*
@@ -2189,6 +2224,17 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
 	if (err)
 		return err;
 
+	/*
+	 * Acquire and vote the interconnect path before accessing any SMMU
+	 * registers (including ARM_SMMU_GR0_ID0 in arm_smmu_device_cfg_probe).
+	 */
+	err = arm_smmu_icc_get(smmu);
+	if (err) {
+		clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks);
+		return err;
+	}
+	arm_smmu_icc_enable(smmu);
+
 	err = arm_smmu_device_cfg_probe(smmu);
 	if (err)
 		return err;
@@ -2273,8 +2319,10 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev)
 
 	if (pm_runtime_enabled(smmu->dev))
 		pm_runtime_force_suspend(smmu->dev);
-	else
+	else {
 		clk_bulk_disable(smmu->num_clks, smmu->clks);
+		arm_smmu_icc_disable(smmu);
+	}
 
 	clk_bulk_unprepare(smmu->num_clks, smmu->clks);
 }
@@ -2294,9 +2342,13 @@ static int __maybe_unused arm_smmu_runtime_resume(struct device *dev)
 	struct arm_smmu_device *smmu = dev_get_drvdata(dev);
 	int ret;
 
+	arm_smmu_icc_enable(smmu);
+
 	ret = clk_bulk_enable(smmu->num_clks, smmu->clks);
-	if (ret)
+	if (ret) {
+		arm_smmu_icc_disable(smmu);
 		return ret;
+	}
 
 	arm_smmu_device_reset(smmu);
 
@@ -2308,6 +2360,7 @@ static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev)
 	struct arm_smmu_device *smmu = dev_get_drvdata(dev);
 
 	clk_bulk_disable(smmu->num_clks, smmu->clks);
+	arm_smmu_icc_disable(smmu);
 
 	return 0;
 }
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h b/drivers/iommu/arm/arm-smmu/arm-smmu.h
index 26d2e33cd328b8278888585fc07a31485d9397e2..c00606a416b2f4bb44a35e5d67f6ef801df68e1c 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
@@ -15,6 +15,7 @@
 #include <linux/bits.h>
 #include <linux/clk.h>
 #include <linux/device.h>
+#include <linux/interconnect.h>
 #include <linux/io-64-nonatomic-hi-lo.h>
 #include <linux/io-pgtable.h>
 #include <linux/iommu.h>
@@ -335,6 +336,7 @@ struct arm_smmu_device {
 	int				num_clks;
 	unsigned int			*irqs;
 	struct clk_bulk_data		*clks;
+	struct icc_path			*icc_path;
 
 	spinlock_t			global_sync_lock;
 

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/6] arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU
  2026-05-26 14:42 [PATCH v2 0/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 1/6] dt-bindings: iommu: arm,smmu: Document interconnects property Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 2/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
@ 2026-05-26 14:42 ` Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 4/6] arm64: dts: qcom: lemans: " Bibek Kumar Patro
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Bibek Kumar Patro @ 2026-05-26 14:42 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-kernel, iommu, devicetree, linux-kernel, linux-arm-msm,
	Bibek Kumar Patro

On Kodiak platforms, the Adreno SMMU requires a bandwidth vote on
the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers
are accessible. Without this vote, the SMMU may become unreachable,
leading to intermittent probe failures and runtime issues.

Add the required interconnect to ensure reliable register access.

Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/kodiak.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/kodiak.dtsi b/arch/arm64/boot/dts/qcom/kodiak.dtsi
index fa540d8c2615dc02d941eb16bc7253204c2750bd..eefa4b836a81374ff437ab4bbcbc3fecc1590ab6 100644
--- a/arch/arm64/boot/dts/qcom/kodiak.dtsi
+++ b/arch/arm64/boot/dts/qcom/kodiak.dtsi
@@ -3386,6 +3386,8 @@ adreno_smmu: iommu@3da0000 {
 
 			power-domains = <&gpucc GPU_CC_CX_GDSC>;
 			dma-coherent;
+			interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS
+					 &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
 		};
 
 		gfx_0_tbu: tbu@3dd9000 {

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 4/6] arm64: dts: qcom: lemans: Add GEM_NOC interconnect for adreno SMMU
  2026-05-26 14:42 [PATCH v2 0/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
                   ` (2 preceding siblings ...)
  2026-05-26 14:42 ` [PATCH v2 3/6] arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU Bibek Kumar Patro
@ 2026-05-26 14:42 ` Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 5/6] arm64: dts: qcom: monaco: " Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 6/6] arm64: dts: qcom: talos: " Bibek Kumar Patro
  5 siblings, 0 replies; 8+ messages in thread
From: Bibek Kumar Patro @ 2026-05-26 14:42 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-kernel, iommu, devicetree, linux-kernel, linux-arm-msm,
	Bibek Kumar Patro

On Lemans platforms, the Adreno SMMU requires a bandwidth vote on
the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers
are accessible. Without this vote, the SMMU may become unreachable,
leading to intermittent probe failures and runtime issues.

Add the required interconnect to ensure reliable register access.

Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/lemans.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi
index 522ba43836a2425a8612506f5f7113f291f34706..ac9f529d2719105609d997874a6319c7d04e1655 100644
--- a/arch/arm64/boot/dts/qcom/lemans.dtsi
+++ b/arch/arm64/boot/dts/qcom/lemans.dtsi
@@ -4796,6 +4796,8 @@ adreno_smmu: iommu@3da0000 {
 				     <GIC_SPI 685 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 686 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 687 IRQ_TYPE_LEVEL_HIGH>;
+			interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS
+					 &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
 		};
 
 		serdes0: phy@8901000 {

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 5/6] arm64: dts: qcom: monaco: Add GEM_NOC interconnect for adreno SMMU
  2026-05-26 14:42 [PATCH v2 0/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
                   ` (3 preceding siblings ...)
  2026-05-26 14:42 ` [PATCH v2 4/6] arm64: dts: qcom: lemans: " Bibek Kumar Patro
@ 2026-05-26 14:42 ` Bibek Kumar Patro
  2026-05-26 14:42 ` [PATCH v2 6/6] arm64: dts: qcom: talos: " Bibek Kumar Patro
  5 siblings, 0 replies; 8+ messages in thread
From: Bibek Kumar Patro @ 2026-05-26 14:42 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-kernel, iommu, devicetree, linux-kernel, linux-arm-msm,
	Bibek Kumar Patro

On Monaco platforms, the Adreno SMMU requires a bandwidth vote on
the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers
are accessible. Without this vote, the SMMU may become unreachable,
leading to intermittent probe failures and runtime issues.

Add the required interconnect to ensure reliable register access.

Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/monaco.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/monaco.dtsi b/arch/arm64/boot/dts/qcom/monaco.dtsi
index 2660c161c3d74f4002aebff40634509e885fb3b3..00183ed67ebf0645e1da0c4674248354fa2af941 100644
--- a/arch/arm64/boot/dts/qcom/monaco.dtsi
+++ b/arch/arm64/boot/dts/qcom/monaco.dtsi
@@ -5088,6 +5088,8 @@ adreno_smmu: iommu@3da0000 {
 				      "gpu_cc_hub_aon_clk";
 			power-domains = <&gpucc GPU_CC_CX_GDSC>;
 			dma-coherent;
+			interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS
+					 &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
 		};
 
 		pmu@9091000 {

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 6/6] arm64: dts: qcom: talos: Add GEM_NOC interconnect for adreno SMMU
  2026-05-26 14:42 [PATCH v2 0/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
                   ` (4 preceding siblings ...)
  2026-05-26 14:42 ` [PATCH v2 5/6] arm64: dts: qcom: monaco: " Bibek Kumar Patro
@ 2026-05-26 14:42 ` Bibek Kumar Patro
  5 siblings, 0 replies; 8+ messages in thread
From: Bibek Kumar Patro @ 2026-05-26 14:42 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-kernel, iommu, devicetree, linux-kernel, linux-arm-msm,
	Bibek Kumar Patro

On Talos platforms, the Adreno SMMU requires a bandwidth vote on
the GEM_NOC path (MASTER_GPU_TCU -> SLAVE_EBI1) before its registers
are accessible. Without this vote, the SMMU may become unreachable,
leading to intermittent probe failures and runtime issues.

Add the required interconnect to ensure reliable register access.

Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
---
 arch/arm64/boot/dts/qcom/talos.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/talos.dtsi b/arch/arm64/boot/dts/qcom/talos.dtsi
index fb1bbc51bb8a45832568da26847312e00cae722a..74322507f4e8c796bf9529a9f0adcafbd725ac73 100644
--- a/arch/arm64/boot/dts/qcom/talos.dtsi
+++ b/arch/arm64/boot/dts/qcom/talos.dtsi
@@ -2090,6 +2090,8 @@ adreno_smmu: iommu@50a0000 {
 				      "iface";
 			power-domains = <&gpucc CX_GDSC>;
 			dma-coherent;
+			interconnects = <&gem_noc MASTER_GPU_TCU QCOM_ICC_TAG_ALWAYS
+					 &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
 		};
 
 		stm@6002000 {

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/6] iommu/arm-smmu: Add interconnect bandwidth voting support
  2026-05-26 14:42 ` [PATCH v2 2/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
@ 2026-05-26 16:21   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-05-26 16:21 UTC (permalink / raw)
  To: Bibek Kumar Patro; +Cc: robh, conor+dt, devicetree

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

New issues:
- [High] Missing cleanup of clock and interconnect resources on probe error paths.
- [High] Failures to enable the interconnect bandwidth vote are ignored, risking a system crash.
- [Medium] Interconnect bandwidth is voted after clocks are enabled during probe, contradicting architectural requirements and resume ordering.

Pre-existing issues:
- [High] Shared interrupt handlers access hardware registers without verifying if the device is active, violating PM guidelines and causing crashes.
- [High] The IOMMU device is exposed to the system before Runtime PM is fully initialized, creating a race condition that can lead to a PM usage counter underflow.
--

commit a35c4344b83f53cca1914e7921a505dbdaa63eb5
Author: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
Subject: iommu/arm-smmu: Add interconnect bandwidth voting support

This commit adds support for an optional interconnect path to the arm-smmu
driver. It votes for bandwidth while the SMMU is active to prevent
intermittent register access failures during sleep/wakeup transitions.

> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 0bd21d206eb3e..07c7e44ec6a5b 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
[ ... ]
> @@ -86,6 +91,36 @@ static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu)
[ ... ]
> +static void arm_smmu_icc_enable(struct arm_smmu_device *smmu)
> +{
> +	if (smmu->icc_path)
> +		WARN_ON(icc_set_bw(smmu->icc_path, ARM_SMMU_ICC_AVG_BW,
> +				   ARM_SMMU_ICC_PEAK_BW_HIGH));
> +}

[Severity: High]
Does this code need to propagate the return value of icc_set_bw() instead of
ignoring it?

If the bandwidth vote fails due to aggregation failures or invalid constraints,
the hardware might lack the vote required for register access.

Proceeding to access SMMU registers in arm_smmu_device_probe() or
arm_smmu_runtime_resume() without the required bandwidth vote could result in
an unrecoverable bus fault.

Could we handle the error and propagate it to fail the probe or resume
sequence gracefully?

[ ... ]
> @@ -2189,6 +2224,17 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
>  	if (err)
>  		return err;
>  
> +	/*
> +	 * Acquire and vote the interconnect path before accessing any SMMU
> +	 * registers (including ARM_SMMU_GR0_ID0 in arm_smmu_device_cfg_probe).
> +	 */
> +	err = arm_smmu_icc_get(smmu);

[Severity: Medium]
Could this ordering cause an architectural violation?

The commit message notes that the interconnect must have an active vote
whenever the adreno_smmu block is powered on. In arm_smmu_runtime_resume(),
this is handled correctly by calling arm_smmu_icc_enable() before
clk_bulk_enable().

However, in arm_smmu_device_probe(), clk_bulk_prepare_enable() is called
just before this code, before arm_smmu_icc_get() and arm_smmu_icc_enable().

Would it be better to match the resume path ordering to ensure the SMMU clocks
are not powered on without the required interconnect bandwidth vote?

> +	if (err) {
> +		clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks);
> +		return err;
> +	}
> +	arm_smmu_icc_enable(smmu);
> +
>  	err = arm_smmu_device_cfg_probe(smmu);
>  	if (err)
>  		return err;

[Severity: High]
Are we leaking the clock references and interconnect vote on subsequent error
paths?

If arm_smmu_device_cfg_probe() or other subsequent initialization steps fail,
the function returns directly without calling clk_bulk_disable_unprepare() or
arm_smmu_icc_disable().

Should there be a cleanup path that properly releases these resources when
probe fails?

[Severity: High]
This is a pre-existing issue, but does arm_smmu_device_probe() expose the
IOMMU device to the system before Runtime PM is fully initialized?

Later in arm_smmu_device_probe(), iommu_device_register() is called before
pm_runtime_enable(). Registering the IOMMU makes it visible to the system,
allowing concurrent device probes to attach to it and trigger mapping
operations, which call arm_smmu_rpm_get().

Since pm_runtime_enable() hasn't run yet, pm_runtime_enabled() evaluates to
false, and arm_smmu_rpm_get() returns 0 without incrementing the usage counter.

If the probe thread subsequently executes pm_runtime_enable(), the concurrent
thread's matching arm_smmu_rpm_put() will see pm_runtime_enabled() as true and
decrement the counter, causing a structural underflow.

[ ... ]
> @@ -2308,6 +2360,7 @@ static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev)
>  	struct arm_smmu_device *smmu = dev_get_drvdata(dev);
>  
>  	clk_bulk_disable(smmu->num_clks, smmu->clks);
> +	arm_smmu_icc_disable(smmu);
>  
>  	return 0;
>  }

[Severity: High]
This is a pre-existing issue, but does disabling the interconnect vote and
clocks here expose a crash in the shared interrupt handler?

The driver requests its IRQs (such as arm_smmu_global_fault) using the
IRQF_SHARED flag, and arm_smmu_global_fault() reads hardware registers
directly without checking the power state.

Since the handler doesn't use pm_runtime_get_if_active() to verify the device
is active, if another device on the shared IRQ line triggers an interrupt
while the SMMU is suspended, won't the SMMU's handler access unclocked and
unvoted hardware, leading to a synchronous bus abort?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260526-smmu_interconnect_addition-v2-0-2a6d8ca30d63@oss.qualcomm.com?part=2

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-05-26 16:21 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-26 14:42 [PATCH v2 0/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
2026-05-26 14:42 ` [PATCH v2 1/6] dt-bindings: iommu: arm,smmu: Document interconnects property Bibek Kumar Patro
2026-05-26 14:42 ` [PATCH v2 2/6] iommu/arm-smmu: Add interconnect bandwidth voting support Bibek Kumar Patro
2026-05-26 16:21   ` sashiko-bot
2026-05-26 14:42 ` [PATCH v2 3/6] arm64: dts: qcom: kodiak: Add GEM_NOC interconnect for adreno SMMU Bibek Kumar Patro
2026-05-26 14:42 ` [PATCH v2 4/6] arm64: dts: qcom: lemans: " Bibek Kumar Patro
2026-05-26 14:42 ` [PATCH v2 5/6] arm64: dts: qcom: monaco: " Bibek Kumar Patro
2026-05-26 14:42 ` [PATCH v2 6/6] arm64: dts: qcom: talos: " Bibek Kumar Patro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox