o Add iommu de-initialization method for MSI interface.
o Add iommu_unmap_msi() to release the msi GAS entry. o Provide default implementations for iommu init/deinit methods. Reviewed by: kib Sponsored by: Innovate DSbD Differential Revision: https://reviews.freebsd.org/D26906
This commit is contained in:
parent
73577bf01d
commit
f32f0095e9
@ -727,6 +727,31 @@ iommu_map(struct iommu_domain *domain,
|
||||
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)
|
||||
|
@ -42,5 +42,6 @@ struct iommu_ctx;
|
||||
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_ */
|
||||
|
@ -38,6 +38,22 @@ HEADER {
|
||||
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 @@ METHOD int iommu_init {
|
||||
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;
|
||||
|
@ -1297,9 +1297,7 @@ 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;
|
||||
@ -1314,7 +1312,6 @@ 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.
|
||||
@ -1322,7 +1319,6 @@ intr_alloc_msi(device_t pci, device_t child, intptr_t xref, int count,
|
||||
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 @@ 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];
|
||||
@ -1375,6 +1369,8 @@ intr_release_msi(device_t pci, device_t child, intptr_t xref, int count,
|
||||
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 @@ 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;
|
||||
@ -1406,7 +1400,6 @@ 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.
|
||||
@ -1414,15 +1407,12 @@ intr_alloc_msix(device_t pci, device_t child, intptr_t xref, int *irq)
|
||||
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;
|
||||
@ -1457,6 +1447,8 @@ intr_release_msix(device_t pci, device_t child, intptr_t xref, int irq)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
MSI_IOMMU_DEINIT(pic->pic_dev, child);
|
||||
|
||||
err = MSI_RELEASE_MSIX(pic->pic_dev, child, isrc);
|
||||
intr_unmap_irq(irq);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user