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)
This commit is contained in:
Hartmut Brandt 2003-02-04 16:30:27 +00:00
parent 5a63c107db
commit e557905435
6 changed files with 88 additions and 60 deletions

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {