PERFORCE change 136646 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Mar 2 10:07:21 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=136646
Change 136646 by hselasky at hselasky_laptop001 on 2008/03/02 10:06:57
Bugfix. This commit is USB device side related.
When clearing the stall we need to set the stall first to
abort the current transfer.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#119 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#119 (text+ko) ====
@@ -71,6 +71,7 @@
static void usbd_do_request_callback(struct usbd_xfer *xfer);
static void usbd_handle_request_callback(struct usbd_xfer *xfer);
static usbd_status_t usbd_handle_set_config(struct usbd_xfer *xfer, uint8_t conf_no);
+static struct usbd_xfer *usbd_get_curr_xfer(struct usbd_pipe *pipe);
static usbd_status_t usbd_handle_set_stall_sub(struct usbd_device *udev, uint8_t ea_val, uint8_t do_stall);
static usbd_status_t usbd_handle_set_stall(struct usbd_xfer *xfer, uint8_t ep, uint8_t do_stall);
static uint8_t usbd_handle_get_stall(struct usbd_device *udev, uint8_t ea_val);
@@ -3092,6 +3093,35 @@
}
/*------------------------------------------------------------------------*
+ * usbd_get_curr_xfer - get current transfer on a pipe
+ *
+ * Returns:
+ * NULL: No transfer
+ * Else: Current USB transfer
+ *------------------------------------------------------------------------*/
+static struct usbd_xfer *
+usbd_get_curr_xfer(struct usbd_pipe *pipe)
+{
+ struct usbd_xfer *xfer;
+
+ xfer = LIST_FIRST(&(pipe->list_head));
+ if (xfer) {
+
+ /* search to the end of the LIST */
+ while (LIST_NEXT(xfer, pipe_list)) {
+ xfer = LIST_NEXT(xfer, pipe_list);
+ }
+
+ /*
+ * If "priv_mtx" is locked the "udev->bus->mtx" mutex
+ * can get dropped in "usbd_callback_wrapper()" !
+ */
+ mtx_assert(xfer->priv_mtx, MA_NOTOWNED);
+ }
+ return (xfer);
+}
+
+/*------------------------------------------------------------------------*
* usbd_handle_set_stall_sub
*
* This function is used to make a BULK or INTERRUPT endpoint
@@ -3108,6 +3138,7 @@
struct usbd_pipe *pipe;
struct usbd_xfer *xfer;
uint8_t et;
+ uint8_t was_stalled;
pipe = usbd_get_pipe_by_addr(udev, ea_val);
if (pipe == NULL) {
@@ -3134,48 +3165,48 @@
}
mtx_lock(&(udev->bus->mtx));
- if (pipe->is_stalled == do_stall) {
+ /* store current stall state */
+ was_stalled = pipe->is_stalled;
+
+ /* check for no change */
+ if (was_stalled && do_stall) {
/* if the pipe is already stalled do nothing */
mtx_unlock(&(udev->bus->mtx));
PRINTFN(0, ("No change\n"));
return (0);
}
- /* update stalled state */
- pipe->is_stalled = do_stall;
+ /* set stalled state */
+ pipe->is_stalled = 1;
- /* lookup the current USB transfer */
- xfer = LIST_FIRST(&(pipe->list_head));
- if (xfer) {
-
- /* search to the end of the LIST */
- while (LIST_NEXT(xfer, pipe_list)) {
- xfer = LIST_NEXT(xfer, pipe_list);
+ if (do_stall || (!was_stalled)) {
+ if (!was_stalled) {
+ /* lookup the current USB transfer */
+ xfer = usbd_get_curr_xfer(pipe);
+ } else {
+ xfer = NULL;
}
/*
- * If "priv_mtx" is locked the "udev->bus->mtx" mutex
- * can get dropped in "usbd_callback_wrapper()" !
- */
- mtx_assert(xfer->priv_mtx, MA_NOTOWNED);
- }
- if (do_stall) {
- /*
* If "xfer" is non-NULL the "set_stall" method will
* complete the USB transfer like in case of a timeout
* setting the error code "USBD_ERR_STALLED".
*/
(udev->bus->methods->set_stall) (udev, xfer, pipe);
- } else {
+ }
+ if (!do_stall) {
pipe->toggle_next = 0; /* reset data toggle */
+ pipe->is_stalled = 0; /* clear stalled state */
(udev->bus->methods->clear_stall) (udev, pipe);
- /* start up the first transfer, if any */
+ /* lookup the current USB transfer */
+ xfer = usbd_get_curr_xfer(pipe);
+
+ /* start up the current transfer, if any */
if (xfer) {
usbd_transfer_enqueue(xfer);
}
}
-
mtx_unlock(&(udev->bus->mtx));
return (0);
}
More information about the p4-projects
mailing list