PERFORCE change 129926 for review

Hans Petter Selasky hselasky at FreeBSD.org
Sat Dec 1 16:16:51 PST 2007


http://perforce.freebsd.org/chv.cgi?CH=129926

Change 129926 by hselasky at hselasky_laptop001 on 2007/12/02 00:16:43

	
	This commit finishes change 129799 with regard to
	"usb_subr.c".
	
	The "page_cache" now holds the pointer to
	the virtual buffer and "usbd_get_page" has
	been updated to reflect the latest changes.
	
	Factored out most CPU cache flush / invalidate
	calls.
	
	There is a new set of functions added that abstract
	the BUS-DMA interface towards USB. The old BUS-DMA
	abstraction functions were removed. The NetBSD
	specific part of "usb_subr.c" has not been updated
	with regard to this. TODO.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#57 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#57 (text+ko) ====

@@ -1783,6 +1783,8 @@
 {
 	struct usbd_page *page;
 
+	res->buffer = USBD_ADD_BYTES(pc->buffer, offset);
+
 	offset += pc->page_offset_buf;
 
 	if ((offset >= pc->page_offset_end) ||
@@ -1793,7 +1795,6 @@
 		res->length = 0;
 		res->buffer = NULL;
 		res->physaddr = 0;
-		res->page = NULL;
 		return;
 	}
 	/* compute destination page */
@@ -1805,9 +1806,7 @@
 	offset %= USB_PAGE_SIZE;
 
 	res->length = USB_PAGE_SIZE - offset;
-	res->buffer = USBD_ADD_BYTES(page->buffer, offset);
 	res->physaddr = page->physaddr + offset;
-	res->page = page;
 	return;
 }
 
@@ -1831,15 +1830,11 @@
 		if (res.length > len) {
 			res.length = len;
 		}
-		usbd_page_cpu_invalidate(res.page);
-
 		bcopy(ptr, res.buffer, res.length);
 
-		usbd_page_cpu_flush(res.page);
-
 		offset += res.length;
 		len -= res.length;
-		ptr = ((const uint8_t *)ptr) + res.length;
+		ptr = USBD_ADD_BYTES(ptr, res.length);
 	}
 	return;
 }
@@ -1898,16 +1893,12 @@
 		if (res.length > len) {
 			res.length = len;
 		}
-		usbd_page_cpu_invalidate(res.page);
-
 		/*
 		 * "uiomove()" can sleep so one needs to make a wrapper,
 		 * exiting the mutex and checking things
 		 */
 		error = uiomove(res.buffer, len, uio);
 
-		usbd_page_cpu_flush(res.page);
-
 		if (error) {
 			break;
 		}
@@ -1937,12 +1928,8 @@
 		if (res.length > len) {
 			res.length = len;
 		}
-		usbd_page_cpu_invalidate(res.page);
-
 		bcopy(res.buffer, ptr, res.length);
 
-		usbd_page_cpu_flush(res.page);
-
 		offset += res.length;
 		len -= res.length;
 		ptr = USBD_ADD_BYTES(ptr, res.length);
@@ -1969,480 +1956,283 @@
 		if (res.length > len) {
 			res.length = len;
 		}
-		usbd_page_cpu_invalidate(res.page);
-
 		bzero(res.buffer, res.length);
 
-		usbd_page_cpu_flush(res.page);
-
 		offset += res.length;
 		len -= res.length;
 	}
 	return;
 }
 
+#ifdef __FreeBSD__
+
 /*------------------------------------------------------------------------*
- *  usbd_page_alloc - allocate multiple DMA-able memory pages
+ *	usbd_pc_tag_create - allocate a DMA tag
  *
- * Returns:
- *   1: failure
- *   0: success
+ * NOTE: If the "align" parameter has a value of 1 the DMA-tag will
+ * allow multi-segment mappings. Else all mappings are single-segment.
  *------------------------------------------------------------------------*/
-uint8_t
-usbd_page_alloc(bus_dma_tag_t tag, struct usbd_page *page,
-    uint32_t npages)
+bus_dma_tag_t
+usbd_dma_tag_create(bus_dma_tag_t tag_parent, uint32_t size, uint32_t align)
 {
-	uint32_t x;
-	void *ptr;
+	bus_dma_tag_t tag;
 
-	for (x = 0; x < npages; x++) {
-
-repeat:
-
-		ptr = usbd_mem_alloc_sub(tag, page + x,
-		    USB_PAGE_SIZE, USB_PAGE_SIZE);
-		if (ptr == NULL) {
-
-			while (x--) {
-				usbd_mem_free_sub(page + x);
-			}
-			return (1);	/* failure */
-		} else {
-
-			if ((page + x)->physaddr == 0) {
-
-				/*
-				 * at least the OHCI controller gives
-				 * special meaning to physaddr == 0, so
-				 * discard that page if it gets here:
-				 */
-				printf("%s:%d: Discarded memory "
-				    "page with physaddr=0!\n",
-				    __FUNCTION__, __LINE__);
-				goto repeat;
-			}
-		}
+	if (bus_dma_tag_create
+	    ( /* parent    */ tag_parent,
+	     /* alignment */ align,
+	     /* boundary  */ 0,
+	     /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
+	     /* highaddr  */ BUS_SPACE_MAXADDR,
+	     /* filter    */ NULL,
+	     /* filterarg */ NULL,
+	     /* maxsize   */ size,
+	     /* nsegments */ (align == 1) ?
+	    (2 + (size / USB_PAGE_SIZE)) : 1,
+	     /* maxsegsz  */ USB_PAGE_SIZE,
+	     /* flags     */ 0,
+	     /* lock      */ NULL,
+	     /* */ NULL,
+	    &tag)) {
+		tag = NULL;
 	}
-	return (0);			/* success */
+	return (tag);
 }
 
 /*------------------------------------------------------------------------*
- *  usbd_page_free - free multiple DMA-able memory pages
+ *	usbd_dma_tag_free - free a DMA tag
  *------------------------------------------------------------------------*/
 void
-usbd_page_free(struct usbd_page *page, uint32_t npages)
+usbd_dma_tag_destroy(bus_dma_tag_t tag)
 {
-	while (npages--) {
-		usbd_mem_free_sub(page + npages);
-	}
+	bus_dma_tag_destroy(tag);
 	return;
 }
 
 /*------------------------------------------------------------------------*
- *  usbd_page_cache_init
+ *	usbd_pc_alloc_mem_cb
  *------------------------------------------------------------------------*/
-void
-usbd_page_cache_init(struct usbd_page_cache *pc, struct usbd_page *page_ptr,
-    uint32_t offset, uint32_t size)
+static void
+usbd_pc_alloc_mem_cb(void *arg, bus_dma_segment_t *segs,
+    int nseg, int error)
 {
-	pc->page_start = page_ptr + (offset / USB_PAGE_SIZE);
-	pc->page_offset_buf = (offset % USB_PAGE_SIZE);
-	pc->page_offset_end = pc->page_offset_buf + size;
-	return;
-}
+	struct usbd_xfer *xfer;
+	struct usbd_page_cache *pc;
+	struct usbd_page *pg;
+	uint32_t rem;
 
-/*------------------------------------------------------------------------*
- *  usbd_page_fit_obj - fit object function
- *------------------------------------------------------------------------*/
-uint32_t
-usbd_page_fit_obj(uint32_t size, uint32_t obj_len)
-{
-	uint32_t adj;
+	xfer = pc->xfer;
 
-	if (obj_len > (USB_PAGE_SIZE - (size & (USB_PAGE_SIZE - 1)))) {
+	/* XXX sometimes recursive locking here */
 
-		if (obj_len > USB_PAGE_SIZE) {
-			panic("%s:%d Too large object, %d bytes, will "
-			    "not fit on a USB page, %d bytes!\n",
-			    __FUNCTION__, __LINE__, obj_len,
-			    (int32_t)USB_PAGE_SIZE);
+	if (error) {
+		if (xfer) {
+			mtx_lock(xfer->priv_mtx);
+			xfer->usb_root->dma_error = 1;
+			usbd_bdma_done_event(xfer->usb_root);
+			mtx_unlock(xfer->priv_mtx);
 		}
-		/*
-		 * adjust offset to the beginning of the next page:
-		 */
-		adj = ((-size) & (USB_PAGE_SIZE - 1));
-	} else {
-		adj = 0;
+		return;
 	}
-	return (adj);
-}
+	pc = arg;
+	pg = pc->page_start;
+	pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
+	rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
+	pc->page_offset_buf = rem;
+	pc->page_offset_end += rem;
+	nseg--;
 
-/*------------------------------------------------------------------------*
- *  usbd_mem_alloc - allocate DMA-able memory
- *------------------------------------------------------------------------*/
-void   *
-usbd_mem_alloc(bus_dma_tag_t parent, struct usbd_page *page, uint32_t size,
-    uint8_t align_power)
-{
-	bus_dma_tag_t tag;
-	uint32_t alignment = (1 << align_power);
-	void *ptr;
-
-	tag = usbd_dma_tag_alloc(parent, size, alignment, size, 1);
-
-	if (tag == NULL) {
-		return (NULL);
+	while (nseg > 0) {
+		nseg--;
+		segs++;
+		pg++;
+		pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
 	}
-	ptr = usbd_mem_alloc_sub(tag, page, size, alignment);
 
-	if (ptr == NULL) {
-		usbd_dma_tag_free(tag);
-		return (NULL);
+	if (xfer) {
+		mtx_lock(xfer->priv_mtx);
+		usbd_bdma_done_event(xfer->usb_root);
+		mtx_unlock(xfer->priv_mtx);
 	}
-	return (ptr);
-}
-
-/*------------------------------------------------------------------------*
- *  usbd_mem_free - free DMA-able memory
- *------------------------------------------------------------------------*/
-void
-usbd_mem_free(struct usbd_page *page)
-{
-	bus_dma_tag_t tag;
-
-	tag = page->tag;
-
-	usbd_mem_free_sub(page);
-
-	usbd_dma_tag_free(tag);
-
 	return;
 }
 
-#ifdef __FreeBSD__
 /*------------------------------------------------------------------------*
- *  bus_dmamap_load_callback
+ *	usbd_pc_alloc_mem - allocate DMA'able memory
+ *
+ * Returns:
+ *    0: Success
+ * Else: Failure
  *------------------------------------------------------------------------*/
-static void
-bus_dmamap_load_callback(void *arg, bus_dma_segment_t *segs,
-    int nseg, int error)
-{
-	__KASSERT(nseg == 1, ("Invalid number of segments, %d!\n", nseg));
-	__KASSERT(error == 0, ("Could not load memory into DMA!\n"));
-
-	*((bus_size_t *)arg) = segs->ds_addr;
-
-	return;
-}
-
-/*------------------------------------------------------------------------*
- *  usbd_dma_tag_alloc - allocate a bus-DMA tag
- *------------------------------------------------------------------------*/
-bus_dma_tag_t
-usbd_dma_tag_alloc(bus_dma_tag_t parent, uint32_t seg_size,
-    uint32_t alignment, uint32_t max_size, uint8_t single_seg)
+uint8_t
+usbd_pc_alloc_mem(bus_dma_tag_t parent_tag, struct usbd_dma_tag *utag,
+    struct usbd_page_cache *pc, struct usbd_page *pg, uint32_t size,
+    uint32_t align, uint8_t utag_max)
 {
 	bus_dma_tag_t tag;
-
-	if (bus_dma_tag_create
-	    ( /* parent    */ parent,
-	     /* alignment */ alignment,
-	     /* boundary  */ 0,
-	     /* lowaddr   */ BUS_SPACE_MAXADDR_32BIT,
-	     /* highaddr  */ BUS_SPACE_MAXADDR,
-	     /* filter    */ NULL,
-	     /* filterarg */ NULL,
-	     /* maxsize   */ max_size,
-	     /* nsegments */ (single_seg ? 1 : ((16 * 1024 * 1024) / USB_PAGE_SIZE)),
-	     /* maxsegsz  */ seg_size,
-	     /* flags     */ 0,
-	     /* lock      */ NULL,
-	     /* */ NULL,
-	    &tag)) {
-		tag = NULL;
-	}
-	return (tag);
-}
-
-/*------------------------------------------------------------------------*
- *  usbd_dma_tag_free - free a bus-DMA tag
- *------------------------------------------------------------------------*/
-void
-usbd_dma_tag_free(bus_dma_tag_t tag)
-{
-	bus_dma_tag_destroy(tag);
-	return;
-}
-
-/*------------------------------------------------------------------------*
- *  usbd_mem_alloc_sub - allocate DMA-able memory
- *------------------------------------------------------------------------*/
-void   *
-usbd_mem_alloc_sub(bus_dma_tag_t tag, struct usbd_page *page,
-    uint32_t size, uint32_t alignment)
-{
 	bus_dmamap_t map;
-	bus_size_t physaddr = 0;
 	void *ptr;
 
+	/* get the correct DMA tag */
+	tag = usbd_dma_tag_setup(parent_tag, utag, size, align, utag_max);
+	if (tag == NULL) {
+		goto error;
+	}
+	/* allocate memory */
 	if (bus_dmamem_alloc
 	    (tag, &ptr, (BUS_DMA_WAITOK | BUS_DMA_COHERENT), &map)) {
-		return (NULL);
+		goto error;
 	}
+	/* setup page cache */
+	pc->buffer = ptr;
+	pc->page_start = pg;
+	pc->page_offset_buf = 0;
+	pc->page_offset_end = size;
+	pc->map = map;
+	pc->tag = tag;
+
+	/* load memory into DMA */
 	if (bus_dmamap_load
-	    (tag, map, ptr, size, &bus_dmamap_load_callback,
-	    &physaddr, (BUS_DMA_WAITOK | BUS_DMA_COHERENT))) {
+	    (tag, map, ptr, size, &usbd_pc_alloc_mem_cb,
+	    pc, (BUS_DMA_WAITOK | BUS_DMA_COHERENT))) {
 		bus_dmamem_free(tag, ptr, map);
-		return (NULL);
+		goto error;
 	}
-	page->tag = tag;
-	page->map = map;
-	page->physaddr = physaddr;
-	page->buffer = ptr;
-	page->length = size;
+	bzero(ptr, size);
+
+	usbd_pc_cpu_flush(pc);
 
-	usbd_page_cpu_invalidate(page);
-	bzero(ptr, size);
-	usbd_page_cpu_flush(page);
+	return (0);
 
-#ifdef USB_DEBUG
-	if (usbdebug > 14) {
-		printf("%s: %p, %d bytes, phys=%p\n",
-		    __FUNCTION__, ptr, size,
-		    ((char *)0) + physaddr);
-	}
-#endif
-	return (ptr);
+error:
+	/* reset most of the page cache */
+	pc->buffer = NULL;
+	pc->page_start = NULL;
+	pc->page_offset_buf = 0;
+	pc->page_offset_end = 0;
+	pc->map = NULL;
+	pc->tag = NULL;
+	return (1);
 }
 
 /*------------------------------------------------------------------------*
- *  usbd_mem_free_sub - free DMA-able memory
+ *	usbd_pc_free_mem - free DMA memory
+ *
+ * This function is NULL safe.
  *------------------------------------------------------------------------*/
 void
-usbd_mem_free_sub(struct usbd_page *page)
+usbd_pc_free_mem(struct usbd_page_cache *pc)
 {
-	/*
-	 * NOTE: make a copy of "tag", "map", and "buffer" in case "page" is
-	 * part of the allocated memory:
-	 */
-	bus_dma_tag_t tag = page->tag;
-	bus_dmamap_t map = page->map;
-	void *ptr = page->buffer;
+	if (pc && pc->buffer) {
 
-	bus_dmamap_unload(tag, map);
+		bus_dmamap_unload(pc->tag, pc->map);
 
-	bus_dmamem_free(tag, ptr, map);
+		bus_dmamem_free(pc->tag, pc->buffer, pc->map);
 
-#ifdef USB_DEBUG
-	if (usbdebug > 14) {
-		printf("%s: %p\n",
-		    __FUNCTION__, ptr);
+		pc->buffer = NULL;
 	}
-#endif
 	return;
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_dma_load_setup - allocate BUS-DMA maps
+ *	usbd_pc_load_mem - load virtual memory into DMA
  *------------------------------------------------------------------------*/
 void
-usbd_dma_load_setup(struct usbd_setup_params *parm)
+usbd_pc_load_mem(struct usbd_page_cache *pc, uint32_t size)
 {
-	struct usbd_xfer *xfer;
-
-	if (parm->buf == NULL) {
+	/* sanity check */
+	if (pc->xfer == NULL) {
+		panic("This page cache is not loadable!\n");
 		return;
 	}
-	xfer = parm->curr_xfer;
+	/* setup page cache */
+	pc->page_offset_buf = 0;
+	pc->page_offset_end = size;
+
+	if (size > 0) {
 
-	if (bus_dmamap_create(xfer->udev->bus->dma_tag_1b, 0,
-	    &(xfer->dma_tx_map))) {
-		xfer->dma_tx_map = NULL;
-		parm->err = USBD_NOMEM;
-		return;
-	}
-	if (bus_dmamap_create(xfer->udev->bus->dma_tag_1b, 0,
-	    &(xfer->dma_rx_map))) {
-		xfer->dma_rx_map = NULL;
-		parm->err = USBD_NOMEM;
-		return;
-	}
-	return;
-}
+		pc->xfer->usb_root->dma_refcount++;
 
-/*------------------------------------------------------------------------*
- *	usbd_dma_load_unsetup - release BUS-DMA maps
- *------------------------------------------------------------------------*/
-void
-usbd_dma_load_unsetup(struct usbd_xfer *xfer)
-{
-	if (xfer->dma_tx_map) {
-		bus_dmamap_destroy(xfer->udev->bus->dma_tag_1b,
-		    xfer->dma_tx_map);
+		/* try to load memory into DMA */
+		if (bus_dmamap_load(
+		    pc->tag, pc->map, pc->buffer, size,
+		    &usbd_pc_alloc_mem_cb, pc, 0)) {
+		}
 	}
-	if (xfer->dma_rx_map) {
-		bus_dmamap_destroy(xfer->udev->bus->dma_tag_1b,
-		    xfer->dma_rx_map);
-	}
 	return;
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_dma_load_pre_sync - flush CPU cache, if any
+ *	usbd_pc_cpu_invalidate - invalidate CPU cache
  *------------------------------------------------------------------------*/
 void
-usbd_dma_load_pre_sync(struct usbd_xfer *xfer)
+usbd_pc_cpu_invalidate(struct usbd_page_cache *pc)
 {
-	bus_dmamap_sync(xfer->udev->bus->dma_tag_1b, xfer->dma_tx_map,
-	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-	return;
-}
-
-/*------------------------------------------------------------------------*
- *	usbd_dma_load_post_sync - invalidate CPU cache, if any
- *------------------------------------------------------------------------*/
-void
-usbd_dma_load_post_sync(struct usbd_xfer *xfer)
-{
-	bus_dmamap_sync(xfer->udev->bus->dma_tag_1b, xfer->dma_rx_map,
+	bus_dmamap_sync(pc->tag, pc->map,
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 	return;
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_page_cpu_invalidate - invalidate CPU cache
+ *	usbd_pc_cpu_flush - flush CPU cache
  *------------------------------------------------------------------------*/
 void
-usbd_page_cpu_invalidate(struct usbd_page *page)
+usbd_pc_cpu_flush(struct usbd_page_cache *pc)
 {
-	bus_dmamap_sync(page->tag, page->map,
-	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
-	return;
-}
-
-/*------------------------------------------------------------------------*
- *	usbd_page_cpu_flush - flush CPU cache
- *------------------------------------------------------------------------*/
-void
-usbd_page_cpu_flush(struct usbd_page *page)
-{
-	bus_dmamap_sync(page->tag, page->map,
+	bus_dmamap_sync(pc->tag, pc->map,
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	return;
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_dma_load_mem_callback - internal callback
+ *	usbd_pc_dmamap_create
+ *
+ * Returns:
+ *    0: Success
+ * Else: Failure
  *------------------------------------------------------------------------*/
-static void
-usbd_dma_load_mem_callback(void *arg, bus_dma_segment_t *segs,
-    int nseg, int error)
+uint8_t
+usbd_pc_dmamap_create(struct usbd_page_cache *pc, uint32_t size)
 {
-	struct usbd_page_cache *pc;
-	struct usbd_xfer *xfer;
-	struct usbd_page *pg;
-	uint32_t rem;
+	struct usbd_memory_info *info;
+	bus_dma_tag_t tag;
 
-	pc = arg;
-	xfer = pc->p_xfer;
+	/* sanity check */
+	if (pc->xfer == NULL) {
+		goto error;
+	}
+	info = pc->xfer->usb_root;
+	tag = pc->xfer->udev->bus->dma_tag_parent;
 
-	/* XXX sometimes recursive locking here */
-
-	mtx_lock(xfer->priv_mtx);
-
-	if (error) {
-		printf("%s: %s: error=%d\n",
-		    __FILE__, __FUNCTION__, error);
-
-		xfer->flags_int.bdma_error = 1;
-	} else {
-		__KASSERT(nseg > 0, ("Invalid number of segments!\n"));
-
-		pg = pc->page_start;
-		rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
-
-		pc->page_offset_buf += rem;
-		pc->page_offset_end += rem;
-
-		pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
-
-		while (1) {
-
-			if (--nseg == 0) {
-				break;
-			}
-			pg++;
-			segs++;
-			pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
-		}
+	tag = usbd_dma_tag_setup(tag, info->dma_tag_p,
+	    size, 1, info->dma_tag_max);
+	if (tag == NULL) {
+		goto error;
+	}
+	if (bus_dmamap_create(tag, 0, &(pc->map))) {
+		goto error;
 	}
+	pc->tag = tag;
+	return 0;			/* success */
 
-	usbd_bdma_done_event(xfer);
-
-	mtx_unlock(xfer->priv_mtx);
-	return;
+error:
+	pc->map = NULL;
+	pc->tag = NULL;
+	return 1;			/* failure */
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_dma_load_mem - load DMA memory if any
+ *	usbd_pc_dmamap_destroy
+ *
+ * This function is NULL safe.
  *------------------------------------------------------------------------*/
 void
-usbd_dma_load_mem(struct usbd_xfer *xfer, struct usbd_dma_load_mem_info *info)
+usbd_pc_dmamap_destroy(struct usbd_page_cache *pc)
 {
-	struct usbd_page_cache *pc;
-	struct usbd_page *pg;
-	bus_dma_tag_t dma_tag;
-	bus_dmamap_t dma_map;
-	uint32_t npg;
-	int error;
-
-	pc = info->page_cache;
-
-	if (info->frame_length == 0) {
-		/* not used */
-		pc->page_start = NULL;
-		pc->page_offset_buf = 0;
-		pc->page_offset_end = 0;
-		return;
-	}
-	/* select the one byte alignment DMA tag */
-
-	dma_tag = xfer->udev->bus->dma_tag_1b;
-	if (pc->isread) {
-		dma_map = xfer->dma_rx_map;
-	} else {
-		dma_map = xfer->dma_tx_map;
+	if (pc && pc->tag) {
+		bus_dmamap_destroy(pc->tag, pc->map);
+		pc->tag = NULL;
+		pc->map = NULL;
 	}
-
-	/* increment refcount */
-
-	xfer->dma_refcount++;
-
-	/* initialize the "usbd_page_cache" structure */
-
-	pc->page_start = info->page_ptr;
-	pc->page_offset_buf = 0;
-	pc->page_offset_end = info->frame_length;
-
-	/* initialize the "usbd_page" structure */
-
-	npg = (info->frame_length / USB_PAGE_SIZE) + 2;
-	pg = info->page_ptr;
-
-	while (npg--) {
-		pg->tag = dma_tag;
-		pg->map = dma_map;
-		pg->length = USB_PAGE_SIZE;
-		pg++;
-	}
-
-	/* update "page_ptr" to the next pointer value */
-
-	info->page_ptr = pg;
-
-	error = bus_dmamap_load(dma_tag, dma_map, pc->p_buffer,
-	    info->frame_length, usbd_dma_load_mem_callback, pc, 0);
-
 	return;
 }
 
@@ -2496,9 +2286,7 @@
 	page->length = size;
 
 	usbd_page_cpu_invalidate(page);
-
 	bzero(ptr, size);
-
 	usbd_page_cpu_flush(page);
 
 #ifdef USB_DEBUG
@@ -2547,23 +2335,31 @@
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_page_cpu_invalidate - invalidate CPU cache
+ *	usbd_pc_cpu_invalidate - invalidate CPU cache
  *------------------------------------------------------------------------*/
 void
-usbd_page_cpu_invalidate(struct usbd_page *page)
+usbd_pc_cpu_invalidate(struct usbd_page_cache *pc)
 {
-	bus_dmamap_sync(page->tag, page->map, 0, page->length,
+	uint32_t len;
+
+	len = pc->page_offset_end - pc->page_offset_buf;
+
+	bus_dmamap_sync(pc->tag, pc->map, 0, len,
 	    BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 	return;
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_page_cpu_flush - flush CPU cache
+ *	usbd_pc_cpu_flush - flush CPU cache
  *------------------------------------------------------------------------*/
 void
-usbd_page_cpu_flush(struct usbd_page *page)
+usbd_pc_cpu_flush(struct usbd_page_cache *pc)
 {
-	bus_dmamap_sync(page->tag, page->map, 0, page->length,
+	uint32_t len;
+
+	len = pc->page_offset_end - pc->page_offset_buf;
+
+	bus_dmamap_sync(page->tag, page->map, 0, len,
 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 	return;
 }
@@ -2571,59 +2367,6 @@
 #endif
 
 /*------------------------------------------------------------------------*
- *	usbd_pio_load_mem - load virtual memory if any
- *------------------------------------------------------------------------*/
-void
-usbd_pio_load_mem(struct usbd_xfer *xfer, struct usbd_dma_load_mem_info *info)
-{
-	struct usbd_page_cache *pc;
-	struct usbd_page *pg;
-	uint32_t npg;
-	uint32_t rem;
-	uint8_t *ptr;
-
-	pc = info->page_cache;
-	pg = info->page_ptr;
-
-	if (info->frame_length == 0) {
-		/* not used */
-		pc->page_start = NULL;
-		pc->page_offset_buf = 0;
-		pc->page_offset_end = 0;
-		return;
-	}
-	ptr = pc->p_buffer;
-	rem = POINTER_TO_UNSIGNED(ptr) & (USB_PAGE_SIZE - 1);
-	ptr -= rem;			/* page align */
-	info->frame_length += rem;	/* adjust */
-
-	pc->page_start = pg;
-	pc->page_offset_buf = rem;
-	pc->page_offset_end = info->frame_length;
-
-	npg = (info->frame_length + (USB_PAGE_SIZE - 1)) / USB_PAGE_SIZE;
-
-	while (npg--) {
-
-		/*
-	         * NOTE: We only setup the fields
-	         * we need for PIO in "struct usbd_page"
-	         */
-		pg->buffer = ptr;
-		pg->length = USB_PAGE_SIZE;
-
-		ptr += USB_PAGE_SIZE;
-		pg++;
-	}
-
-	/* update page pointer */
-
-	info->page_ptr = pg;
-
-	return;
-}
-
-/*------------------------------------------------------------------------*
  *  usbd_make_str_desc - convert an ASCII string into a UNICODE string
  *------------------------------------------------------------------------*/
 uint8_t
@@ -3121,64 +2864,172 @@
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_bus_mem_setup - factored out code
- *
- * Return:
- *    0: Success
- * Else: Failure
+ *	usbd_bus_tag_setup - factored out code
  *------------------------------------------------------------------------*/
-uint8_t
-usbd_bus_mem_setup(struct usbd_bus *bus, bus_dma_tag_t parent_tag,
-    uint32_t hw_mem_size, uint8_t hw_addr_lines, uint8_t hw_align_power)
+bus_dma_tag_t
+usbd_dma_tag_setup(bus_dma_tag_t tag_parent, struct usbd_dma_tag *udt,
+    uint32_t size, uint32_t align, uint8_t nudt)
 {
+	__KASSERT(align > 0, ("Invalid parameter align = 0!\n"));
+	__KASSERT(size > 0, ("Invalid parameter size = 0!\n"));
+
+	while (nudt--) {
 
-	if (hw_mem_size > 0) {
+		if (udt->align == 0) {
+			udt->tag =
+			    usbd_dma_tag_create(tag_parent, size, align);
+			if (udt->tag == NULL) {
+				return (NULL);
+			}
+			udt->align = align;
+			udt->size = size;
+			return (udt->tag);
+		}
+		if ((udt->align == align) && (udt->size == size)) {
+			return (udt->tag);
+		}
+		udt++;
+	}
+	return (NULL);
+}
 
-		bus->hw_ptr.data =
-		usbd_mem_alloc(parent_tag, &(bus->hw_page),
-		    hw_mem_size, hw_align_power);
+/*------------------------------------------------------------------------*
+ *	usbd_bus_tag_unsetup - factored out code
+ *------------------------------------------------------------------------*/
+void
+usbd_dma_tag_unsetup(struct usbd_dma_tag *udt, uint8_t nudt)
+{
+	while (nudt--) {
 
-		if (bus->hw_ptr.data == NULL) {
-			goto error;
+		if (udt->align) {
+			usbd_dma_tag_destroy(udt->tag);
+			udt->align = 0;
 		}
+		udt++;
 	}
-	bus->dma_tag_1b =
-	    usbd_dma_tag_alloc(parent_tag, USB_PAGE_SIZE, 1, 0 - 1, 0);
+	return;
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_bus_mem_flush_all_cb
+ *------------------------------------------------------------------------*/
+static void
+usbd_bus_mem_flush_all_cb(struct usbd_bus *bus, struct usbd_page_cache *pc,
+    struct usbd_page *pg, uint32_t size, uint32_t align)
+{
+	usbd_pc_cpu_flush(pc);
+	return;
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_bus_mem_flush_all - factored out code
+ *------------------------------------------------------------------------*/
+void
+usbd_bus_mem_flush_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb)
+{
+	cb(bus, &usbd_bus_mem_flush_all_cb);
+	return;
+}
 
-	if (bus->dma_tag_1b == NULL) {
-		goto error;
+/*------------------------------------------------------------------------*
+ *	usbd_bus_mem_alloc_all_cb
+ *------------------------------------------------------------------------*/
+static void
+usbd_bus_mem_alloc_all_cb(struct usbd_bus *bus, struct usbd_page_cache *pc,
+    struct usbd_page *pg, uint32_t size, uint32_t align)
+{
+	if (usbd_pc_alloc_mem(bus->dma_tag_parent,
+	    bus->dma_tags, pc, pg, size, align,
+	    USB_BUS_DMA_TAG_MAX)) {
+		bus->alloc_failed = 1;
 	}
-	bus->dma_tag_ps =
-	    usbd_dma_tag_alloc(parent_tag, USB_PAGE_SIZE,
-	    USB_PAGE_SIZE, USB_PAGE_SIZE, 1);
+	return;
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_bus_mem_alloc_all - factored out code
+ *
+ * Returns:
+ *    0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+uint8_t
+usbd_bus_mem_alloc_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb)
+{
+	bus->alloc_failed = 0;
+
+	cb(bus, &usbd_bus_mem_alloc_all_cb);
 
-	if (bus->dma_tag_ps == NULL) {
-		goto error;
+	if (bus->alloc_failed) {
+		usbd_bus_mem_free_all(bus, cb);
 	}
-	return (0);
+	return (bus->alloc_failed);
+}
 
-error:
-	usbd_bus_mem_unsetup(bus);
-	return (1);
+/*------------------------------------------------------------------------*
+ *	usbd_bus_mem_free_all_cb
+ *------------------------------------------------------------------------*/
+static void
+usbd_bus_mem_free_all_cb(struct usbd_bus *bus, struct usbd_page_cache *pc,
+    struct usbd_page *pg, uint32_t size, uint32_t align)
+{
+	usbd_pc_free_mem(pc);

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list