1 /* $FreeBSD: stable/9/sys/dev/usb/usb_busdma.c 291251 2015-11-24 12:19:20Z hselasky $ */
2 /*-
3  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/stdint.h>
28 #include <sys/stddef.h>
29 #include <sys/param.h>
30 #include <sys/queue.h>
31 #include <sys/types.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/bus.h>
35 #include <sys/module.h>
36 #include <sys/lock.h>
37 #include <sys/mutex.h>
38 #include <sys/condvar.h>
39 #include <sys/sysctl.h>
40 #include <sys/sx.h>
41 #include <sys/unistd.h>
42 #include <sys/callout.h>
43 #include <sys/malloc.h>
44 #include <sys/priv.h>
45 
46 #include <dev/usb/usb.h>
47 #include <dev/usb/usbdi.h>
48 #include <dev/usb/usbdi_util.h>
49 
50 #define	USB_DEBUG_VAR usb_debug
51 
52 #include <dev/usb/usb_core.h>
53 #include <dev/usb/usb_busdma.h>
54 #include <dev/usb/usb_process.h>
55 #include <dev/usb/usb_transfer.h>
56 #include <dev/usb/usb_device.h>
57 #include <dev/usb/usb_util.h>
58 #include <dev/usb/usb_debug.h>
59 
60 #include <dev/usb/usb_controller.h>
61 #include <dev/usb/usb_bus.h>
62 
63 #if USB_HAVE_BUSDMA
64 static void	usb_dma_tag_create(struct usb_dma_tag *, usb_size_t, usb_size_t);
65 static void	usb_dma_tag_destroy(struct usb_dma_tag *);
66 static void	usb_dma_lock_cb(void *, bus_dma_lock_op_t);
67 static void	usb_pc_alloc_mem_cb(void *, bus_dma_segment_t *, int, int);
68 static void	usb_pc_load_mem_cb(void *, bus_dma_segment_t *, int, int);
69 static void	usb_pc_common_mem_cb(void *, bus_dma_segment_t *, int, int,
70 		    uint8_t);
71 #endif
72 
73 /*------------------------------------------------------------------------*
74  *  usbd_get_page - lookup DMA-able memory for the given offset
75  *
76  * NOTE: Only call this function when the "page_cache" structure has
77  * been properly initialized !
78  *------------------------------------------------------------------------*/
79 void
usbd_get_page(struct usb_page_cache * pc,usb_frlength_t offset,struct usb_page_search * res)80 usbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
81     struct usb_page_search *res)
82 {
83 #if USB_HAVE_BUSDMA
84 	struct usb_page *page;
85 
86 	if (pc->page_start) {
87 
88 		/* Case 1 - something has been loaded into DMA */
89 
90 		if (pc->buffer) {
91 
92 			/* Case 1a - Kernel Virtual Address */
93 
94 			res->buffer = USB_ADD_BYTES(pc->buffer, offset);
95 		}
96 		offset += pc->page_offset_buf;
97 
98 		/* compute destination page */
99 
100 		page = pc->page_start;
101 
102 		if (pc->ismultiseg) {
103 
104 			page += (offset / USB_PAGE_SIZE);
105 
106 			offset %= USB_PAGE_SIZE;
107 
108 			res->length = USB_PAGE_SIZE - offset;
109 			res->physaddr = page->physaddr + offset;
110 		} else {
111 			res->length = (usb_size_t)-1;
112 			res->physaddr = page->physaddr + offset;
113 		}
114 		if (!pc->buffer) {
115 
116 			/* Case 1b - Non Kernel Virtual Address */
117 
118 			res->buffer = USB_ADD_BYTES(page->buffer, offset);
119 		}
120 		return;
121 	}
122 #endif
123 	/* Case 2 - Plain PIO */
124 
125 	res->buffer = USB_ADD_BYTES(pc->buffer, offset);
126 	res->length = (usb_size_t)-1;
127 #if USB_HAVE_BUSDMA
128 	res->physaddr = 0;
129 #endif
130 }
131 
132 /*------------------------------------------------------------------------*
133  *  usb_pc_buffer_is_aligned - verify alignment
134  *
135  * This function is used to check if a page cache buffer is properly
136  * aligned to reduce the use of bounce buffers in PIO mode.
137  *------------------------------------------------------------------------*/
138 uint8_t
usb_pc_buffer_is_aligned(struct usb_page_cache * pc,usb_frlength_t offset,usb_frlength_t len,usb_frlength_t mask)139 usb_pc_buffer_is_aligned(struct usb_page_cache *pc, usb_frlength_t offset,
140     usb_frlength_t len, usb_frlength_t mask)
141 {
142 	struct usb_page_search buf_res;
143 
144 	while (len != 0) {
145 
146 		usbd_get_page(pc, offset, &buf_res);
147 
148 		if (buf_res.length > len)
149 			buf_res.length = len;
150 		if (USB_P2U(buf_res.buffer) & mask)
151 			return (0);
152 		if (buf_res.length & mask)
153 			return (0);
154 
155 		offset += buf_res.length;
156 		len -= buf_res.length;
157 	}
158 	return (1);
159 }
160 
161 /*------------------------------------------------------------------------*
162  *  usbd_copy_in - copy directly to DMA-able memory
163  *------------------------------------------------------------------------*/
164 void
usbd_copy_in(struct usb_page_cache * cache,usb_frlength_t offset,const void * ptr,usb_frlength_t len)165 usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
166     const void *ptr, usb_frlength_t len)
167 {
168 	struct usb_page_search buf_res;
169 
170 	while (len != 0) {
171 
172 		usbd_get_page(cache, offset, &buf_res);
173 
174 		if (buf_res.length > len) {
175 			buf_res.length = len;
176 		}
177 		memcpy(buf_res.buffer, ptr, buf_res.length);
178 
179 		offset += buf_res.length;
180 		len -= buf_res.length;
181 		ptr = USB_ADD_BYTES(ptr, buf_res.length);
182 	}
183 }
184 
185 /*------------------------------------------------------------------------*
186  *  usbd_copy_in_user - copy directly to DMA-able memory from userland
187  *
188  * Return values:
189  *    0: Success
190  * Else: Failure
191  *------------------------------------------------------------------------*/
192 #if USB_HAVE_USER_IO
193 int
usbd_copy_in_user(struct usb_page_cache * cache,usb_frlength_t offset,const void * ptr,usb_frlength_t len)194 usbd_copy_in_user(struct usb_page_cache *cache, usb_frlength_t offset,
195     const void *ptr, usb_frlength_t len)
196 {
197 	struct usb_page_search buf_res;
198 	int error;
199 
200 	while (len != 0) {
201 
202 		usbd_get_page(cache, offset, &buf_res);
203 
204 		if (buf_res.length > len) {
205 			buf_res.length = len;
206 		}
207 		error = copyin(ptr, buf_res.buffer, buf_res.length);
208 		if (error)
209 			return (error);
210 
211 		offset += buf_res.length;
212 		len -= buf_res.length;
213 		ptr = USB_ADD_BYTES(ptr, buf_res.length);
214 	}
215 	return (0);			/* success */
216 }
217 #endif
218 
219 /*------------------------------------------------------------------------*
220  *  usbd_m_copy_in - copy a mbuf chain directly into DMA-able memory
221  *------------------------------------------------------------------------*/
222 #if USB_HAVE_MBUF
223 struct usb_m_copy_in_arg {
224 	struct usb_page_cache *cache;
225 	usb_frlength_t dst_offset;
226 };
227 
228 static int
usbd_m_copy_in_cb(void * arg,void * src,uint32_t count)229 usbd_m_copy_in_cb(void *arg, void *src, uint32_t count)
230 {
231 	register struct usb_m_copy_in_arg *ua = arg;
232 
233 	usbd_copy_in(ua->cache, ua->dst_offset, src, count);
234 	ua->dst_offset += count;
235 	return (0);
236 }
237 
238 void
usbd_m_copy_in(struct usb_page_cache * cache,usb_frlength_t dst_offset,struct mbuf * m,usb_size_t src_offset,usb_frlength_t src_len)239 usbd_m_copy_in(struct usb_page_cache *cache, usb_frlength_t dst_offset,
240     struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len)
241 {
242 	struct usb_m_copy_in_arg arg = {cache, dst_offset};
243 	(void) m_apply(m, src_offset, src_len, &usbd_m_copy_in_cb, &arg);
244 }
245 #endif
246 
247 /*------------------------------------------------------------------------*
248  *  usb_uiomove - factored out code
249  *------------------------------------------------------------------------*/
250 #if USB_HAVE_USER_IO
251 int
usb_uiomove(struct usb_page_cache * pc,struct uio * uio,usb_frlength_t pc_offset,usb_frlength_t len)252 usb_uiomove(struct usb_page_cache *pc, struct uio *uio,
253     usb_frlength_t pc_offset, usb_frlength_t len)
254 {
255 	struct usb_page_search res;
256 	int error = 0;
257 
258 	while (len != 0) {
259 
260 		usbd_get_page(pc, pc_offset, &res);
261 
262 		if (res.length > len) {
263 			res.length = len;
264 		}
265 		/*
266 		 * "uiomove()" can sleep so one needs to make a wrapper,
267 		 * exiting the mutex and checking things
268 		 */
269 		error = uiomove(res.buffer, res.length, uio);
270 
271 		if (error) {
272 			break;
273 		}
274 		pc_offset += res.length;
275 		len -= res.length;
276 	}
277 	return (error);
278 }
279 #endif
280 
281 /*------------------------------------------------------------------------*
282  *  usbd_copy_out - copy directly from DMA-able memory
283  *------------------------------------------------------------------------*/
284 void
usbd_copy_out(struct usb_page_cache * cache,usb_frlength_t offset,void * ptr,usb_frlength_t len)285 usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset,
286     void *ptr, usb_frlength_t len)
287 {
288 	struct usb_page_search res;
289 
290 	while (len != 0) {
291 
292 		usbd_get_page(cache, offset, &res);
293 
294 		if (res.length > len) {
295 			res.length = len;
296 		}
297 		memcpy(ptr, res.buffer, res.length);
298 
299 		offset += res.length;
300 		len -= res.length;
301 		ptr = USB_ADD_BYTES(ptr, res.length);
302 	}
303 }
304 
305 /*------------------------------------------------------------------------*
306  *  usbd_copy_out_user - copy directly from DMA-able memory to userland
307  *
308  * Return values:
309  *    0: Success
310  * Else: Failure
311  *------------------------------------------------------------------------*/
312 #if USB_HAVE_USER_IO
313 int
usbd_copy_out_user(struct usb_page_cache * cache,usb_frlength_t offset,void * ptr,usb_frlength_t len)314 usbd_copy_out_user(struct usb_page_cache *cache, usb_frlength_t offset,
315     void *ptr, usb_frlength_t len)
316 {
317 	struct usb_page_search res;
318 	int error;
319 
320 	while (len != 0) {
321 
322 		usbd_get_page(cache, offset, &res);
323 
324 		if (res.length > len) {
325 			res.length = len;
326 		}
327 		error = copyout(res.buffer, ptr, res.length);
328 		if (error)
329 			return (error);
330 
331 		offset += res.length;
332 		len -= res.length;
333 		ptr = USB_ADD_BYTES(ptr, res.length);
334 	}
335 	return (0);			/* success */
336 }
337 #endif
338 
339 /*------------------------------------------------------------------------*
340  *  usbd_frame_zero - zero DMA-able memory
341  *------------------------------------------------------------------------*/
342 void
usbd_frame_zero(struct usb_page_cache * cache,usb_frlength_t offset,usb_frlength_t len)343 usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
344     usb_frlength_t len)
345 {
346 	struct usb_page_search res;
347 
348 	while (len != 0) {
349 
350 		usbd_get_page(cache, offset, &res);
351 
352 		if (res.length > len) {
353 			res.length = len;
354 		}
355 		memset(res.buffer, 0, res.length);
356 
357 		offset += res.length;
358 		len -= res.length;
359 	}
360 }
361 
362 #if USB_HAVE_BUSDMA
363 
364 /*------------------------------------------------------------------------*
365  *	usb_dma_lock_cb - dummy callback
366  *------------------------------------------------------------------------*/
367 static void
usb_dma_lock_cb(void * arg,bus_dma_lock_op_t op)368 usb_dma_lock_cb(void *arg, bus_dma_lock_op_t op)
369 {
370 	/* we use "mtx_owned()" instead of this function */
371 }
372 
373 /*------------------------------------------------------------------------*
374  *	usb_dma_tag_create - allocate a DMA tag
375  *
376  * NOTE: If the "align" parameter has a value of 1 the DMA-tag will
377  * allow multi-segment mappings. Else all mappings are single-segment.
378  *------------------------------------------------------------------------*/
379 static void
usb_dma_tag_create(struct usb_dma_tag * udt,usb_size_t size,usb_size_t align)380 usb_dma_tag_create(struct usb_dma_tag *udt,
381     usb_size_t size, usb_size_t align)
382 {
383 	bus_dma_tag_t tag;
384 
385 	if (bus_dma_tag_create
386 	    ( /* parent    */ udt->tag_parent->tag,
387 	     /* alignment */ align,
388 	     /* boundary  */ 0,
389 	     /* lowaddr   */ (2ULL << (udt->tag_parent->dma_bits - 1)) - 1,
390 	     /* highaddr  */ BUS_SPACE_MAXADDR,
391 	     /* filter    */ NULL,
392 	     /* filterarg */ NULL,
393 	     /* maxsize   */ size,
394 	     /* nsegments */ (align == 1 && size > 1) ?
395 	    (2 + (size / USB_PAGE_SIZE)) : 1,
396 	     /* maxsegsz  */ (align == 1 && size > USB_PAGE_SIZE) ?
397 	    USB_PAGE_SIZE : size,
398 	     /* flags     */ BUS_DMA_KEEP_PG_OFFSET,
399 	     /* lockfn    */ &usb_dma_lock_cb,
400 	     /* lockarg   */ NULL,
401 	    &tag)) {
402 		tag = NULL;
403 	}
404 	udt->tag = tag;
405 }
406 
407 /*------------------------------------------------------------------------*
408  *	usb_dma_tag_free - free a DMA tag
409  *------------------------------------------------------------------------*/
410 static void
usb_dma_tag_destroy(struct usb_dma_tag * udt)411 usb_dma_tag_destroy(struct usb_dma_tag *udt)
412 {
413 	bus_dma_tag_destroy(udt->tag);
414 }
415 
416 /*------------------------------------------------------------------------*
417  *	usb_pc_alloc_mem_cb - BUS-DMA callback function
418  *------------------------------------------------------------------------*/
419 static void
usb_pc_alloc_mem_cb(void * arg,bus_dma_segment_t * segs,int nseg,int error)420 usb_pc_alloc_mem_cb(void *arg, bus_dma_segment_t *segs,
421     int nseg, int error)
422 {
423 	usb_pc_common_mem_cb(arg, segs, nseg, error, 0);
424 }
425 
426 /*------------------------------------------------------------------------*
427  *	usb_pc_load_mem_cb - BUS-DMA callback function
428  *------------------------------------------------------------------------*/
429 static void
usb_pc_load_mem_cb(void * arg,bus_dma_segment_t * segs,int nseg,int error)430 usb_pc_load_mem_cb(void *arg, bus_dma_segment_t *segs,
431     int nseg, int error)
432 {
433 	usb_pc_common_mem_cb(arg, segs, nseg, error, 1);
434 }
435 
436 /*------------------------------------------------------------------------*
437  *	usb_pc_common_mem_cb - BUS-DMA callback function
438  *------------------------------------------------------------------------*/
439 static void
usb_pc_common_mem_cb(void * arg,bus_dma_segment_t * segs,int nseg,int error,uint8_t isload)440 usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
441     int nseg, int error, uint8_t isload)
442 {
443 	struct usb_dma_parent_tag *uptag;
444 	struct usb_page_cache *pc;
445 	struct usb_page *pg;
446 	usb_size_t rem;
447 	bus_size_t off;
448 	uint8_t owned;
449 
450 	pc = arg;
451 	uptag = pc->tag_parent;
452 
453 	/*
454 	 * XXX There is sometimes recursive locking here.
455 	 * XXX We should try to find a better solution.
456 	 * XXX Until further the "owned" variable does
457 	 * XXX the trick.
458 	 */
459 
460 	if (error) {
461 		goto done;
462 	}
463 
464 	off = 0;
465 	pg = pc->page_start;
466 	pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
467 	rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
468 	pc->page_offset_buf = rem;
469 	pc->page_offset_end += rem;
470 #ifdef USB_DEBUG
471 	if (nseg > 1 &&
472 	    ((segs->ds_addr + segs->ds_len) & (USB_PAGE_SIZE - 1)) !=
473 	    ((segs + 1)->ds_addr & (USB_PAGE_SIZE - 1))) {
474 		/*
475 		 * This check verifies there is no page offset hole
476 		 * between the first and second segment. See the
477 		 * BUS_DMA_KEEP_PG_OFFSET flag.
478 		 */
479 		DPRINTFN(0, "Page offset was not preserved\n");
480 		error = 1;
481 		goto done;
482 	}
483 #endif
484 	while (pc->ismultiseg) {
485 		off += USB_PAGE_SIZE;
486 		if (off >= (segs->ds_len + rem)) {
487 			/* page crossing */
488 			nseg--;
489 			segs++;
490 			off = 0;
491 			rem = 0;
492 			if (nseg == 0)
493 				break;
494 		}
495 		pg++;
496 		pg->physaddr = (segs->ds_addr + off) & ~(USB_PAGE_SIZE - 1);
497 	}
498 
499 done:
500 	owned = mtx_owned(uptag->mtx);
501 	if (!owned)
502 		mtx_lock(uptag->mtx);
503 
504 	uptag->dma_error = (error ? 1 : 0);
505 	if (isload) {
506 		(uptag->func) (uptag);
507 	} else {
508 		cv_broadcast(uptag->cv);
509 	}
510 	if (!owned)
511 		mtx_unlock(uptag->mtx);
512 }
513 
514 /*------------------------------------------------------------------------*
515  *	usb_pc_alloc_mem - allocate DMA'able memory
516  *
517  * Returns:
518  *    0: Success
519  * Else: Failure
520  *------------------------------------------------------------------------*/
521 uint8_t
usb_pc_alloc_mem(struct usb_page_cache * pc,struct usb_page * pg,usb_size_t size,usb_size_t align)522 usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
523     usb_size_t size, usb_size_t align)
524 {
525 	struct usb_dma_parent_tag *uptag;
526 	struct usb_dma_tag *utag;
527 	bus_dmamap_t map;
528 	void *ptr;
529 	int err;
530 
531 	uptag = pc->tag_parent;
532 
533 	if (align != 1) {
534 		/*
535 	         * The alignment must be greater or equal to the
536 	         * "size" else the object can be split between two
537 	         * memory pages and we get a problem!
538 	         */
539 		while (align < size) {
540 			align *= 2;
541 			if (align == 0) {
542 				goto error;
543 			}
544 		}
545 #if 1
546 		/*
547 		 * XXX BUS-DMA workaround - FIXME later:
548 		 *
549 		 * We assume that that the aligment at this point of
550 		 * the code is greater than or equal to the size and
551 		 * less than two times the size, so that if we double
552 		 * the size, the size will be greater than the
553 		 * alignment.
554 		 *
555 		 * The bus-dma system has a check for "alignment"
556 		 * being less than "size". If that check fails we end
557 		 * up using contigmalloc which is page based even for
558 		 * small allocations. Try to avoid that to save
559 		 * memory, hence we sometimes to a large number of
560 		 * small allocations!
561 		 */
562 		if (size <= (USB_PAGE_SIZE / 2)) {
563 			size *= 2;
564 		}
565 #endif
566 	}
567 	/* get the correct DMA tag */
568 	utag = usb_dma_tag_find(uptag, size, align);
569 	if (utag == NULL) {
570 		goto error;
571 	}
572 	/* allocate memory */
573 	if (bus_dmamem_alloc(
574 	    utag->tag, &ptr, (BUS_DMA_WAITOK | BUS_DMA_COHERENT), &map)) {
575 		goto error;
576 	}
577 	/* setup page cache */
578 	pc->buffer = ptr;
579 	pc->page_start = pg;
580 	pc->page_offset_buf = 0;
581 	pc->page_offset_end = size;
582 	pc->map = map;
583 	pc->tag = utag->tag;
584 	pc->ismultiseg = (align == 1);
585 
586 	mtx_lock(uptag->mtx);
587 
588 	/* load memory into DMA */
589 	err = bus_dmamap_load(
590 	    utag->tag, map, ptr, size, &usb_pc_alloc_mem_cb,
591 	    pc, (BUS_DMA_WAITOK | BUS_DMA_COHERENT));
592 
593 	if (err == EINPROGRESS) {
594 		cv_wait(uptag->cv, uptag->mtx);
595 		err = 0;
596 	}
597 	mtx_unlock(uptag->mtx);
598 
599 	if (err || uptag->dma_error) {
600 		bus_dmamem_free(utag->tag, ptr, map);
601 		goto error;
602 	}
603 	memset(ptr, 0, size);
604 
605 	usb_pc_cpu_flush(pc);
606 
607 	return (0);
608 
609 error:
610 	/* reset most of the page cache */
611 	pc->buffer = NULL;
612 	pc->page_start = NULL;
613 	pc->page_offset_buf = 0;
614 	pc->page_offset_end = 0;
615 	pc->map = NULL;
616 	pc->tag = NULL;
617 	return (1);
618 }
619 
620 /*------------------------------------------------------------------------*
621  *	usb_pc_free_mem - free DMA memory
622  *
623  * This function is NULL safe.
624  *------------------------------------------------------------------------*/
625 void
usb_pc_free_mem(struct usb_page_cache * pc)626 usb_pc_free_mem(struct usb_page_cache *pc)
627 {
628 	if (pc && pc->buffer) {
629 
630 		bus_dmamap_unload(pc->tag, pc->map);
631 
632 		bus_dmamem_free(pc->tag, pc->buffer, pc->map);
633 
634 		pc->buffer = NULL;
635 	}
636 }
637 
638 /*------------------------------------------------------------------------*
639  *	usb_pc_load_mem - load virtual memory into DMA
640  *
641  * Return values:
642  * 0: Success
643  * Else: Error
644  *------------------------------------------------------------------------*/
645 uint8_t
usb_pc_load_mem(struct usb_page_cache * pc,usb_size_t size,uint8_t sync)646 usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, uint8_t sync)
647 {
648 	/* setup page cache */
649 	pc->page_offset_buf = 0;
650 	pc->page_offset_end = size;
651 	pc->ismultiseg = 1;
652 
653 	mtx_assert(pc->tag_parent->mtx, MA_OWNED);
654 
655 	if (size > 0) {
656 		if (sync) {
657 			struct usb_dma_parent_tag *uptag;
658 			int err;
659 
660 			uptag = pc->tag_parent;
661 
662 			/*
663 			 * We have to unload the previous loaded DMA
664 			 * pages before trying to load a new one!
665 			 */
666 			bus_dmamap_unload(pc->tag, pc->map);
667 
668 			/*
669 			 * Try to load memory into DMA.
670 			 */
671 			err = bus_dmamap_load(
672 			    pc->tag, pc->map, pc->buffer, size,
673 			    &usb_pc_alloc_mem_cb, pc, BUS_DMA_WAITOK);
674 			if (err == EINPROGRESS) {
675 				cv_wait(uptag->cv, uptag->mtx);
676 				err = 0;
677 			}
678 			if (err || uptag->dma_error) {
679 				return (1);
680 			}
681 		} else {
682 
683 			/*
684 			 * We have to unload the previous loaded DMA
685 			 * pages before trying to load a new one!
686 			 */
687 			bus_dmamap_unload(pc->tag, pc->map);
688 
689 			/*
690 			 * Try to load memory into DMA. The callback
691 			 * will be called in all cases:
692 			 */
693 			if (bus_dmamap_load(
694 			    pc->tag, pc->map, pc->buffer, size,
695 			    &usb_pc_load_mem_cb, pc, BUS_DMA_WAITOK)) {
696 			}
697 		}
698 	} else {
699 		if (!sync) {
700 			/*
701 			 * Call callback so that refcount is decremented
702 			 * properly:
703 			 */
704 			pc->tag_parent->dma_error = 0;
705 			(pc->tag_parent->func) (pc->tag_parent);
706 		}
707 	}
708 	return (0);
709 }
710 
711 /*------------------------------------------------------------------------*
712  *	usb_pc_cpu_invalidate - invalidate CPU cache
713  *------------------------------------------------------------------------*/
714 void
usb_pc_cpu_invalidate(struct usb_page_cache * pc)715 usb_pc_cpu_invalidate(struct usb_page_cache *pc)
716 {
717 	if (pc->page_offset_end == pc->page_offset_buf) {
718 		/* nothing has been loaded into this page cache! */
719 		return;
720 	}
721 
722 	/*
723 	 * TODO: We currently do XXX_POSTREAD and XXX_PREREAD at the
724 	 * same time, but in the future we should try to isolate the
725 	 * different cases to optimise the code. --HPS
726 	 */
727 	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_POSTREAD);
728 	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREREAD);
729 }
730 
731 /*------------------------------------------------------------------------*
732  *	usb_pc_cpu_flush - flush CPU cache
733  *------------------------------------------------------------------------*/
734 void
usb_pc_cpu_flush(struct usb_page_cache * pc)735 usb_pc_cpu_flush(struct usb_page_cache *pc)
736 {
737 	if (pc->page_offset_end == pc->page_offset_buf) {
738 		/* nothing has been loaded into this page cache! */
739 		return;
740 	}
741 	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREWRITE);
742 }
743 
744 /*------------------------------------------------------------------------*
745  *	usb_pc_dmamap_create - create a DMA map
746  *
747  * Returns:
748  *    0: Success
749  * Else: Failure
750  *------------------------------------------------------------------------*/
751 uint8_t
usb_pc_dmamap_create(struct usb_page_cache * pc,usb_size_t size)752 usb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size)
753 {
754 	struct usb_xfer_root *info;
755 	struct usb_dma_tag *utag;
756 
757 	/* get info */
758 	info = USB_DMATAG_TO_XROOT(pc->tag_parent);
759 
760 	/* sanity check */
761 	if (info == NULL) {
762 		goto error;
763 	}
764 	utag = usb_dma_tag_find(pc->tag_parent, size, 1);
765 	if (utag == NULL) {
766 		goto error;
767 	}
768 	/* create DMA map */
769 	if (bus_dmamap_create(utag->tag, 0, &pc->map)) {
770 		goto error;
771 	}
772 	pc->tag = utag->tag;
773 	return 0;			/* success */
774 
775 error:
776 	pc->map = NULL;
777 	pc->tag = NULL;
778 	return 1;			/* failure */
779 }
780 
781 /*------------------------------------------------------------------------*
782  *	usb_pc_dmamap_destroy
783  *
784  * This function is NULL safe.
785  *------------------------------------------------------------------------*/
786 void
usb_pc_dmamap_destroy(struct usb_page_cache * pc)787 usb_pc_dmamap_destroy(struct usb_page_cache *pc)
788 {
789 	if (pc && pc->tag) {
790 		bus_dmamap_destroy(pc->tag, pc->map);
791 		pc->tag = NULL;
792 		pc->map = NULL;
793 	}
794 }
795 
796 /*------------------------------------------------------------------------*
797  *	usb_dma_tag_find - factored out code
798  *------------------------------------------------------------------------*/
799 struct usb_dma_tag *
usb_dma_tag_find(struct usb_dma_parent_tag * udpt,usb_size_t size,usb_size_t align)800 usb_dma_tag_find(struct usb_dma_parent_tag *udpt,
801     usb_size_t size, usb_size_t align)
802 {
803 	struct usb_dma_tag *udt;
804 	uint8_t nudt;
805 
806 	USB_ASSERT(align > 0, ("Invalid parameter align = 0\n"));
807 	USB_ASSERT(size > 0, ("Invalid parameter size = 0\n"));
808 
809 	udt = udpt->utag_first;
810 	nudt = udpt->utag_max;
811 
812 	while (nudt--) {
813 
814 		if (udt->align == 0) {
815 			usb_dma_tag_create(udt, size, align);
816 			if (udt->tag == NULL) {
817 				return (NULL);
818 			}
819 			udt->align = align;
820 			udt->size = size;
821 			return (udt);
822 		}
823 		if ((udt->align == align) && (udt->size == size)) {
824 			return (udt);
825 		}
826 		udt++;
827 	}
828 	return (NULL);
829 }
830 
831 /*------------------------------------------------------------------------*
832  *	usb_dma_tag_setup - initialise USB DMA tags
833  *------------------------------------------------------------------------*/
834 void
usb_dma_tag_setup(struct usb_dma_parent_tag * udpt,struct usb_dma_tag * udt,bus_dma_tag_t dmat,struct mtx * mtx,usb_dma_callback_t * func,uint8_t ndmabits,uint8_t nudt)835 usb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
836     struct usb_dma_tag *udt, bus_dma_tag_t dmat,
837     struct mtx *mtx, usb_dma_callback_t *func,
838     uint8_t ndmabits, uint8_t nudt)
839 {
840 	memset(udpt, 0, sizeof(*udpt));
841 
842 	/* sanity checking */
843 	if ((nudt == 0) ||
844 	    (ndmabits == 0) ||
845 	    (mtx == NULL)) {
846 		/* something is corrupt */
847 		return;
848 	}
849 	/* initialise condition variable */
850 	cv_init(udpt->cv, "USB DMA CV");
851 
852 	/* store some information */
853 	udpt->mtx = mtx;
854 	udpt->func = func;
855 	udpt->tag = dmat;
856 	udpt->utag_first = udt;
857 	udpt->utag_max = nudt;
858 	udpt->dma_bits = ndmabits;
859 
860 	while (nudt--) {
861 		memset(udt, 0, sizeof(*udt));
862 		udt->tag_parent = udpt;
863 		udt++;
864 	}
865 }
866 
867 /*------------------------------------------------------------------------*
868  *	usb_bus_tag_unsetup - factored out code
869  *------------------------------------------------------------------------*/
870 void
usb_dma_tag_unsetup(struct usb_dma_parent_tag * udpt)871 usb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt)
872 {
873 	struct usb_dma_tag *udt;
874 	uint8_t nudt;
875 
876 	udt = udpt->utag_first;
877 	nudt = udpt->utag_max;
878 
879 	while (nudt--) {
880 
881 		if (udt->align) {
882 			/* destroy the USB DMA tag */
883 			usb_dma_tag_destroy(udt);
884 			udt->align = 0;
885 		}
886 		udt++;
887 	}
888 
889 	if (udpt->utag_max) {
890 		/* destroy the condition variable */
891 		cv_destroy(udpt->cv);
892 	}
893 }
894 
895 /*------------------------------------------------------------------------*
896  *	usb_bdma_work_loop
897  *
898  * This function handles loading of virtual buffers into DMA and is
899  * only called when "dma_refcount" is zero.
900  *------------------------------------------------------------------------*/
901 void
usb_bdma_work_loop(struct usb_xfer_queue * pq)902 usb_bdma_work_loop(struct usb_xfer_queue *pq)
903 {
904 	struct usb_xfer_root *info;
905 	struct usb_xfer *xfer;
906 	usb_frcount_t nframes;
907 
908 	xfer = pq->curr;
909 	info = xfer->xroot;
910 
911 	mtx_assert(info->xfer_mtx, MA_OWNED);
912 
913 	if (xfer->error) {
914 		/* some error happened */
915 		USB_BUS_LOCK(info->bus);
916 		usbd_transfer_done(xfer, 0);
917 		USB_BUS_UNLOCK(info->bus);
918 		return;
919 	}
920 	if (!xfer->flags_int.bdma_setup) {
921 		struct usb_page *pg;
922 		usb_frlength_t frlength_0;
923 		uint8_t isread;
924 
925 		xfer->flags_int.bdma_setup = 1;
926 
927 		/* reset BUS-DMA load state */
928 
929 		info->dma_error = 0;
930 
931 		if (xfer->flags_int.isochronous_xfr) {
932 			/* only one frame buffer */
933 			nframes = 1;
934 			frlength_0 = xfer->sumlen;
935 		} else {
936 			/* can be multiple frame buffers */
937 			nframes = xfer->nframes;
938 			frlength_0 = xfer->frlengths[0];
939 		}
940 
941 		/*
942 		 * Set DMA direction first. This is needed to
943 		 * select the correct cache invalidate and cache
944 		 * flush operations.
945 		 */
946 		isread = USB_GET_DATA_ISREAD(xfer);
947 		pg = xfer->dma_page_ptr;
948 
949 		if (xfer->flags_int.control_xfr &&
950 		    xfer->flags_int.control_hdr) {
951 			/* special case */
952 			if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
953 				/* The device controller writes to memory */
954 				xfer->frbuffers[0].isread = 1;
955 			} else {
956 				/* The host controller reads from memory */
957 				xfer->frbuffers[0].isread = 0;
958 			}
959 		} else {
960 			/* default case */
961 			xfer->frbuffers[0].isread = isread;
962 		}
963 
964 		/*
965 		 * Setup the "page_start" pointer which points to an array of
966 		 * USB pages where information about the physical address of a
967 		 * page will be stored. Also initialise the "isread" field of
968 		 * the USB page caches.
969 		 */
970 		xfer->frbuffers[0].page_start = pg;
971 
972 		info->dma_nframes = nframes;
973 		info->dma_currframe = 0;
974 		info->dma_frlength_0 = frlength_0;
975 
976 		pg += (frlength_0 / USB_PAGE_SIZE);
977 		pg += 2;
978 
979 		while (--nframes > 0) {
980 			xfer->frbuffers[nframes].isread = isread;
981 			xfer->frbuffers[nframes].page_start = pg;
982 
983 			pg += (xfer->frlengths[nframes] / USB_PAGE_SIZE);
984 			pg += 2;
985 		}
986 
987 	}
988 	if (info->dma_error) {
989 		USB_BUS_LOCK(info->bus);
990 		usbd_transfer_done(xfer, USB_ERR_DMA_LOAD_FAILED);
991 		USB_BUS_UNLOCK(info->bus);
992 		return;
993 	}
994 	if (info->dma_currframe != info->dma_nframes) {
995 
996 		if (info->dma_currframe == 0) {
997 			/* special case */
998 			usb_pc_load_mem(xfer->frbuffers,
999 			    info->dma_frlength_0, 0);
1000 		} else {
1001 			/* default case */
1002 			nframes = info->dma_currframe;
1003 			usb_pc_load_mem(xfer->frbuffers + nframes,
1004 			    xfer->frlengths[nframes], 0);
1005 		}
1006 
1007 		/* advance frame index */
1008 		info->dma_currframe++;
1009 
1010 		return;
1011 	}
1012 	/* go ahead */
1013 	usb_bdma_pre_sync(xfer);
1014 
1015 	/* start loading next USB transfer, if any */
1016 	usb_command_wrapper(pq, NULL);
1017 
1018 	/* finally start the hardware */
1019 	usbd_pipe_enter(xfer);
1020 }
1021 
1022 /*------------------------------------------------------------------------*
1023  *	usb_bdma_done_event
1024  *
1025  * This function is called when the BUS-DMA has loaded virtual memory
1026  * into DMA, if any.
1027  *------------------------------------------------------------------------*/
1028 void
usb_bdma_done_event(struct usb_dma_parent_tag * udpt)1029 usb_bdma_done_event(struct usb_dma_parent_tag *udpt)
1030 {
1031 	struct usb_xfer_root *info;
1032 
1033 	info = USB_DMATAG_TO_XROOT(udpt);
1034 
1035 	mtx_assert(info->xfer_mtx, MA_OWNED);
1036 
1037 	/* copy error */
1038 	info->dma_error = udpt->dma_error;
1039 
1040 	/* enter workloop again */
1041 	usb_command_wrapper(&info->dma_q,
1042 	    info->dma_q.curr);
1043 }
1044 
1045 /*------------------------------------------------------------------------*
1046  *	usb_bdma_pre_sync
1047  *
1048  * This function handles DMA synchronisation that must be done before
1049  * an USB transfer is started.
1050  *------------------------------------------------------------------------*/
1051 void
usb_bdma_pre_sync(struct usb_xfer * xfer)1052 usb_bdma_pre_sync(struct usb_xfer *xfer)
1053 {
1054 	struct usb_page_cache *pc;
1055 	usb_frcount_t nframes;
1056 
1057 	if (xfer->flags_int.isochronous_xfr) {
1058 		/* only one frame buffer */
1059 		nframes = 1;
1060 	} else {
1061 		/* can be multiple frame buffers */
1062 		nframes = xfer->nframes;
1063 	}
1064 
1065 	pc = xfer->frbuffers;
1066 
1067 	while (nframes--) {
1068 
1069 		if (pc->isread) {
1070 			usb_pc_cpu_invalidate(pc);
1071 		} else {
1072 			usb_pc_cpu_flush(pc);
1073 		}
1074 		pc++;
1075 	}
1076 }
1077 
1078 /*------------------------------------------------------------------------*
1079  *	usb_bdma_post_sync
1080  *
1081  * This function handles DMA synchronisation that must be done after
1082  * an USB transfer is complete.
1083  *------------------------------------------------------------------------*/
1084 void
usb_bdma_post_sync(struct usb_xfer * xfer)1085 usb_bdma_post_sync(struct usb_xfer *xfer)
1086 {
1087 	struct usb_page_cache *pc;
1088 	usb_frcount_t nframes;
1089 
1090 	if (xfer->flags_int.isochronous_xfr) {
1091 		/* only one frame buffer */
1092 		nframes = 1;
1093 	} else {
1094 		/* can be multiple frame buffers */
1095 		nframes = xfer->nframes;
1096 	}
1097 
1098 	pc = xfer->frbuffers;
1099 
1100 	while (nframes--) {
1101 		if (pc->isread) {
1102 			usb_pc_cpu_invalidate(pc);
1103 		}
1104 		pc++;
1105 	}
1106 }
1107 
1108 #endif
1109