From owner-svn-src-head@FreeBSD.ORG Sat Jun 27 21:23:30 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 875861065672; Sat, 27 Jun 2009 21:23:30 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 73C778FC0C; Sat, 27 Jun 2009 21:23:30 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n5RLNUjX088710; Sat, 27 Jun 2009 21:23:30 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n5RLNU2r088696; Sat, 27 Jun 2009 21:23:30 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <200906272123.n5RLNU2r088696@svn.freebsd.org> From: Andrew Thompson Date: Sat, 27 Jun 2009 21:23:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r195121 - in head/sys/dev/usb: . controller net storage X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 27 Jun 2009 21:23:31 -0000 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);