* [PATCH v3 0/3] of: parsing of multi #{iommu,msi}-cells in maps
@ 2025-12-21 21:35 Vijayanand Jitta
2025-12-21 21:36 ` [PATCH v3 1/3] of: Add convenience wrappers for of_map_id() Vijayanand Jitta
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Vijayanand Jitta @ 2025-12-21 21:35 UTC (permalink / raw)
To: robin.murphy, will, joro, robh, dmitry.baryshkov, konrad.dybcio,
bjorn.andersson, bod, conor+dt, krzk+dt, saravanak, prakash.gupta,
vikash.garodia
Cc: iommu, linux-kernel, devicetree, Vijayanand Jitta
So far our parsing of {iommu,msi}-map properites has always blindly
assumed that the output specifiers will always have exactly 1 cell.
This typically does happen to be the case, but is not actually enforced
(and the PCI msi-map binding even explicitly states support for 0 or 1
cells) - as a result we've now ended up with dodgy DTs out in the field
which depend on this behaviour to map a 1-cell specifier for a 2-cell
provider, despite that being bogus per the bindings themselves.
Since there is some potential use[1] in being able to map at least
single input IDs to multi-cell output specifiers (and properly support
0-cell outputs as well), add support for properly parsing and using the
target nodes' #cells values, albeit with the unfortunate complication of
still having to work around expectations of the old behaviour too.
-- Robin.
Unlike single #{}-cell, it is complex to establish a linear relation
between input 'id' and output specifier for multi-cell properties, thus
it is always expected that len never going to be > 1.
The motivation for this patchset originates from the multi-map use case
described in V1, which will be addressed in a subsequent series once the
current fixes for iommu-cell handling are concluded.
These changes have been tested on QEMU for the arm64 architecture. We
plan to perform more extensive testing based on community feedback and
are sending this series out early to gather review comments.
[1] https://lore.kernel.org/all/20250627-video_cb-v3-0-51e18c0ffbce@quicinc.com/
V3:
1) Added Reviewed-by tag.
2) Updated of_map_id_args struct as a wrapper to of_phandle_args and
added comment description as suggested by Rob Herring.
Link to V2:
https://lore.kernel.org/all/20251204095530.8627-1-vijayanand.jitta@oss.qualcomm.com/
V2:
1) Incorporated the patches from Robin that does the clean implementation.
2) Dropped the patches the were adding multi-map support from this series
as suggested.
V1:
https://lore.kernel.org/all/cover.1762235099.git.charan.kalla@oss.qualcomm.com/
RFC:
https://lore.kernel.org/all/20250928171718.436440-1-charan.kalla@oss.qualcomm.com/#r
Charan Teja Kalla (1):
of: factor arguments passed to of_map_id() into a struct
Robin Murphy (2):
of: Add convenience wrappers for of_map_id()
of: Respect #{iommu,msi}-cells in maps
drivers/cdx/cdx_msi.c | 3 +-
drivers/iommu/of_iommu.c | 9 +-
drivers/irqchip/irq-gic-its-msi-parent.c | 4 +-
drivers/of/base.c | 147 +++++++++++++++++------
drivers/of/irq.c | 3 +-
drivers/pci/controller/dwc/pci-imx6.c | 10 +-
drivers/pci/controller/pcie-apple.c | 6 +-
drivers/xen/grant-dma-ops.c | 5 +-
include/linux/of.h | 36 +++++-
9 files changed, 161 insertions(+), 62 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 1/3] of: Add convenience wrappers for of_map_id()
2025-12-21 21:35 [PATCH v3 0/3] of: parsing of multi #{iommu,msi}-cells in maps Vijayanand Jitta
@ 2025-12-21 21:36 ` Vijayanand Jitta
2025-12-30 15:29 ` Frank Li
2025-12-21 21:36 ` [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct Vijayanand Jitta
2025-12-21 21:36 ` [PATCH v3 3/3] of: Respect #{iommu,msi}-cells in maps Vijayanand Jitta
2 siblings, 1 reply; 7+ messages in thread
From: Vijayanand Jitta @ 2025-12-21 21:36 UTC (permalink / raw)
To: robin.murphy, will, joro, robh, dmitry.baryshkov, konrad.dybcio,
bjorn.andersson, bod, conor+dt, krzk+dt, saravanak, prakash.gupta,
vikash.garodia
Cc: iommu, linux-kernel, devicetree, Vijayanand Jitta
From: Robin Murphy <robin.murphy@arm.com>
Since we now have quite a few users parsing "iommu-map" and "msi-map"
properties, give them some wrappers to conveniently encapsulate the
appropriate sets of property names. This will also make it easier to
then change of_map_id() to correctly account for specifier cells.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
---
drivers/cdx/cdx_msi.c | 3 +--
drivers/iommu/of_iommu.c | 4 +---
drivers/irqchip/irq-gic-its-msi-parent.c | 4 ++--
drivers/of/irq.c | 3 +--
drivers/pci/controller/dwc/pci-imx6.c | 6 ++----
drivers/pci/controller/pcie-apple.c | 3 +--
drivers/xen/grant-dma-ops.c | 3 +--
include/linux/of.h | 14 ++++++++++++++
8 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/drivers/cdx/cdx_msi.c b/drivers/cdx/cdx_msi.c
index 91b95422b263..63b3544ec997 100644
--- a/drivers/cdx/cdx_msi.c
+++ b/drivers/cdx/cdx_msi.c
@@ -128,8 +128,7 @@ static int cdx_msi_prepare(struct irq_domain *msi_domain,
int ret;
/* Retrieve device ID from requestor ID using parent device */
- ret = of_map_id(parent->of_node, cdx_dev->msi_dev_id, "msi-map", "msi-map-mask",
- NULL, &dev_id);
+ ret = of_map_msi_id(parent->of_node, cdx_dev->msi_dev_id, NULL, &dev_id);
if (ret) {
dev_err(dev, "of_map_id failed for MSI: %d\n", ret);
return ret;
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 6b989a62def2..a511ecf21fcd 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -48,9 +48,7 @@ static int of_iommu_configure_dev_id(struct device_node *master_np,
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
- err = of_map_id(master_np, *id, "iommu-map",
- "iommu-map-mask", &iommu_spec.np,
- iommu_spec.args);
+ err = of_map_iommu_id(master_np, *id, &iommu_spec.np, iommu_spec.args);
if (err)
return err;
diff --git a/drivers/irqchip/irq-gic-its-msi-parent.c b/drivers/irqchip/irq-gic-its-msi-parent.c
index eb1473f1448a..0884c4cbd245 100644
--- a/drivers/irqchip/irq-gic-its-msi-parent.c
+++ b/drivers/irqchip/irq-gic-its-msi-parent.c
@@ -166,7 +166,7 @@ static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev,
if (ret) {
struct device_node *np = NULL;
- ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id);
+ ret = of_map_msi_id(dev->of_node, dev->id, &np, dev_id);
if (np)
of_node_put(np);
}
@@ -211,7 +211,7 @@ static int of_v5_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev
if (ret) {
struct device_node *np = NULL;
- ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id);
+ ret = of_map_msi_id(dev->of_node, dev->id, &np, dev_id);
if (np) {
ret = its_translate_frame_address(np, pa);
of_node_put(np);
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 1cd93549d093..9549dda8f9d6 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -725,8 +725,7 @@ u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in)
* "msi-map" or an "msi-parent" property.
*/
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) {
- if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
- "msi-map-mask", msi_np, &id_out))
+ if (!of_map_msi_id(parent_dev->of_node, id_in, msi_np, &id_out))
break;
if (!of_check_msi_parent(parent_dev->of_node, msi_np))
break;
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 4668fc9648bf..c8da2e88e9c6 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1106,8 +1106,7 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
u32 sid = 0;
target = NULL;
- err_i = of_map_id(dev->of_node, rid, "iommu-map", "iommu-map-mask",
- &target, &sid_i);
+ err_i = of_map_iommu_id(dev->of_node, rid, &target, &sid_i);
if (target) {
of_node_put(target);
} else {
@@ -1120,8 +1119,7 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
}
target = NULL;
- err_m = of_map_id(dev->of_node, rid, "msi-map", "msi-map-mask",
- &target, &sid_m);
+ err_m = of_map_msi_id(dev->of_node, rid, &target, &sid_m);
/*
* err_m target
diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index 0380d300adca..ce21728d6e51 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -791,8 +791,7 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
dev_dbg(&pdev->dev, "added to bus %s, index %d\n",
pci_name(pdev->bus->self), port->idx);
- err = of_map_id(port->pcie->dev->of_node, rid, "iommu-map",
- "iommu-map-mask", NULL, &sid);
+ err = of_map_iommu_id(port->pcie->dev->of_node, rid, NULL, &sid);
if (err)
return err;
diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c
index 29257d2639db..b661f9c1f4fe 100644
--- a/drivers/xen/grant-dma-ops.c
+++ b/drivers/xen/grant-dma-ops.c
@@ -321,8 +321,7 @@ static int xen_dt_grant_init_backend_domid(struct device *dev,
struct pci_dev *pdev = to_pci_dev(dev);
u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
- if (of_map_id(np, rid, "iommu-map", "iommu-map-mask", &iommu_spec.np,
- iommu_spec.args)) {
+ if (of_map_iommu_id(np, rid, &iommu_spec.np, iommu_spec.args)) {
dev_dbg(dev, "Cannot translate ID\n");
return -ESRCH;
}
diff --git a/include/linux/of.h b/include/linux/of.h
index 121a288ca92d..8cd486d89da2 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -1435,6 +1435,20 @@ static inline int of_property_read_s32(const struct device_node *np,
return of_property_read_u32(np, propname, (u32*) out_value);
}
+static inline int of_map_iommu_id(const struct device_node *np, u32 id,
+ struct device_node **target, u32 *id_out)
+{
+ return of_map_id(np, id, "iommu-map", "iommu-map-mask",
+ target, id_out);
+}
+
+static inline int of_map_msi_id(const struct device_node *np, u32 id,
+ struct device_node **target, u32 *id_out)
+{
+ return of_map_id(np, id, "msi-map", "msi-map-mask",
+ target, id_out);
+}
+
#define of_for_each_phandle(it, err, np, ln, cn, cc) \
for (of_phandle_iterator_init((it), (np), (ln), (cn), (cc)), \
err = of_phandle_iterator_next(it); \
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct
2025-12-21 21:35 [PATCH v3 0/3] of: parsing of multi #{iommu,msi}-cells in maps Vijayanand Jitta
2025-12-21 21:36 ` [PATCH v3 1/3] of: Add convenience wrappers for of_map_id() Vijayanand Jitta
@ 2025-12-21 21:36 ` Vijayanand Jitta
2025-12-24 3:37 ` kernel test robot
2025-12-24 3:37 ` kernel test robot
2025-12-21 21:36 ` [PATCH v3 3/3] of: Respect #{iommu,msi}-cells in maps Vijayanand Jitta
2 siblings, 2 replies; 7+ messages in thread
From: Vijayanand Jitta @ 2025-12-21 21:36 UTC (permalink / raw)
To: robin.murphy, will, joro, robh, dmitry.baryshkov, konrad.dybcio,
bjorn.andersson, bod, conor+dt, krzk+dt, saravanak, prakash.gupta,
vikash.garodia
Cc: iommu, linux-kernel, devicetree, Charan Teja Kalla,
Vijayanand Jitta
From: Charan Teja Kalla <charan.kalla@oss.qualcomm.com>
Introduce a new struct type where the optional arguments passed to
of_map_id() are Currently embedded as of_phandle_args struct.
Subsequent patches add additional arguments to the struct that the
caller expects to be filled of_map_id().
Suggested-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Charan Teja Kalla <charan.kalla@oss.qualcomm.com>
Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
---
drivers/iommu/of_iommu.c | 5 +++-
drivers/of/base.c | 39 ++++++++++++++-------------
drivers/pci/controller/dwc/pci-imx6.c | 6 ++++-
drivers/pci/controller/pcie-apple.c | 5 +++-
drivers/xen/grant-dma-ops.c | 4 ++-
include/linux/of.h | 24 ++++++++++++-----
6 files changed, 53 insertions(+), 30 deletions(-)
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index a511ecf21fcd..74779b77ba13 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -46,9 +46,12 @@ static int of_iommu_configure_dev_id(struct device_node *master_np,
const u32 *id)
{
struct of_phandle_args iommu_spec = { .args_count = 1 };
+ struct of_map_id_arg arg = {
+ .map_args = iommu_spec,
+ };
int err;
- err = of_map_iommu_id(master_np, *id, &iommu_spec.np, iommu_spec.args);
+ err = of_map_iommu_id(master_np, *id, &arg);
if (err)
return err;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 7043acd971a0..4dca3d37a34b 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2051,8 +2051,11 @@ int of_find_last_cache_level(unsigned int cpu)
* @id: device ID to map.
* @map_name: property name of the map to use.
* @map_mask_name: optional property name of the mask to use.
- * @target: optional pointer to a target device node.
- * @id_out: optional pointer to receive the translated ID.
+ * @arg: contains the optional params, wrapped in a struct of_phandle_args,
+ * which includes:
+ * np: pointer to the target device node
+ * args_count: number of arguments
+ * args[]: array to receive the translated ID(s).
*
* Given a device ID, look up the appropriate implementation-defined
* platform ID and/or the target device which receives transactions on that
@@ -2066,21 +2069,21 @@ int of_find_last_cache_level(unsigned int cpu)
*/
int of_map_id(const struct device_node *np, u32 id,
const char *map_name, const char *map_mask_name,
- struct device_node **target, u32 *id_out)
+ struct of_map_id_arg *arg)
{
u32 map_mask, masked_id;
int map_len;
const __be32 *map = NULL;
- if (!np || !map_name || (!target && !id_out))
+ if (!np || !map_name || !arg || (!arg->map_args.np && !arg->map_args.args))
return -EINVAL;
map = of_get_property(np, map_name, &map_len);
if (!map) {
- if (target)
+ if (arg->map_args.np)
return -ENODEV;
/* Otherwise, no map implies no translation */
- *id_out = id;
+ *arg->map_args.args = id;
return 0;
}
@@ -2122,18 +2125,16 @@ int of_map_id(const struct device_node *np, u32 id,
if (!phandle_node)
return -ENODEV;
- if (target) {
- if (*target)
- of_node_put(phandle_node);
- else
- *target = phandle_node;
+ if (arg->map_args.np)
+ of_node_put(phandle_node);
+ else
+ arg->map_args.np = phandle_node;
- if (*target != phandle_node)
- continue;
- }
+ if (arg->map_args.np != phandle_node)
+ continue;
- if (id_out)
- *id_out = masked_id - id_base + out_base;
+ if (arg->map_args.args)
+ *arg->map_args.args = masked_id - id_base + out_base;
pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
np, map_name, map_mask, id_base, out_base,
@@ -2142,11 +2143,11 @@ int of_map_id(const struct device_node *np, u32 id,
}
pr_info("%pOF: no %s translation for id 0x%x on %pOF\n", np, map_name,
- id, target && *target ? *target : NULL);
+ id, arg->map_args.np ? arg->map_args.np : NULL);
/* Bypasses translation */
- if (id_out)
- *id_out = id;
+ if (arg->map_args.args)
+ *arg->map_args.args = id;
return 0;
}
EXPORT_SYMBOL_GPL(of_map_id);
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index c8da2e88e9c6..8dcdde2efb8a 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1101,12 +1101,16 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
{
struct device *dev = imx_pcie->pci->dev;
struct device_node *target;
+ struct of_map_id_arg arg = {};
u32 sid_i, sid_m;
int err_i, err_m;
u32 sid = 0;
target = NULL;
- err_i = of_map_iommu_id(dev->of_node, rid, &target, &sid_i);
+
+ arg.map_args.np = target;
+ arg.map_args.args[0] = sid_i;
+ err_i = of_map_iommu_id(dev->of_node, rid, &arg);
if (target) {
of_node_put(target);
} else {
diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
index ce21728d6e51..dea4a38cb4bb 100644
--- a/drivers/pci/controller/pcie-apple.c
+++ b/drivers/pci/controller/pcie-apple.c
@@ -782,6 +782,7 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
{
u32 sid, rid = pci_dev_id(pdev);
struct apple_pcie_port *port;
+ struct of_map_id_arg arg = {};
int idx, err;
port = apple_pcie_get_port(pdev);
@@ -791,7 +792,9 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
dev_dbg(&pdev->dev, "added to bus %s, index %d\n",
pci_name(pdev->bus->self), port->idx);
- err = of_map_iommu_id(port->pcie->dev->of_node, rid, NULL, &sid);
+ arg.map_args.np = NULL;
+ arg.map_args.args[0] = sid;
+ err = of_map_iommu_id(port->pcie->dev->of_node, rid, &arg);
if (err)
return err;
diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c
index b661f9c1f4fe..d455104de159 100644
--- a/drivers/xen/grant-dma-ops.c
+++ b/drivers/xen/grant-dma-ops.c
@@ -319,9 +319,11 @@ static int xen_dt_grant_init_backend_domid(struct device *dev,
if (dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(dev);
+ struct of_map_id_arg arg = {};
u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
- if (of_map_iommu_id(np, rid, &iommu_spec.np, iommu_spec.args)) {
+ arg.map_args = iommu_spec;
+ if (of_map_iommu_id(np, rid, &arg)) {
dev_dbg(dev, "Cannot translate ID\n");
return -ESRCH;
}
diff --git a/include/linux/of.h b/include/linux/of.h
index 8cd486d89da2..0b0d545b80a3 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -74,6 +74,10 @@ struct of_phandle_args {
uint32_t args[MAX_PHANDLE_ARGS];
};
+struct of_map_id_arg {
+ struct of_phandle_args map_args;
+};
+
struct of_phandle_iterator {
/* Common iterator information */
const char *cells_name;
@@ -458,7 +462,7 @@ bool of_console_check(const struct device_node *dn, char *name, int index);
int of_map_id(const struct device_node *np, u32 id,
const char *map_name, const char *map_mask_name,
- struct device_node **target, u32 *id_out);
+ struct of_map_id_arg *arg);
phys_addr_t of_dma_get_max_cpu_address(struct device_node *np);
@@ -907,7 +911,7 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag
static inline int of_map_id(const struct device_node *np, u32 id,
const char *map_name, const char *map_mask_name,
- struct device_node **target, u32 *id_out)
+ struct of_map_id_arg *arg)
{
return -EINVAL;
}
@@ -1436,17 +1440,23 @@ static inline int of_property_read_s32(const struct device_node *np,
}
static inline int of_map_iommu_id(const struct device_node *np, u32 id,
- struct device_node **target, u32 *id_out)
+ struct of_map_id_arg *arg)
{
- return of_map_id(np, id, "iommu-map", "iommu-map-mask",
- target, id_out);
+ return of_map_id(np, id, "iommu-map", "iommu-map-mask", arg);
}
static inline int of_map_msi_id(const struct device_node *np, u32 id,
struct device_node **target, u32 *id_out)
{
- return of_map_id(np, id, "msi-map", "msi-map-mask",
- target, id_out);
+ struct of_map_id_arg arg = {
+ .map_args = {
+ .np = *target,
+ .args_count = 1,
+ .args = { *id_out },
+ },
+ };
+
+ return of_map_id(np, id, "msi-map", "msi-map-mask", &arg);
}
#define of_for_each_phandle(it, err, np, ln, cn, cc) \
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v3 3/3] of: Respect #{iommu,msi}-cells in maps
2025-12-21 21:35 [PATCH v3 0/3] of: parsing of multi #{iommu,msi}-cells in maps Vijayanand Jitta
2025-12-21 21:36 ` [PATCH v3 1/3] of: Add convenience wrappers for of_map_id() Vijayanand Jitta
2025-12-21 21:36 ` [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct Vijayanand Jitta
@ 2025-12-21 21:36 ` Vijayanand Jitta
2 siblings, 0 replies; 7+ messages in thread
From: Vijayanand Jitta @ 2025-12-21 21:36 UTC (permalink / raw)
To: robin.murphy, will, joro, robh, dmitry.baryshkov, konrad.dybcio,
bjorn.andersson, bod, conor+dt, krzk+dt, saravanak, prakash.gupta,
vikash.garodia
Cc: iommu, linux-kernel, devicetree, Vijayanand Jitta
From: Robin Murphy <robin.murphy@arm.com>
So far our parsing of {iommu,msi}-map properites has always blindly
asusmed that the output specifiers will always have exactly 1 cell.
This typically does happen to be the case, but is not actually enforced
(and the PCI msi-map binding even explicitly states support for 0 or 1
cells) - as a result we've now ended up with dodgy DTs out in the field
which depend on this behaviour to map a 1-cell specifier for a 2-cell
provider, despite that being bogus per the bindings themselves.
Since there is some potential use in being able to map at least single
input IDs to multi-cell output specifiers (and properly support 0-cell
outputs as well), add support for properly parsing and using the target
nodes' #cells values, albeit with the unfortunate complication of still
having to work around expectations of the old behaviour too.
Since there are multi-cell output specifiers, the callers of of_map_id()
may need to get the exact cell output value for further processing.
Added support for that part --charan
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
---
drivers/iommu/of_iommu.c | 2 +-
drivers/of/base.c | 116 +++++++++++++++++++++++++++++++--------
include/linux/of.h | 16 +++---
3 files changed, 102 insertions(+), 32 deletions(-)
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 74779b77ba13..ece830ec4c19 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -45,7 +45,7 @@ static int of_iommu_configure_dev_id(struct device_node *master_np,
struct device *dev,
const u32 *id)
{
- struct of_phandle_args iommu_spec = { .args_count = 1 };
+ struct of_phandle_args iommu_spec = {};
struct of_map_id_arg arg = {
.map_args = iommu_spec,
};
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 4dca3d37a34b..aedff1c03995 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2045,11 +2045,38 @@ int of_find_last_cache_level(unsigned int cpu)
return cache_level;
}
+/*
+ * Some DTs have an iommu-map targeting a 2-cell IOMMU node while
+ * specifying only 1 cell. Fortunately they all consist of value '1'
+ * as the 2nd cell entry with the same target, so check for that pattern.
+ *
+ * Example:
+ * IOMMU node:
+ * #iommu-cells = <2>;
+ *
+ * Device node:
+ * iommu-map = <0x0000 &smmu 0x0000 0x1>,
+ * <0x0100 &smmu 0x0100 0x1>;
+ */
+static bool of_check_bad_map(const __be32 *map, int len)
+{
+ __be32 phandle = map[1];
+
+ if (len % 4)
+ return false;
+ for (int i = 0; i < len; i += 4) {
+ if (map[i + 1] != phandle || map[i + 3] != cpu_to_be32(1))
+ return false;
+ }
+ return true;
+}
+
/**
* of_map_id - Translate an ID through a downstream mapping.
* @np: root complex device node.
* @id: device ID to map.
* @map_name: property name of the map to use.
+ * @cells_name: property name of target specifier cells.
* @map_mask_name: optional property name of the mask to use.
* @arg: contains the optional params, wrapped in a struct of_phandle_args,
* which includes:
@@ -2067,18 +2094,19 @@ int of_find_last_cache_level(unsigned int cpu)
*
* Return: 0 on success or a standard error code on failure.
*/
-int of_map_id(const struct device_node *np, u32 id,
- const char *map_name, const char *map_mask_name,
- struct of_map_id_arg *arg)
+int of_map_id(const struct device_node *np, u32 id, const char *map_name,
+ const char *cells_name, const char *map_mask_name,
+ struct of_map_id_arg *arg)
{
u32 map_mask, masked_id;
- int map_len;
+ int map_bytes, map_len, offset = 0;
+ bool bad_map = false;
const __be32 *map = NULL;
if (!np || !map_name || !arg || (!arg->map_args.np && !arg->map_args.args))
return -EINVAL;
- map = of_get_property(np, map_name, &map_len);
+ map = of_get_property(np, map_name, &map_bytes);
if (!map) {
if (arg->map_args.np)
return -ENODEV;
@@ -2087,11 +2115,9 @@ int of_map_id(const struct device_node *np, u32 id,
return 0;
}
- if (!map_len || map_len % (4 * sizeof(*map))) {
- pr_err("%pOF: Error: Bad %s length: %d\n", np,
- map_name, map_len);
- return -EINVAL;
- }
+ if (map_bytes % sizeof(*map))
+ goto err_map_len;
+ map_len = map_bytes / sizeof(*map);
/* The default is to select all bits. */
map_mask = 0xffffffff;
@@ -2104,27 +2130,64 @@ int of_map_id(const struct device_node *np, u32 id,
of_property_read_u32(np, map_mask_name, &map_mask);
masked_id = map_mask & id;
- for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
+ while (offset < map_len) {
struct device_node *phandle_node;
- u32 id_base = be32_to_cpup(map + 0);
- u32 phandle = be32_to_cpup(map + 1);
- u32 out_base = be32_to_cpup(map + 2);
- u32 id_len = be32_to_cpup(map + 3);
+ u32 id_base, phandle, id_len, id_off, cells = 0;
+ const __be32 *out_base;
+
+ if (map_len - offset < 2)
+ goto err_map_len;
+
+ id_base = be32_to_cpup(map + offset);
if (id_base & ~map_mask) {
- pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)\n",
- np, map_name, map_name,
+ pr_err("%pOF: Invalid %s translation - %s (0x%x) ignores id-base (0x%x)\n",
+ np, map_name, map_mask_name,
map_mask, id_base);
return -EFAULT;
}
- if (masked_id < id_base || masked_id >= id_base + id_len)
- continue;
+ phandle = be32_to_cpup(map + offset + 1);
phandle_node = of_find_node_by_phandle(phandle);
if (!phandle_node)
return -ENODEV;
+ if (!bad_map && of_property_read_u32(phandle_node, cells_name, &cells)) {
+ pr_err("%pOF: missing %s property\n", phandle_node, cells_name);
+ return -EINVAL;
+ }
+
+ if (map_len - offset < 3 + cells)
+ goto err_map_len;
+
+ if (offset == 0 && cells == 2) {
+ bad_map = of_check_bad_map(map, map_len);
+ if (bad_map) {
+ pr_warn_once("%pOF: %s mismatches target %s, assuming extra cell of 0\n",
+ np, map_name, cells_name);
+ cells = 1;
+ }
+ }
+
+ out_base = map + offset + 2;
+ offset += 3 + cells;
+
+ id_len = be32_to_cpup(map + offset - 1);
+ if (id_len > 1 && cells > 1) {
+ /*
+ * With 1 output cell we reasonably assume its value
+ * has a linear relationship to the input; with more,
+ * we'd need help from the provider to know what to do.
+ */
+ pr_err("%pOF: Unsupported %s - cannot handle %d-ID range with %d-cell output specifier\n",
+ np, map_name, id_len, cells);
+ return -EINVAL;
+ }
+ id_off = masked_id - id_base;
+ if (masked_id < id_base || id_off >= id_len)
+ continue;
+
if (arg->map_args.np)
of_node_put(phandle_node);
else
@@ -2133,12 +2196,15 @@ int of_map_id(const struct device_node *np, u32 id,
if (arg->map_args.np != phandle_node)
continue;
- if (arg->map_args.args)
- *arg->map_args.args = masked_id - id_base + out_base;
+ for (int i = 0; arg->map_args.args && i < cells; i++)
+ arg->map_args.args[i] += (id_off + be32_to_cpu(out_base[i]));
+
+ if (arg->map_args.args_count)
+ arg->map_args.args_count = cells;
pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
- np, map_name, map_mask, id_base, out_base,
- id_len, id, masked_id - id_base + out_base);
+ np, map_name, map_mask, id_base, be32_to_cpup(out_base),
+ id_len, id, id_off + be32_to_cpup(out_base));
return 0;
}
@@ -2149,5 +2215,9 @@ int of_map_id(const struct device_node *np, u32 id,
if (arg->map_args.args)
*arg->map_args.args = id;
return 0;
+
+err_map_len:
+ pr_err("%pOF: Error: Bad %s length: %d\n", np, map_name, map_bytes);
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(of_map_id);
diff --git a/include/linux/of.h b/include/linux/of.h
index 0b0d545b80a3..ee07e8642133 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -460,9 +460,9 @@ const char *of_prop_next_string(const struct property *prop, const char *cur);
bool of_console_check(const struct device_node *dn, char *name, int index);
-int of_map_id(const struct device_node *np, u32 id,
- const char *map_name, const char *map_mask_name,
- struct of_map_id_arg *arg);
+int of_map_id(const struct device_node *np, u32 id, const char *map_name,
+ const char *cells_name, const char *map_mask_name,
+ struct of_map_id_arg *arg);
phys_addr_t of_dma_get_max_cpu_address(struct device_node *np);
@@ -909,9 +909,9 @@ static inline void of_property_clear_flag(struct property *p, unsigned long flag
{
}
-static inline int of_map_id(const struct device_node *np, u32 id,
- const char *map_name, const char *map_mask_name,
- struct of_map_id_arg *arg)
+static inline int of_map_id(const struct device_node *np, u32 id, const char *map_name,
+ const char *cells_name, const char *map_mask_name,
+ struct of_map_id_arg *arg);
{
return -EINVAL;
}
@@ -1442,7 +1442,7 @@ static inline int of_property_read_s32(const struct device_node *np,
static inline int of_map_iommu_id(const struct device_node *np, u32 id,
struct of_map_id_arg *arg)
{
- return of_map_id(np, id, "iommu-map", "iommu-map-mask", arg);
+ return of_map_id(np, id, "iommu-map", "#iommu-cells", "iommu-map-mask", arg);
}
static inline int of_map_msi_id(const struct device_node *np, u32 id,
@@ -1456,7 +1456,7 @@ static inline int of_map_msi_id(const struct device_node *np, u32 id,
},
};
- return of_map_id(np, id, "msi-map", "msi-map-mask", &arg);
+ return of_map_id(np, id, "msi-map", "#msi-cells", "msi-map-mask", &arg);
}
#define of_for_each_phandle(it, err, np, ln, cn, cc) \
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct
2025-12-21 21:36 ` [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct Vijayanand Jitta
@ 2025-12-24 3:37 ` kernel test robot
2025-12-24 3:37 ` kernel test robot
1 sibling, 0 replies; 7+ messages in thread
From: kernel test robot @ 2025-12-24 3:37 UTC (permalink / raw)
To: Vijayanand Jitta, robin.murphy, will, joro, robh,
dmitry.baryshkov, konrad.dybcio, bjorn.andersson, bod, conor+dt,
krzk+dt, saravanak, prakash.gupta, vikash.garodia
Cc: llvm, oe-kbuild-all, iommu, linux-kernel, devicetree,
Charan Teja Kalla, Vijayanand Jitta
Hi Vijayanand,
kernel test robot noticed the following build warnings:
[auto build test WARNING on xen-tip/linux-next]
[cannot apply to robh/for-next pci/next pci/for-linus linus/master v6.19-rc2 next-20251219]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Vijayanand-Jitta/of-Add-convenience-wrappers-for-of_map_id/20251222-053941
base: https://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git linux-next
patch link: https://lore.kernel.org/r/20251221213602.2413124-3-vijayanand.jitta%40oss.qualcomm.com
patch subject: [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct
config: arm-allnoconfig (https://download.01.org/0day-ci/archive/20251224/202512241124.Tl95CT1C-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 4ef602d446057dabf5f61fb221669ecbeda49279)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251224/202512241124.Tl95CT1C-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512241124.Tl95CT1C-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/of/base.c:2078:71: warning: address of array 'arg->map_args.args' will always evaluate to 'true' [-Wpointer-bool-conversion]
2078 | if (!np || !map_name || !arg || (!arg->map_args.np && !arg->map_args.args))
| ~~~~~~~~~~~~~~~^~~~
drivers/of/base.c:2136:21: warning: address of array 'arg->map_args.args' will always evaluate to 'true' [-Wpointer-bool-conversion]
2136 | if (arg->map_args.args)
| ~~ ~~~~~~~~~~~~~~^~~~
drivers/of/base.c:2149:20: warning: address of array 'arg->map_args.args' will always evaluate to 'true' [-Wpointer-bool-conversion]
2149 | if (arg->map_args.args)
| ~~ ~~~~~~~~~~~~~~^~~~
3 warnings generated.
vim +2078 drivers/of/base.c
2047
2048 /**
2049 * of_map_id - Translate an ID through a downstream mapping.
2050 * @np: root complex device node.
2051 * @id: device ID to map.
2052 * @map_name: property name of the map to use.
2053 * @map_mask_name: optional property name of the mask to use.
2054 * @arg: contains the optional params, wrapped in a struct of_phandle_args,
2055 * which includes:
2056 * np: pointer to the target device node
2057 * args_count: number of arguments
2058 * args[]: array to receive the translated ID(s).
2059 *
2060 * Given a device ID, look up the appropriate implementation-defined
2061 * platform ID and/or the target device which receives transactions on that
2062 * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
2063 * @id_out may be NULL if only the other is required. If @target points to
2064 * a non-NULL device node pointer, only entries targeting that node will be
2065 * matched; if it points to a NULL value, it will receive the device node of
2066 * the first matching target phandle, with a reference held.
2067 *
2068 * Return: 0 on success or a standard error code on failure.
2069 */
2070 int of_map_id(const struct device_node *np, u32 id,
2071 const char *map_name, const char *map_mask_name,
2072 struct of_map_id_arg *arg)
2073 {
2074 u32 map_mask, masked_id;
2075 int map_len;
2076 const __be32 *map = NULL;
2077
> 2078 if (!np || !map_name || !arg || (!arg->map_args.np && !arg->map_args.args))
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct
2025-12-21 21:36 ` [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct Vijayanand Jitta
2025-12-24 3:37 ` kernel test robot
@ 2025-12-24 3:37 ` kernel test robot
1 sibling, 0 replies; 7+ messages in thread
From: kernel test robot @ 2025-12-24 3:37 UTC (permalink / raw)
To: Vijayanand Jitta, robin.murphy, will, joro, robh,
dmitry.baryshkov, konrad.dybcio, bjorn.andersson, bod, conor+dt,
krzk+dt, saravanak, prakash.gupta, vikash.garodia
Cc: oe-kbuild-all, iommu, linux-kernel, devicetree, Charan Teja Kalla,
Vijayanand Jitta
Hi Vijayanand,
kernel test robot noticed the following build warnings:
[auto build test WARNING on xen-tip/linux-next]
[cannot apply to robh/for-next pci/next pci/for-linus linus/master v6.19-rc2 next-20251219]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Vijayanand-Jitta/of-Add-convenience-wrappers-for-of_map_id/20251222-053941
base: https://git.kernel.org/pub/scm/linux/kernel/git/xen/tip.git linux-next
patch link: https://lore.kernel.org/r/20251221213602.2413124-3-vijayanand.jitta%40oss.qualcomm.com
patch subject: [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct
config: arc-allnoconfig (https://download.01.org/0day-ci/archive/20251224/202512241116.41ldSEgi-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251224/202512241116.41ldSEgi-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512241116.41ldSEgi-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/of/base.c: In function 'of_map_id':
>> drivers/of/base.c:2078:63: warning: the comparison will always evaluate as 'true' for the address of 'args' will never be NULL [-Waddress]
2078 | if (!np || !map_name || !arg || (!arg->map_args.np && !arg->map_args.args))
| ^
In file included from drivers/of/base.c:24:
include/linux/of.h:74:18: note: 'args' declared here
74 | uint32_t args[MAX_PHANDLE_ARGS];
| ^~~~
drivers/of/base.c:2136:21: warning: the comparison will always evaluate as 'true' for the address of 'args' will never be NULL [-Waddress]
2136 | if (arg->map_args.args)
| ^~~
include/linux/of.h:74:18: note: 'args' declared here
74 | uint32_t args[MAX_PHANDLE_ARGS];
| ^~~~
drivers/of/base.c:2149:13: warning: the comparison will always evaluate as 'true' for the address of 'args' will never be NULL [-Waddress]
2149 | if (arg->map_args.args)
| ^~~
include/linux/of.h:74:18: note: 'args' declared here
74 | uint32_t args[MAX_PHANDLE_ARGS];
| ^~~~
vim +2078 drivers/of/base.c
2047
2048 /**
2049 * of_map_id - Translate an ID through a downstream mapping.
2050 * @np: root complex device node.
2051 * @id: device ID to map.
2052 * @map_name: property name of the map to use.
2053 * @map_mask_name: optional property name of the mask to use.
2054 * @arg: contains the optional params, wrapped in a struct of_phandle_args,
2055 * which includes:
2056 * np: pointer to the target device node
2057 * args_count: number of arguments
2058 * args[]: array to receive the translated ID(s).
2059 *
2060 * Given a device ID, look up the appropriate implementation-defined
2061 * platform ID and/or the target device which receives transactions on that
2062 * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
2063 * @id_out may be NULL if only the other is required. If @target points to
2064 * a non-NULL device node pointer, only entries targeting that node will be
2065 * matched; if it points to a NULL value, it will receive the device node of
2066 * the first matching target phandle, with a reference held.
2067 *
2068 * Return: 0 on success or a standard error code on failure.
2069 */
2070 int of_map_id(const struct device_node *np, u32 id,
2071 const char *map_name, const char *map_mask_name,
2072 struct of_map_id_arg *arg)
2073 {
2074 u32 map_mask, masked_id;
2075 int map_len;
2076 const __be32 *map = NULL;
2077
> 2078 if (!np || !map_name || !arg || (!arg->map_args.np && !arg->map_args.args))
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/3] of: Add convenience wrappers for of_map_id()
2025-12-21 21:36 ` [PATCH v3 1/3] of: Add convenience wrappers for of_map_id() Vijayanand Jitta
@ 2025-12-30 15:29 ` Frank Li
0 siblings, 0 replies; 7+ messages in thread
From: Frank Li @ 2025-12-30 15:29 UTC (permalink / raw)
To: Vijayanand Jitta
Cc: robin.murphy, will, joro, robh, dmitry.baryshkov, konrad.dybcio,
bjorn.andersson, bod, conor+dt, krzk+dt, saravanak, prakash.gupta,
vikash.garodia, iommu, linux-kernel, devicetree
On Mon, Dec 22, 2025 at 03:06:00AM +0530, Vijayanand Jitta wrote:
> From: Robin Murphy <robin.murphy@arm.com>
>
> Since we now have quite a few users parsing "iommu-map" and "msi-map"
> properties, give them some wrappers to conveniently encapsulate the
> appropriate sets of property names. This will also make it easier to
> then change of_map_id() to correctly account for specifier cells.
>
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> Signed-off-by: Vijayanand Jitta <vijayanand.jitta@oss.qualcomm.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/cdx/cdx_msi.c | 3 +--
> drivers/iommu/of_iommu.c | 4 +---
> drivers/irqchip/irq-gic-its-msi-parent.c | 4 ++--
> drivers/of/irq.c | 3 +--
> drivers/pci/controller/dwc/pci-imx6.c | 6 ++----
> drivers/pci/controller/pcie-apple.c | 3 +--
> drivers/xen/grant-dma-ops.c | 3 +--
> include/linux/of.h | 14 ++++++++++++++
> 8 files changed, 23 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/cdx/cdx_msi.c b/drivers/cdx/cdx_msi.c
> index 91b95422b263..63b3544ec997 100644
> --- a/drivers/cdx/cdx_msi.c
> +++ b/drivers/cdx/cdx_msi.c
> @@ -128,8 +128,7 @@ static int cdx_msi_prepare(struct irq_domain *msi_domain,
> int ret;
>
> /* Retrieve device ID from requestor ID using parent device */
> - ret = of_map_id(parent->of_node, cdx_dev->msi_dev_id, "msi-map", "msi-map-mask",
> - NULL, &dev_id);
> + ret = of_map_msi_id(parent->of_node, cdx_dev->msi_dev_id, NULL, &dev_id);
> if (ret) {
> dev_err(dev, "of_map_id failed for MSI: %d\n", ret);
> return ret;
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index 6b989a62def2..a511ecf21fcd 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -48,9 +48,7 @@ static int of_iommu_configure_dev_id(struct device_node *master_np,
> struct of_phandle_args iommu_spec = { .args_count = 1 };
> int err;
>
> - err = of_map_id(master_np, *id, "iommu-map",
> - "iommu-map-mask", &iommu_spec.np,
> - iommu_spec.args);
> + err = of_map_iommu_id(master_np, *id, &iommu_spec.np, iommu_spec.args);
> if (err)
> return err;
>
> diff --git a/drivers/irqchip/irq-gic-its-msi-parent.c b/drivers/irqchip/irq-gic-its-msi-parent.c
> index eb1473f1448a..0884c4cbd245 100644
> --- a/drivers/irqchip/irq-gic-its-msi-parent.c
> +++ b/drivers/irqchip/irq-gic-its-msi-parent.c
> @@ -166,7 +166,7 @@ static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev,
> if (ret) {
> struct device_node *np = NULL;
>
> - ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id);
> + ret = of_map_msi_id(dev->of_node, dev->id, &np, dev_id);
> if (np)
> of_node_put(np);
> }
> @@ -211,7 +211,7 @@ static int of_v5_pmsi_get_msi_info(struct irq_domain *domain, struct device *dev
> if (ret) {
> struct device_node *np = NULL;
>
> - ret = of_map_id(dev->of_node, dev->id, "msi-map", "msi-map-mask", &np, dev_id);
> + ret = of_map_msi_id(dev->of_node, dev->id, &np, dev_id);
> if (np) {
> ret = its_translate_frame_address(np, pa);
> of_node_put(np);
> diff --git a/drivers/of/irq.c b/drivers/of/irq.c
> index 1cd93549d093..9549dda8f9d6 100644
> --- a/drivers/of/irq.c
> +++ b/drivers/of/irq.c
> @@ -725,8 +725,7 @@ u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in)
> * "msi-map" or an "msi-parent" property.
> */
> for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) {
> - if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
> - "msi-map-mask", msi_np, &id_out))
> + if (!of_map_msi_id(parent_dev->of_node, id_in, msi_np, &id_out))
> break;
> if (!of_check_msi_parent(parent_dev->of_node, msi_np))
> break;
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 4668fc9648bf..c8da2e88e9c6 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -1106,8 +1106,7 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
> u32 sid = 0;
>
> target = NULL;
> - err_i = of_map_id(dev->of_node, rid, "iommu-map", "iommu-map-mask",
> - &target, &sid_i);
> + err_i = of_map_iommu_id(dev->of_node, rid, &target, &sid_i);
> if (target) {
> of_node_put(target);
> } else {
> @@ -1120,8 +1119,7 @@ static int imx_pcie_add_lut_by_rid(struct imx_pcie *imx_pcie, u32 rid)
> }
>
> target = NULL;
> - err_m = of_map_id(dev->of_node, rid, "msi-map", "msi-map-mask",
> - &target, &sid_m);
> + err_m = of_map_msi_id(dev->of_node, rid, &target, &sid_m);
>
> /*
> * err_m target
> diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c
> index 0380d300adca..ce21728d6e51 100644
> --- a/drivers/pci/controller/pcie-apple.c
> +++ b/drivers/pci/controller/pcie-apple.c
> @@ -791,8 +791,7 @@ static int apple_pcie_enable_device(struct pci_host_bridge *bridge, struct pci_d
> dev_dbg(&pdev->dev, "added to bus %s, index %d\n",
> pci_name(pdev->bus->self), port->idx);
>
> - err = of_map_id(port->pcie->dev->of_node, rid, "iommu-map",
> - "iommu-map-mask", NULL, &sid);
> + err = of_map_iommu_id(port->pcie->dev->of_node, rid, NULL, &sid);
> if (err)
> return err;
>
> diff --git a/drivers/xen/grant-dma-ops.c b/drivers/xen/grant-dma-ops.c
> index 29257d2639db..b661f9c1f4fe 100644
> --- a/drivers/xen/grant-dma-ops.c
> +++ b/drivers/xen/grant-dma-ops.c
> @@ -321,8 +321,7 @@ static int xen_dt_grant_init_backend_domid(struct device *dev,
> struct pci_dev *pdev = to_pci_dev(dev);
> u32 rid = PCI_DEVID(pdev->bus->number, pdev->devfn);
>
> - if (of_map_id(np, rid, "iommu-map", "iommu-map-mask", &iommu_spec.np,
> - iommu_spec.args)) {
> + if (of_map_iommu_id(np, rid, &iommu_spec.np, iommu_spec.args)) {
> dev_dbg(dev, "Cannot translate ID\n");
> return -ESRCH;
> }
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 121a288ca92d..8cd486d89da2 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -1435,6 +1435,20 @@ static inline int of_property_read_s32(const struct device_node *np,
> return of_property_read_u32(np, propname, (u32*) out_value);
> }
>
> +static inline int of_map_iommu_id(const struct device_node *np, u32 id,
> + struct device_node **target, u32 *id_out)
> +{
> + return of_map_id(np, id, "iommu-map", "iommu-map-mask",
> + target, id_out);
> +}
> +
> +static inline int of_map_msi_id(const struct device_node *np, u32 id,
> + struct device_node **target, u32 *id_out)
> +{
> + return of_map_id(np, id, "msi-map", "msi-map-mask",
> + target, id_out);
> +}
> +
> #define of_for_each_phandle(it, err, np, ln, cn, cc) \
> for (of_phandle_iterator_init((it), (np), (ln), (cn), (cc)), \
> err = of_phandle_iterator_next(it); \
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-12-30 15:29 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-21 21:35 [PATCH v3 0/3] of: parsing of multi #{iommu,msi}-cells in maps Vijayanand Jitta
2025-12-21 21:36 ` [PATCH v3 1/3] of: Add convenience wrappers for of_map_id() Vijayanand Jitta
2025-12-30 15:29 ` Frank Li
2025-12-21 21:36 ` [PATCH v3 2/3] of: factor arguments passed to of_map_id() into a struct Vijayanand Jitta
2025-12-24 3:37 ` kernel test robot
2025-12-24 3:37 ` kernel test robot
2025-12-21 21:36 ` [PATCH v3 3/3] of: Respect #{iommu,msi}-cells in maps Vijayanand Jitta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox