summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2003-02-04 16:30:27 +0000
committerharti <harti@FreeBSD.org>2003-02-04 16:30:27 +0000
commit570156f24c833c50ded55e900b5d6284fc04ccee (patch)
tree456b763a94213088811e390d3dfe4a45d7fa5de6
parent865d0cfd1290a3611baf60c7619c4fca51305464 (diff)
downloadFreeBSD-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.c27
-rw-r--r--sys/amd64/amd64/busdma_machdep.c27
-rw-r--r--sys/i386/i386/busdma_machdep.c27
-rw-r--r--sys/ia64/ia64/busdma_machdep.c27
-rw-r--r--sys/powerpc/powerpc/busdma_machdep.c20
-rw-r--r--sys/sparc64/sparc64/bus_machdep.c20
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) {
OpenPOWER on IntegriCloud