linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] iommu: Remove iommu_fwspec ops
@ 2024-06-21 18:46 Robin Murphy
  2024-06-21 18:46 ` [PATCH v2 1/4] iommu: Resolve fwspec ops automatically Robin Murphy
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Robin Murphy @ 2024-06-21 18:46 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, iommu, devicetree,
	Rob Herring, Saravana Kannan, Lorenzo Pieralisi, Hanjun Guo,
	Sudeep Holla, Rafael J. Wysocki, Len Brown, Jean-Philippe Brucker,
	Andy Shevchenko

v1: https://lore.kernel.org/linux-iommu/cover.1713523251.git.robin.murphy@arm.com

Hi all,

Here's v2 of this little cleanup, with acks and the additional cosmetic
tweak suggested by Andy. There were some slightly non-trivial changes in
the rebase so I've left off Jean-Philippe's tested-by from v1, but I've
given it a quick spin on arm64 ACPI and DT and all seems well still.

Thanks,
Robin.


Robin Murphy (4):
  iommu: Resolve fwspec ops automatically
  ACPI: Retire acpi_iommu_fwspec_ops()
  OF: Simplify of_iommu_configure()
  iommu: Remove iommu_fwspec ops

 drivers/acpi/arm64/iort.c             | 19 +++-------
 drivers/acpi/scan.c                   | 36 +++++--------------
 drivers/acpi/viot.c                   | 11 ++----
 drivers/iommu/arm/arm-smmu/arm-smmu.c |  3 +-
 drivers/iommu/iommu-priv.h            |  7 ++++
 drivers/iommu/iommu.c                 | 20 +++++------
 drivers/iommu/mtk_iommu_v1.c          |  2 +-
 drivers/iommu/of_iommu.c              | 50 ++++++++++-----------------
 drivers/iommu/tegra-smmu.c            |  2 +-
 drivers/of/device.c                   | 30 ++++++----------
 include/acpi/acpi_bus.h               |  3 +-
 include/linux/iommu.h                 | 15 ++------
 12 files changed, 65 insertions(+), 133 deletions(-)

-- 
2.39.2.101.g768bb238c484.dirty



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

* [PATCH v2 1/4] iommu: Resolve fwspec ops automatically
  2024-06-21 18:46 [PATCH v2 0/4] iommu: Remove iommu_fwspec ops Robin Murphy
@ 2024-06-21 18:46 ` Robin Murphy
  2024-06-21 18:46 ` [PATCH v2 2/4] ACPI: Retire acpi_iommu_fwspec_ops() Robin Murphy
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Robin Murphy @ 2024-06-21 18:46 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, iommu, devicetree,
	Rob Herring, Saravana Kannan, Lorenzo Pieralisi, Hanjun Guo,
	Sudeep Holla, Rafael J. Wysocki, Len Brown, Jean-Philippe Brucker,
	Andy Shevchenko

There's no real need for callers to resolve ops from a fwnode in order
to then pass both to iommu_fwspec_init() - it's simpler and more sensible
for that to resolve the ops itself. This in turn means we can centralise
the notion of checking for a present driver, and enforce that fwspecs
aren't allocated unless and until we know they will be usable.

Also use this opportunity to modernise with some "new" helpers that
arrived shortly after this code was first written; the generic
fwnode_handle_get() clears up that ugly get/put mismatch, while
of_fwnode_handle() can now abstract those open-coded dereferences.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
v2: Add of_fwnode_handle() cleanup as well
---
 drivers/acpi/arm64/iort.c             | 19 +++++--------------
 drivers/acpi/scan.c                   |  8 +++-----
 drivers/acpi/viot.c                   | 11 ++---------
 drivers/iommu/arm/arm-smmu/arm-smmu.c |  3 +--
 drivers/iommu/iommu-priv.h            |  2 ++
 drivers/iommu/iommu.c                 |  9 ++++++---
 drivers/iommu/mtk_iommu_v1.c          |  2 +-
 drivers/iommu/of_iommu.c              | 19 ++++++-------------
 drivers/iommu/tegra-smmu.c            |  2 +-
 include/acpi/acpi_bus.h               |  3 +--
 include/linux/iommu.h                 | 13 ++-----------
 11 files changed, 30 insertions(+), 61 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index c0b1c2c19444..1b39e9ae7ac1 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1221,10 +1221,10 @@ static bool iort_pci_rc_supports_ats(struct acpi_iort_node *node)
 static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node,
 			    u32 streamid)
 {
-	const struct iommu_ops *ops;
 	struct fwnode_handle *iort_fwnode;
 
-	if (!node)
+	/* If there's no SMMU driver at all, give up now */
+	if (!node || !iort_iommu_driver_enabled(node->type))
 		return -ENODEV;
 
 	iort_fwnode = iort_get_fwnode(node);
@@ -1232,19 +1232,10 @@ static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node,
 		return -ENODEV;
 
 	/*
-	 * If the ops look-up fails, this means that either
-	 * the SMMU drivers have not been probed yet or that
-	 * the SMMU drivers are not built in the kernel;
-	 * Depending on whether the SMMU drivers are built-in
-	 * in the kernel or not, defer the IOMMU configuration
-	 * or just abort it.
+	 * If the SMMU drivers are enabled but not loaded/probed
+	 * yet, this will defer.
 	 */
-	ops = iommu_ops_from_fwnode(iort_fwnode);
-	if (!ops)
-		return iort_iommu_driver_enabled(node->type) ?
-		       -EPROBE_DEFER : -ENODEV;
-
-	return acpi_iommu_fwspec_init(dev, streamid, iort_fwnode, ops);
+	return acpi_iommu_fwspec_init(dev, streamid, iort_fwnode);
 }
 
 struct iort_pci_alias_info {
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 503773707e01..8d5a589db141 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1577,12 +1577,11 @@ int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)
 
 #ifdef CONFIG_IOMMU_API
 int acpi_iommu_fwspec_init(struct device *dev, u32 id,
-			   struct fwnode_handle *fwnode,
-			   const struct iommu_ops *ops)
+			   struct fwnode_handle *fwnode)
 {
 	int ret;
 
-	ret = iommu_fwspec_init(dev, fwnode, ops);
+	ret = iommu_fwspec_init(dev, fwnode);
 	if (ret)
 		return ret;
 
@@ -1639,8 +1638,7 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
 #else /* !CONFIG_IOMMU_API */
 
 int acpi_iommu_fwspec_init(struct device *dev, u32 id,
-			   struct fwnode_handle *fwnode,
-			   const struct iommu_ops *ops)
+			   struct fwnode_handle *fwnode)
 {
 	return -ENODEV;
 }
diff --git a/drivers/acpi/viot.c b/drivers/acpi/viot.c
index c8025921c129..2aa69a2fba73 100644
--- a/drivers/acpi/viot.c
+++ b/drivers/acpi/viot.c
@@ -307,21 +307,14 @@ void __init acpi_viot_init(void)
 static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu,
 			       u32 epid)
 {
-	const struct iommu_ops *ops;
-
-	if (!viommu)
+	if (!viommu || !IS_ENABLED(CONFIG_VIRTIO_IOMMU))
 		return -ENODEV;
 
 	/* We're not translating ourself */
 	if (device_match_fwnode(dev, viommu->fwnode))
 		return -EINVAL;
 
-	ops = iommu_ops_from_fwnode(viommu->fwnode);
-	if (!ops)
-		return IS_ENABLED(CONFIG_VIRTIO_IOMMU) ?
-			-EPROBE_DEFER : -ENODEV;
-
-	return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode, ops);
+	return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode);
 }
 
 static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 87c81f75cf84..c200e6d3aed5 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -178,8 +178,7 @@ static int arm_smmu_register_legacy_master(struct device *dev,
 		it.cur_count = 1;
 	}
 
-	err = iommu_fwspec_init(dev, &smmu_dev->of_node->fwnode,
-				&arm_smmu_ops);
+	err = iommu_fwspec_init(dev, NULL);
 	if (err)
 		return err;
 
diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h
index 5f731d994803..078cafcf49b4 100644
--- a/drivers/iommu/iommu-priv.h
+++ b/drivers/iommu/iommu-priv.h
@@ -17,6 +17,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)
 	return dev->iommu->iommu_dev->ops;
 }
 
+const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode);
+
 int iommu_group_replace_domain(struct iommu_group *group,
 			       struct iommu_domain *new_domain);
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9df7cc75c1bc..7618c4285cf9 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2822,11 +2822,14 @@ const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode
 	return ops;
 }
 
-int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
-		      const struct iommu_ops *ops)
+int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode)
 {
+	const struct iommu_ops *ops = iommu_ops_from_fwnode(iommu_fwnode);
 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
 
+	if (!ops)
+		return -EPROBE_DEFER;
+
 	if (fwspec)
 		return ops == fwspec->ops ? 0 : -EINVAL;
 
@@ -2838,7 +2841,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
 	if (!fwspec)
 		return -ENOMEM;
 
-	of_node_get(to_of_node(iommu_fwnode));
+	fwnode_handle_get(iommu_fwnode);
 	fwspec->iommu_fwnode = iommu_fwnode;
 	fwspec->ops = ops;
 	dev_iommu_fwspec_set(dev, fwspec);
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index d6e4002200bd..9814c7d09497 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -414,7 +414,7 @@ static int mtk_iommu_v1_create_mapping(struct device *dev,
 	}
 
 	if (!fwspec) {
-		ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_v1_ops);
+		ret = iommu_fwspec_init(dev, of_fwnode_handle(args->np));
 		if (ret)
 			return ret;
 		fwspec = dev_iommu_fwspec_get(dev);
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 3afe0b48a48d..08c523ad55ad 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -21,26 +21,19 @@ static int of_iommu_xlate(struct device *dev,
 			  struct of_phandle_args *iommu_spec)
 {
 	const struct iommu_ops *ops;
-	struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
 	int ret;
 
-	ops = iommu_ops_from_fwnode(fwnode);
-	if ((ops && !ops->of_xlate) ||
-	    !of_device_is_available(iommu_spec->np))
+	if (!of_device_is_available(iommu_spec->np))
 		return -ENODEV;
 
-	ret = iommu_fwspec_init(dev, fwnode, ops);
+	ret = iommu_fwspec_init(dev, of_fwnode_handle(iommu_spec->np));
+	if (ret == -EPROBE_DEFER)
+		return driver_deferred_probe_check_state(dev);
 	if (ret)
 		return ret;
-	/*
-	 * The otherwise-empty fwspec handily serves to indicate the specific
-	 * IOMMU device we're waiting for, which will be useful if we ever get
-	 * a proper probe-ordering dependency mechanism in future.
-	 */
-	if (!ops)
-		return driver_deferred_probe_check_state(dev);
 
-	if (!try_module_get(ops->owner))
+	ops = dev_iommu_fwspec_get(dev)->ops;
+	if (!ops->of_xlate || !try_module_get(ops->owner))
 		return -ENODEV;
 
 	ret = ops->of_xlate(dev, iommu_spec);
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index f86c7ae91814..4365d9936e68 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -837,7 +837,7 @@ static int tegra_smmu_configure(struct tegra_smmu *smmu, struct device *dev,
 	const struct iommu_ops *ops = smmu->iommu.ops;
 	int err;
 
-	err = iommu_fwspec_init(dev, &dev->of_node->fwnode, ops);
+	err = iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node));
 	if (err < 0) {
 		dev_err(dev, "failed to initialize fwspec: %d\n", err);
 		return err;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 1a4dfd7a1c4a..9d815837e297 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -736,8 +736,7 @@ struct iommu_ops;
 bool acpi_dma_supported(const struct acpi_device *adev);
 enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
 int acpi_iommu_fwspec_init(struct device *dev, u32 id,
-			   struct fwnode_handle *fwnode,
-			   const struct iommu_ops *ops);
+			   struct fwnode_handle *fwnode);
 int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map);
 int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
 			   const u32 *input_id);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 17b3f36ad843..81893aad9ee4 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -1005,11 +1005,9 @@ struct iommu_mm_data {
 	struct list_head	sva_handles;
 };
 
-int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
-		      const struct iommu_ops *ops);
+int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode);
 void iommu_fwspec_free(struct device *dev);
 int iommu_fwspec_add_ids(struct device *dev, const u32 *ids, int num_ids);
-const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode);
 
 static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev)
 {
@@ -1315,8 +1313,7 @@ static inline void iommu_device_unlink(struct device *dev, struct device *link)
 }
 
 static inline int iommu_fwspec_init(struct device *dev,
-				    struct fwnode_handle *iommu_fwnode,
-				    const struct iommu_ops *ops)
+				    struct fwnode_handle *iommu_fwnode)
 {
 	return -ENODEV;
 }
@@ -1331,12 +1328,6 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,
 	return -ENODEV;
 }
 
-static inline
-const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode)
-{
-	return NULL;
-}
-
 static inline int
 iommu_dev_enable_feature(struct device *dev, enum iommu_dev_features feat)
 {
-- 
2.39.2.101.g768bb238c484.dirty



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

* [PATCH v2 2/4] ACPI: Retire acpi_iommu_fwspec_ops()
  2024-06-21 18:46 [PATCH v2 0/4] iommu: Remove iommu_fwspec ops Robin Murphy
  2024-06-21 18:46 ` [PATCH v2 1/4] iommu: Resolve fwspec ops automatically Robin Murphy
@ 2024-06-21 18:46 ` Robin Murphy
  2024-06-21 18:46 ` [PATCH v2 3/4] OF: Simplify of_iommu_configure() Robin Murphy
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Robin Murphy @ 2024-06-21 18:46 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, iommu, devicetree,
	Rob Herring, Saravana Kannan, Lorenzo Pieralisi, Hanjun Guo,
	Sudeep Holla, Rafael J. Wysocki, Len Brown, Jean-Philippe Brucker,
	Andy Shevchenko, Rafael J . Wysocki

Now that iommu_fwspec_init() can signal for probe deferral directly,
acpi_iommu_fwspec_ops() is unneeded and can be cleaned up.

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/acpi/scan.c | 28 +++++-----------------------
 1 file changed, 5 insertions(+), 23 deletions(-)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 8d5a589db141..2cfbb365c4ab 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1588,26 +1588,14 @@ int acpi_iommu_fwspec_init(struct device *dev, u32 id,
 	return iommu_fwspec_add_ids(dev, &id, 1);
 }
 
-static inline const struct iommu_ops *acpi_iommu_fwspec_ops(struct device *dev)
-{
-	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
-
-	return fwspec ? fwspec->ops : NULL;
-}
-
 static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
 {
 	int err;
-	const struct iommu_ops *ops;
 
 	/* Serialise to make dev->iommu stable under our potential fwspec */
 	mutex_lock(&iommu_probe_device_lock);
-	/*
-	 * If we already translated the fwspec there is nothing left to do,
-	 * return the iommu_ops.
-	 */
-	ops = acpi_iommu_fwspec_ops(dev);
-	if (ops) {
+	/* If we already translated the fwspec there is nothing left to do */
+	if (dev_iommu_fwspec_get(dev)) {
 		mutex_unlock(&iommu_probe_device_lock);
 		return 0;
 	}
@@ -1624,15 +1612,7 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
 	if (!err && dev->bus)
 		err = iommu_probe_device(dev);
 
-	if (err == -EPROBE_DEFER)
-		return err;
-	if (err) {
-		dev_dbg(dev, "Adding to IOMMU failed: %d\n", err);
-		return err;
-	}
-	if (!acpi_iommu_fwspec_ops(dev))
-		return -ENODEV;
-	return 0;
+	return err;
 }
 
 #else /* !CONFIG_IOMMU_API */
@@ -1672,6 +1652,8 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
 	ret = acpi_iommu_configure_id(dev, input_id);
 	if (ret == -EPROBE_DEFER)
 		return -EPROBE_DEFER;
+	if (ret)
+		dev_dbg(dev, "Adding to IOMMU failed: %d\n", ret);
 
 	arch_setup_dma_ops(dev, attr == DEV_DMA_COHERENT);
 
-- 
2.39.2.101.g768bb238c484.dirty



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

* [PATCH v2 3/4] OF: Simplify of_iommu_configure()
  2024-06-21 18:46 [PATCH v2 0/4] iommu: Remove iommu_fwspec ops Robin Murphy
  2024-06-21 18:46 ` [PATCH v2 1/4] iommu: Resolve fwspec ops automatically Robin Murphy
  2024-06-21 18:46 ` [PATCH v2 2/4] ACPI: Retire acpi_iommu_fwspec_ops() Robin Murphy
@ 2024-06-21 18:46 ` Robin Murphy
  2024-06-22 22:23   ` Andy Shevchenko
  2024-06-21 18:46 ` [PATCH v2 4/4] iommu: Remove iommu_fwspec ops Robin Murphy
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Robin Murphy @ 2024-06-21 18:46 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, iommu, devicetree,
	Rob Herring, Saravana Kannan, Lorenzo Pieralisi, Hanjun Guo,
	Sudeep Holla, Rafael J. Wysocki, Len Brown, Jean-Philippe Brucker,
	Andy Shevchenko

We no longer have a notion of partially-initialised fwspecs existing,
and we also no longer need to use an iommu_ops pointer to return status
to of_dma_configure(). Clean up the remains of those, which lends itself
to clarifying the logic around the dma_range_map allocation as well.

Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/iommu/of_iommu.c | 29 ++++++++++-------------------
 drivers/of/device.c      | 30 +++++++++++-------------------
 2 files changed, 21 insertions(+), 38 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 08c523ad55ad..c946521a5906 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -108,7 +108,6 @@ static int of_iommu_configure_device(struct device_node *master_np,
 int of_iommu_configure(struct device *dev, struct device_node *master_np,
 		       const u32 *id)
 {
-	struct iommu_fwspec *fwspec;
 	int err;
 
 	if (!master_np)
@@ -116,14 +115,9 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,
 
 	/* Serialise to make dev->iommu stable under our potential fwspec */
 	mutex_lock(&iommu_probe_device_lock);
-	fwspec = dev_iommu_fwspec_get(dev);
-	if (fwspec) {
-		if (fwspec->ops) {
-			mutex_unlock(&iommu_probe_device_lock);
-			return 0;
-		}
-		/* In the deferred case, start again from scratch */
-		iommu_fwspec_free(dev);
+	if (dev_iommu_fwspec_get(dev)) {
+		mutex_unlock(&iommu_probe_device_lock);
+		return 0;
 	}
 
 	/*
@@ -143,20 +137,17 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,
 	} else {
 		err = of_iommu_configure_device(master_np, dev, id);
 	}
+
+	if (err)
+		iommu_fwspec_free(dev);
 	mutex_unlock(&iommu_probe_device_lock);
 
-	if (err == -ENODEV || err == -EPROBE_DEFER)
-		return err;
-	if (err)
-		goto err_log;
+	if (!err && dev->bus)
+		err = iommu_probe_device(dev);
 
-	err = iommu_probe_device(dev);
-	if (err)
-		goto err_log;
-	return 0;
+	if (err && err != -EPROBE_DEFER)
+		dev_dbg(dev, "Adding to IOMMU failed: %d\n", err);
 
-err_log:
-	dev_dbg(dev, "Adding to IOMMU failed: %pe\n", ERR_PTR(err));
 	return err;
 }
 
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 312c63361211..edf3be197265 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -96,8 +96,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	const struct bus_dma_region *map = NULL;
 	struct device_node *bus_np;
 	u64 mask, end = 0;
-	bool coherent;
-	int iommu_ret;
+	bool coherent, set_map = false;
 	int ret;
 
 	if (np == dev->of_node)
@@ -118,6 +117,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	} else {
 		/* Determine the overall bounds of all DMA regions */
 		end = dma_range_map_max(map);
+		set_map = true;
 	}
 
 	/*
@@ -144,7 +144,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev->coherent_dma_mask &= mask;
 	*dev->dma_mask &= mask;
 	/* ...but only set bus limit and range map if we found valid dma-ranges earlier */
-	if (!ret) {
+	if (set_map) {
 		dev->bus_dma_limit = end;
 		dev->dma_range_map = map;
 	}
@@ -153,29 +153,21 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,
 	dev_dbg(dev, "device is%sdma coherent\n",
 		coherent ? " " : " not ");
 
-	iommu_ret = of_iommu_configure(dev, np, id);
-	if (iommu_ret == -EPROBE_DEFER) {
+	ret = of_iommu_configure(dev, np, id);
+	if (ret == -EPROBE_DEFER) {
 		/* Don't touch range map if it wasn't set from a valid dma-ranges */
-		if (!ret)
+		if (set_map)
 			dev->dma_range_map = NULL;
 		kfree(map);
 		return -EPROBE_DEFER;
-	} else if (iommu_ret == -ENODEV) {
-		dev_dbg(dev, "device is not behind an iommu\n");
-	} else if (iommu_ret) {
-		dev_err(dev, "iommu configuration for device failed with %pe\n",
-			ERR_PTR(iommu_ret));
-
-		/*
-		 * Historically this routine doesn't fail driver probing
-		 * due to errors in of_iommu_configure()
-		 */
-	} else
-		dev_dbg(dev, "device is behind an iommu\n");
+	}
+	/* Take all other IOMMU errors to mean we'll just carry on without it */
+	dev_dbg(dev, "device is%sbehind an iommu\n",
+		!ret ? " " : " not ");
 
 	arch_setup_dma_ops(dev, coherent);
 
-	if (iommu_ret)
+	if (ret)
 		of_dma_set_restricted_buffer(dev, np);
 
 	return 0;
-- 
2.39.2.101.g768bb238c484.dirty



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

* [PATCH v2 4/4] iommu: Remove iommu_fwspec ops
  2024-06-21 18:46 [PATCH v2 0/4] iommu: Remove iommu_fwspec ops Robin Murphy
                   ` (2 preceding siblings ...)
  2024-06-21 18:46 ` [PATCH v2 3/4] OF: Simplify of_iommu_configure() Robin Murphy
@ 2024-06-21 18:46 ` Robin Murphy
  2024-06-21 20:51 ` [PATCH v2 0/4] " Saravana Kannan
  2024-07-01 13:49 ` Jean-Philippe Brucker
  5 siblings, 0 replies; 10+ messages in thread
From: Robin Murphy @ 2024-06-21 18:46 UTC (permalink / raw)
  To: Will Deacon, Joerg Roedel
  Cc: linux-acpi, linux-arm-kernel, linux-kernel, iommu, devicetree,
	Rob Herring, Saravana Kannan, Lorenzo Pieralisi, Hanjun Guo,
	Sudeep Holla, Rafael J. Wysocki, Len Brown, Jean-Philippe Brucker,
	Andy Shevchenko

The ops in iommu_fwspec are only needed for the early configuration and
probe process, and by now are easy enough to derive on-demand in those
couple of places which need them, so remove the redundant stored copy.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/iommu/iommu-priv.h |  5 +++++
 drivers/iommu/iommu.c      | 11 ++---------
 drivers/iommu/of_iommu.c   |  4 +++-
 include/linux/iommu.h      |  2 --
 4 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/iommu-priv.h b/drivers/iommu/iommu-priv.h
index 078cafcf49b4..a34efed2884b 100644
--- a/drivers/iommu/iommu-priv.h
+++ b/drivers/iommu/iommu-priv.h
@@ -19,6 +19,11 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)
 
 const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode);
 
+static inline const struct iommu_ops *iommu_fwspec_ops(struct iommu_fwspec *fwspec)
+{
+	return iommu_ops_from_fwnode(fwspec ? fwspec->iommu_fwnode : NULL);
+}
+
 int iommu_group_replace_domain(struct iommu_group *group,
 			       struct iommu_domain *new_domain);
 
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 7618c4285cf9..e15ae1dd494b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -510,7 +510,6 @@ DEFINE_MUTEX(iommu_probe_device_lock);
 static int __iommu_probe_device(struct device *dev, struct list_head *group_list)
 {
 	const struct iommu_ops *ops;
-	struct iommu_fwspec *fwspec;
 	struct iommu_group *group;
 	struct group_device *gdev;
 	int ret;
@@ -523,12 +522,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
 	 * be present, and that any of their registered instances has suitable
 	 * ops for probing, and thus cheekily co-opt the same mechanism.
 	 */
-	fwspec = dev_iommu_fwspec_get(dev);
-	if (fwspec && fwspec->ops)
-		ops = fwspec->ops;
-	else
-		ops = iommu_ops_from_fwnode(NULL);
-
+	ops = iommu_fwspec_ops(dev_iommu_fwspec_get(dev));
 	if (!ops)
 		return -ENODEV;
 	/*
@@ -2831,7 +2825,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode)
 		return -EPROBE_DEFER;
 
 	if (fwspec)
-		return ops == fwspec->ops ? 0 : -EINVAL;
+		return ops == iommu_fwspec_ops(fwspec) ? 0 : -EINVAL;
 
 	if (!dev_iommu_get(dev))
 		return -ENOMEM;
@@ -2843,7 +2837,6 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode)
 
 	fwnode_handle_get(iommu_fwnode);
 	fwspec->iommu_fwnode = iommu_fwnode;
-	fwspec->ops = ops;
 	dev_iommu_fwspec_set(dev, fwspec);
 	return 0;
 }
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index c946521a5906..559c5db78edb 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -17,6 +17,8 @@
 #include <linux/slab.h>
 #include <linux/fsl/mc.h>
 
+#include "iommu-priv.h"
+
 static int of_iommu_xlate(struct device *dev,
 			  struct of_phandle_args *iommu_spec)
 {
@@ -32,7 +34,7 @@ static int of_iommu_xlate(struct device *dev,
 	if (ret)
 		return ret;
 
-	ops = dev_iommu_fwspec_get(dev)->ops;
+	ops = iommu_ops_from_fwnode(&iommu_spec->np->fwnode);
 	if (!ops->of_xlate || !try_module_get(ops->owner))
 		return -ENODEV;
 
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 81893aad9ee4..11ae1750cb1d 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -968,7 +968,6 @@ extern struct iommu_group *generic_single_device_group(struct device *dev);
 
 /**
  * struct iommu_fwspec - per-device IOMMU instance data
- * @ops: ops for this device's IOMMU
  * @iommu_fwnode: firmware handle for this device's IOMMU
  * @flags: IOMMU_FWSPEC_* flags
  * @num_ids: number of associated device IDs
@@ -979,7 +978,6 @@ extern struct iommu_group *generic_single_device_group(struct device *dev);
  * consumers.
  */
 struct iommu_fwspec {
-	const struct iommu_ops	*ops;
 	struct fwnode_handle	*iommu_fwnode;
 	u32			flags;
 	unsigned int		num_ids;
-- 
2.39.2.101.g768bb238c484.dirty



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

* Re: [PATCH v2 0/4] iommu: Remove iommu_fwspec ops
  2024-06-21 18:46 [PATCH v2 0/4] iommu: Remove iommu_fwspec ops Robin Murphy
                   ` (3 preceding siblings ...)
  2024-06-21 18:46 ` [PATCH v2 4/4] iommu: Remove iommu_fwspec ops Robin Murphy
@ 2024-06-21 20:51 ` Saravana Kannan
  2024-07-02 12:23   ` Robin Murphy
  2024-07-01 13:49 ` Jean-Philippe Brucker
  5 siblings, 1 reply; 10+ messages in thread
From: Saravana Kannan @ 2024-06-21 20:51 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Will Deacon, Joerg Roedel, linux-acpi, linux-arm-kernel,
	linux-kernel, iommu, devicetree, Rob Herring, Lorenzo Pieralisi,
	Hanjun Guo, Sudeep Holla, Rafael J. Wysocki, Len Brown,
	Jean-Philippe Brucker, Andy Shevchenko

On Fri, Jun 21, 2024 at 8:46 PM Robin Murphy <robin.murphy@arm.com> wrote:
>
> v1: https://lore.kernel.org/linux-iommu/cover.1713523251.git.robin.murphy@arm.com
>
> Hi all,
>
> Here's v2 of this little cleanup, with acks and the additional cosmetic
> tweak suggested by Andy. There were some slightly non-trivial changes in
> the rebase so I've left off Jean-Philippe's tested-by from v1, but I've
> given it a quick spin on arm64 ACPI and DT and all seems well still.

Hi Robin,

I see in this series you talk about figuring out if a device has a
driver that could match. There has been a "can_match" flag in every
device that's set if a driver that match it is present, but hasn't
probed the device yet (for whatever reason). Just pointing that out in
case that makes things a lot easier for you. As of now, we don't
handle clearing it when the driver is unregistered, but if that really
needs to be handled, that shouldn't be too difficult.

-Saravana

>
> Thanks,
> Robin.
>
>
> Robin Murphy (4):
>   iommu: Resolve fwspec ops automatically
>   ACPI: Retire acpi_iommu_fwspec_ops()
>   OF: Simplify of_iommu_configure()
>   iommu: Remove iommu_fwspec ops
>
>  drivers/acpi/arm64/iort.c             | 19 +++-------
>  drivers/acpi/scan.c                   | 36 +++++--------------
>  drivers/acpi/viot.c                   | 11 ++----
>  drivers/iommu/arm/arm-smmu/arm-smmu.c |  3 +-
>  drivers/iommu/iommu-priv.h            |  7 ++++
>  drivers/iommu/iommu.c                 | 20 +++++------
>  drivers/iommu/mtk_iommu_v1.c          |  2 +-
>  drivers/iommu/of_iommu.c              | 50 ++++++++++-----------------
>  drivers/iommu/tegra-smmu.c            |  2 +-
>  drivers/of/device.c                   | 30 ++++++----------
>  include/acpi/acpi_bus.h               |  3 +-
>  include/linux/iommu.h                 | 15 ++------
>  12 files changed, 65 insertions(+), 133 deletions(-)
>
> --
> 2.39.2.101.g768bb238c484.dirty
>


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

* Re: [PATCH v2 3/4] OF: Simplify of_iommu_configure()
  2024-06-21 18:46 ` [PATCH v2 3/4] OF: Simplify of_iommu_configure() Robin Murphy
@ 2024-06-22 22:23   ` Andy Shevchenko
  2024-06-25 18:44     ` Robin Murphy
  0 siblings, 1 reply; 10+ messages in thread
From: Andy Shevchenko @ 2024-06-22 22:23 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Will Deacon, Joerg Roedel, linux-acpi, linux-arm-kernel,
	linux-kernel, iommu, devicetree, Rob Herring, Saravana Kannan,
	Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla, Rafael J. Wysocki,
	Len Brown, Jean-Philippe Brucker

On Fri, Jun 21, 2024 at 8:47 PM Robin Murphy <robin.murphy@arm.com> wrote:
>
> We no longer have a notion of partially-initialised fwspecs existing,
> and we also no longer need to use an iommu_ops pointer to return status
> to of_dma_configure(). Clean up the remains of those, which lends itself
> to clarifying the logic around the dma_range_map allocation as well.

...

> +       if (!err && dev->bus)
> +               err = iommu_probe_device(dev);
>
> +       if (err && err != -EPROBE_DEFER)
> +               dev_dbg(dev, "Adding to IOMMU failed: %d\n", err);

Hmm... I'm wondering if dev_err_probe() can be used here.

>         return err;

...

> +       dev_dbg(dev, "device is%sbehind an iommu\n",
> +               !ret ? " " : " not ");

Why not a positive test?

-- 
With Best Regards,
Andy Shevchenko


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

* Re: [PATCH v2 3/4] OF: Simplify of_iommu_configure()
  2024-06-22 22:23   ` Andy Shevchenko
@ 2024-06-25 18:44     ` Robin Murphy
  0 siblings, 0 replies; 10+ messages in thread
From: Robin Murphy @ 2024-06-25 18:44 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Will Deacon, Joerg Roedel, linux-acpi, linux-arm-kernel,
	linux-kernel, iommu, devicetree, Rob Herring, Saravana Kannan,
	Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla, Rafael J. Wysocki,
	Len Brown, Jean-Philippe Brucker

On 2024-06-22 11:23 pm, Andy Shevchenko wrote:
> On Fri, Jun 21, 2024 at 8:47 PM Robin Murphy <robin.murphy@arm.com> wrote:
>>
>> We no longer have a notion of partially-initialised fwspecs existing,
>> and we also no longer need to use an iommu_ops pointer to return status
>> to of_dma_configure(). Clean up the remains of those, which lends itself
>> to clarifying the logic around the dma_range_map allocation as well.
> 
> ...
> 
>> +       if (!err && dev->bus)
>> +               err = iommu_probe_device(dev);
>>
>> +       if (err && err != -EPROBE_DEFER)
>> +               dev_dbg(dev, "Adding to IOMMU failed: %d\n", err);
> 
> Hmm... I'm wondering if dev_err_probe() can be used here.

It's still possible to have other errors here benignly [1] (however 
questionable the underlying reason), and this has always been a 
dev_dbg(), it's just getting shuffled around again. The aim here is to 
carry on removing cruft to work towards getting rid of this 
iommu_probe_device() call altogether since it's fundamentally wrong, so 
I'm not inclined to add anything new or spend too much effort polishing 
code I still want to delete.

>>          return err;
> 
> ...
> 
>> +       dev_dbg(dev, "device is%sbehind an iommu\n",
>> +               !ret ? " " : " not ");
> 
> Why not a positive test?

Again, mostly because that's how it was written in 2014, same reason I'm 
not deduplicating the redundant space despite it still being the tiniest 
bit irritating. If you make me think about it, though, I suppose when 
both outcomes are otherwise equally weighted it does seems natural to 
consider "success" before "failure", thus the condition tests for success.

Thanks,
Robin.

[1] 
https://lore.kernel.org/linux-iommu/bbmhcoghrprmbdibnjum6lefix2eoquxrde7wyqeulm4xabmlm@b6jy32saugqh/


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

* Re: [PATCH v2 0/4] iommu: Remove iommu_fwspec ops
  2024-06-21 18:46 [PATCH v2 0/4] iommu: Remove iommu_fwspec ops Robin Murphy
                   ` (4 preceding siblings ...)
  2024-06-21 20:51 ` [PATCH v2 0/4] " Saravana Kannan
@ 2024-07-01 13:49 ` Jean-Philippe Brucker
  5 siblings, 0 replies; 10+ messages in thread
From: Jean-Philippe Brucker @ 2024-07-01 13:49 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Will Deacon, Joerg Roedel, linux-acpi, linux-arm-kernel,
	linux-kernel, iommu, devicetree, Rob Herring, Saravana Kannan,
	Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla, Rafael J. Wysocki,
	Len Brown, Andy Shevchenko

On Fri, Jun 21, 2024 at 07:46:35PM +0100, Robin Murphy wrote:
> v1: https://lore.kernel.org/linux-iommu/cover.1713523251.git.robin.murphy@arm.com
> 
> Hi all,
> 
> Here's v2 of this little cleanup, with acks and the additional cosmetic
> tweak suggested by Andy. There were some slightly non-trivial changes in
> the rebase so I've left off Jean-Philippe's tested-by from v1, but I've
> given it a quick spin on arm64 ACPI and DT and all seems well still.

virtio-iommu arm64/x86 DT/ACPI still work as well

Tested-by: Jean-Philippe Brucker <jean-philippe@linaro.org>

> 
> Thanks,
> Robin.
> 
> 
> Robin Murphy (4):
>   iommu: Resolve fwspec ops automatically
>   ACPI: Retire acpi_iommu_fwspec_ops()
>   OF: Simplify of_iommu_configure()
>   iommu: Remove iommu_fwspec ops
> 
>  drivers/acpi/arm64/iort.c             | 19 +++-------
>  drivers/acpi/scan.c                   | 36 +++++--------------
>  drivers/acpi/viot.c                   | 11 ++----
>  drivers/iommu/arm/arm-smmu/arm-smmu.c |  3 +-
>  drivers/iommu/iommu-priv.h            |  7 ++++
>  drivers/iommu/iommu.c                 | 20 +++++------
>  drivers/iommu/mtk_iommu_v1.c          |  2 +-
>  drivers/iommu/of_iommu.c              | 50 ++++++++++-----------------
>  drivers/iommu/tegra-smmu.c            |  2 +-
>  drivers/of/device.c                   | 30 ++++++----------
>  include/acpi/acpi_bus.h               |  3 +-
>  include/linux/iommu.h                 | 15 ++------
>  12 files changed, 65 insertions(+), 133 deletions(-)
> 
> -- 
> 2.39.2.101.g768bb238c484.dirty
> 


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

* Re: [PATCH v2 0/4] iommu: Remove iommu_fwspec ops
  2024-06-21 20:51 ` [PATCH v2 0/4] " Saravana Kannan
@ 2024-07-02 12:23   ` Robin Murphy
  0 siblings, 0 replies; 10+ messages in thread
From: Robin Murphy @ 2024-07-02 12:23 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Will Deacon, Joerg Roedel, linux-acpi, linux-arm-kernel,
	linux-kernel, iommu, devicetree, Rob Herring, Lorenzo Pieralisi,
	Hanjun Guo, Sudeep Holla, Rafael J. Wysocki, Len Brown,
	Jean-Philippe Brucker, Andy Shevchenko

On 21/06/2024 9:51 pm, Saravana Kannan wrote:
> On Fri, Jun 21, 2024 at 8:46 PM Robin Murphy <robin.murphy@arm.com> wrote:
>>
>> v1: https://lore.kernel.org/linux-iommu/cover.1713523251.git.robin.murphy@arm.com
>>
>> Hi all,
>>
>> Here's v2 of this little cleanup, with acks and the additional cosmetic
>> tweak suggested by Andy. There were some slightly non-trivial changes in
>> the rebase so I've left off Jean-Philippe's tested-by from v1, but I've
>> given it a quick spin on arm64 ACPI and DT and all seems well still.
> 
> Hi Robin,
> 
> I see in this series you talk about figuring out if a device has a
> driver that could match. There has been a "can_match" flag in every
> device that's set if a driver that match it is present, but hasn't
> probed the device yet (for whatever reason). Just pointing that out in
> case that makes things a lot easier for you. As of now, we don't
> handle clearing it when the driver is unregistered, but if that really
> needs to be handled, that shouldn't be too difficult.

Thanks, that's interesting to know. I'm not sure it's directly 
applicable here since we have the more general case where the IOMMU 
driver may also be a module that's not even loaded yet. What ultimately 
matters is whether someone has called iommu_device_register() for a 
matching IOMMU instance, or may do within a reasonable timeframe, so as 
long as we can keep relying on fw_devlink and deferred_probe_timeout to 
do most of the heavy lifting then I'd actually hope we can avoid getting 
into the low-level details here.

Cheers,
Robin.


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

end of thread, other threads:[~2024-07-02 12:24 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-21 18:46 [PATCH v2 0/4] iommu: Remove iommu_fwspec ops Robin Murphy
2024-06-21 18:46 ` [PATCH v2 1/4] iommu: Resolve fwspec ops automatically Robin Murphy
2024-06-21 18:46 ` [PATCH v2 2/4] ACPI: Retire acpi_iommu_fwspec_ops() Robin Murphy
2024-06-21 18:46 ` [PATCH v2 3/4] OF: Simplify of_iommu_configure() Robin Murphy
2024-06-22 22:23   ` Andy Shevchenko
2024-06-25 18:44     ` Robin Murphy
2024-06-21 18:46 ` [PATCH v2 4/4] iommu: Remove iommu_fwspec ops Robin Murphy
2024-06-21 20:51 ` [PATCH v2 0/4] " Saravana Kannan
2024-07-02 12:23   ` Robin Murphy
2024-07-01 13:49 ` Jean-Philippe Brucker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).