[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <12-v1-f82a05539a64+5042-iommu_fwspec_p2_jgg@nvidia.com>
Date: Wed, 29 Nov 2023 21:10:19 -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 12/30] iommu/of: Add iommu_of_xlate()
This function can be called by drivers in their probe function if they
want to parse their own ID table, almost always because the driver
supports a multi-instance configuration and needs to extract the list of
iommu_driver's and data from the ID into some internal format.
The core code will find the iommu_driver for each ID table entry and
validate that it matches the driver's ops. A driver provided function is
called to handle the (iommu_driver, ID) tuple.
Before calling this function the driver should allocate its per-driver
private data and pass it through the opaque cookie priv argument.
Driver's should follow a typical pattern in their probe_device:
static int apple_dart_of_xlate(struct iommu_device *iommu,
struct of_phandle_args *args, void *priv);
[..]
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
if (!cfg) return ERR_PTR(-ENOMEM);
ret = iommu_of_xlate(pinf, &apple_dart_iommu_ops, 1,
&apple_dart_of_xlate, cfg);
if (ret) goto err_free;
dev_iommu_priv_set(dev, cfg);
return &??->iommu; // The first iommu_device parsed
Signed-off-by: Jason Gunthorpe <jgg@...dia.com>
---
drivers/iommu/of_iommu.c | 58 ++++++++++++++++++++++++++++++++++++
include/linux/iommu-driver.h | 13 ++++++++
2 files changed, 71 insertions(+)
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 37af32a6bc84e5..9c1d398aa2cd9c 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -285,6 +285,8 @@ struct parse_info {
struct iommu_probe_info *pinf;
const struct iommu_ops *ops;
int num_cells;
+ iommu_of_xlate_fn xlate_fn;
+ void *priv;
};
static struct iommu_device *parse_iommu(struct parse_info *info,
@@ -336,3 +338,59 @@ struct iommu_device *__iommu_of_get_single_iommu(struct iommu_probe_info *pinf,
return iommu_fw_finish_get_single(pinf);
}
EXPORT_SYMBOL_GPL(__iommu_of_get_single_iommu);
+
+static int parse_of_xlate(struct of_phandle_args *iommu_spec, void *_info)
+{
+ struct parse_info *info = _info;
+ struct iommu_device *iommu;
+
+ iommu = parse_iommu(info, iommu_spec);
+ if (IS_ERR(iommu))
+ return PTR_ERR(iommu);
+ info->pinf->num_ids++;
+ return info->xlate_fn(iommu, iommu_spec, info->priv);
+}
+
+/**
+ * iommu_of_xlate - Parse all OF ids for an IOMMU
+ * @pinf: The iommu_probe_info
+ * @ops: The ops the iommu instance must have
+ * @num_cells: #iommu-cells value to enforce, -1 is no check
+ * @fn: Call for each Instance and ID
+ * @priv: Opaque cookie for fn
+ *
+ * Drivers that support multiple iommu instances must call this function to
+ * parse each instance from the OF table. fn will be called with the driver's
+ * iommu_driver instance and the raw of_phandle_args that contains the ID.
+ *
+ * Drivers that need to parse a complex ID format should also use this function.
+ */
+int iommu_of_xlate(struct iommu_probe_info *pinf, const struct iommu_ops *ops,
+ int num_cells, iommu_of_xlate_fn fn, void *priv)
+{
+ struct parse_info info = { .pinf = pinf,
+ .ops = ops,
+ .num_cells = num_cells,
+ .xlate_fn = fn,
+ .priv = priv };
+
+ pinf->num_ids = 0;
+ return of_iommu_for_each_id(pinf->dev, pinf->of_master_np,
+ pinf->of_map_id, parse_of_xlate, &info);
+}
+EXPORT_SYMBOL_GPL(iommu_of_xlate);
+
+/*
+ * Temporary approach to allow drivers to opt into the bus probe. It configures
+ * the iommu_probe_info to probe the dev->of_node. This is a bit hacky because
+ * it mutates the iommu_probe_info and thus assumes there is only one op in the
+ * system. Remove when we call probe from the bus always anyhow.
+ */
+void iommu_of_allow_bus_probe(struct iommu_probe_info *pinf)
+{
+ if (pinf->is_dma_configure)
+ return;
+ pinf->of_master_np = pinf->dev->of_node;
+ pinf->is_dma_configure = true;
+}
+EXPORT_SYMBOL_GPL(iommu_of_allow_bus_probe);
diff --git a/include/linux/iommu-driver.h b/include/linux/iommu-driver.h
index 597998a62b0dd6..622d6ad9056ce0 100644
--- a/include/linux/iommu-driver.h
+++ b/include/linux/iommu-driver.h
@@ -60,9 +60,16 @@ iommu_device_from_fwnode_pinf(struct iommu_probe_info *pinf,
struct fwnode_handle *fwnode);
struct iommu_device *iommu_fw_finish_get_single(struct iommu_probe_info *pinf);
+typedef int (*iommu_of_xlate_fn)(struct iommu_device *iommu,
+ struct of_phandle_args *args, void *priv);
+void iommu_of_allow_bus_probe(struct iommu_probe_info *pinf);
+
#if IS_ENABLED(CONFIG_OF_IOMMU)
void of_iommu_get_resv_regions(struct device *dev, struct list_head *list);
+int iommu_of_xlate(struct iommu_probe_info *pinf, const struct iommu_ops *ops,
+ int num_cells, iommu_of_xlate_fn fn, void *priv);
+
struct iommu_device *__iommu_of_get_single_iommu(struct iommu_probe_info *pinf,
const struct iommu_ops *ops,
int num_cells);
@@ -71,6 +78,12 @@ static inline void of_iommu_get_resv_regions(struct device *dev,
struct list_head *list)
{
}
+static inline int iommu_of_xlate(struct iommu_probe_info *pinf,
+ const struct iommu_ops *ops, int num_cells,
+ iommu_of_xlate_fn fn, void *priv)
+{
+ return -ENODEV;
+}
static inline
struct iommu_device *__iommu_of_get_single_iommu(struct iommu_probe_info *pinf,
const struct iommu_ops *ops,
--
2.42.0
Powered by blists - more mailing lists