1246713Skib/*-
2246713Skib * Copyright (c) 2012 EMC Corp.
3246713Skib * All rights reserved.
4246713Skib *
5246713Skib * Copyright (c) 1997, 1998 Justin T. Gibbs.
6246713Skib * All rights reserved.
7246713Skib *
8246713Skib * Redistribution and use in source and binary forms, with or without
9246713Skib * modification, are permitted provided that the following conditions
10246713Skib * are met:
11246713Skib * 1. Redistributions of source code must retain the above copyright
12246713Skib *    notice, this list of conditions and the following disclaimer.
13246713Skib * 2. Redistributions in binary form must reproduce the above copyright
14246713Skib *    notice, this list of conditions and the following disclaimer in the
15246713Skib *    documentation and/or other materials provided with the distribution.
16246713Skib *
17246713Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18246713Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19246713Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20246713Skib * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21246713Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22246713Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23246713Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24246713Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25246713Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26246713Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27246713Skib * SUCH DAMAGE.
28246713Skib */
29246713Skib
30246713Skib#include <sys/cdefs.h>
31246713Skib__FBSDID("$FreeBSD$");
32246713Skib
33246713Skib#include "opt_bus.h"
34246713Skib
35246713Skib#include <sys/param.h>
36246713Skib#include <sys/conf.h>
37246713Skib#include <sys/systm.h>
38246713Skib#include <sys/bio.h>
39246713Skib#include <sys/bus.h>
40246713Skib#include <sys/callout.h>
41246713Skib#include <sys/mbuf.h>
42246713Skib#include <sys/memdesc.h>
43246713Skib#include <sys/proc.h>
44246713Skib#include <sys/uio.h>
45246713Skib
46246713Skib#include <vm/vm.h>
47246713Skib#include <vm/vm_page.h>
48246713Skib#include <vm/vm_map.h>
49246713Skib#include <vm/pmap.h>
50246713Skib
51246713Skib#include <cam/cam.h>
52246713Skib#include <cam/cam_ccb.h>
53246713Skib
54246713Skib#include <machine/bus.h>
55246713Skib
56246713Skib/*
57246713Skib * Load a list of virtual addresses.
58246713Skib */
59246713Skibstatic int
60246713Skib_bus_dmamap_load_vlist(bus_dma_tag_t dmat, bus_dmamap_t map,
61246713Skib    bus_dma_segment_t *list, int sglist_cnt, struct pmap *pmap, int *nsegs,
62246713Skib    int flags)
63246713Skib{
64246713Skib	int error;
65246713Skib
66246713Skib	error = 0;
67246713Skib	for (; sglist_cnt > 0; sglist_cnt--, list++) {
68246713Skib		error = _bus_dmamap_load_buffer(dmat, map,
69249538Skib		    (void *)(uintptr_t)list->ds_addr, list->ds_len, pmap,
70249538Skib		    flags, NULL, nsegs);
71246713Skib		if (error)
72246713Skib			break;
73246713Skib	}
74246713Skib	return (error);
75246713Skib}
76246713Skib
77246713Skib/*
78246713Skib * Load a list of physical addresses.
79246713Skib */
80246713Skibstatic int
81246713Skib_bus_dmamap_load_plist(bus_dma_tag_t dmat, bus_dmamap_t map,
82246713Skib    bus_dma_segment_t *list, int sglist_cnt, int *nsegs, int flags)
83246713Skib{
84246713Skib	int error;
85246713Skib
86246713Skib	error = 0;
87246713Skib	for (; sglist_cnt > 0; sglist_cnt--, list++) {
88246713Skib		error = _bus_dmamap_load_phys(dmat, map,
89246713Skib		    (vm_paddr_t)list->ds_addr, list->ds_len, flags, NULL,
90246713Skib		    nsegs);
91246713Skib		if (error)
92246713Skib			break;
93246713Skib	}
94246713Skib	return (error);
95246713Skib}
96246713Skib
97246713Skib/*
98246713Skib * Load an mbuf chain.
99246713Skib */
100246713Skibstatic int
101246713Skib_bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map,
102246713Skib    struct mbuf *m0, bus_dma_segment_t *segs, int *nsegs, int flags)
103246713Skib{
104246713Skib	struct mbuf *m;
105246713Skib	int error;
106246713Skib
107246713Skib	error = 0;
108246713Skib	for (m = m0; m != NULL && error == 0; m = m->m_next) {
109246713Skib		if (m->m_len > 0) {
110246713Skib			error = _bus_dmamap_load_buffer(dmat, map, m->m_data,
111246713Skib			    m->m_len, kernel_pmap, flags | BUS_DMA_LOAD_MBUF,
112246713Skib			    segs, nsegs);
113246713Skib		}
114246713Skib	}
115246713Skib	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
116246713Skib	    __func__, dmat, flags, error, *nsegs);
117246713Skib	return (error);
118246713Skib}
119246713Skib
120246713Skib/*
121246713Skib * Load from block io.
122246713Skib */
123246713Skibstatic int
124246713Skib_bus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio,
125246713Skib    int *nsegs, int flags)
126246713Skib{
127259510Skib	int error;
128246713Skib
129248508Skib	if ((bio->bio_flags & BIO_UNMAPPED) == 0) {
130248508Skib		error = _bus_dmamap_load_buffer(dmat, map, bio->bio_data,
131248508Skib		    bio->bio_bcount, kernel_pmap, flags, NULL, nsegs);
132259510Skib	} else {
133259510Skib		error = _bus_dmamap_load_ma(dmat, map, bio->bio_ma,
134259510Skib		    bio->bio_bcount, bio->bio_ma_offset, flags, NULL, nsegs);
135248508Skib	}
136259510Skib	return (error);
137259510Skib}
138246713Skib
139259510Skibint
140259510Skibbus_dmamap_load_ma_triv(bus_dma_tag_t dmat, bus_dmamap_t map,
141259510Skib    struct vm_page **ma, bus_size_t tlen, int ma_offs, int flags,
142259510Skib    bus_dma_segment_t *segs, int *segp)
143259510Skib{
144259510Skib	vm_paddr_t paddr;
145259510Skib	bus_size_t len;
146259510Skib	int error, i;
147259510Skib
148248508Skib	error = 0;
149248508Skib	for (i = 0; tlen > 0; i++, tlen -= len) {
150248508Skib		len = min(PAGE_SIZE - ma_offs, tlen);
151259510Skib		paddr = VM_PAGE_TO_PHYS(ma[i]) + ma_offs;
152248508Skib		error = _bus_dmamap_load_phys(dmat, map, paddr, len,
153259510Skib		    flags, segs, segp);
154248508Skib		if (error != 0)
155248508Skib			break;
156248508Skib		ma_offs = 0;
157248508Skib	}
158246713Skib	return (error);
159246713Skib}
160246713Skib
161246713Skib/*
162246713Skib * Load a cam control block.
163246713Skib */
164246713Skibstatic int
165246713Skib_bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb,
166246713Skib		    int *nsegs, int flags)
167246713Skib{
168246713Skib	struct ccb_hdr *ccb_h;
169246713Skib	void *data_ptr;
170246713Skib	int error;
171246713Skib	uint32_t dxfer_len;
172246713Skib	uint16_t sglist_cnt;
173246713Skib
174246713Skib	error = 0;
175246713Skib	ccb_h = &ccb->ccb_h;
176246713Skib	switch (ccb_h->func_code) {
177249025Sken	case XPT_SCSI_IO: {
178249025Sken		struct ccb_scsiio *csio;
179249025Sken
180246713Skib		csio = &ccb->csio;
181246713Skib		data_ptr = csio->data_ptr;
182246713Skib		dxfer_len = csio->dxfer_len;
183246713Skib		sglist_cnt = csio->sglist_cnt;
184246713Skib		break;
185249025Sken	}
186249025Sken	case XPT_CONT_TARGET_IO: {
187249025Sken		struct ccb_scsiio *ctio;
188249025Sken
189249025Sken		ctio = &ccb->ctio;
190249025Sken		data_ptr = ctio->data_ptr;
191249025Sken		dxfer_len = ctio->dxfer_len;
192249025Sken		sglist_cnt = ctio->sglist_cnt;
193249025Sken		break;
194249025Sken	}
195249025Sken	case XPT_ATA_IO: {
196249025Sken		struct ccb_ataio *ataio;
197249025Sken
198246713Skib		ataio = &ccb->ataio;
199246713Skib		data_ptr = ataio->data_ptr;
200246713Skib		dxfer_len = ataio->dxfer_len;
201246713Skib		sglist_cnt = 0;
202246713Skib		break;
203249025Sken	}
204246713Skib	default:
205246713Skib		panic("_bus_dmamap_load_ccb: Unsupported func code %d",
206246713Skib		    ccb_h->func_code);
207246713Skib	}
208246713Skib
209246713Skib	switch ((ccb_h->flags & CAM_DATA_MASK)) {
210246713Skib	case CAM_DATA_VADDR:
211246713Skib		error = _bus_dmamap_load_buffer(dmat, map, data_ptr, dxfer_len,
212246713Skib		    kernel_pmap, flags, NULL, nsegs);
213246713Skib		break;
214246713Skib	case CAM_DATA_PADDR:
215246713Skib		error = _bus_dmamap_load_phys(dmat, map,
216246713Skib		    (vm_paddr_t)(uintptr_t)data_ptr, dxfer_len, flags, NULL,
217246713Skib		    nsegs);
218246713Skib		break;
219246713Skib	case CAM_DATA_SG:
220246713Skib		error = _bus_dmamap_load_vlist(dmat, map,
221246713Skib		    (bus_dma_segment_t *)data_ptr, sglist_cnt, kernel_pmap,
222246713Skib		    nsegs, flags);
223246713Skib		break;
224246713Skib	case CAM_DATA_SG_PADDR:
225246713Skib		error = _bus_dmamap_load_plist(dmat, map,
226246713Skib		    (bus_dma_segment_t *)data_ptr, sglist_cnt, nsegs, flags);
227246713Skib		break;
228246713Skib	case CAM_DATA_BIO:
229246713Skib		error = _bus_dmamap_load_bio(dmat, map, (struct bio *)data_ptr,
230246713Skib		    nsegs, flags);
231246713Skib		break;
232246713Skib	default:
233246713Skib		panic("_bus_dmamap_load_ccb: flags 0x%X unimplemented",
234246713Skib		    ccb_h->flags);
235246713Skib	}
236246713Skib	return (error);
237246713Skib}
238246713Skib
239246713Skib/*
240246713Skib * Load a uio.
241246713Skib */
242246713Skibstatic int
243246713Skib_bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio,
244246713Skib    int *nsegs, int flags)
245246713Skib{
246246713Skib	bus_size_t resid;
247246713Skib	bus_size_t minlen;
248246713Skib	struct iovec *iov;
249246713Skib	pmap_t pmap;
250246713Skib	caddr_t addr;
251246713Skib	int error, i;
252246713Skib
253246713Skib	if (uio->uio_segflg == UIO_USERSPACE) {
254246713Skib		KASSERT(uio->uio_td != NULL,
255246713Skib			("bus_dmamap_load_uio: USERSPACE but no proc"));
256246713Skib		pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace);
257246713Skib	} else
258246713Skib		pmap = kernel_pmap;
259246713Skib	resid = uio->uio_resid;
260246713Skib	iov = uio->uio_iov;
261246713Skib	error = 0;
262246713Skib
263246713Skib	for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) {
264246713Skib		/*
265246713Skib		 * Now at the first iovec to load.  Load each iovec
266246713Skib		 * until we have exhausted the residual count.
267246713Skib		 */
268246713Skib
269246713Skib		addr = (caddr_t) iov[i].iov_base;
270246713Skib		minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
271246713Skib		if (minlen > 0) {
272246713Skib			error = _bus_dmamap_load_buffer(dmat, map, addr,
273246713Skib			    minlen, pmap, flags, NULL, nsegs);
274246713Skib			resid -= minlen;
275246713Skib		}
276246713Skib	}
277246713Skib
278246713Skib	return (error);
279246713Skib}
280246713Skib
281246713Skib/*
282246713Skib * Map the buffer buf into bus space using the dmamap map.
283246713Skib */
284246713Skibint
285246713Skibbus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
286246713Skib    bus_size_t buflen, bus_dmamap_callback_t *callback,
287246713Skib    void *callback_arg, int flags)
288246713Skib{
289246713Skib	bus_dma_segment_t *segs;
290246713Skib	struct memdesc mem;
291246713Skib	int error;
292246713Skib	int nsegs;
293246713Skib
294246713Skib	if ((flags & BUS_DMA_NOWAIT) == 0) {
295246713Skib		mem = memdesc_vaddr(buf, buflen);
296246713Skib		_bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg);
297246713Skib	}
298246713Skib
299246713Skib	nsegs = -1;
300246713Skib	error = _bus_dmamap_load_buffer(dmat, map, buf, buflen, kernel_pmap,
301246713Skib	    flags, NULL, &nsegs);
302246713Skib	nsegs++;
303246713Skib
304246713Skib	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
305248892Sjimharris	    __func__, dmat, flags, error, nsegs);
306246713Skib
307246713Skib	if (error == EINPROGRESS)
308246713Skib		return (error);
309246713Skib
310246713Skib	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
311246713Skib	if (error)
312246713Skib		(*callback)(callback_arg, segs, 0, error);
313246713Skib	else
314246713Skib		(*callback)(callback_arg, segs, nsegs, 0);
315246713Skib
316246713Skib	/*
317246713Skib	 * Return ENOMEM to the caller so that it can pass it up the stack.
318248804Sjimharris	 * This error only happens when NOWAIT is set, so deferral is disabled.
319246713Skib	 */
320246713Skib	if (error == ENOMEM)
321246713Skib		return (error);
322246713Skib
323246713Skib	return (0);
324246713Skib}
325246713Skib
326246713Skibint
327246713Skibbus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
328246713Skib    bus_dmamap_callback2_t *callback, void *callback_arg, int flags)
329246713Skib{
330246713Skib	bus_dma_segment_t *segs;
331246713Skib	int nsegs, error;
332246713Skib
333251221Smarius	M_ASSERTPKTHDR(m0);
334251221Smarius
335246713Skib	flags |= BUS_DMA_NOWAIT;
336246713Skib	nsegs = -1;
337246713Skib	error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, NULL, &nsegs, flags);
338246713Skib	++nsegs;
339246713Skib
340246713Skib	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
341246713Skib	if (error)
342246713Skib		(*callback)(callback_arg, segs, 0, 0, error);
343246713Skib	else
344246713Skib		(*callback)(callback_arg, segs, nsegs, m0->m_pkthdr.len, error);
345246713Skib
346246713Skib	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
347246713Skib	    __func__, dmat, flags, error, nsegs);
348246713Skib	return (error);
349246713Skib}
350246713Skib
351246713Skibint
352246713Skibbus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0,
353246713Skib    bus_dma_segment_t *segs, int *nsegs, int flags)
354246713Skib{
355246713Skib	int error;
356246713Skib
357246713Skib	flags |= BUS_DMA_NOWAIT;
358246713Skib	*nsegs = -1;
359246713Skib	error = _bus_dmamap_load_mbuf_sg(dmat, map, m0, segs, nsegs, flags);
360246713Skib	++*nsegs;
361246713Skib	_bus_dmamap_complete(dmat, map, segs, *nsegs, error);
362246713Skib	return (error);
363246713Skib}
364246713Skib
365246713Skibint
366246713Skibbus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio,
367246713Skib    bus_dmamap_callback2_t *callback, void *callback_arg, int flags)
368246713Skib{
369246713Skib	bus_dma_segment_t *segs;
370246713Skib	int nsegs, error;
371246713Skib
372246713Skib	flags |= BUS_DMA_NOWAIT;
373246713Skib	nsegs = -1;
374246713Skib	error = _bus_dmamap_load_uio(dmat, map, uio, &nsegs, flags);
375246713Skib	nsegs++;
376246713Skib
377246713Skib	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
378246713Skib	if (error)
379246713Skib		(*callback)(callback_arg, segs, 0, 0, error);
380246713Skib	else
381246713Skib		(*callback)(callback_arg, segs, nsegs, uio->uio_resid, error);
382246713Skib
383246713Skib	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
384248892Sjimharris	    __func__, dmat, flags, error, nsegs);
385246713Skib	return (error);
386246713Skib}
387246713Skib
388246713Skibint
389246713Skibbus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb,
390246713Skib		    bus_dmamap_callback_t *callback, void *callback_arg,
391246713Skib		    int flags)
392246713Skib{
393246713Skib	bus_dma_segment_t *segs;
394246713Skib	struct ccb_hdr *ccb_h;
395246713Skib	struct memdesc mem;
396246713Skib	int error;
397246713Skib	int nsegs;
398246713Skib
399246713Skib	ccb_h = &ccb->ccb_h;
400246713Skib	if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
401246713Skib		callback(callback_arg, NULL, 0, 0);
402246713Skib		return (0);
403246713Skib	}
404246713Skib	if ((flags & BUS_DMA_NOWAIT) == 0) {
405246713Skib		mem = memdesc_ccb(ccb);
406246713Skib		_bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg);
407246713Skib	}
408246713Skib	nsegs = -1;
409246713Skib	error = _bus_dmamap_load_ccb(dmat, map, ccb, &nsegs, flags);
410246713Skib	nsegs++;
411248893Sjimharris
412248893Sjimharris	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
413248893Sjimharris	    __func__, dmat, flags, error, nsegs);
414248893Sjimharris
415246713Skib	if (error == EINPROGRESS)
416246713Skib		return (error);
417246713Skib
418246713Skib	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
419246713Skib	if (error)
420246713Skib		(*callback)(callback_arg, segs, 0, error);
421246713Skib	else
422246713Skib		(*callback)(callback_arg, segs, nsegs, error);
423246713Skib	/*
424246713Skib	 * Return ENOMEM to the caller so that it can pass it up the stack.
425248804Sjimharris	 * This error only happens when NOWAIT is set, so deferral is disabled.
426246713Skib	 */
427246713Skib	if (error == ENOMEM)
428246713Skib		return (error);
429246713Skib
430246713Skib	return (0);
431246713Skib}
432246713Skib
433246713Skibint
434248896Sjimharrisbus_dmamap_load_bio(bus_dma_tag_t dmat, bus_dmamap_t map, struct bio *bio,
435248896Sjimharris		    bus_dmamap_callback_t *callback, void *callback_arg,
436248896Sjimharris		    int flags)
437248896Sjimharris{
438248896Sjimharris	bus_dma_segment_t *segs;
439248896Sjimharris	struct memdesc mem;
440248896Sjimharris	int error;
441248896Sjimharris	int nsegs;
442248896Sjimharris
443248896Sjimharris	if ((flags & BUS_DMA_NOWAIT) == 0) {
444248896Sjimharris		mem = memdesc_bio(bio);
445248896Sjimharris		_bus_dmamap_waitok(dmat, map, &mem, callback, callback_arg);
446248896Sjimharris	}
447248896Sjimharris	nsegs = -1;
448248896Sjimharris	error = _bus_dmamap_load_bio(dmat, map, bio, &nsegs, flags);
449248896Sjimharris	nsegs++;
450248896Sjimharris
451248896Sjimharris	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
452248896Sjimharris	    __func__, dmat, flags, error, nsegs);
453248896Sjimharris
454248896Sjimharris	if (error == EINPROGRESS)
455248896Sjimharris		return (error);
456248896Sjimharris
457248896Sjimharris	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
458248896Sjimharris	if (error)
459248896Sjimharris		(*callback)(callback_arg, segs, 0, error);
460248896Sjimharris	else
461248896Sjimharris		(*callback)(callback_arg, segs, nsegs, error);
462248896Sjimharris	/*
463248896Sjimharris	 * Return ENOMEM to the caller so that it can pass it up the stack.
464248896Sjimharris	 * This error only happens when NOWAIT is set, so deferral is disabled.
465248896Sjimharris	 */
466248896Sjimharris	if (error == ENOMEM)
467248896Sjimharris		return (error);
468248896Sjimharris
469248896Sjimharris	return (0);
470248896Sjimharris}
471248896Sjimharris
472248896Sjimharrisint
473246713Skibbus_dmamap_load_mem(bus_dma_tag_t dmat, bus_dmamap_t map,
474246713Skib    struct memdesc *mem, bus_dmamap_callback_t *callback,
475246713Skib    void *callback_arg, int flags)
476246713Skib{
477246713Skib	bus_dma_segment_t *segs;
478246713Skib	int error;
479246713Skib	int nsegs;
480246713Skib
481246713Skib	if ((flags & BUS_DMA_NOWAIT) == 0)
482246713Skib		_bus_dmamap_waitok(dmat, map, mem, callback, callback_arg);
483246713Skib
484246713Skib	nsegs = -1;
485246713Skib	error = 0;
486246713Skib	switch (mem->md_type) {
487246713Skib	case MEMDESC_VADDR:
488246713Skib		error = _bus_dmamap_load_buffer(dmat, map, mem->u.md_vaddr,
489246713Skib		    mem->md_opaque, kernel_pmap, flags, NULL, &nsegs);
490246713Skib		break;
491246713Skib	case MEMDESC_PADDR:
492246713Skib		error = _bus_dmamap_load_phys(dmat, map, mem->u.md_paddr,
493246713Skib		    mem->md_opaque, flags, NULL, &nsegs);
494246713Skib		break;
495246713Skib	case MEMDESC_VLIST:
496246713Skib		error = _bus_dmamap_load_vlist(dmat, map, mem->u.md_list,
497246713Skib		    mem->md_opaque, kernel_pmap, &nsegs, flags);
498246713Skib		break;
499246713Skib	case MEMDESC_PLIST:
500246713Skib		error = _bus_dmamap_load_plist(dmat, map, mem->u.md_list,
501246713Skib		    mem->md_opaque, &nsegs, flags);
502246713Skib		break;
503246713Skib	case MEMDESC_BIO:
504246713Skib		error = _bus_dmamap_load_bio(dmat, map, mem->u.md_bio,
505246713Skib		    &nsegs, flags);
506246713Skib		break;
507246713Skib	case MEMDESC_UIO:
508246713Skib		error = _bus_dmamap_load_uio(dmat, map, mem->u.md_uio,
509246713Skib		    &nsegs, flags);
510246713Skib		break;
511246713Skib	case MEMDESC_MBUF:
512246713Skib		error = _bus_dmamap_load_mbuf_sg(dmat, map, mem->u.md_mbuf,
513246713Skib		    NULL, &nsegs, flags);
514246713Skib		break;
515246713Skib	case MEMDESC_CCB:
516246713Skib		error = _bus_dmamap_load_ccb(dmat, map, mem->u.md_ccb, &nsegs,
517246713Skib		    flags);
518246713Skib		break;
519246713Skib	}
520246713Skib	nsegs++;
521246713Skib
522246713Skib	CTR5(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d nsegs %d",
523248892Sjimharris	    __func__, dmat, flags, error, nsegs);
524246713Skib
525246713Skib	if (error == EINPROGRESS)
526246713Skib		return (error);
527246713Skib
528246713Skib	segs = _bus_dmamap_complete(dmat, map, NULL, nsegs, error);
529246713Skib	if (error)
530246713Skib		(*callback)(callback_arg, segs, 0, error);
531246713Skib	else
532246713Skib		(*callback)(callback_arg, segs, nsegs, 0);
533246713Skib
534246713Skib	/*
535246713Skib	 * Return ENOMEM to the caller so that it can pass it up the stack.
536248804Sjimharris	 * This error only happens when NOWAIT is set, so deferral is disabled.
537246713Skib	 */
538246713Skib	if (error == ENOMEM)
539246713Skib		return (error);
540246713Skib
541246713Skib	return (0);
542246713Skib}
543