From 987068fcbdb7a085bb11151b91dc6f4c956c4a1b Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Mon, 12 Sep 2016 17:13:40 +0100 Subject: of/irq: Break out msi-map lookup (again) The PCI msi-map code is already doing double-duty translating IDs and retrieving MSI parents, which unsurprisingly is the same functionality we need for the identically-formatted PCI iommu-map property. Drag the core parsing routine up yet another layer into the general OF-PCI code, and further generalise it for either kind of lookup in either flavour of map property. Acked-by: Rob Herring Acked-by: Marc Zyngier Tested-by: Lorenzo Pieralisi Signed-off-by: Robin Murphy Signed-off-by: Will Deacon --- drivers/of/irq.c | 78 +++----------------------------------------------------- 1 file changed, 4 insertions(+), 74 deletions(-) (limited to 'drivers/of/irq.c') diff --git a/drivers/of/irq.c b/drivers/of/irq.c index a2e68f740eda..393fea85eb4e 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -592,87 +593,16 @@ static u32 __of_msi_map_rid(struct device *dev, struct device_node **np, u32 rid_in) { struct device *parent_dev; - struct device_node *msi_controller_node; - struct device_node *msi_np = *np; - u32 map_mask, masked_rid, rid_base, msi_base, rid_len, phandle; - int msi_map_len; - bool matched; u32 rid_out = rid_in; - const __be32 *msi_map = NULL; /* * Walk up the device parent links looking for one with a * "msi-map" property. */ - for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) { - if (!parent_dev->of_node) - continue; - - msi_map = of_get_property(parent_dev->of_node, - "msi-map", &msi_map_len); - if (!msi_map) - continue; - - if (msi_map_len % (4 * sizeof(__be32))) { - dev_err(parent_dev, "Error: Bad msi-map length: %d\n", - msi_map_len); - return rid_out; - } - /* We have a good parent_dev and msi_map, let's use them. */ - break; - } - if (!msi_map) - return rid_out; - - /* The default is to select all bits. */ - map_mask = 0xffffffff; - - /* - * Can be overridden by "msi-map-mask" property. If - * of_property_read_u32() fails, the default is used. - */ - of_property_read_u32(parent_dev->of_node, "msi-map-mask", &map_mask); - - masked_rid = map_mask & rid_in; - matched = false; - while (!matched && msi_map_len >= 4 * sizeof(__be32)) { - rid_base = be32_to_cpup(msi_map + 0); - phandle = be32_to_cpup(msi_map + 1); - msi_base = be32_to_cpup(msi_map + 2); - rid_len = be32_to_cpup(msi_map + 3); - - if (rid_base & ~map_mask) { - dev_err(parent_dev, - "Invalid msi-map translation - msi-map-mask (0x%x) ignores rid-base (0x%x)\n", - map_mask, rid_base); - return rid_out; - } - - msi_controller_node = of_find_node_by_phandle(phandle); - - matched = (masked_rid >= rid_base && - masked_rid < rid_base + rid_len); - if (msi_np) - matched &= msi_np == msi_controller_node; - - if (matched && !msi_np) { - *np = msi_np = msi_controller_node; + for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) + if (!of_pci_map_rid(parent_dev->of_node, rid_in, "msi-map", + "msi-map-mask", np, &rid_out)) break; - } - - of_node_put(msi_controller_node); - msi_map_len -= 4 * sizeof(__be32); - msi_map += 4; - } - if (!matched) - return rid_out; - - rid_out = masked_rid - rid_base + msi_base; - dev_dbg(dev, - "msi-map at: %s, using mask %08x, rid-base: %08x, msi-base: %08x, length: %08x, rid: %08x -> %08x\n", - dev_name(parent_dev), map_mask, rid_base, msi_base, - rid_len, rid_in, rid_out); - return rid_out; } -- cgit v1.2.3