aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuslan Bukin <br@FreeBSD.org>2022-05-06 15:41:11 +0000
committerRuslan Bukin <br@FreeBSD.org>2022-05-06 15:48:04 +0000
commit0b6bacc7874f9c68ad35b06f1a7614171eb9ab10 (patch)
treedf3e0ccbd159b8fb046e7d44d4c6fa47155695df
parent4d48dd68906230f8c41caee6a5c9d7b9f272bdb1 (diff)
downloadsrc-0b6bacc7874f9c68ad35b06f1a7614171eb9ab10.tar.gz
src-0b6bacc7874f9c68ad35b06f1a7614171eb9ab10.zip
Add ofw_bus_iommu_map() that maps PCI requester ID to an IOMMU
specifier based on "iommu-map" DTS property. Sponsored by: UKRI
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c44
-rw-r--r--sys/dev/ofw/ofw_bus_subr.h3
2 files changed, 46 insertions, 1 deletions
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c
index ea57d1086779..408d554b3c7f 100644
--- a/sys/dev/ofw/ofw_bus_subr.c
+++ b/sys/dev/ofw/ofw_bus_subr.c
@@ -491,6 +491,50 @@ ofw_bus_msimap(phandle_t node, uint16_t pci_rid, phandle_t *msi_parent,
return (err);
}
+int
+ofw_bus_iommu_map(phandle_t node, uint16_t pci_rid, phandle_t *iommu_parent,
+ uint32_t *iommu_rid)
+{
+ pcell_t mask, iommu_base, rid_base, rid_length;
+ uint32_t masked_rid;
+ pcell_t map[4];
+ ssize_t len;
+ int err, i;
+
+ len = OF_getproplen(node, "iommu-map");
+ if (len <= 0)
+ return (ENOENT);
+ if (len > sizeof(map))
+ return (ENOMEM);
+
+ len = OF_getencprop(node, "iommu-map", map, 16);
+
+ err = ENOENT;
+ mask = 0xffffffff;
+ OF_getencprop(node, "iommu-map-mask", &mask, sizeof(mask));
+
+ masked_rid = pci_rid & mask;
+ for (i = 0; i < len; i += 4) {
+ rid_base = map[i + 0];
+ rid_length = map[i + 3];
+
+ if (masked_rid < rid_base ||
+ masked_rid >= (rid_base + rid_length))
+ continue;
+
+ iommu_base = map[i + 2];
+
+ if (iommu_parent != NULL)
+ *iommu_parent = map[i + 1];
+ if (iommu_rid != NULL)
+ *iommu_rid = masked_rid - rid_base + iommu_base;
+ err = 0;
+ break;
+ }
+
+ return (err);
+}
+
static int
ofw_bus_reg_to_rl_helper(device_t dev, phandle_t node, pcell_t acells, pcell_t scells,
struct resource_list *rl, const char *reg_source)
diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h
index 45709c92c1f7..89f291f92373 100644
--- a/sys/dev/ofw/ofw_bus_subr.h
+++ b/sys/dev/ofw/ofw_bus_subr.h
@@ -92,8 +92,9 @@ int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
void *, void *, int, phandle_t *);
-/* Routines for processing msi maps */
+/* Routines for processing msi and iommu maps. */
int ofw_bus_msimap(phandle_t, uint16_t, phandle_t *, uint32_t *);
+int ofw_bus_iommu_map(phandle_t, uint16_t, phandle_t *, uint32_t *);
/* Routines for parsing device-tree data into resource lists. */
int ofw_bus_reg_to_rl(device_t, phandle_t, pcell_t, pcell_t,