Author: thompsa
Date: Wed May 12 23:40:44 2010
New Revision: 208018
URL: http://svn.freebsd.org/changeset/base/208018

Log:
  Reduce diffs to p4.
  
   Add test code for delaying or failing usb control requests, disabled by
   default under ifdef USB_REQ_DEBUG.
  
  Submitted by: Hans Petter Selasky

Modified:
  head/sys/dev/usb/usb_request.c

Modified: head/sys/dev/usb/usb_request.c
==============================================================================
--- head/sys/dev/usb/usb_request.c      Wed May 12 23:00:36 2010        
(r208017)
+++ head/sys/dev/usb/usb_request.c      Wed May 12 23:40:44 2010        
(r208018)
@@ -71,15 +71,122 @@
 #ifdef USB_DEBUG
 static int usb_pr_poll_delay = USB_PORT_RESET_DELAY;
 static int usb_pr_recovery_delay = USB_PORT_RESET_RECOVERY;
-static int usb_ss_delay = 0;
 
 SYSCTL_INT(_hw_usb, OID_AUTO, pr_poll_delay, CTLFLAG_RW,
     &usb_pr_poll_delay, 0, "USB port reset poll delay in ms");
 SYSCTL_INT(_hw_usb, OID_AUTO, pr_recovery_delay, CTLFLAG_RW,
     &usb_pr_recovery_delay, 0, "USB port reset recovery delay in ms");
-SYSCTL_INT(_hw_usb, OID_AUTO, ss_delay, CTLFLAG_RW,
-    &usb_ss_delay, 0, "USB status stage delay in ms");
-#endif
+
+#ifdef USB_REQ_DEBUG
+/* The following structures are used in connection to fault injection. */
+struct usb_ctrl_debug {
+       int bus_index;          /* target bus */
+       int dev_index;          /* target address */
+       int ds_fail;            /* fail data stage */
+       int ss_fail;            /* fail data stage */
+       int ds_delay;           /* data stage delay in ms */
+       int ss_delay;           /* status stage delay in ms */
+       int bmRequestType_value;
+       int bRequest_value;
+};
+
+struct usb_ctrl_debug_bits {
+       uint16_t ds_delay;
+       uint16_t ss_delay;
+       uint8_t ds_fail:1;
+       uint8_t ss_fail:1;
+       uint8_t enabled:1;
+};
+
+/* The default is to disable fault injection. */
+
+static struct usb_ctrl_debug usb_ctrl_debug = {
+       .bus_index = -1,
+       .dev_index = -1,
+       .bmRequestType_value = -1,
+       .bRequest_value = -1,
+};
+
+SYSCTL_INT(_hw_usb, OID_AUTO, ctrl_bus_fail, CTLFLAG_RW,
+    &usb_ctrl_debug.bus_index, 0, "USB controller index to fail");
+SYSCTL_INT(_hw_usb, OID_AUTO, ctrl_dev_fail, CTLFLAG_RW,
+    &usb_ctrl_debug.dev_index, 0, "USB device address to fail");
+SYSCTL_INT(_hw_usb, OID_AUTO, ctrl_ds_fail, CTLFLAG_RW,
+    &usb_ctrl_debug.ds_fail, 0, "USB fail data stage");
+SYSCTL_INT(_hw_usb, OID_AUTO, ctrl_ss_fail, CTLFLAG_RW,
+    &usb_ctrl_debug.ss_fail, 0, "USB fail status stage");
+SYSCTL_INT(_hw_usb, OID_AUTO, ctrl_ds_delay, CTLFLAG_RW,
+    &usb_ctrl_debug.ds_delay, 0, "USB data stage delay in ms");
+SYSCTL_INT(_hw_usb, OID_AUTO, ctrl_ss_delay, CTLFLAG_RW,
+    &usb_ctrl_debug.ss_delay, 0, "USB status stage delay in ms");
+SYSCTL_INT(_hw_usb, OID_AUTO, ctrl_rt_fail, CTLFLAG_RW,
+    &usb_ctrl_debug.bmRequestType_value, 0, "USB bmRequestType to fail");
+SYSCTL_INT(_hw_usb, OID_AUTO, ctrl_rv_fail, CTLFLAG_RW,
+    &usb_ctrl_debug.bRequest_value, 0, "USB bRequest to fail");
+
+/*------------------------------------------------------------------------*
+ *     usbd_get_debug_bits
+ *
+ * This function is only useful in USB host mode.
+ *------------------------------------------------------------------------*/
+static void
+usbd_get_debug_bits(struct usb_device *udev, struct usb_device_request *req,
+    struct usb_ctrl_debug_bits *dbg)
+{
+       int temp;
+
+       memset(dbg, 0, sizeof(*dbg));
+
+       /* Compute data stage delay */
+
+       temp = usb_ctrl_debug.ds_delay;
+       if (temp < 0)
+               temp = 0;
+       else if (temp > (16*1024))
+               temp = (16*1024);
+
+       dbg->ds_delay = temp;
+
+       /* Compute status stage delay */
+
+       temp = usb_ctrl_debug.ss_delay;
+       if (temp < 0)
+               temp = 0;
+       else if (temp > (16*1024))
+               temp = (16*1024);
+
+       dbg->ss_delay = temp;
+
+       /* Check if this control request should be failed */
+
+       if (usbd_get_bus_index(udev) != usb_ctrl_debug.bus_index)
+               return;
+
+       if (usbd_get_device_index(udev) != usb_ctrl_debug.dev_index)
+               return;
+
+       temp = usb_ctrl_debug.bmRequestType_value;
+
+       if ((temp != req->bmRequestType) && (temp >= 0) && (temp <= 255))
+               return;
+
+       temp = usb_ctrl_debug.bRequest_value;
+
+       if ((temp != req->bRequest) && (temp >= 0) && (temp <= 255))
+               return;
+
+       temp = usb_ctrl_debug.ds_fail;
+       if (temp)
+               dbg->ds_fail = 1;
+
+       temp = usb_ctrl_debug.ss_fail;
+       if (temp)
+               dbg->ss_fail = 1;
+
+       dbg->enabled = 1;
+}
+#endif /* USB_REQ_DEBUG */
+#endif /* USB_DEBUG */
 
 /*------------------------------------------------------------------------*
  *     usbd_do_request_callback
@@ -264,6 +371,9 @@ usbd_do_request_flags(struct usb_device 
     struct usb_device_request *req, void *data, uint16_t flags,
     uint16_t *actlen, usb_timeout_t timeout)
 {
+#ifdef USB_REQ_DEBUG
+       struct usb_ctrl_debug_bits dbg;
+#endif
        usb_handle_req_t *hr_func;
        struct usb_xfer *xfer;
        const void *desc;
@@ -273,6 +383,7 @@ usbd_do_request_flags(struct usb_device 
        usb_ticks_t max_ticks;
        uint16_t length;
        uint16_t temp;
+       uint16_t acttemp;
        uint8_t enum_locked;
 
        if (timeout < 50) {
@@ -327,7 +438,6 @@ usbd_do_request_flags(struct usb_device 
         * Grab the default sx-lock so that serialisation
         * is achieved when multiple threads are involved:
         */
-
        sx_xlock(&udev->ctrl_sx);
 
        hr_func = usbd_get_hr_func(udev);
@@ -391,6 +501,15 @@ usbd_do_request_flags(struct usb_device 
                err = USB_ERR_NOMEM;
                goto done;
        }
+
+#ifdef USB_REQ_DEBUG
+       /* Get debug bits */
+       usbd_get_debug_bits(udev, req, &dbg);
+
+       /* Check for fault injection */
+       if (dbg.enabled)
+               flags |= USB_DELAY_STATUS_STAGE;
+#endif
        USB_XFER_LOCK(xfer);
 
        if (flags & USB_DELAY_STATUS_STAGE)
@@ -412,13 +531,32 @@ usbd_do_request_flags(struct usb_device 
        usbd_copy_in(xfer->frbuffers, 0, req, sizeof(*req));
 
        usbd_xfer_set_frame_len(xfer, 0, sizeof(*req));
-       xfer->nframes = 2;
 
        while (1) {
                temp = length;
-               if (temp > xfer->max_data_length) {
+               if (temp > usbd_xfer_max_len(xfer)) {
                        temp = usbd_xfer_max_len(xfer);
                }
+#ifdef USB_REQ_DEBUG
+               if (xfer->flags.manual_status) {
+                       if (usbd_xfer_frame_len(xfer, 0) != 0) {
+                               /* Execute data stage separately */
+                               temp = 0;
+                       } else if (temp > 0) {
+                               if (dbg.ds_fail) {
+                                       err = USB_ERR_INVAL;
+                                       break;
+                               }
+                               if (dbg.ds_delay > 0) {
+                                       usb_pause_mtx(
+                                           xfer->xroot->xfer_mtx,
+                                           USB_MS_TO_TICKS(dbg.ds_delay));
+                                       /* make sure we don't time out */
+                                       start_ticks = ticks;
+                               }
+                       }
+               }
+#endif
                usbd_xfer_set_frame_len(xfer, 1, temp);
 
                if (temp > 0) {
@@ -438,21 +576,21 @@ usbd_do_request_flags(struct usb_device 
                                        usbd_copy_in(xfer->frbuffers + 1,
                                            0, data, temp);
                        }
-                       xfer->nframes = 2;
+                       usbd_xfer_set_frames(xfer, 2);
                } else {
-                       if (xfer->frlengths[0] == 0) {
+                       if (usbd_xfer_frame_len(xfer, 0) == 0) {
                                if (xfer->flags.manual_status) {
-#ifdef USB_DEBUG
-                                       int temp;
-
-                                       temp = usb_ss_delay;
-                                       if (temp > 5000) {
-                                               temp = 5000;
+#ifdef USB_REQ_DEBUG
+                                       if (dbg.ss_fail) {
+                                               err = USB_ERR_INVAL;
+                                               break;
                                        }
-                                       if (temp > 0) {
+                                       if (dbg.ss_delay > 0) {
                                                usb_pause_mtx(
                                                    xfer->xroot->xfer_mtx,
-                                                   USB_MS_TO_TICKS(temp));
+                                                   
USB_MS_TO_TICKS(dbg.ss_delay));
+                                               /* make sure we don't time out 
*/
+                                               start_ticks = ticks;
                                        }
 #endif
                                        xfer->flags.manual_status = 0;
@@ -460,7 +598,7 @@ usbd_do_request_flags(struct usb_device 
                                        break;
                                }
                        }
-                       xfer->nframes = 1;
+                       usbd_xfer_set_frames(xfer, 1);
                }
 
                usbd_transfer_start(xfer);
@@ -475,18 +613,19 @@ usbd_do_request_flags(struct usb_device 
                if (err) {
                        break;
                }
-               /* subtract length of SETUP packet, if any */
 
-               if (xfer->aframes > 0) {
-                       xfer->actlen -= xfer->frlengths[0];
+               /* get actual length of DATA stage */
+
+               if (xfer->aframes < 2) {
+                       acttemp = 0;
                } else {
-                       xfer->actlen = 0;
+                       acttemp = usbd_xfer_frame_len(xfer, 1);
                }
 
                /* check for short packet */
 
-               if (temp > xfer->actlen) {
-                       temp = xfer->actlen;
+               if (temp > acttemp) {
+                       temp = acttemp;
                        length = temp;
                }
                if (temp > 0) {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to