[PATCH 4/8] iommu/msm: Look up masters per IOMMU instance
From: Alexandre MINETTE via B4 Relay
Date: Tue Apr 21 2026 - 05:50:33 EST
From: Alexandre MINETTE <contact@xxxxxxxxxxx>
MSM IOMMU stores context descriptors on each IOMMU instance. Looking up
the descriptor through dev_iommu_priv_get() is not sufficient because a
device can reference multiple IOMMU provider nodes.
Look up the master from the target IOMMU ctx_list instead, and use the
same helper when probing and attaching devices. This avoids dereferencing
a NULL master when an IOMMU already has context entries for another
device, and keeps separate context descriptors for separate IOMMU
instances.
This is required to boot APQ8064 boards using multiple IOMMU contexts.
Signed-off-by: Alexandre MINETTE <contact@xxxxxxxxxxx>
---
drivers/iommu/msm_iommu.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 0ad5ff431d5b..9c03878d0d2c 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -357,17 +357,25 @@ static int msm_iommu_domain_config(struct msm_priv *priv)
return 0;
}
+static struct msm_iommu_ctx_dev *find_iommu_master(struct msm_iommu_dev *iommu,
+ struct device *dev)
+{
+ struct msm_iommu_ctx_dev *master;
+
+ list_for_each_entry(master, &iommu->ctx_list, list)
+ if (master->of_node == dev->of_node)
+ return master;
+
+ return NULL;
+}
+
/* Must be called under msm_iommu_lock */
static struct msm_iommu_dev *find_iommu_for_dev(struct device *dev)
{
struct msm_iommu_dev *iommu, *ret = NULL;
- struct msm_iommu_ctx_dev *master;
list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
- master = list_first_entry(&iommu->ctx_list,
- struct msm_iommu_ctx_dev,
- list);
- if (master->of_node == dev->of_node) {
+ if (find_iommu_master(iommu, dev)) {
ret = iommu;
break;
}
@@ -405,10 +413,7 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev,
spin_lock_irqsave(&msm_iommu_lock, flags);
list_for_each_entry(iommu, &qcom_iommu_devices, dev_node) {
- master = list_first_entry(&iommu->ctx_list,
- struct msm_iommu_ctx_dev,
- list);
- if (master->of_node == dev->of_node) {
+ if (find_iommu_master(iommu, dev)) {
ret = __enable_clocks(iommu);
if (ret)
goto fail;
@@ -601,10 +606,10 @@ static int insert_iommu_master(struct device *dev,
struct msm_iommu_dev **iommu,
const struct of_phandle_args *spec)
{
- struct msm_iommu_ctx_dev *master = dev_iommu_priv_get(dev);
+ struct msm_iommu_ctx_dev *master = find_iommu_master(*iommu, dev);
int sid;
- if (list_empty(&(*iommu)->ctx_list)) {
+ if (!master) {
master = kzalloc_obj(*master, GFP_ATOMIC);
if (!master) {
dev_err(dev, "Failed to allocate iommu_master\n");
@@ -612,7 +617,6 @@ static int insert_iommu_master(struct device *dev,
}
master->of_node = dev->of_node;
list_add(&master->list, &(*iommu)->ctx_list);
- dev_iommu_priv_set(dev, master);
}
for (sid = 0; sid < master->num_mids; sid++)
--
2.43.0