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:
parent
5a63c107db
commit
e557905435
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user