diff mbox series

[15/30] iommu/msm: Move to iommu_of_xlate()

Message ID 15-v1-f82a05539a64+5042-iommu_fwspec_p2_jgg@nvidia.com
State Handled Elsewhere
Headers show
Series Make a new API for drivers to use to get their FW | expand

Commit Message

Jason Gunthorpe Nov. 30, 2023, 1:10 a.m. UTC
It is confusing what this driver is doing. The insert_iommu_master(),
especially the list_empty(), doesn't make a lot of sense.

Based on the dtsi this supports an iommu instance that has exactly one
device attached it. However each device may be connected to multiple
instances with multiple stream ids. The iommus list must be sorted by
instance or it will not parse correctly.

Ideally this driver would work more like dart where each master allocates
memory for dev_iommu_priv and records a list of the all the iommus and
stream ids in that struct. That is too big of a change for this patch.

Keep things basically the same, but rely on the core code to discover the
iommu_device and stop confusingly using dev_iommu_priv to join SIDs into
the same master when processing the assumed-to-be-sorted iommus list.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/iommu/msm_iommu.c | 93 ++++++++++++++++-----------------------
 1 file changed, 37 insertions(+), 56 deletions(-)
diff mbox series

Patch

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index f86af9815d6f98..6f21eec857c7d7 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -16,6 +16,7 @@ 
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/iommu.h>
+#include <linux/iommu-driver.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 
@@ -37,6 +38,15 @@  static DEFINE_SPINLOCK(msm_iommu_lock);
 static LIST_HEAD(qcom_iommu_devices);
 static struct iommu_ops msm_iommu_ops;
 
+struct msm_xlate_args {
+	struct device *dev;
+	struct msm_iommu_ctx_dev *master;
+	struct msm_iommu_dev *iommu;
+};
+
+static int msm_iommu_of_xlate(struct iommu_device *core_iommu,
+			      struct of_phandle_args *args, void *priv);
+
 struct msm_priv {
 	struct list_head list_attached;
 	struct iommu_domain domain;
@@ -357,38 +367,17 @@  static int msm_iommu_domain_config(struct msm_priv *priv)
 	return 0;
 }
 
-/* Must be called under msm_iommu_lock */
-static struct msm_iommu_dev *find_iommu_for_dev(struct device *dev)
+static struct iommu_device *
+msm_iommu_probe_device(struct iommu_probe_info *pinf)
 {
-	struct msm_iommu_dev *iommu, *ret = NULL;
-	struct msm_iommu_ctx_dev *master;
+	struct msm_xlate_args args = { .dev = pinf->dev };
+	int ret;
 
-	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) {
-			ret = iommu;
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static struct iommu_device *msm_iommu_probe_device(struct device *dev)
-{
-	struct msm_iommu_dev *iommu;
-	unsigned long flags;
-
-	spin_lock_irqsave(&msm_iommu_lock, flags);
-	iommu = find_iommu_for_dev(dev);
-	spin_unlock_irqrestore(&msm_iommu_lock, flags);
-
-	if (!iommu)
-		return ERR_PTR(-ENODEV);
-
-	return &iommu->iommu;
+	ret = iommu_of_xlate(pinf, &msm_iommu_ops, -1, &msm_iommu_of_xlate,
+			     &args);
+	if (ret)
+		return ERR_PTR(ret);
+	return &args.iommu->iommu;
 }
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -596,22 +585,26 @@  static void print_ctx_regs(void __iomem *base, int ctx)
 	       GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
 }
 
-static int insert_iommu_master(struct device *dev,
-				struct msm_iommu_dev **iommu,
-				struct of_phandle_args *spec)
+static int insert_iommu_master(struct msm_xlate_args *args,
+			       struct msm_iommu_dev *iommu,
+			       struct of_phandle_args *spec)
 {
-	struct msm_iommu_ctx_dev *master = dev_iommu_priv_get(dev);
+	struct msm_iommu_ctx_dev *master = args->master;
+	struct device *dev = args->dev;
 	int sid;
 
-	if (list_empty(&(*iommu)->ctx_list)) {
+	if (!args->iommu)
+		args->iommu = iommu;
+
+	if (list_empty(&iommu->ctx_list)) {
 		master = kzalloc(sizeof(*master), GFP_ATOMIC);
 		if (!master) {
 			dev_err(dev, "Failed to allocate iommu_master\n");
 			return -ENOMEM;
 		}
 		master->of_node = dev->of_node;
-		list_add(&master->list, &(*iommu)->ctx_list);
-		dev_iommu_priv_set(dev, master);
+		list_add(&master->list, &iommu->ctx_list);
+		args->master = master;
 	}
 
 	for (sid = 0; sid < master->num_mids; sid++)
@@ -625,28 +618,16 @@  static int insert_iommu_master(struct device *dev,
 	return 0;
 }
 
-static int qcom_iommu_of_xlate(struct device *dev,
-			       struct of_phandle_args *spec)
+static int msm_iommu_of_xlate(struct iommu_device *core_iommu,
+			      struct of_phandle_args *args, void *priv)
 {
-	struct msm_iommu_dev *iommu = NULL, *iter;
+	struct msm_iommu_dev *iommu =
+		container_of(core_iommu, struct msm_iommu_dev, iommu);
 	unsigned long flags;
 	int ret = 0;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-	list_for_each_entry(iter, &qcom_iommu_devices, dev_node) {
-		if (iter->dev->of_node == spec->np) {
-			iommu = iter;
-			break;
-		}
-	}
-
-	if (!iommu) {
-		ret = -ENODEV;
-		goto fail;
-	}
-
-	ret = insert_iommu_master(dev, &iommu, spec);
-fail:
+	ret = insert_iommu_master(priv, iommu, args);
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 
 	return ret;
@@ -690,10 +671,10 @@  irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 static struct iommu_ops msm_iommu_ops = {
 	.identity_domain = &msm_iommu_identity_domain,
 	.domain_alloc_paging = msm_iommu_domain_alloc_paging,
-	.probe_device = msm_iommu_probe_device,
+	.probe_device_pinf = msm_iommu_probe_device,
 	.device_group = generic_device_group,
 	.pgsize_bitmap = MSM_IOMMU_PGSIZES,
-	.of_xlate = qcom_iommu_of_xlate,
+	.of_xlate = iommu_dummy_of_xlate,
 	.default_domain_ops = &(const struct iommu_domain_ops) {
 		.attach_dev	= msm_iommu_attach_dev,
 		.map_pages	= msm_iommu_map,