Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_bus_dma.c
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | error = _bus_dmamap_load_phys(dmat, map, | ||||
nsegs); | nsegs); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Load an unmapped mbuf | |||||
*/ | |||||
static int | |||||
_bus_dmamap_load_unmapped_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, | |||||
struct mbuf *m, bus_dma_segment_t *segs, int *nsegs, int flags) | |||||
{ | |||||
struct mbuf_ext_pgs *ext_pgs; | |||||
int error, i, off, len, pglen, pgoff, seglen, segoff; | |||||
MBUF_EXT_PGS_ASSERT(m); | |||||
ext_pgs = m->m_ext.ext_pgs; | |||||
len = m->m_len; | |||||
error = 0; | |||||
/* Skip over any data removed from the front. */ | |||||
off = mtod(m, vm_offset_t); | |||||
if (ext_pgs->hdr_len != 0) { | |||||
if (off >= ext_pgs->hdr_len) { | |||||
off -= ext_pgs->hdr_len; | |||||
} else { | |||||
seglen = ext_pgs->hdr_len - off; | |||||
segoff = off; | |||||
seglen = min(seglen, len); | |||||
off = 0; | |||||
len -= seglen; | |||||
error = _bus_dmamap_load_buffer(dmat, map, | |||||
&ext_pgs->hdr[segoff], seglen, kernel_pmap, | |||||
flags, segs, nsegs); | |||||
} | |||||
} | |||||
pgoff = ext_pgs->first_pg_off; | |||||
for (i = 0; i < ext_pgs->npgs && error == 0 && len > 0; i++) { | |||||
pglen = mbuf_ext_pg_len(ext_pgs, i, pgoff); | |||||
if (off >= pglen) { | |||||
off -= pglen; | |||||
pgoff = 0; | |||||
continue; | |||||
} | |||||
seglen = pglen - off; | |||||
segoff = pgoff + off; | |||||
off = 0; | |||||
seglen = min(seglen, len); | |||||
len -= seglen; | |||||
error = _bus_dmamap_load_phys(dmat, map, | |||||
ext_pgs->pa[i] + segoff, seglen, flags, segs, nsegs); | |||||
pgoff = 0; | |||||
}; | |||||
if (len != 0 && error == 0) { | |||||
KASSERT((off + len) <= ext_pgs->trail_len, | |||||
("off + len > trail (%d + %d > %d)", off, len, | |||||
ext_pgs->trail_len)); | |||||
error = _bus_dmamap_load_buffer(dmat, map, | |||||
&ext_pgs->trail[off], len, kernel_pmap, flags, segs, | |||||
nsegs); | |||||
} | |||||
return (error); | |||||
} | |||||
/* | |||||
* Load an mbuf chain. | * Load an mbuf chain. | ||||
*/ | */ | ||||
static int | static int | ||||
_bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, | _bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, | ||||
struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, int flags) | struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, int flags) | ||||
{ | { | ||||
struct mbuf *m; | struct mbuf *m; | ||||
int error; | int error; | ||||
error = 0; | error = 0; | ||||
for (m = m0; m != NULL && error == 0; m = m->m_next) { | for (m = m0; m != NULL && error == 0; m = m->m_next) { | ||||
if (m->m_len > 0) { | if (m->m_len > 0) { | ||||
error = _bus_dmamap_load_buffer(dmat, map, m->m_data, | if ((m->m_flags & M_NOMAP) != 0) | ||||
m->m_len, kernel_pmap, flags | BUS_DMA_LOAD_MBUF, | error = _bus_dmamap_load_unmapped_mbuf_sg(dmat, | ||||
segs, nsegs); | map, m, segs, nsegs, flags); | ||||
else | |||||
error = _bus_dmamap_load_buffer(dmat, map, | |||||
m->m_data, m->m_len, kernel_pmap, | |||||
flags | BUS_DMA_LOAD_MBUF, segs, nsegs); | |||||
} | } | ||||
} | } | ||||
CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", | CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d", | ||||
__func__, dmat, flags, error, *nsegs); | __func__, dmat, flags, error, *nsegs); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 436 Lines • Show Last 20 Lines |