git: 273b4de3462d - main - iommu: add iommu_gas_remove_locked()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 26 Dec 2023 01:28:55 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=273b4de3462d7825ebe4ace7a1930f098311287f commit 273b4de3462d7825ebe4ace7a1930f098311287f Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2023-12-14 02:41:31 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2023-12-26 01:28:22 +0000 iommu: add iommu_gas_remove_locked() Sponsored by: The FreeBSD Foundation MFC after: 1 week --- sys/dev/iommu/iommu_gas.c | 83 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/sys/dev/iommu/iommu_gas.c b/sys/dev/iommu/iommu_gas.c index dc850747512a..9a74854f926f 100644 --- a/sys/dev/iommu/iommu_gas.c +++ b/sys/dev/iommu/iommu_gas.c @@ -708,28 +708,20 @@ iommu_gas_remove_unmap(struct iommu_domain *domain, TAILQ_INSERT_TAIL(gcp, entry, dmamap_link); } -/* - * Remove specified range from the GAS of the domain. Note that the - * removal is not guaranteed to occur upon the function return, it - * might be finalized some time after, when hardware reports that - * (queued) IOTLB invalidation was performed. - */ -void -iommu_gas_remove(struct iommu_domain *domain, iommu_gaddr_t start, - iommu_gaddr_t size) +static void +iommu_gas_remove_locked(struct iommu_domain *domain, + iommu_gaddr_t start, iommu_gaddr_t size, + struct iommu_map_entries_tailq *gc, + struct iommu_map_entry **r1, struct iommu_map_entry **r2) { - struct iommu_map_entry *entry, *nentry, *r1, *r2; - struct iommu_map_entries_tailq gc; + struct iommu_map_entry *entry, *nentry; iommu_gaddr_t end; - end = start + size; - r1 = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); - r2 = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); - TAILQ_INIT(&gc); + IOMMU_DOMAIN_ASSERT_LOCKED(domain); - IOMMU_DOMAIN_LOCK(domain); + end = start + size; - nentry = iommu_gas_remove_clip_left(domain, start, end, &r1); + nentry = iommu_gas_remove_clip_left(domain, start, end, r1); RB_FOREACH_FROM(entry, iommu_gas_entries_tree, nentry) { if (entry->start >= end) break; @@ -738,11 +730,11 @@ iommu_gas_remove(struct iommu_domain *domain, iommu_gaddr_t start, entry->start, entry->end, start)); if ((entry->flags & IOMMU_MAP_ENTRY_RMRR) != 0) continue; - iommu_gas_remove_unmap(domain, entry, &gc); + iommu_gas_remove_unmap(domain, entry, gc); } - if (iommu_gas_remove_clip_right(domain, end, entry, r2)) { - iommu_gas_remove_unmap(domain, r2, &gc); - r2 = NULL; + if (iommu_gas_remove_clip_right(domain, end, entry, *r2)) { + iommu_gas_remove_unmap(domain, *r2, gc); + *r2 = NULL; } #ifdef INVARIANTS @@ -755,13 +747,52 @@ iommu_gas_remove(struct iommu_domain *domain, iommu_gaddr_t start, entry->start, entry->end, start, end)); } #endif +} + +static void +iommu_gas_remove_init(struct iommu_domain *domain, + struct iommu_map_entries_tailq *gc, struct iommu_map_entry **r1, + struct iommu_map_entry **r2) +{ + TAILQ_INIT(gc); + *r1 = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); + *r2 = iommu_gas_alloc_entry(domain, IOMMU_PGF_WAITOK); +} +static void +iommu_gas_remove_cleanup(struct iommu_domain *domain, + struct iommu_map_entries_tailq *gc, struct iommu_map_entry **r1, + struct iommu_map_entry **r2) +{ + if (*r1 != NULL) { + iommu_gas_free_entry(*r1); + *r1 = NULL; + } + if (*r2 != NULL) { + iommu_gas_free_entry(*r2); + *r2 = NULL; + } + iommu_domain_unload(domain, gc, true); +} + +/* + * Remove specified range from the GAS of the domain. Note that the + * removal is not guaranteed to occur upon the function return, it + * might be finalized some time after, when hardware reports that + * (queued) IOTLB invalidation was performed. + */ +void +iommu_gas_remove(struct iommu_domain *domain, iommu_gaddr_t start, + iommu_gaddr_t size) +{ + struct iommu_map_entry *r1, *r2; + struct iommu_map_entries_tailq gc; + + iommu_gas_remove_init(domain, &gc, &r1, &r2); + IOMMU_DOMAIN_LOCK(domain); + iommu_gas_remove_locked(domain, start, size, &gc, &r1, &r2); IOMMU_DOMAIN_UNLOCK(domain); - if (r1 != NULL) - iommu_gas_free_entry(r1); - if (r2 != NULL) - iommu_gas_free_entry(r2); - iommu_domain_unload(domain, &gc, true); + iommu_gas_remove_cleanup(domain, &gc, &r1, &r2); } int