Index: head/sys/dev/iommu/iommu_gas.c =================================================================== --- head/sys/dev/iommu/iommu_gas.c +++ head/sys/dev/iommu/iommu_gas.c @@ -727,6 +727,31 @@ return (error); } +void +iommu_unmap_msi(struct iommu_ctx *ctx) +{ + struct iommu_map_entry *entry; + struct iommu_domain *domain; + + domain = ctx->domain; + entry = domain->msi_entry; + if (entry == NULL) + return; + + domain->ops->unmap(domain, entry->start, entry->end - + entry->start, IOMMU_PGF_WAITOK); + + IOMMU_DOMAIN_LOCK(domain); + iommu_gas_free_space(domain, entry); + IOMMU_DOMAIN_UNLOCK(domain); + + iommu_gas_free_entry(domain, entry); + + domain->msi_entry = NULL; + domain->msi_base = 0; + domain->msi_phys = 0; +} + int iommu_map_msi(struct iommu_ctx *ctx, iommu_gaddr_t size, int offset, u_int eflags, u_int flags, vm_page_t *ma) Index: head/sys/dev/iommu/iommu_msi.h =================================================================== --- head/sys/dev/iommu/iommu_msi.h +++ head/sys/dev/iommu/iommu_msi.h @@ -42,5 +42,6 @@ void iommu_translate_msi(struct iommu_domain *domain, uint64_t *addr); int iommu_map_msi(struct iommu_ctx *ctx, iommu_gaddr_t size, int offset, u_int eflags, u_int flags, vm_page_t *ma); +void iommu_unmap_msi(struct iommu_ctx *ctx); #endif /* !_DEV_IOMMU_IOMMU_MSI_H_ */ Index: head/sys/kern/msi_if.m =================================================================== --- head/sys/kern/msi_if.m +++ head/sys/kern/msi_if.m @@ -38,6 +38,22 @@ struct intr_irqsrc; }; +# +# Default implementations of some methods. +# +CODE { + static int + iommu_init(device_t dev, device_t child, struct iommu_domain **domain) + { + *domain = NULL; + return (0); + } + static void + iommu_deinit(device_t dev, device_t child) + { + } +}; + METHOD int alloc_msi { device_t dev; device_t child; @@ -79,4 +95,9 @@ device_t dev; device_t child; struct iommu_domain **domain; -}; +} DEFAULT iommu_init; + +METHOD void iommu_deinit { + device_t dev; + device_t child; +} DEFAULT iommu_deinit; Index: head/sys/kern/subr_intr.c =================================================================== --- head/sys/kern/subr_intr.c +++ head/sys/kern/subr_intr.c @@ -1297,9 +1297,7 @@ 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; @@ -1314,7 +1312,6 @@ ("%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. @@ -1322,7 +1319,6 @@ 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); @@ -1332,9 +1328,7 @@ } 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]; @@ -1375,6 +1369,8 @@ isrc[i] = msi->isrc; } + MSI_IOMMU_DEINIT(pic->pic_dev, child); + err = MSI_RELEASE_MSI(pic->pic_dev, child, count, isrc); for (i = 0; i < count; i++) { @@ -1389,9 +1385,7 @@ 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; @@ -1406,7 +1400,6 @@ ("%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. @@ -1414,15 +1407,12 @@ 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; @@ -1456,6 +1446,8 @@ intr_unmap_irq(irq); return (EINVAL); } + + MSI_IOMMU_DEINIT(pic->pic_dev, child); err = MSI_RELEASE_MSIX(pic->pic_dev, child, isrc); intr_unmap_irq(irq);