git: 264e49515fb0 - stable/14 - iommu: add iommu_gas_remove_locked()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 02 Jan 2024 00:41:59 UTC
The branch stable/14 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=264e49515fb0028bc77af953d8f98ff9de24ae8f
commit 264e49515fb0028bc77af953d8f98ff9de24ae8f
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-12-14 02:41:31 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-01-02 00:41:39 +0000
iommu: add iommu_gas_remove_locked()
(cherry picked from commit 273b4de3462d7825ebe4ace7a1930f098311287f)
---
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