diff options
author | Ruslan Bukin <br@FreeBSD.org> | 2020-10-19 13:10:21 +0000 |
---|---|---|
committer | Ruslan Bukin <br@FreeBSD.org> | 2020-10-19 13:10:21 +0000 |
commit | e707c8be4e8d5f4d542a1344dc6d96bcc08d0b4f (patch) | |
tree | fa698d3f9d545d101b8785b048ccbf0bd2883c25 /sys/kern | |
parent | 956cc8e1b9401bb53ee3696206ad3f6ea5d3d6ab (diff) |
Notes
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/msi_if.m | 8 | ||||
-rw-r--r-- | sys/kern/subr_intr.c | 46 |
2 files changed, 54 insertions, 0 deletions
diff --git a/sys/kern/msi_if.m b/sys/kern/msi_if.m index 19b6af4501cb..0f537bad541a 100644 --- a/sys/kern/msi_if.m +++ b/sys/kern/msi_if.m @@ -32,6 +32,9 @@ INTERFACE msi; HEADER { + #include <machine/bus.h> + #include <dev/iommu/iommu_msi.h> + struct intr_irqsrc; }; @@ -72,3 +75,8 @@ METHOD int map_msi { uint32_t *data; }; +METHOD int iommu_init { + device_t dev; + device_t child; + struct iommu_domain **domain; +}; diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index 325ae78e1615..a8749217d625 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_hwpmc_hooks.h" +#include "opt_iommu.h" #include <sys/param.h> #include <sys/systm.h> @@ -50,6 +51,8 @@ __FBSDID("$FreeBSD$"); #include <sys/queue.h> #include <sys/bus.h> #include <sys/interrupt.h> +#include <sys/taskqueue.h> +#include <sys/tree.h> #include <sys/conf.h> #include <sys/cpuset.h> #include <sys/rman.h> @@ -70,6 +73,10 @@ __FBSDID("$FreeBSD$"); #include <ddb/ddb.h> #endif +#ifdef IOMMU +#include <dev/iommu/iommu_msi.h> +#endif + #include "pic_if.h" #include "msi_if.h" @@ -1290,6 +1297,9 @@ int intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count, int maxcount, int *irqs) { +#ifdef IOMMU + struct iommu_domain *domain; +#endif struct intr_irqsrc **isrc; struct intr_pic *pic; device_t pdev; @@ -1304,6 +1314,16 @@ intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count, ("%s: Found a non-MSI controller: %s", __func__, device_get_name(pic->pic_dev))); +#ifdef IOMMU + /* + * If this is the first time we have used this context ask the + * interrupt controller to map memory the msi source will need. + */ + err = MSI_IOMMU_INIT(pic->pic_dev, child, &domain); + if (err != 0) + return (err); +#endif + isrc = malloc(sizeof(*isrc) * count, M_INTRNG, M_WAITOK); err = MSI_ALLOC_MSI(pic->pic_dev, child, count, maxcount, &pdev, isrc); if (err != 0) { @@ -1312,9 +1332,13 @@ intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count, } for (i = 0; i < count; i++) { +#ifdef IOMMU + isrc[i]->isrc_iommu = domain; +#endif msi = (struct intr_map_data_msi *)intr_alloc_map_data( INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO); msi-> isrc = isrc[i]; + irqs[i] = intr_map_irq(pic->pic_dev, xref, (struct intr_map_data *)msi); } @@ -1365,6 +1389,9 @@ intr_release_msi(device_t pci, device_t child, intptr_t xref, int count, int intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq) { +#ifdef IOMMU + struct iommu_domain *domain; +#endif struct intr_irqsrc *isrc; struct intr_pic *pic; device_t pdev; @@ -1379,10 +1406,23 @@ intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq) ("%s: Found a non-MSI controller: %s", __func__, device_get_name(pic->pic_dev))); +#ifdef IOMMU + /* + * If this is the first time we have used this context ask the + * interrupt controller to map memory the msi source will need. + */ + err = MSI_IOMMU_INIT(pic->pic_dev, child, &domain); + if (err != 0) + return (err); +#endif + err = MSI_ALLOC_MSIX(pic->pic_dev, child, &pdev, &isrc); if (err != 0) return (err); +#ifdef IOMMU + isrc->isrc_iommu = domain; +#endif msi = (struct intr_map_data_msi *)intr_alloc_map_data( INTR_MAP_DATA_MSI, sizeof(*msi), M_WAITOK | M_ZERO); msi->isrc = isrc; @@ -1444,6 +1484,12 @@ intr_map_msi(device_t pci, device_t child, intptr_t xref, int irq, return (EINVAL); err = MSI_MAP_MSI(pic->pic_dev, child, isrc, addr, data); + +#ifdef IOMMU + if (isrc->isrc_iommu != NULL) + iommu_translate_msi(isrc->isrc_iommu, addr); +#endif + return (err); } |