diff options
author | tmm <tmm@FreeBSD.org> | 2004-03-23 23:20:34 +0000 |
---|---|---|
committer | tmm <tmm@FreeBSD.org> | 2004-03-23 23:20:34 +0000 |
commit | 7f1a3eaf9e2d40200c0bdf4f3e241f649e159a58 (patch) | |
tree | a4e4ae83cbb0b699cb37a38997e9f47a4379ef1f | |
parent | f95d851c99d106308aed500a55f78808d5e83ae2 (diff) | |
download | FreeBSD-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.c | 14 |
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) |