[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <5-v1-f82a05539a64+5042-iommu_fwspec_p2_jgg@nvidia.com>
Date: Wed, 29 Nov 2023 21:10:12 -0400
From: Jason Gunthorpe <jgg@...dia.com>
To: acpica-devel@...ts.linux.dev,
Andy Gross <agross@...nel.org>,
Alim Akhtar <alim.akhtar@...sung.com>,
Alyssa Rosenzweig <alyssa@...enzweig.io>,
Bjorn Andersson <andersson@...nel.org>,
AngeloGioacchino Del Regno <angelogioacchino.delregno@...labora.com>,
asahi@...ts.linux.dev,
Baolin Wang <baolin.wang@...ux.alibaba.com>,
devicetree@...r.kernel.org,
Frank Rowand <frowand.list@...il.com>,
Hanjun Guo <guohanjun@...wei.com>,
"Gustavo A. R. Silva" <gustavoars@...nel.org>,
Heiko Stuebner <heiko@...ech.de>,
iommu@...ts.linux.dev,
Jean-Philippe Brucker <jean-philippe@...aro.org>,
Jernej Skrabec <jernej.skrabec@...il.com>,
Jonathan Hunter <jonathanh@...dia.com>,
Joerg Roedel <joro@...tes.org>,
Kees Cook <keescook@...omium.org>,
Konrad Dybcio <konrad.dybcio@...aro.org>,
Krzysztof Kozlowski <krzysztof.kozlowski@...aro.org>,
Len Brown <lenb@...nel.org>,
linux-acpi@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
linux-arm-msm@...r.kernel.org,
linux-hardening@...r.kernel.org,
linux-mediatek@...ts.infradead.org,
linux-rockchip@...ts.infradead.org,
linux-samsung-soc@...r.kernel.org,
linux-sunxi@...ts.linux.dev,
linux-tegra@...r.kernel.org,
Lorenzo Pieralisi <lpieralisi@...nel.org>,
Marek Szyprowski <m.szyprowski@...sung.com>,
Hector Martin <marcan@...can.st>,
Matthias Brugger <matthias.bgg@...il.com>,
Orson Zhai <orsonzhai@...il.com>,
"Rafael J. Wysocki" <rafael@...nel.org>,
Rob Clark <robdclark@...il.com>,
Robert Moore <robert.moore@...el.com>,
Rob Herring <robh+dt@...nel.org>,
Robin Murphy <robin.murphy@....com>,
Samuel Holland <samuel@...lland.org>,
Sudeep Holla <sudeep.holla@....com>,
Sven Peter <sven@...npeter.dev>,
Thierry Reding <thierry.reding@...il.com>,
Krishna Reddy <vdumpa@...dia.com>,
virtualization@...ts.linux.dev,
Chen-Yu Tsai <wens@...e.org>,
Will Deacon <will@...nel.org>,
Yong Wu <yong.wu@...iatek.com>,
Chunyan Zhang <zhang.lyra@...il.com>
Cc: André Draszik <andre.draszik@...aro.org>,
patches@...ts.linux.dev
Subject: [PATCH 05/30] iommu: Add iommu_probe_info
This is a stack structure that is passed around all the parts of probe to
allow them to exchange data.
With the new design this will be a place for the FW logic to cache data to
avoid reparsing and a to convey the currently active call path for probe
while we work on restructuring parts of it.
Place this in a new header "iommu-driver.h" which is intended to help
isolate APIs that are only for use by the drivers away from the consumers
of the IOMMU API.
Signed-off-by: Jason Gunthorpe <jgg@...dia.com>
---
drivers/acpi/scan.c | 7 +++++-
drivers/iommu/iommu.c | 42 ++++++++++++++++++++++++++----------
drivers/iommu/of_iommu.c | 6 +++++-
include/linux/iommu-driver.h | 25 +++++++++++++++++++++
include/linux/iommu.h | 3 +++
5 files changed, 70 insertions(+), 13 deletions(-)
create mode 100644 include/linux/iommu-driver.h
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 340ba720c72129..9c13df632aa5e0 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1543,6 +1543,8 @@ int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)
}
#ifdef CONFIG_IOMMU_API
+#include <linux/iommu-driver.h>
+
int acpi_iommu_fwspec_init(struct device *dev, u32 id,
struct fwnode_handle *fwnode,
const struct iommu_ops *ops)
@@ -1566,6 +1568,9 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
{
int err;
const struct iommu_ops *ops;
+ struct iommu_probe_info pinf = {
+ .dev = dev,
+ };
/* Serialise to make dev->iommu stable under our potential fwspec */
mutex_lock(&iommu_probe_device_lock);
@@ -1589,7 +1594,7 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)
* iommu_probe_device() call for dev, replay it to get things in order.
*/
if (!err && dev->bus)
- err = iommu_probe_device(dev);
+ err = iommu_probe_device_pinf(&pinf);
/* Ignore all other errors apart from EPROBE_DEFER */
if (err == -EPROBE_DEFER) {
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9557c2ec08d915..76b245973cfafc 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/host1x_context_bus.h>
#include <linux/iommu.h>
+#include <linux/iommu-driver.h>
#include <linux/idr.h>
#include <linux/err.h>
#include <linux/pci.h>
@@ -399,8 +400,10 @@ EXPORT_SYMBOL_GPL(dev_iommu_priv_set);
* Init the dev->iommu and dev->iommu_group in the struct device and get the
* driver probed
*/
-static int iommu_init_device(struct device *dev, const struct iommu_ops *ops)
+static int iommu_init_device(struct iommu_probe_info *pinf,
+ const struct iommu_ops *ops)
{
+ struct device *dev = pinf->dev;
struct iommu_device *iommu_dev;
struct iommu_group *group;
int ret;
@@ -413,7 +416,10 @@ static int iommu_init_device(struct device *dev, const struct iommu_ops *ops)
goto err_free;
}
- iommu_dev = ops->probe_device(dev);
+ if (ops->probe_device_pinf)
+ iommu_dev = ops->probe_device_pinf(pinf);
+ else
+ iommu_dev = ops->probe_device(dev);
if (IS_ERR(iommu_dev)) {
ret = PTR_ERR(iommu_dev);
goto err_module_put;
@@ -496,8 +502,9 @@ static void iommu_deinit_device(struct device *dev)
DEFINE_MUTEX(iommu_probe_device_lock);
-static int __iommu_probe_device(struct device *dev, struct list_head *group_list)
+static int __iommu_probe_device(struct iommu_probe_info *pinf)
{
+ struct device *dev = pinf->dev;
const struct iommu_ops *ops;
struct iommu_fwspec *fwspec;
struct iommu_group *group;
@@ -533,7 +540,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
if (dev->iommu_group)
return 0;
- ret = iommu_init_device(dev, ops);
+ ret = iommu_init_device(pinf, ops);
if (ret)
return ret;
@@ -557,7 +564,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
ret = __iommu_device_set_domain(group, dev, group->domain, 0);
if (ret)
goto err_remove_gdev;
- } else if (!group->default_domain && !group_list) {
+ } else if (!group->default_domain && !pinf->defer_setup) {
ret = iommu_setup_default_domain(group, 0);
if (ret)
goto err_remove_gdev;
@@ -568,7 +575,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
* that need further setup.
*/
if (list_empty(&group->entry))
- list_add_tail(&group->entry, group_list);
+ list_add_tail(&group->entry, pinf->deferred_group_list);
}
mutex_unlock(&group->mutex);
@@ -588,13 +595,14 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
return ret;
}
-int iommu_probe_device(struct device *dev)
+int iommu_probe_device_pinf(struct iommu_probe_info *pinf)
{
+ struct device *dev = pinf->dev;
const struct iommu_ops *ops;
int ret;
mutex_lock(&iommu_probe_device_lock);
- ret = __iommu_probe_device(dev, NULL);
+ ret = __iommu_probe_device(pinf);
mutex_unlock(&iommu_probe_device_lock);
if (ret)
return ret;
@@ -606,6 +614,13 @@ int iommu_probe_device(struct device *dev)
return 0;
}
+int iommu_probe_device(struct device *dev)
+{
+ struct iommu_probe_info pinf = {.dev = dev};
+
+ return iommu_probe_device_pinf(&pinf);
+}
+
static void __iommu_group_free_device(struct iommu_group *group,
struct group_device *grp_dev)
{
@@ -1830,11 +1845,12 @@ struct iommu_domain *iommu_group_default_domain(struct iommu_group *group)
static int probe_iommu_group(struct device *dev, void *data)
{
- struct list_head *group_list = data;
+ struct iommu_probe_info *pinf = data;
int ret;
+ pinf->dev = dev;
mutex_lock(&iommu_probe_device_lock);
- ret = __iommu_probe_device(dev, group_list);
+ ret = __iommu_probe_device(pinf);
mutex_unlock(&iommu_probe_device_lock);
if (ret == -ENODEV)
ret = 0;
@@ -1977,9 +1993,13 @@ int bus_iommu_probe(const struct bus_type *bus)
{
struct iommu_group *group, *next;
LIST_HEAD(group_list);
+ struct iommu_probe_info pinf = {
+ .deferred_group_list = &group_list,
+ .defer_setup = true,
+ };
int ret;
- ret = bus_for_each_dev(bus, NULL, &group_list, probe_iommu_group);
+ ret = bus_for_each_dev(bus, NULL, &pinf, probe_iommu_group);
if (ret)
return ret;
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 3d4580f1fbb378..fb743ddd239e0b 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -7,6 +7,7 @@
#include <linux/export.h>
#include <linux/iommu.h>
+#include <linux/iommu-driver.h>
#include <linux/limits.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -139,6 +140,9 @@ static int of_iommu_for_each_id(struct device *dev,
int of_iommu_configure(struct device *dev, struct device_node *master_np,
const u32 *id)
{
+ struct iommu_probe_info pinf = {
+ .dev = dev,
+ };
struct iommu_fwspec *fwspec;
int err;
@@ -167,7 +171,7 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,
if (err)
goto err_log;
- err = iommu_probe_device(dev);
+ err = iommu_probe_device_pinf(&pinf);
if (err)
goto err_log;
return 0;
diff --git a/include/linux/iommu-driver.h b/include/linux/iommu-driver.h
new file mode 100644
index 00000000000000..b85c9f15cf478b
--- /dev/null
+++ b/include/linux/iommu-driver.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES
+ *
+ * This file should ONLY be included by iommu drivers. These API
+ * calls are NOT to be used generally.
+ */
+#ifndef __LINUX_IOMMU_DRIVER_H
+#define __LINUX_IOMMU_DRIVER_H
+
+#ifndef CONFIG_IOMMU_API
+#error "CONFIG_IOMMU_API is not set, should this header be included?"
+#endif
+
+#include <linux/types.h>
+
+struct iommu_probe_info {
+ struct device *dev;
+ struct list_head *deferred_group_list;
+ bool defer_setup : 1;
+};
+
+int iommu_probe_device_pinf(struct iommu_probe_info *pinf);
+
+#endif
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index c24933a1d0d643..cf578b8e0b59a4 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -43,6 +43,7 @@ struct notifier_block;
struct iommu_sva;
struct iommu_fault_event;
struct iommu_dma_cookie;
+struct iommu_probe_info;
/* iommu fault flags */
#define IOMMU_FAULT_READ 0x0
@@ -347,6 +348,7 @@ static inline int __iommu_copy_struct_from_user(
* @domain_alloc_paging: Allocate an iommu_domain that can be used for
* UNMANAGED, DMA, and DMA_FQ domain types.
* @probe_device: Add device to iommu driver handling
+ * @probe_device_pinf: New API for probe_device
* @release_device: Remove device from iommu driver handling
* @probe_finalize: Do final setup work after the device is added to an IOMMU
* group and attached to the groups domain
@@ -388,6 +390,7 @@ struct iommu_ops {
struct iommu_domain *(*domain_alloc_paging)(struct device *dev);
struct iommu_device *(*probe_device)(struct device *dev);
+ struct iommu_device *(*probe_device_pinf)(struct iommu_probe_info *pinf);
void (*release_device)(struct device *dev);
void (*probe_finalize)(struct device *dev);
struct iommu_group *(*device_group)(struct device *dev);
--
2.42.0
Powered by blists - more mailing lists