summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortmm <tmm@FreeBSD.org>2004-03-23 23:20:34 +0000
committertmm <tmm@FreeBSD.org>2004-03-23 23:20:34 +0000
commit7f1a3eaf9e2d40200c0bdf4f3e241f649e159a58 (patch)
treea4e4ae83cbb0b699cb37a38997e9f47a4379ef1f
parentf95d851c99d106308aed500a55f78808d5e83ae2 (diff)
downloadFreeBSD-src-7f1a3eaf9e2d40200c0bdf4f3e241f649e159a58.zip
FreeBSD-src-7f1a3eaf9e2d40200c0bdf4f3e241f649e159a58.tar.gz
Correct the termination condition of the DVMA pruning loop in
iommu_dvma_vallocseg(), which I botched in r1.32. This bug could cause an endless loop when a map was loaded and DVMA was scarce, or that map had a stringent alignment or boundary. Report and additional testing: Marius Strobl <marius@alchemy.franken.de>
-rw-r--r--sys/sparc64/sparc64/iommu.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/sys/sparc64/sparc64/iommu.c b/sys/sparc64/sparc64/iommu.c
index f87863e..1c25061 100644
--- a/sys/sparc64/sparc64/iommu.c
+++ b/sys/sparc64/sparc64/iommu.c
@@ -190,7 +190,7 @@ struct mtx iommu_mtx;
* the IOTSBs are divorced.
* LRU queue handling for lazy resource allocation.
*/
-static TAILQ_HEAD(, bus_dmamap) iommu_maplruq =
+static TAILQ_HEAD(iommu_maplruq_head, bus_dmamap) iommu_maplruq =
TAILQ_HEAD_INITIALIZER(iommu_maplruq);
/* DVMA space rman. */
@@ -746,7 +746,7 @@ static int
iommu_dvma_vallocseg(bus_dma_tag_t dt, struct iommu_state *is, bus_dmamap_t map,
vm_offset_t voffs, bus_size_t size, bus_addr_t amask, bus_addr_t *addr)
{
- bus_dmamap_t tm;
+ bus_dmamap_t tm, last;
bus_addr_t dvmaddr, freed;
int error, complete = 0;
@@ -757,7 +757,7 @@ iommu_dvma_vallocseg(bus_dma_tag_t dt, struct iommu_state *is, bus_dmamap_t map,
while ((error = iommu_dvma_valloc(dt, is, map,
voffs + size)) == ENOMEM && !complete) {
/*
- * Free the allocated DVMA of a few tags until
+ * Free the allocated DVMA of a few maps until
* the required size is reached. This is an
* approximation to not have to call the allocation
* function too often; most likely one free run
@@ -766,16 +766,16 @@ iommu_dvma_vallocseg(bus_dma_tag_t dt, struct iommu_state *is, bus_dmamap_t map,
*/
IS_LOCK(is);
freed = 0;
+ last = TAILQ_LAST(&iommu_maplruq, iommu_maplruq_head);
do {
tm = TAILQ_FIRST(&iommu_maplruq);
- if (tm == NULL) {
- complete = 1;
+ complete = tm == last;
+ if (tm == NULL)
break;
- }
freed += iommu_dvma_vprune(is, tm);
/* Move to the end. */
iommu_map_insq(is, tm);
- } while (freed < size);
+ } while (freed < size && !complete);
IS_UNLOCK(is);
}
if (error != 0)
OpenPOWER on IntegriCloud