Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Dec 2007 12:00:52 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 130003 for review
Message-ID:  <200712021200.lB2C0qbe051196@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=130003

Change 130003 by hselasky@hselasky_laptop001 on 2007/12/02 12:00:36

	
	Enable zero-copy for the Linux USB API by default.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_compat_linux.c#13 edit

Differences ...

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

@@ -761,6 +761,16 @@
 		cfg[0].bufsize = 0;	/* use wMaxPacketSize */
 		cfg[0].frames = usb_max_isoc_frames(dev);
 		cfg[0].flags.proxy_buffer = 1;
+#if 0
+		/*
+		 * The Linux USB API allows non back-to-back
+		 * isochronous frames which we do not support. If the
+		 * isochronous frames are not back-to-back we need to
+		 * do a copy, and then we need a buffer for
+		 * that. Enable this at your own risk.
+		 */
+		cfg[0].flags.ext_buffer = 1;
+#endif
 		cfg[0].flags.short_xfer_ok = 1;
 
 		bcopy(cfg + 0, cfg + 1, sizeof(*cfg));
@@ -768,8 +778,7 @@
 		/* Allocate and setup two generic FreeBSD USB transfers */
 
 		if (usbd_transfer_setup(dev->bsd_udev, uhe->bsd_iface_index,
-		    uhe->bsd_xfer, cfg, 2, uhe,
-		    &usb_global_lock)) {
+		    uhe->bsd_xfer, cfg, 2, uhe, &usb_global_lock)) {
 			return -EINVAL;
 		}
 	} else {
@@ -784,12 +793,12 @@
 		cfg[0].direction = addr & (UE_DIR_OUT | UE_DIR_IN);
 		cfg[0].callback = &usb_linux_non_isoc_callback;
 		cfg[0].bufsize = bufsize;
+		cfg[0].flags.ext_buffer = 1;	/* enable zero-copy */
 		cfg[0].flags.proxy_buffer = 1;
 		cfg[0].flags.short_xfer_ok = 1;
 
 		if (usbd_transfer_setup(dev->bsd_udev, uhe->bsd_iface_index,
-		    uhe->bsd_xfer, cfg, 1, uhe,
-		    &usb_global_lock)) {
+		    uhe->bsd_xfer, cfg, 1, uhe, &usb_global_lock)) {
 			return -EINVAL;
 		}
 	}
@@ -1286,9 +1295,11 @@
 				uipd = urb->iso_frame_desc + x;
 				uipd->actual_length = xfer->frlengths[x];
 				uipd->status = 0;
-				usbd_copy_out(xfer->frbuffers + 0, offset,
-				    ((uint8_t *)(urb->transfer_buffer)) + uipd->offset,
-				    uipd->actual_length);
+				if (!xfer->flags.ext_buffer) {
+					usbd_copy_out(xfer->frbuffers + 0, offset,
+					    USBD_ADD_BYTES(urb->transfer_buffer,
+					    uipd->offset), uipd->actual_length);
+				}
 				offset += max_frame;
 			}
 		} else {
@@ -1354,9 +1365,11 @@
 			for (x = 0; x < urb->number_of_packets; x++) {
 				uipd = urb->iso_frame_desc + x;
 				xfer->frlengths[x] = uipd->length;
-				usbd_copy_in(xfer->frbuffers + 0, offset,
-				    ((uint8_t *)(urb->transfer_buffer)) + uipd->offset,
-				    uipd->length);
+				if (!xfer->flags.ext_buffer) {
+					usbd_copy_in(xfer->frbuffers + 0, offset,
+					    USBD_ADD_BYTES(urb->transfer_buffer,
+					    uipd->offset), uipd->length);
+				}
 				offset += uipd->length;
 			}
 		} else {
@@ -1376,6 +1389,11 @@
 			}
 		}
 
+		if (xfer->flags.ext_buffer) {
+			/* set virtual address to load */
+			usbd_set_frame_data(xfer,
+			    urb->transfer_buffer, 0);
+		}
 		xfer->priv_fifo = urb;
 		xfer->flags.force_short_xfer = 0;
 		xfer->timeout = urb->timeout;
@@ -1441,7 +1459,7 @@
 
 			xfer->frlengths[0] = 0;
 		}
-		if (urb->bsd_isread) {
+		if (urb->bsd_isread && (!xfer->flags.ext_buffer)) {
 			/* copy in data with regard to the URB */
 			usbd_copy_out(xfer->frbuffers + data_frame, 0,
 			    urb->bsd_data_ptr, xfer->frlengths[data_frame]);
@@ -1495,8 +1513,14 @@
 		         * USB control transfers need special handling.
 		         * First copy in the header, then copy in data!
 		         */
-			usbd_copy_in(xfer->frbuffers + 0, 0,
-			    urb->setup_packet, REQ_SIZE);
+			if (!xfer->flags.ext_buffer) {
+				usbd_copy_in(xfer->frbuffers + 0, 0,
+				    urb->setup_packet, REQ_SIZE);
+			} else {
+				/* set virtual address to load */
+				usbd_set_frame_data(xfer,
+				    urb->setup_packet, 0);
+			}
 
 			xfer->frlengths[0] = REQ_SIZE;
 
@@ -1528,7 +1552,11 @@
 		}
 		/* check if we need to copy in data */
 
-		if (!(urb->bsd_isread)) {
+		if (xfer->flags.ext_buffer) {
+			/* set virtual address to load */
+			usbd_set_frame_data(xfer, urb->bsd_data_ptr,
+			    data_frame);
+		} else if (!urb->bsd_isread) {
 			/* copy out data with regard to the URB */
 			usbd_copy_in(xfer->frbuffers + data_frame, 0,
 			    urb->bsd_data_ptr, max_bulk);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712021200.lB2C0qbe051196>