svn commit: r195121 - in head/sys/dev/usb: . controller net storage

Andrew Thompson thompsa at FreeBSD.org
Sat Jun 27 21:23:31 UTC 2009


Author: thompsa
Date: Sat Jun 27 21:23:30 2009
New Revision: 195121
URL: http://svn.freebsd.org/changeset/base/195121

Log:
  Sync to p4
  
   - Add support for devices that handle set and clear stall in hardware.
   - Add missing get timestamp function
   - Add more xfer flags
  
  Submitted by:	Hans Petter Selasky
  Approved by:	re (kib)

Modified:
  head/sys/dev/usb/controller/at91dci.c
  head/sys/dev/usb/controller/atmegadci.c
  head/sys/dev/usb/controller/avr32dci.c
  head/sys/dev/usb/controller/musb_otg.c
  head/sys/dev/usb/controller/uss820dci.c
  head/sys/dev/usb/net/if_cdce.c
  head/sys/dev/usb/storage/ustorage_fs.c
  head/sys/dev/usb/usb_controller.h
  head/sys/dev/usb/usb_device.c
  head/sys/dev/usb/usb_handle_request.c
  head/sys/dev/usb/usb_if.m
  head/sys/dev/usb/usb_transfer.c
  head/sys/dev/usb/usbdi.h

Modified: head/sys/dev/usb/controller/at91dci.c
==============================================================================
--- head/sys/dev/usb/controller/at91dci.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/controller/at91dci.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -1227,7 +1227,7 @@ at91dci_device_done(struct usb_xfer *xfe
 
 static void
 at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct at91dci_softc *sc;
 	uint32_t csr_val;

Modified: head/sys/dev/usb/controller/atmegadci.c
==============================================================================
--- head/sys/dev/usb/controller/atmegadci.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/controller/atmegadci.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -1113,7 +1113,7 @@ atmegadci_device_done(struct usb_xfer *x
 
 static void
 atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct atmegadci_softc *sc;
 	uint8_t ep_no;

Modified: head/sys/dev/usb/controller/avr32dci.c
==============================================================================
--- head/sys/dev/usb/controller/avr32dci.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/controller/avr32dci.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -1081,7 +1081,7 @@ avr32dci_device_done(struct usb_xfer *xf
 
 static void
 avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct avr32dci_softc *sc;
 	uint8_t ep_no;

Modified: head/sys/dev/usb/controller/musb_otg.c
==============================================================================
--- head/sys/dev/usb/controller/musb_otg.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/controller/musb_otg.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -1473,7 +1473,7 @@ musbotg_device_done(struct usb_xfer *xfe
 
 static void
 musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct musbotg_softc *sc;
 	uint8_t ep_no;

Modified: head/sys/dev/usb/controller/uss820dci.c
==============================================================================
--- head/sys/dev/usb/controller/uss820dci.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/controller/uss820dci.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -1202,7 +1202,7 @@ uss820dci_device_done(struct usb_xfer *x
 
 static void
 uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
-    struct usb_endpoint *ep)
+    struct usb_endpoint *ep, uint8_t *did_stall)
 {
 	struct uss820dci_softc *sc;
 	uint8_t ep_no;

Modified: head/sys/dev/usb/net/if_cdce.c
==============================================================================
--- head/sys/dev/usb/net/if_cdce.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/net/if_cdce.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -764,7 +764,7 @@ tr_setup:
 static int
 cdce_handle_request(device_t dev,
     const void *req, void **pptr, uint16_t *plen,
-    uint16_t offset, uint8_t is_complete)
+    uint16_t offset, uint8_t *pstate)
 {
 	return (ENXIO);			/* use builtin handler */
 }

Modified: head/sys/dev/usb/storage/ustorage_fs.c
==============================================================================
--- head/sys/dev/usb/storage/ustorage_fs.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/storage/ustorage_fs.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -475,10 +475,11 @@ ustorage_fs_transfer_stop(struct ustorag
 static int
 ustorage_fs_handle_request(device_t dev,
     const void *preq, void **pptr, uint16_t *plen,
-    uint16_t offset, uint8_t is_complete)
+    uint16_t offset, uint8_t *pstate)
 {
 	struct ustorage_fs_softc *sc = device_get_softc(dev);
 	const struct usb_device_request *req = preq;
+	uint8_t is_complete = *pstate;
 
 	if (!is_complete) {
 		if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&

Modified: head/sys/dev/usb/usb_controller.h
==============================================================================
--- head/sys/dev/usb/usb_controller.h	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/usb_controller.h	Sat Jun 27 21:23:30 2009	(r195121)
@@ -96,7 +96,7 @@ struct usb_bus_methods {
 	/* USB Device mode only - Mandatory */
 
 	void    (*get_hw_ep_profile) (struct usb_device *udev, const struct usb_hw_ep_profile **ppf, uint8_t ep_addr);
-	void    (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep);
+	void    (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep, uint8_t *did_stall);
 	void    (*clear_stall) (struct usb_device *udev, struct usb_endpoint *ep);
 
 };

Modified: head/sys/dev/usb/usb_device.c
==============================================================================
--- head/sys/dev/usb/usb_device.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/usb_device.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -936,7 +936,7 @@ usbd_set_endpoint_stall(struct usb_devic
 		 * complete the USB transfer like in case of a timeout
 		 * setting the error code "USB_ERR_STALLED".
 		 */
-		(udev->bus->methods->set_stall) (udev, xfer, ep);
+		(udev->bus->methods->set_stall) (udev, xfer, ep, &do_stall);
 	}
 	if (!do_stall) {
 		ep->toggle_next = 0;	/* reset data toggle */

Modified: head/sys/dev/usb/usb_handle_request.c
==============================================================================
--- head/sys/dev/usb/usb_handle_request.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/usb_handle_request.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -198,6 +198,7 @@ usb_handle_iface_request(struct usb_xfer
 	struct usb_device *udev = xfer->xroot->udev;
 	int error;
 	uint8_t iface_index;
+	uint8_t temp_state;
 
 	if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
 		iface_index = req.wIndex[0];	/* unicast */
@@ -222,6 +223,10 @@ tr_repeat:
 		/* end of interfaces non-existing interface */
 		goto tr_stalled;
 	}
+	/* set initial state */
+
+	temp_state = state;
+
 	/* forward request to interface, if any */
 
 	if ((error != 0) &&
@@ -233,7 +238,7 @@ tr_repeat:
 #endif
 		error = USB_HANDLE_REQUEST(iface->subdev,
 		    &req, ppdata, plen,
-		    off, state);
+		    off, &temp_state);
 	}
 	iface_parent = usbd_get_iface(udev, iface->parent_iface_index);
 
@@ -252,14 +257,18 @@ tr_repeat:
 	    (iface_parent->subdev != iface->subdev) &&
 	    device_is_attached(iface_parent->subdev)) {
 		error = USB_HANDLE_REQUEST(iface_parent->subdev,
-		    &req, ppdata, plen, off,
-		    state);
+		    &req, ppdata, plen, off, &temp_state);
 	}
 	if (error == 0) {
 		/* negativly adjust pointer and length */
 		*ppdata = ((uint8_t *)(*ppdata)) - off;
 		*plen += off;
-		goto tr_valid;
+
+		if ((state == USB_HR_NOT_COMPLETE) &&
+		    (temp_state == USB_HR_COMPLETE_OK))
+			goto tr_short;
+		else
+			goto tr_valid;
 	} else if (error == ENOTTY) {
 		goto tr_stalled;
 	}
@@ -337,6 +346,12 @@ tr_valid:
 	USB_XFER_LOCK(xfer);
 	return (0);
 
+tr_short:
+	mtx_unlock(&Giant);
+	sx_unlock(udev->default_sx + 1);
+	USB_XFER_LOCK(xfer);
+	return (USB_ERR_SHORT_XFER);
+
 tr_stalled:
 	mtx_unlock(&Giant);
 	sx_unlock(udev->default_sx + 1);
@@ -444,6 +459,7 @@ usb_handle_request(struct usb_xfer *xfer
 	uint16_t wValue;
 	uint16_t wIndex;
 	uint8_t state;
+	uint8_t is_complete = 1;
 	usb_error_t err;
 	union {
 		uWord	wStatus;
@@ -596,6 +612,9 @@ usb_handle_request(struct usb_xfer *xfer
 		    USB_ADD_BYTES(&src_zcopy, 0),
 		    &max_len, req, off, state);
 		if (err == 0) {
+			is_complete = 0;
+			goto tr_valid;
+		} else if (err == USB_ERR_SHORT_XFER) {
 			goto tr_valid;
 		}
 		/*
@@ -735,7 +754,7 @@ tr_valid:
 	if (rem > xfer->max_data_length) {
 		rem = usbd_xfer_max_len(xfer);
 	}
-	if (rem != max_len) {
+	if ((rem != max_len) && (is_complete != 0)) {
 		/*
 	         * If we don't transfer the data we can transfer, then
 	         * the transfer is short !

Modified: head/sys/dev/usb/usb_if.m
==============================================================================
--- head/sys/dev/usb/usb_if.m	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/usb_if.m	Sat Jun 27 21:23:30 2009	(r195121)
@@ -36,6 +36,11 @@ INTERFACE usb;
 
 # The device received a control request
 #
+# The value pointed to by "pstate" can be updated to
+# "USB_HR_COMPLETE_OK" to indicate that the control
+# read transfer is complete, in case of short USB
+# control transfers.
+#
 # Return values:
 # 0: Success
 # ENOTTY: Transaction stalled
@@ -47,5 +52,5 @@ METHOD int handle_request {
 	void **pptr; /* data pointer */
 	uint16_t *plen; /* maximum transfer length */
 	uint16_t offset; /* data offset */
-	uint8_t is_complete; /* set if transfer is complete, see USB_HR_XXX */
+	uint8_t *pstate; /* set if transfer is complete, see USB_HR_XXX */
 };

Modified: head/sys/dev/usb/usb_transfer.c
==============================================================================
--- head/sys/dev/usb/usb_transfer.c	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/usb_transfer.c	Sat Jun 27 21:23:30 2009	(r195121)
@@ -2352,29 +2352,37 @@ usbd_pipe_start(struct usb_xfer_queue *p
 		    (type == UE_INTERRUPT)) {
 			struct usb_device *udev;
 			struct usb_xfer_root *info;
+			uint8_t did_stall;
 
 			info = xfer->xroot;
 			udev = info->udev;
-			ep->is_stalled = 1;
+			did_stall = 1;
 
 			if (udev->flags.usb_mode == USB_MODE_DEVICE) {
 				(udev->bus->methods->set_stall) (
-				    udev, NULL, ep);
+				    udev, NULL, ep, &did_stall);
 			} else if (udev->default_xfer[1]) {
 				info = udev->default_xfer[1]->xroot;
-				if (usb_proc_msignal(
+				usb_proc_msignal(
 				    &info->bus->non_giant_callback_proc,
-				    &udev->cs_msg[0], &udev->cs_msg[1])) {
-					/* ignore */
-				}
+				    &udev->cs_msg[0], &udev->cs_msg[1]);
 			} else {
 				/* should not happen */
 				DPRINTFN(0, "No stall handler!\n");
 			}
 			/*
-			 * We get started again when the stall is cleared!
+			 * Check if we should stall. Some USB hardware
+			 * handles set- and clear-stall in hardware.
 			 */
-			return;
+			if (did_stall) {
+				/*
+				 * The transfer will be continued when
+				 * the clear-stall control endpoint
+				 * message is received.
+				 */
+				ep->is_stalled = 1;
+				return;
+			}
 		}
 	}
 	/* Set or clear stall complete - special case */
@@ -2966,6 +2974,12 @@ usbd_xfer_set_flag(struct usb_xfer *xfer
 		case USB_SHORT_XFER_OK:
 			xfer->flags.short_xfer_ok = 1;
 			break;
+		case USB_MULTI_SHORT_OK:
+			xfer->flags.short_frames_ok = 1;
+			break;
+		case USB_MANUAL_STATUS:
+			xfer->flags.manual_status = 1;
+			break;
 	}
 }
 
@@ -2979,5 +2993,22 @@ usbd_xfer_clr_flag(struct usb_xfer *xfer
 		case USB_SHORT_XFER_OK:
 			xfer->flags.short_xfer_ok = 0;
 			break;
+		case USB_MULTI_SHORT_OK:
+			xfer->flags.short_frames_ok = 0;
+			break;
+		case USB_MANUAL_STATUS:
+			xfer->flags.manual_status = 0;
+			break;
 	}
 }
+
+/*
+ * The following function returns in milliseconds when the isochronous
+ * transfer was completed by the hardware. The returned value wraps
+ * around 65536 milliseconds.
+ */
+uint16_t
+usbd_xfer_get_timestamp(struct usb_xfer *xfer)
+{
+	return (xfer->isoc_time_complete);
+}

Modified: head/sys/dev/usb/usbdi.h
==============================================================================
--- head/sys/dev/usb/usbdi.h	Sat Jun 27 21:21:11 2009	(r195120)
+++ head/sys/dev/usb/usbdi.h	Sat Jun 27 21:23:30 2009	(r195121)
@@ -78,6 +78,8 @@ typedef enum {	/* keep in sync with usb_
 #define	USB_SHORT_XFER_OK	0x0004	/* allow short reads */
 #define	USB_DELAY_STATUS_STAGE	0x0010	/* insert delay before STATUS stage */
 #define	USB_USER_DATA_PTR	0x0020	/* internal flag */
+#define	USB_MULTI_SHORT_OK	0x0040	/* allow multiple short frames */
+#define	USB_MANUAL_STATUS	0x0080	/* manual ctrl status */
 
 #define	USB_NO_TIMEOUT 0
 #define	USB_DEFAULT_TIMEOUT 5000	/* 5000 ms = 5 seconds */
@@ -486,6 +488,7 @@ void	usbd_xfer_set_stall(struct usb_xfer
 int	usbd_xfer_is_stalled(struct usb_xfer *xfer);
 void	usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
 void	usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag);
+uint16_t usbd_xfer_get_timestamp(struct usb_xfer *xfer);
 
 void	usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
 	    const void *ptr, usb_frlength_t len);


More information about the svn-src-all mailing list