diff options
author | harti <harti@FreeBSD.org> | 2003-02-04 16:30:27 +0000 |
---|---|---|
committer | harti <harti@FreeBSD.org> | 2003-02-04 16:30:27 +0000 |
commit | 570156f24c833c50ded55e900b5d6284fc04ccee (patch) | |
tree | 456b763a94213088811e390d3dfe4a45d7fa5de6 | |
parent | 865d0cfd1290a3611baf60c7619c4fca51305464 (diff) | |
download | FreeBSD-src-570156f24c833c50ded55e900b5d6284fc04ccee.zip FreeBSD-src-570156f24c833c50ded55e900b5d6284fc04ccee.tar.gz |
Fix a problem in bus_dmamap_load_{mbuf,uio} when the first mbuf or the first
uio segment is empty. In this case no dma segment is create by
bus_dmamap_load_buffer, but the calling routine clears the first flag.
Under certain combinations of addresses of the first and second mbuf/uio
buffer this leads to corrupted DMA segment descriptors. This was already
fixed by tmm in sparc64/sparc64/iommu.c.
PR: kern/47733
Reviewed by: sam
Approved by: jake (mentor)
-rw-r--r-- | sys/alpha/alpha/busdma_machdep.c | 27 | ||||
-rw-r--r-- | sys/amd64/amd64/busdma_machdep.c | 27 | ||||
-rw-r--r-- | sys/i386/i386/busdma_machdep.c | 27 | ||||
-rw-r--r-- | sys/ia64/ia64/busdma_machdep.c | 27 | ||||
-rw-r--r-- | sys/powerpc/powerpc/busdma_machdep.c | 20 | ||||
-rw-r--r-- | sys/sparc64/sparc64/bus_machdep.c | 20 |
6 files changed, 88 insertions, 60 deletions
diff --git a/sys/alpha/alpha/busdma_machdep.c b/sys/alpha/alpha/busdma_machdep.c index 28240ae..8b70104 100644 --- a/sys/alpha/alpha/busdma_machdep.c +++ b/sys/alpha/alpha/busdma_machdep.c @@ -674,11 +674,14 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m; for (m = m0; m != NULL && error == 0; m = m->m_next) { - error = _bus_dmamap_load_buffer(dmat, - dm_segments, - m->m_data, m->m_len, - NULL, flags, &lastaddr, &nsegs, first); - first = 0; + if (m->m_len > 0) { + error = _bus_dmamap_load_buffer(dmat, + dm_segments, + m->m_data, m->m_len, + NULL, flags, &lastaddr, + &nsegs, first); + first = 0; + } } } else { error = EINVAL; @@ -738,13 +741,15 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, resid < iov[i].iov_len ? resid : iov[i].iov_len; caddr_t addr = (caddr_t) iov[i].iov_base; - error = _bus_dmamap_load_buffer(dmat, - dm_segments, - addr, minlen, - td, flags, &lastaddr, &nsegs, first); - first = 0; + if (minlen > 0) { + error = _bus_dmamap_load_buffer(dmat, + dm_segments, + addr, minlen, + td, flags, &lastaddr, &nsegs, first); + first = 0; - resid -= minlen; + resid -= minlen; + } } if (error) { diff --git a/sys/amd64/amd64/busdma_machdep.c b/sys/amd64/amd64/busdma_machdep.c index 21e6025..a5a20fc 100644 --- a/sys/amd64/amd64/busdma_machdep.c +++ b/sys/amd64/amd64/busdma_machdep.c @@ -632,11 +632,14 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m; for (m = m0; m != NULL && error == 0; m = m->m_next) { - error = _bus_dmamap_load_buffer(dmat, - dm_segments, - m->m_data, m->m_len, - NULL, flags, &lastaddr, &nsegs, first); - first = 0; + if (m->m_len > 0) { + error = _bus_dmamap_load_buffer(dmat, + dm_segments, + m->m_data, m->m_len, + NULL, flags, &lastaddr, + &nsegs, first); + first = 0; + } } } else { error = EINVAL; @@ -696,13 +699,15 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, resid < iov[i].iov_len ? resid : iov[i].iov_len; caddr_t addr = (caddr_t) iov[i].iov_base; - error = _bus_dmamap_load_buffer(dmat, - dm_segments, - addr, minlen, - td, flags, &lastaddr, &nsegs, first); - first = 0; + if (minlen > 0) { + error = _bus_dmamap_load_buffer(dmat, + dm_segments, + addr, minlen, + td, flags, &lastaddr, &nsegs, first); + first = 0; - resid -= minlen; + resid -= minlen; + } } if (error) { diff --git a/sys/i386/i386/busdma_machdep.c b/sys/i386/i386/busdma_machdep.c index 21e6025..a5a20fc 100644 --- a/sys/i386/i386/busdma_machdep.c +++ b/sys/i386/i386/busdma_machdep.c @@ -632,11 +632,14 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m; for (m = m0; m != NULL && error == 0; m = m->m_next) { - error = _bus_dmamap_load_buffer(dmat, - dm_segments, - m->m_data, m->m_len, - NULL, flags, &lastaddr, &nsegs, first); - first = 0; + if (m->m_len > 0) { + error = _bus_dmamap_load_buffer(dmat, + dm_segments, + m->m_data, m->m_len, + NULL, flags, &lastaddr, + &nsegs, first); + first = 0; + } } } else { error = EINVAL; @@ -696,13 +699,15 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, resid < iov[i].iov_len ? resid : iov[i].iov_len; caddr_t addr = (caddr_t) iov[i].iov_base; - error = _bus_dmamap_load_buffer(dmat, - dm_segments, - addr, minlen, - td, flags, &lastaddr, &nsegs, first); - first = 0; + if (minlen > 0) { + error = _bus_dmamap_load_buffer(dmat, + dm_segments, + addr, minlen, + td, flags, &lastaddr, &nsegs, first); + first = 0; - resid -= minlen; + resid -= minlen; + } } if (error) { diff --git a/sys/ia64/ia64/busdma_machdep.c b/sys/ia64/ia64/busdma_machdep.c index e10f084..d12ea4f 100644 --- a/sys/ia64/ia64/busdma_machdep.c +++ b/sys/ia64/ia64/busdma_machdep.c @@ -644,11 +644,14 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m; for (m = m0; m != NULL && error == 0; m = m->m_next) { - error = _bus_dmamap_load_buffer(dmat, - dm_segments, - m->m_data, m->m_len, - NULL, flags, &lastaddr, &nsegs, first); - first = 0; + if (m->m_len > 0) { + error = _bus_dmamap_load_buffer(dmat, + dm_segments, + m->m_data, m->m_len, + NULL, flags, &lastaddr, + &nsegs, first); + first = 0; + } } } else { error = EINVAL; @@ -708,13 +711,15 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, resid < iov[i].iov_len ? resid : iov[i].iov_len; caddr_t addr = (caddr_t) iov[i].iov_base; - error = _bus_dmamap_load_buffer(dmat, - dm_segments, - addr, minlen, - td, flags, &lastaddr, &nsegs, first); - first = 0; + if (minlen > 0) { + error = _bus_dmamap_load_buffer(dmat, + dm_segments, + addr, minlen, + td, flags, &lastaddr, &nsegs, first); + first = 0; - resid -= minlen; + resid -= minlen; + } } if (error) { diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c index 4bb5f0c..6ab1667 100644 --- a/sys/powerpc/powerpc/busdma_machdep.c +++ b/sys/powerpc/powerpc/busdma_machdep.c @@ -423,10 +423,12 @@ bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, struct mbuf *m; for (m = m0; m != NULL && error == 0; m = m->m_next) { - error = bus_dmamap_load_buffer(dmat, dm_segments, - m->m_data, m->m_len, NULL, flags, - &lastaddr, &nsegs, first); - first = 0; + if (m->m_len > 0) { + error = bus_dmamap_load_buffer(dmat, + dm_segments, m->m_data, m->m_len, NULL, + flags, &lastaddr, &nsegs, first); + first = 0; + } } } else { error = EINVAL; @@ -483,12 +485,14 @@ bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, resid < iov[i].iov_len ? resid : iov[i].iov_len; caddr_t addr = (caddr_t) iov[i].iov_base; - error = bus_dmamap_load_buffer(dmat, dm_segments, addr, - minlen, td, flags, &lastaddr, &nsegs, first); + if (minlen > 0) { + error = bus_dmamap_load_buffer(dmat, dm_segments, addr, + minlen, td, flags, &lastaddr, &nsegs, first); - first = 0; + first = 0; - resid -= minlen; + resid -= minlen; + } } if (error) { diff --git a/sys/sparc64/sparc64/bus_machdep.c b/sys/sparc64/sparc64/bus_machdep.c index f11e9a0..0c26023 100644 --- a/sys/sparc64/sparc64/bus_machdep.c +++ b/sys/sparc64/sparc64/bus_machdep.c @@ -454,10 +454,12 @@ nexus_dmamap_load_mbuf(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, struct mbuf *m; for (m = m0; m != NULL && error == 0; m = m->m_next) { - error = _nexus_dmamap_load_buffer(ddmat, - dm_segments, m->m_data, m->m_len, NULL, flags, - &lastaddr, &nsegs, first); - first = 0; + if (m->m_len > 0) { + error = _nexus_dmamap_load_buffer(ddmat, + dm_segments, m->m_data, m->m_len, NULL, + flags, &lastaddr, &nsegs, first); + first = 0; + } } } else { error = EINVAL; @@ -514,11 +516,13 @@ nexus_dmamap_load_uio(bus_dma_tag_t pdmat, bus_dma_tag_t ddmat, resid < iov[i].iov_len ? resid : iov[i].iov_len; caddr_t addr = (caddr_t) iov[i].iov_base; - error = _nexus_dmamap_load_buffer(ddmat, dm_segments, addr, - minlen, td, flags, &lastaddr, &nsegs, first); - first = 0; + if (minlen > 0) { + error = _nexus_dmamap_load_buffer(ddmat, dm_segments, + addr, minlen, td, flags, &lastaddr, &nsegs, first); + first = 0; - resid -= minlen; + resid -= minlen; + } } if (error) { |