]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.31 xhci fun
authorGreg Kroah-Hartman <gregkh@suse.de>
Thu, 1 Oct 2009 22:17:55 +0000 (15:17 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 1 Oct 2009 22:17:55 +0000 (15:17 -0700)
16 files changed:
queue-2.6.31/series
queue-2.6.31/usb-fix-ss-endpoint-companion-descriptor-parsing.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-add-quirk-for-fresco-logic-xhci-hardware.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-check-urb-s-actual-transfer-buffer-size.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-check-urb_short_not_ok-before-setting-short-packet-status.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-configure-endpoint-code-refactoring.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-don-t-touch-xhci_td-after-it-s-freed.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-fix-slot-and-endpoint-context-debugging.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-handle-babbling-endpoints-correctly.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-handle-stalled-control-endpoints.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-make-trb-completion-code-comparison-readable.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-set-correct-max-packet-size-for-hs-fs-control-endpoints.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-set-eremoteio-when-xhc-gives-bad-transfer-length.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-support-full-speed-devices.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-support-interrupt-transfers.patch [new file with mode: 0644]
queue-2.6.31/usb-xhci-work-around-for-chain-bit-in-link-trbs.patch [new file with mode: 0644]

index 5c42b8de5bfa15c261a823bb0d5a2826caab8767..8bb6ee149c579f60d3f9495718471d01e2dcfa3d 100644 (file)
@@ -99,3 +99,18 @@ usb-serial-rename-subroutines.patch
 usb-serial-add-missing-tests-and-debug-lines.patch
 usb-serial-straighten-out-serial_open.patch
 usb-serial-update-the-console-driver.patch
+usb-xhci-work-around-for-chain-bit-in-link-trbs.patch
+usb-xhci-fix-slot-and-endpoint-context-debugging.patch
+usb-xhci-configure-endpoint-code-refactoring.patch
+usb-xhci-set-correct-max-packet-size-for-hs-fs-control-endpoints.patch
+usb-xhci-support-full-speed-devices.patch
+usb-xhci-handle-stalled-control-endpoints.patch
+usb-xhci-add-quirk-for-fresco-logic-xhci-hardware.patch
+usb-xhci-make-trb-completion-code-comparison-readable.patch
+usb-xhci-handle-babbling-endpoints-correctly.patch
+usb-xhci-don-t-touch-xhci_td-after-it-s-freed.patch
+usb-xhci-check-urb-s-actual-transfer-buffer-size.patch
+usb-xhci-check-urb_short_not_ok-before-setting-short-packet-status.patch
+usb-xhci-set-eremoteio-when-xhc-gives-bad-transfer-length.patch
+usb-xhci-support-interrupt-transfers.patch
+usb-fix-ss-endpoint-companion-descriptor-parsing.patch
diff --git a/queue-2.6.31/usb-fix-ss-endpoint-companion-descriptor-parsing.patch b/queue-2.6.31/usb-fix-ss-endpoint-companion-descriptor-parsing.patch
new file mode 100644 (file)
index 0000000..6a17d39
--- /dev/null
@@ -0,0 +1,32 @@
+From 6682bb39e111b34290e25c4d275c5bcf8bbccbe1 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 8 Sep 2009 13:20:16 -0700
+Subject: USB: Fix SS endpoint companion descriptor parsing.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 6682bb39e111b34290e25c4d275c5bcf8bbccbe1 upstream.
+
+When there's a descriptor after the SuperSpeed endpoint companion
+descriptor, the previous code would have skipped over twice the length it
+was supposed to.  This code fixes crashes seen with UASP devices (which
+have a UASP descriptor after the SS endpoint companion descriptor).
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/config.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -105,7 +105,7 @@ static int usb_parse_ss_endpoint_compani
+       ep->ss_ep_comp->extralen = i;
+       buffer += i;
+       size -= i;
+-      retval = buffer - buffer_start + i;
++      retval = buffer - buffer_start;
+       if (num_skipped > 0)
+               dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
+                               num_skipped, plural(num_skipped),
diff --git a/queue-2.6.31/usb-xhci-add-quirk-for-fresco-logic-xhci-hardware.patch b/queue-2.6.31/usb-xhci-add-quirk-for-fresco-logic-xhci-hardware.patch
new file mode 100644 (file)
index 0000000..2bb9140
--- /dev/null
@@ -0,0 +1,359 @@
+From ac9d8fe7c6a8041cca5a0738915d2c4e21381421 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 7 Aug 2009 14:04:55 -0700
+Subject: USB: xhci: Add quirk for Fresco Logic xHCI hardware.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit ac9d8fe7c6a8041cca5a0738915d2c4e21381421 upstream.
+
+This Fresco Logic xHCI host controller chip revision puts bad data into
+the output endpoint context after a Reset Endpoint command.  It needs a
+Configure Endpoint command (instead of a Set TR Dequeue Pointer command)
+after the reset endpoint command.
+
+Set up the input context before issuing the Reset Endpoint command so we
+don't copy bad data from the output endpoint context.  The HW also can't
+handle two commands queued at once, so submit the TRB for the Configure
+Endpoint command in the event handler for the Reset Endpoint command.
+
+Devices that stall on control endpoints before a configuration is selected
+will not work under this Fresco Logic xHCI host controller revision.
+
+This patch is for prototype hardware that will be given to other companies
+for evaluation purposes only, and should not reach consumer hands.  Fresco
+Logic's next chip rev should have this bug fixed.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-hcd.c  |   77 +++++++++++++++++++++++++++++++++++++------
+ drivers/usb/host/xhci-pci.c  |   13 +++++++
+ drivers/usb/host/xhci-ring.c |   61 ++++++++++++++++++++++++++++++----
+ drivers/usb/host/xhci.h      |   20 +++++++----
+ 4 files changed, 148 insertions(+), 23 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -929,6 +929,12 @@ struct xhci_td {
+       union xhci_trb          *last_trb;
+ };
++struct xhci_dequeue_state {
++      struct xhci_segment *new_deq_seg;
++      union xhci_trb *new_deq_ptr;
++      int new_cycle_state;
++};
++
+ struct xhci_ring {
+       struct xhci_segment     *first_seg;
+       union  xhci_trb         *enqueue;
+@@ -955,12 +961,6 @@ struct xhci_ring {
+       u32                     cycle_state;
+ };
+-struct xhci_dequeue_state {
+-      struct xhci_segment *new_deq_seg;
+-      union xhci_trb *new_deq_ptr;
+-      int new_cycle_state;
+-};
+-
+ struct xhci_erst_entry {
+       /* 64-bit event ring segment address */
+       u64     seg_addr;
+@@ -1063,6 +1063,7 @@ struct xhci_hcd {
+       int                     error_bitmask;
+       unsigned int            quirks;
+ #define       XHCI_LINK_TRB_QUIRK     (1 << 0)
++#define XHCI_RESET_EP_QUIRK   (1 << 1)
+ };
+ /* For testing purposes */
+@@ -1170,6 +1171,8 @@ int xhci_alloc_virt_device(struct xhci_h
+ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev);
+ unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);
+ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
++unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index);
++unsigned int xhci_last_valid_endpoint(u32 added_ctxs);
+ void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep);
+ void xhci_endpoint_copy(struct xhci_hcd *xhci,
+               struct xhci_virt_device *vdev, unsigned int ep_index);
+@@ -1233,8 +1236,11 @@ void xhci_queue_new_dequeue_state(struct
+               struct xhci_ring *ep_ring, unsigned int slot_id,
+               unsigned int ep_index, struct xhci_dequeue_state *deq_state);
+ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
+-              struct usb_device *udev, struct usb_host_endpoint *ep,
++              struct usb_device *udev,
+               unsigned int ep_index, struct xhci_ring *ep_ring);
++void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci,
++              unsigned int slot_id, unsigned int ep_index,
++              struct xhci_dequeue_state *deq_state);
+ /* xHCI roothub code */
+ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -224,7 +224,7 @@ int xhci_init(struct usb_hcd *hcd)
+               xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits.\n");
+               xhci->quirks |= XHCI_LINK_TRB_QUIRK;
+       } else {
+-              xhci_dbg(xhci, "xHCI has no QUIRKS\n");
++              xhci_dbg(xhci, "xHCI doesn't need link TRB QUIRK\n");
+       }
+       retval = xhci_mem_init(xhci, GFP_KERNEL);
+       xhci_dbg(xhci, "Finished xhci_init\n");
+@@ -567,13 +567,22 @@ unsigned int xhci_get_endpoint_flag(stru
+       return 1 << (xhci_get_endpoint_index(desc) + 1);
+ }
++/* Find the flag for this endpoint (for use in the control context).  Use the
++ * endpoint index to create a bitmask.  The slot context is bit 0, endpoint 0 is
++ * bit 1, etc.
++ */
++unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index)
++{
++      return 1 << (ep_index + 1);
++}
++
+ /* Compute the last valid endpoint context index.  Basically, this is the
+  * endpoint index plus one.  For slot contexts with more than valid endpoint,
+  * we find the most significant bit set in the added contexts flags.
+  * e.g. ep 1 IN (with epnum 0x81) => added_ctxs = 0b1000
+  * fls(0b1000) = 4, but the endpoint context index is 3, so subtract one.
+  */
+-static inline unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
++unsigned int xhci_last_valid_endpoint(u32 added_ctxs)
+ {
+       return fls(added_ctxs) - 1;
+ }
+@@ -1230,8 +1239,44 @@ void xhci_reset_bandwidth(struct usb_hcd
+       xhci_zero_in_ctx(xhci, virt_dev);
+ }
++void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
++              unsigned int slot_id, unsigned int ep_index,
++              struct xhci_dequeue_state *deq_state)
++{
++      struct xhci_container_ctx *in_ctx;
++      struct xhci_input_control_ctx *ctrl_ctx;
++      struct xhci_ep_ctx *ep_ctx;
++      u32 added_ctxs;
++      dma_addr_t addr;
++
++      xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index);
++      in_ctx = xhci->devs[slot_id]->in_ctx;
++      ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
++      addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg,
++                      deq_state->new_deq_ptr);
++      if (addr == 0) {
++              xhci_warn(xhci, "WARN Cannot submit config ep after "
++                              "reset ep command\n");
++              xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n",
++                              deq_state->new_deq_seg,
++                              deq_state->new_deq_ptr);
++              return;
++      }
++      ep_ctx->deq = addr | deq_state->new_cycle_state;
++
++      xhci_slot_copy(xhci, xhci->devs[slot_id]);
++
++      ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
++      added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
++      ctrl_ctx->add_flags = added_ctxs | SLOT_FLAG;
++      ctrl_ctx->drop_flags = added_ctxs;
++
++      xhci_dbg(xhci, "Slot ID %d Input Context:\n", slot_id);
++      xhci_dbg_ctx(xhci, in_ctx, ep_index);
++}
++
+ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
+-              struct usb_device *udev, struct usb_host_endpoint *ep,
++              struct usb_device *udev,
+               unsigned int ep_index, struct xhci_ring *ep_ring)
+ {
+       struct xhci_dequeue_state deq_state;
+@@ -1241,12 +1286,26 @@ void xhci_cleanup_stalled_ring(struct xh
+        * or it will attempt to resend it on the next doorbell ring.
+        */
+       xhci_find_new_dequeue_state(xhci, udev->slot_id,
+-                      ep_index, ep_ring->stopped_td, &deq_state);
++                      ep_index, ep_ring->stopped_td,
++                      &deq_state);
+-      xhci_dbg(xhci, "Queueing new dequeue state\n");
+-      xhci_queue_new_dequeue_state(xhci, ep_ring,
+-                      udev->slot_id,
+-                      ep_index, &deq_state);
++      /* HW with the reset endpoint quirk will use the saved dequeue state to
++       * issue a configure endpoint command later.
++       */
++      if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
++              xhci_dbg(xhci, "Queueing new dequeue state\n");
++              xhci_queue_new_dequeue_state(xhci, ep_ring,
++                              udev->slot_id,
++                              ep_index, &deq_state);
++      } else {
++              /* Better hope no one uses the input context between now and the
++               * reset endpoint completion!
++               */
++              xhci_dbg(xhci, "Setting up input context for "
++                              "configure endpoint command\n");
++              xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id,
++                              ep_index, &deq_state);
++      }
+ }
+ /* Deal with stalled endpoints.  The core should have sent the control message
+@@ -1293,7 +1352,7 @@ void xhci_endpoint_reset(struct usb_hcd 
+        * command.  Better hope that last command worked!
+        */
+       if (!ret) {
+-              xhci_cleanup_stalled_ring(xhci, udev, ep, ep_index, ep_ring);
++              xhci_cleanup_stalled_ring(xhci, udev, ep_index, ep_ring);
+               kfree(ep_ring->stopped_td);
+               xhci_ring_cmd_db(xhci);
+       }
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -24,6 +24,10 @@
+ #include "xhci.h"
++/* Device for a quirk */
++#define PCI_VENDOR_ID_FRESCO_LOGIC    0x1b73
++#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK        0x1000
++
+ static const char hcd_name[] = "xhci_hcd";
+ /* called after powerup, by probe or system-pm "wakeup" */
+@@ -62,6 +66,15 @@ static int xhci_pci_setup(struct usb_hcd
+       xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
+       xhci_print_registers(xhci);
++      /* Look for vendor-specific quirks */
++      if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
++                      pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
++                      pdev->revision == 0x0) {
++                      xhci->quirks |= XHCI_RESET_EP_QUIRK;
++                      xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
++                                      " endpoint cmd after reset endpoint\n");
++      }
++
+       /* Make sure the HC is halted. */
+       retval = xhci_halt(xhci);
+       if (retval)
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -469,7 +469,6 @@ void xhci_queue_new_dequeue_state(struct
+        * ring running.
+        */
+       ep_ring->state |= SET_DEQ_PENDING;
+-      xhci_ring_cmd_db(xhci);
+ }
+ /*
+@@ -538,6 +537,7 @@ static void handle_stopped_endpoint(stru
+       if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
+               xhci_queue_new_dequeue_state(xhci, ep_ring,
+                               slot_id, ep_index, &deq_state);
++              xhci_ring_cmd_db(xhci);
+       } else {
+               /* Otherwise just ring the doorbell to restart the ring */
+               ring_ep_doorbell(xhci, slot_id, ep_index);
+@@ -651,18 +651,31 @@ static void handle_reset_ep_completion(s
+ {
+       int slot_id;
+       unsigned int ep_index;
++      struct xhci_ring *ep_ring;
+       slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
+       ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
++      ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
+       /* This command will only fail if the endpoint wasn't halted,
+        * but we don't care.
+        */
+       xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
+                       (unsigned int) GET_COMP_CODE(event->status));
+-      /* Clear our internal halted state and restart the ring */
+-      xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED;
+-      ring_ep_doorbell(xhci, slot_id, ep_index);
++      /* HW with the reset endpoint quirk needs to have a configure endpoint
++       * command complete before the endpoint can be used.  Queue that here
++       * because the HW can't handle two commands being queued in a row.
++       */
++      if (xhci->quirks & XHCI_RESET_EP_QUIRK) {
++              xhci_dbg(xhci, "Queueing configure endpoint command\n");
++              xhci_queue_configure_endpoint(xhci,
++                              xhci->devs[slot_id]->in_ctx->dma, slot_id);
++              xhci_ring_cmd_db(xhci);
++      } else {
++              /* Clear our internal halted state and restart the ring */
++              ep_ring->state &= ~EP_HALTED;
++              ring_ep_doorbell(xhci, slot_id, ep_index);
++      }
+ }
+ static void handle_cmd_completion(struct xhci_hcd *xhci,
+@@ -671,6 +684,10 @@ static void handle_cmd_completion(struct
+       int slot_id = TRB_TO_SLOT_ID(event->flags);
+       u64 cmd_dma;
+       dma_addr_t cmd_dequeue_dma;
++      struct xhci_input_control_ctx *ctrl_ctx;
++      unsigned int ep_index;
++      struct xhci_ring *ep_ring;
++      unsigned int ep_state;
+       cmd_dma = event->cmd_trb;
+       cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+@@ -698,8 +715,39 @@ static void handle_cmd_completion(struct
+                       xhci_free_virt_device(xhci, slot_id);
+               break;
+       case TRB_TYPE(TRB_CONFIG_EP):
+-              xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
+-              complete(&xhci->devs[slot_id]->cmd_completion);
++              /*
++               * Configure endpoint commands can come from the USB core
++               * configuration or alt setting changes, or because the HW
++               * needed an extra configure endpoint command after a reset
++               * endpoint command.  In the latter case, the xHCI driver is
++               * not waiting on the configure endpoint command.
++               */
++              ctrl_ctx = xhci_get_input_control_ctx(xhci,
++                              xhci->devs[slot_id]->in_ctx);
++              /* Input ctx add_flags are the endpoint index plus one */
++              ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
++              ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
++              if (!ep_ring) {
++                      /* This must have been an initial configure endpoint */
++                      xhci->devs[slot_id]->cmd_status =
++                              GET_COMP_CODE(event->status);
++                      complete(&xhci->devs[slot_id]->cmd_completion);
++                      break;
++              }
++              ep_state = ep_ring->state;
++              xhci_dbg(xhci, "Completed config ep cmd - last ep index = %d, "
++                              "state = %d\n", ep_index, ep_state);
++              if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
++                              ep_state & EP_HALTED) {
++                      /* Clear our internal halted state and restart ring */
++                      xhci->devs[slot_id]->ep_rings[ep_index]->state &=
++                              ~EP_HALTED;
++                      ring_ep_doorbell(xhci, slot_id, ep_index);
++              } else {
++                      xhci->devs[slot_id]->cmd_status =
++                              GET_COMP_CODE(event->status);
++                      complete(&xhci->devs[slot_id]->cmd_completion);
++              }
+               break;
+       case TRB_TYPE(TRB_EVAL_CONTEXT):
+               xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
+@@ -958,7 +1006,6 @@ static int handle_tx_event(struct xhci_h
+                       xhci_queue_reset_ep(xhci, slot_id, ep_index);
+                       xhci_cleanup_stalled_ring(xhci,
+                                       td->urb->dev,
+-                                      td->urb->ep,
+                                       ep_index, ep_ring);
+                       xhci_ring_cmd_db(xhci);
+                       goto td_cleanup;
diff --git a/queue-2.6.31/usb-xhci-check-urb-s-actual-transfer-buffer-size.patch b/queue-2.6.31/usb-xhci-check-urb-s-actual-transfer-buffer-size.patch
new file mode 100644 (file)
index 0000000..ce3eab8
--- /dev/null
@@ -0,0 +1,57 @@
+From 99eb32db45061443ab7552b8fdceae68b90fde55 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 27 Aug 2009 14:36:24 -0700
+Subject: USB: xhci: Check URB's actual transfer buffer size.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 99eb32db45061443ab7552b8fdceae68b90fde55 upstream.
+
+Make sure that the amount of data the xHC says was transmitted is less
+than or equal to the size of the requested transfer buffer.  Before, if
+the host controller erroneously reported that the number of bytes
+untransferred was bigger than the buffer in the URB, urb->actual_length
+could be set to a very large size.
+
+Make sure urb->actual_length <= urb->transfer_buffer_length.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |   17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1092,7 +1092,8 @@ static int handle_tx_event(struct xhci_h
+                               td->urb->actual_length =
+                                       td->urb->transfer_buffer_length -
+                                       TRB_LEN(event->transfer_len);
+-                              if (td->urb->actual_length < 0) {
++                              if (td->urb->transfer_buffer_length <
++                                              td->urb->actual_length) {
+                                       xhci_warn(xhci, "HC gave bad length "
+                                                       "of %d bytes left\n",
+                                                       TRB_LEN(event->transfer_len));
+@@ -1167,6 +1168,20 @@ static int handle_tx_event(struct xhci_h
+ td_cleanup:
+               /* Clean up the endpoint's TD list */
+               urb = td->urb;
++              /* Do one last check of the actual transfer length.
++               * If the host controller said we transferred more data than
++               * the buffer length, urb->actual_length will be a very big
++               * number (since it's unsigned).  Play it safe and say we didn't
++               * transfer anything.
++               */
++              if (urb->actual_length > urb->transfer_buffer_length) {
++                      xhci_warn(xhci, "URB transfer length is wrong, "
++                                      "xHC issue? req. len = %u, "
++                                      "act. len = %u\n",
++                                      urb->transfer_buffer_length,
++                                      urb->actual_length);
++                      urb->actual_length = 0;
++              }
+               list_del(&td->td_list);
+               /* Was this TD slated to be cancelled but completed anyway? */
+               if (!list_empty(&td->cancelled_td_list)) {
diff --git a/queue-2.6.31/usb-xhci-check-urb_short_not_ok-before-setting-short-packet-status.patch b/queue-2.6.31/usb-xhci-check-urb_short_not_ok-before-setting-short-packet-status.patch
new file mode 100644 (file)
index 0000000..59ec41e
--- /dev/null
@@ -0,0 +1,45 @@
+From 204970a4bb2f584afc430ae330cd44aee329cea4 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 28 Aug 2009 14:28:15 -0700
+Subject: USB: xhci: Check URB_SHORT_NOT_OK before setting short packet status.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 204970a4bb2f584afc430ae330cd44aee329cea4 upstream.
+
+Make sure that the driver that submitted the URB considers a short packet
+an error before setting -EREMOTEIO during a short control transfer.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -991,7 +991,10 @@ static int handle_tx_event(struct xhci_h
+                       break;
+               case COMP_SHORT_TX:
+                       xhci_warn(xhci, "WARN: short transfer on control ep\n");
+-                      status = -EREMOTEIO;
++                      if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++                              status = -EREMOTEIO;
++                      else
++                              status = 0;
+                       break;
+               case COMP_BABBLE:
+                       /* The 0.96 spec says a babbling control endpoint
+@@ -1034,7 +1037,10 @@ static int handle_tx_event(struct xhci_h
+                       if (event_trb == td->last_trb) {
+                               if (td->urb->actual_length != 0) {
+                                       /* Don't overwrite a previously set error code */
+-                                      if (status == -EINPROGRESS || status == 0)
++                                      if ((status == -EINPROGRESS ||
++                                                              status == 0) &&
++                                                      (td->urb->transfer_flags
++                                                       & URB_SHORT_NOT_OK))
+                                               /* Did we already see a short data stage? */
+                                               status = -EREMOTEIO;
+                               } else {
diff --git a/queue-2.6.31/usb-xhci-configure-endpoint-code-refactoring.patch b/queue-2.6.31/usb-xhci-configure-endpoint-code-refactoring.patch
new file mode 100644 (file)
index 0000000..3e9ba4d
--- /dev/null
@@ -0,0 +1,303 @@
+From f2217e8edd95b0428d8123d426e0097a5e955f9f Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 7 Aug 2009 14:04:43 -0700
+Subject: USB: xhci: Configure endpoint code refactoring.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit f2217e8edd95b0428d8123d426e0097a5e955f9f upstream.
+
+Refactor out the code issue, wait for, and parse the event completion code
+for a configure endpoint command.  Modify it to support the evaluate
+context command, which has a very similar submission process.  Add
+functions to copy parts of the output context into the input context
+(which will be used in the evaluate context command).
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-hcd.c  |  169 +++++++++++++++++++++++++++++--------------
+ drivers/usb/host/xhci-mem.c  |   38 +++++++++
+ drivers/usb/host/xhci-ring.c |    9 ++
+ drivers/usb/host/xhci.h      |    5 +
+ 4 files changed, 169 insertions(+), 52 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1168,6 +1168,9 @@ int xhci_setup_addressable_virt_dev(stru
+ unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc);
+ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc);
+ void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep);
++void xhci_endpoint_copy(struct xhci_hcd *xhci,
++              struct xhci_virt_device *vdev, unsigned int ep_index);
++void xhci_slot_copy(struct xhci_hcd *xhci, struct xhci_virt_device *vdev);
+ int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev,
+               struct usb_device *udev, struct usb_host_endpoint *ep,
+               gfp_t mem_flags);
+@@ -1216,6 +1219,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+               int slot_id, unsigned int ep_index);
+ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+               u32 slot_id);
++int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
++              u32 slot_id);
+ int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
+               unsigned int ep_index);
+ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -942,6 +942,122 @@ static void xhci_zero_in_ctx(struct xhci
+       }
+ }
++static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
++              struct usb_device *udev, struct xhci_virt_device *virt_dev)
++{
++      int ret;
++
++      switch (virt_dev->cmd_status) {
++      case COMP_ENOMEM:
++              dev_warn(&udev->dev, "Not enough host controller resources "
++                              "for new device state.\n");
++              ret = -ENOMEM;
++              /* FIXME: can we allocate more resources for the HC? */
++              break;
++      case COMP_BW_ERR:
++              dev_warn(&udev->dev, "Not enough bandwidth "
++                              "for new device state.\n");
++              ret = -ENOSPC;
++              /* FIXME: can we go back to the old state? */
++              break;
++      case COMP_TRB_ERR:
++              /* the HCD set up something wrong */
++              dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, "
++                              "add flag = 1, "
++                              "and endpoint is not disabled.\n");
++              ret = -EINVAL;
++              break;
++      case COMP_SUCCESS:
++              dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
++              ret = 0;
++              break;
++      default:
++              xhci_err(xhci, "ERROR: unexpected command completion "
++                              "code 0x%x.\n", virt_dev->cmd_status);
++              ret = -EINVAL;
++              break;
++      }
++      return ret;
++}
++
++static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
++              struct usb_device *udev, struct xhci_virt_device *virt_dev)
++{
++      int ret;
++
++      switch (virt_dev->cmd_status) {
++      case COMP_EINVAL:
++              dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate "
++                              "context command.\n");
++              ret = -EINVAL;
++              break;
++      case COMP_EBADSLT:
++              dev_warn(&udev->dev, "WARN: slot not enabled for"
++                              "evaluate context command.\n");
++      case COMP_CTX_STATE:
++              dev_warn(&udev->dev, "WARN: invalid context state for "
++                              "evaluate context command.\n");
++              xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1);
++              ret = -EINVAL;
++              break;
++      case COMP_SUCCESS:
++              dev_dbg(&udev->dev, "Successful evaluate context command\n");
++              ret = 0;
++              break;
++      default:
++              xhci_err(xhci, "ERROR: unexpected command completion "
++                              "code 0x%x.\n", virt_dev->cmd_status);
++              ret = -EINVAL;
++              break;
++      }
++      return ret;
++}
++
++/* Issue a configure endpoint command or evaluate context command
++ * and wait for it to finish.
++ */
++static int xhci_configure_endpoint(struct xhci_hcd *xhci,
++              struct usb_device *udev, struct xhci_virt_device *virt_dev,
++              bool ctx_change)
++{
++      int ret;
++      int timeleft;
++      unsigned long flags;
++
++      spin_lock_irqsave(&xhci->lock, flags);
++      if (!ctx_change)
++              ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
++                              udev->slot_id);
++      else
++              ret = xhci_queue_evaluate_context(xhci, virt_dev->in_ctx->dma,
++                              udev->slot_id);
++      if (ret < 0) {
++              spin_unlock_irqrestore(&xhci->lock, flags);
++              xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
++              return -ENOMEM;
++      }
++      xhci_ring_cmd_db(xhci);
++      spin_unlock_irqrestore(&xhci->lock, flags);
++
++      /* Wait for the configure endpoint command to complete */
++      timeleft = wait_for_completion_interruptible_timeout(
++                      &virt_dev->cmd_completion,
++                      USB_CTRL_SET_TIMEOUT);
++      if (timeleft <= 0) {
++              xhci_warn(xhci, "%s while waiting for %s command\n",
++                              timeleft == 0 ? "Timeout" : "Signal",
++                              ctx_change == 0 ?
++                                      "configure endpoint" :
++                                      "evaluate context");
++              /* FIXME cancel the configure endpoint command */
++              return -ETIME;
++      }
++
++      if (!ctx_change)
++              return xhci_configure_endpoint_result(xhci, udev, virt_dev);
++      return xhci_evaluate_context_result(xhci, udev, virt_dev);
++}
++
+ /* Called after one or more calls to xhci_add_endpoint() or
+  * xhci_drop_endpoint().  If this call fails, the USB core is expected
+  * to call xhci_reset_bandwidth().
+@@ -956,8 +1072,6 @@ int xhci_check_bandwidth(struct usb_hcd 
+ {
+       int i;
+       int ret = 0;
+-      int timeleft;
+-      unsigned long flags;
+       struct xhci_hcd *xhci;
+       struct xhci_virt_device *virt_dev;
+       struct xhci_input_control_ctx *ctrl_ctx;
+@@ -987,56 +1101,7 @@ int xhci_check_bandwidth(struct usb_hcd 
+       xhci_dbg_ctx(xhci, virt_dev->in_ctx,
+                       LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
+-      spin_lock_irqsave(&xhci->lock, flags);
+-      ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
+-                      udev->slot_id);
+-      if (ret < 0) {
+-              spin_unlock_irqrestore(&xhci->lock, flags);
+-              xhci_dbg(xhci, "FIXME allocate a new ring segment\n");
+-              return -ENOMEM;
+-      }
+-      xhci_ring_cmd_db(xhci);
+-      spin_unlock_irqrestore(&xhci->lock, flags);
+-
+-      /* Wait for the configure endpoint command to complete */
+-      timeleft = wait_for_completion_interruptible_timeout(
+-                      &virt_dev->cmd_completion,
+-                      USB_CTRL_SET_TIMEOUT);
+-      if (timeleft <= 0) {
+-              xhci_warn(xhci, "%s while waiting for configure endpoint command\n",
+-                              timeleft == 0 ? "Timeout" : "Signal");
+-              /* FIXME cancel the configure endpoint command */
+-              return -ETIME;
+-      }
+-
+-      switch (virt_dev->cmd_status) {
+-      case COMP_ENOMEM:
+-              dev_warn(&udev->dev, "Not enough host controller resources "
+-                              "for new device state.\n");
+-              ret = -ENOMEM;
+-              /* FIXME: can we allocate more resources for the HC? */
+-              break;
+-      case COMP_BW_ERR:
+-              dev_warn(&udev->dev, "Not enough bandwidth "
+-                              "for new device state.\n");
+-              ret = -ENOSPC;
+-              /* FIXME: can we go back to the old state? */
+-              break;
+-      case COMP_TRB_ERR:
+-              /* the HCD set up something wrong */
+-              dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, add flag = 1, "
+-                              "and endpoint is not disabled.\n");
+-              ret = -EINVAL;
+-              break;
+-      case COMP_SUCCESS:
+-              dev_dbg(&udev->dev, "Successful Endpoint Configure command\n");
+-              break;
+-      default:
+-              xhci_err(xhci, "ERROR: unexpected command completion "
+-                              "code 0x%x.\n", virt_dev->cmd_status);
+-              ret = -EINVAL;
+-              break;
+-      }
++      ret = xhci_configure_endpoint(xhci, udev, virt_dev, false);
+       if (ret) {
+               /* Callee should call reset_bandwidth() */
+               return ret;
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -601,6 +601,44 @@ void xhci_endpoint_zero(struct xhci_hcd 
+        */
+ }
++/* Copy output xhci_ep_ctx to the input xhci_ep_ctx copy.
++ * Useful when you want to change one particular aspect of the endpoint and then
++ * issue a configure endpoint command.
++ */
++void xhci_endpoint_copy(struct xhci_hcd *xhci,
++              struct xhci_virt_device *vdev, unsigned int ep_index)
++{
++      struct xhci_ep_ctx *out_ep_ctx;
++      struct xhci_ep_ctx *in_ep_ctx;
++
++      out_ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index);
++      in_ep_ctx = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index);
++
++      in_ep_ctx->ep_info = out_ep_ctx->ep_info;
++      in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2;
++      in_ep_ctx->deq = out_ep_ctx->deq;
++      in_ep_ctx->tx_info = out_ep_ctx->tx_info;
++}
++
++/* Copy output xhci_slot_ctx to the input xhci_slot_ctx.
++ * Useful when you want to change one particular aspect of the endpoint and then
++ * issue a configure endpoint command.  Only the context entries field matters,
++ * but we'll copy the whole thing anyway.
++ */
++void xhci_slot_copy(struct xhci_hcd *xhci, struct xhci_virt_device *vdev)
++{
++      struct xhci_slot_ctx *in_slot_ctx;
++      struct xhci_slot_ctx *out_slot_ctx;
++
++      in_slot_ctx = xhci_get_slot_ctx(xhci, vdev->in_ctx);
++      out_slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
++
++      in_slot_ctx->dev_info = out_slot_ctx->dev_info;
++      in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2;
++      in_slot_ctx->tt_info = out_slot_ctx->tt_info;
++      in_slot_ctx->dev_state = out_slot_ctx->dev_state;
++}
++
+ /* Set up the scratchpad buffer array and scratchpad buffers, if needed. */
+ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
+ {
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1740,6 +1740,15 @@ int xhci_queue_configure_endpoint(struct
+                       TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
+ }
++/* Queue an evaluate context command TRB */
++int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
++              u32 slot_id)
++{
++      return queue_command(xhci, lower_32_bits(in_ctx_ptr),
++                      upper_32_bits(in_ctx_ptr), 0,
++                      TRB_TYPE(TRB_EVAL_CONTEXT) | SLOT_ID_FOR_TRB(slot_id));
++}
++
+ int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id,
+               unsigned int ep_index)
+ {
diff --git a/queue-2.6.31/usb-xhci-don-t-touch-xhci_td-after-it-s-freed.patch b/queue-2.6.31/usb-xhci-don-t-touch-xhci_td-after-it-s-freed.patch
new file mode 100644 (file)
index 0000000..f799550
--- /dev/null
@@ -0,0 +1,32 @@
+From 9191eee7b8a0e18c07c06d6da502706805cab6d2 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 27 Aug 2009 14:36:14 -0700
+Subject: USB: xhci: Don't touch xhci_td after it's freed.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 9191eee7b8a0e18c07c06d6da502706805cab6d2 upstream.
+
+On a successful transfer, urb->td is freed before the URB is ready to be
+given back to the driver.  Don't touch urb->td after it's freed.  This bug
+would have only shown up when xHCI debugging was turned on, and the freed
+memory was quickly reused for something else.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1193,7 +1193,7 @@ cleanup:
+       if (urb) {
+               usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
+               xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
+-                              urb, td->urb->actual_length, status);
++                              urb, urb->actual_length, status);
+               spin_unlock(&xhci->lock);
+               usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
+               spin_lock(&xhci->lock);
diff --git a/queue-2.6.31/usb-xhci-fix-slot-and-endpoint-context-debugging.patch b/queue-2.6.31/usb-xhci-fix-slot-and-endpoint-context-debugging.patch
new file mode 100644 (file)
index 0000000..97c873d
--- /dev/null
@@ -0,0 +1,40 @@
+From 018218d1d9eb06116d24a02dd5e7a390f0353d0f Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 7 Aug 2009 14:04:40 -0700
+Subject: USB: xhci: Fix slot and endpoint context debugging.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 018218d1d9eb06116d24a02dd5e7a390f0353d0f upstream.
+
+Use the virtual address of the memory hardware uses, not the address for
+the container of that memory.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-dbg.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-dbg.c
++++ b/drivers/usb/host/xhci-dbg.c
+@@ -413,7 +413,8 @@ void xhci_dbg_slot_ctx(struct xhci_hcd *
+       int i;
+       struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
+-      dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx);
++      dma_addr_t dma = ctx->dma +
++              ((unsigned long)slot_ctx - (unsigned long)ctx->bytes);
+       int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
+       xhci_dbg(xhci, "Slot Context:\n");
+@@ -459,7 +460,7 @@ void xhci_dbg_ep_ctx(struct xhci_hcd *xh
+       for (i = 0; i < last_ep_ctx; ++i) {
+               struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
+               dma_addr_t dma = ctx->dma +
+-                      ((unsigned long)ep_ctx - (unsigned long)ctx);
++                      ((unsigned long)ep_ctx - (unsigned long)ctx->bytes);
+               xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
+               xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
diff --git a/queue-2.6.31/usb-xhci-handle-babbling-endpoints-correctly.patch b/queue-2.6.31/usb-xhci-handle-babbling-endpoints-correctly.patch
new file mode 100644 (file)
index 0000000..76790ed
--- /dev/null
@@ -0,0 +1,69 @@
+From 83fbcdcca03013bb5af130d6d91eba11e3d3269e Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 27 Aug 2009 14:36:03 -0700
+Subject: USB: xhci: Handle babbling endpoints correctly.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 83fbcdcca03013bb5af130d6d91eba11e3d3269e upstream.
+
+The 0.95 xHCI spec says that non-control endpoints will be halted if a
+babble is detected on a transfer.  The 0.96 xHCI spec says all types of
+endpoints will be halted when a babble is detected.  Some hardware that
+claims to be 0.95 compliant halts the control endpoint anyway.
+
+When a babble is detected on a control endpoint, check the hardware's
+output endpoint context to see if the endpoint is marked as halted.  If
+the control endpoint is halted, a reset endpoint command must be issued
+and the transfer ring dequeue pointer needs to be moved past the stopped
+transfer.  Basically, we treat it as if the control endpoint had stalled.
+
+Handle bulk babbling endpoints as if we got a completion event with a
+stall completion code.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |   16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -993,6 +993,16 @@ static int handle_tx_event(struct xhci_h
+                       xhci_warn(xhci, "WARN: short transfer on control ep\n");
+                       status = -EREMOTEIO;
+                       break;
++              case COMP_BABBLE:
++                      /* The 0.96 spec says a babbling control endpoint
++                       * is not halted. The 0.96 spec says it is.  Some HW
++                       * claims to be 0.95 compliant, but it halts the control
++                       * endpoint anyway.  Check if a babble halted the
++                       * endpoint.
++                       */
++                      if (ep_ctx->ep_info != EP_STATE_HALTED)
++                              break;
++                      /* else fall through */
+               case COMP_STALL:
+                       /* Did we transfer part of the data (middle) phase? */
+                       if (event_trb != ep_ring->dequeue &&
+@@ -1137,7 +1147,8 @@ static int handle_tx_event(struct xhci_h
+               ep_ring->stopped_td = td;
+               ep_ring->stopped_trb = event_trb;
+       } else {
+-              if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) {
++              if (trb_comp_code == COMP_STALL ||
++                              trb_comp_code == COMP_BABBLE) {
+                       /* The transfer is completed from the driver's
+                        * perspective, but we need to issue a set dequeue
+                        * command for this stalled endpoint to move the dequeue
+@@ -1168,7 +1179,8 @@ td_cleanup:
+                * control endpoints).
+                */
+               if (usb_endpoint_xfer_control(&urb->ep->desc) ||
+-                      GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
++                      (trb_comp_code != COMP_STALL &&
++                              trb_comp_code != COMP_BABBLE)) {
+                       kfree(td);
+               }
+               urb->hcpriv = NULL;
diff --git a/queue-2.6.31/usb-xhci-handle-stalled-control-endpoints.patch b/queue-2.6.31/usb-xhci-handle-stalled-control-endpoints.patch
new file mode 100644 (file)
index 0000000..a4f787a
--- /dev/null
@@ -0,0 +1,190 @@
+From 82d1009f537c2a43be0a410abd33521f76ee3a5a Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 7 Aug 2009 14:04:52 -0700
+Subject: USB: xhci: Handle stalled control endpoints.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 82d1009f537c2a43be0a410abd33521f76ee3a5a upstream.
+
+When a control endpoint stalls, the next control transfer will clear the
+stall.  The USB core doesn't call down to the host controller driver's
+endpoint_reset() method when control endpoints stall, so the xHCI driver
+has to do all its stall handling for internal state in its interrupt handler.
+
+When the host stalls on a control endpoint, it may stop on the data phase
+or status phase of the control transfer.  Like other stalled endpoints,
+the xHCI driver needs to queue a Reset Endpoint command and move the
+hardware's control endpoint ring dequeue pointer past the failed control
+transfer (with a Set TR Dequeue Pointer or a Configure Endpoint command).
+
+Since the USB core doesn't call usb_hcd_reset_endpoint() for control
+endpoints, we need to do this in interrupt context when we get notified of
+the stalled transfer.  URBs may be queued to the hardware before these two
+commands complete.  The endpoint queue will be restarted once both
+commands complete.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-hcd.c  |   35 ++++++++++++++++++++++++-----------
+ drivers/usb/host/xhci-ring.c |   33 ++++++++++++++++++++++++++++++---
+ drivers/usb/host/xhci.h      |    4 ++++
+ 3 files changed, 58 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -589,6 +589,7 @@ struct xhci_ep_ctx {
+  */
+ #define       FORCE_EVENT     (0x1)
+ #define ERROR_COUNT(p)        (((p) & 0x3) << 1)
++#define CTX_TO_EP_TYPE(p)     (((p) >> 3) & 0x7)
+ #define EP_TYPE(p)    ((p) << 3)
+ #define ISOC_OUT_EP   1
+ #define BULK_OUT_EP   2
+@@ -1231,6 +1232,9 @@ void xhci_find_new_dequeue_state(struct 
+ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
+               struct xhci_ring *ep_ring, unsigned int slot_id,
+               unsigned int ep_index, struct xhci_dequeue_state *deq_state);
++void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
++              struct usb_device *udev, struct usb_host_endpoint *ep,
++              unsigned int ep_index, struct xhci_ring *ep_ring);
+ /* xHCI roothub code */
+ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -1230,6 +1230,25 @@ void xhci_reset_bandwidth(struct usb_hcd
+       xhci_zero_in_ctx(xhci, virt_dev);
+ }
++void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
++              struct usb_device *udev, struct usb_host_endpoint *ep,
++              unsigned int ep_index, struct xhci_ring *ep_ring)
++{
++      struct xhci_dequeue_state deq_state;
++
++      xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
++      /* We need to move the HW's dequeue pointer past this TD,
++       * or it will attempt to resend it on the next doorbell ring.
++       */
++      xhci_find_new_dequeue_state(xhci, udev->slot_id,
++                      ep_index, ep_ring->stopped_td, &deq_state);
++
++      xhci_dbg(xhci, "Queueing new dequeue state\n");
++      xhci_queue_new_dequeue_state(xhci, ep_ring,
++                      udev->slot_id,
++                      ep_index, &deq_state);
++}
++
+ /* Deal with stalled endpoints.  The core should have sent the control message
+  * to clear the halt condition.  However, we need to make the xHCI hardware
+  * reset its sequence number, since a device will expect a sequence number of
+@@ -1244,7 +1263,6 @@ void xhci_endpoint_reset(struct usb_hcd 
+       unsigned int ep_index;
+       unsigned long flags;
+       int ret;
+-      struct xhci_dequeue_state deq_state;
+       struct xhci_ring *ep_ring;
+       xhci = hcd_to_xhci(hcd);
+@@ -1261,6 +1279,10 @@ void xhci_endpoint_reset(struct usb_hcd 
+                               ep->desc.bEndpointAddress);
+               return;
+       }
++      if (usb_endpoint_xfer_control(&ep->desc)) {
++              xhci_dbg(xhci, "Control endpoint stall already handled.\n");
++              return;
++      }
+       xhci_dbg(xhci, "Queueing reset endpoint command\n");
+       spin_lock_irqsave(&xhci->lock, flags);
+@@ -1271,16 +1293,7 @@ void xhci_endpoint_reset(struct usb_hcd 
+        * command.  Better hope that last command worked!
+        */
+       if (!ret) {
+-              xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
+-              /* We need to move the HW's dequeue pointer past this TD,
+-               * or it will attempt to resend it on the next doorbell ring.
+-               */
+-              xhci_find_new_dequeue_state(xhci, udev->slot_id,
+-                              ep_index, ep_ring->stopped_td, &deq_state);
+-              xhci_dbg(xhci, "Queueing new dequeue state\n");
+-              xhci_queue_new_dequeue_state(xhci, ep_ring,
+-                              udev->slot_id,
+-                              ep_index, &deq_state);
++              xhci_cleanup_stalled_ring(xhci, udev, ep, ep_index, ep_ring);
+               kfree(ep_ring->stopped_td);
+               xhci_ring_cmd_db(xhci);
+       }
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -817,6 +817,7 @@ static int handle_tx_event(struct xhci_h
+ {
+       struct xhci_virt_device *xdev;
+       struct xhci_ring *ep_ring;
++      unsigned int slot_id;
+       int ep_index;
+       struct xhci_td *td = 0;
+       dma_addr_t event_dma;
+@@ -827,7 +828,8 @@ static int handle_tx_event(struct xhci_h
+       struct xhci_ep_ctx *ep_ctx;
+       xhci_dbg(xhci, "In %s\n", __func__);
+-      xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)];
++      slot_id = TRB_TO_SLOT_ID(event->flags);
++      xdev = xhci->devs[slot_id];
+       if (!xdev) {
+               xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
+               return -ENODEV;
+@@ -941,6 +943,25 @@ static int handle_tx_event(struct xhci_h
+                       xhci_warn(xhci, "WARN: short transfer on control ep\n");
+                       status = -EREMOTEIO;
+                       break;
++              case COMP_STALL:
++                      /* Did we transfer part of the data (middle) phase? */
++                      if (event_trb != ep_ring->dequeue &&
++                                      event_trb != td->last_trb)
++                              td->urb->actual_length =
++                                      td->urb->transfer_buffer_length
++                                      - TRB_LEN(event->transfer_len);
++                      else
++                              td->urb->actual_length = 0;
++
++                      ep_ring->stopped_td = td;
++                      ep_ring->stopped_trb = event_trb;
++                      xhci_queue_reset_ep(xhci, slot_id, ep_index);
++                      xhci_cleanup_stalled_ring(xhci,
++                                      td->urb->dev,
++                                      td->urb->ep,
++                                      ep_index, ep_ring);
++                      xhci_ring_cmd_db(xhci);
++                      goto td_cleanup;
+               default:
+                       /* Others already handled above */
+                       break;
+@@ -1083,6 +1104,7 @@ static int handle_tx_event(struct xhci_h
+                       inc_deq(xhci, ep_ring, false);
+               }
++td_cleanup:
+               /* Clean up the endpoint's TD list */
+               urb = td->urb;
+               list_del(&td->td_list);
+@@ -1091,8 +1113,13 @@ static int handle_tx_event(struct xhci_h
+                       list_del(&td->cancelled_td_list);
+                       ep_ring->cancels_pending--;
+               }
+-              /* Leave the TD around for the reset endpoint function to use */
+-              if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
++              /* Leave the TD around for the reset endpoint function to use
++               * (but only if it's not a control endpoint, since we already
++               * queued the Set TR dequeue pointer command for stalled
++               * control endpoints).
++               */
++              if (usb_endpoint_xfer_control(&urb->ep->desc) ||
++                      GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
+                       kfree(td);
+               }
+               urb->hcpriv = NULL;
diff --git a/queue-2.6.31/usb-xhci-make-trb-completion-code-comparison-readable.patch b/queue-2.6.31/usb-xhci-make-trb-completion-code-comparison-readable.patch
new file mode 100644 (file)
index 0000000..80ded9f
--- /dev/null
@@ -0,0 +1,84 @@
+From 66d1eebce5cca916e0b08d961690bb01c64751ef Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 27 Aug 2009 14:35:53 -0700
+Subject: USB: xhci: Make TRB completion code comparison readable.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 66d1eebce5cca916e0b08d961690bb01c64751ef upstream.
+
+Use trb_comp_code instead of getting the completion code from the transfer
+event every time.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |   16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -874,6 +874,7 @@ static int handle_tx_event(struct xhci_h
+       struct urb *urb = 0;
+       int status = -EINPROGRESS;
+       struct xhci_ep_ctx *ep_ctx;
++      u32 trb_comp_code;
+       xhci_dbg(xhci, "In %s\n", __func__);
+       slot_id = TRB_TO_SLOT_ID(event->flags);
+@@ -931,7 +932,8 @@ static int handle_tx_event(struct xhci_h
+                       (unsigned int) event->flags);
+       /* Look for common error cases */
+-      switch (GET_COMP_CODE(event->transfer_len)) {
++      trb_comp_code = GET_COMP_CODE(event->transfer_len);
++      switch (trb_comp_code) {
+       /* Skip codes that require special handling depending on
+        * transfer type
+        */
+@@ -974,7 +976,7 @@ static int handle_tx_event(struct xhci_h
+       /* Was this a control transfer? */
+       if (usb_endpoint_xfer_control(&td->urb->ep->desc)) {
+               xhci_debug_trb(xhci, xhci->event_ring->dequeue);
+-              switch (GET_COMP_CODE(event->transfer_len)) {
++              switch (trb_comp_code) {
+               case COMP_SUCCESS:
+                       if (event_trb == ep_ring->dequeue) {
+                               xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n");
+@@ -1031,7 +1033,7 @@ static int handle_tx_event(struct xhci_h
+                               }
+                       } else {
+                       /* Maybe the event was for the data stage? */
+-                              if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
++                              if (trb_comp_code != COMP_STOP_INVAL) {
+                                       /* We didn't stop on a link TRB in the middle */
+                                       td->urb->actual_length =
+                                               td->urb->transfer_buffer_length -
+@@ -1043,7 +1045,7 @@ static int handle_tx_event(struct xhci_h
+                       }
+               }
+       } else {
+-              switch (GET_COMP_CODE(event->transfer_len)) {
++              switch (trb_comp_code) {
+               case COMP_SUCCESS:
+                       /* Double check that the HW transferred everything. */
+                       if (event_trb != td->last_trb) {
+@@ -1120,14 +1122,14 @@ static int handle_tx_event(struct xhci_h
+                       /* If the ring didn't stop on a Link or No-op TRB, add
+                        * in the actual bytes transferred from the Normal TRB
+                        */
+-                      if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL)
++                      if (trb_comp_code != COMP_STOP_INVAL)
+                               td->urb->actual_length +=
+                                       TRB_LEN(cur_trb->generic.field[2]) -
+                                       TRB_LEN(event->transfer_len);
+               }
+       }
+-      if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL ||
+-                      GET_COMP_CODE(event->transfer_len) == COMP_STOP) {
++      if (trb_comp_code == COMP_STOP_INVAL ||
++                      trb_comp_code == COMP_STOP) {
+               /* The Endpoint Stop Command completion will take care of any
+                * stopped TDs.  A stopped TD may be restarted, so don't update
+                * the ring dequeue pointer or take this TD off any lists yet.
diff --git a/queue-2.6.31/usb-xhci-set-correct-max-packet-size-for-hs-fs-control-endpoints.patch b/queue-2.6.31/usb-xhci-set-correct-max-packet-size-for-hs-fs-control-endpoints.patch
new file mode 100644 (file)
index 0000000..11a1e31
--- /dev/null
@@ -0,0 +1,63 @@
+From 47aded8ade9fee6779b121b2b156235f261239d7 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 7 Aug 2009 14:04:46 -0700
+Subject: USB: xhci: Set correct max packet size for HS/FS control endpoints.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 47aded8ade9fee6779b121b2b156235f261239d7 upstream.
+
+Set the max packet size for the default control endpoint on high speed
+devices to be 64 bytes.  High speed devices always have a max packet size
+of 64 bytes.  There's no use setting it to eight for the initial 8 byte
+descriptor fetch and then issuing (and waiting for) an evaluate context
+command to update it to 64 bytes for the subsequent control transfers.
+
+The USB core guesses that the max packet size on a full speed control
+endpoint is 64 bytes, and then updates it after the first 8-byte
+descriptor fetch.  Change the initial setup for the xHCI internal
+representation of the full speed device to have a 64 byte max packet size.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c |   23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -401,15 +401,28 @@ int xhci_setup_addressable_virt_dev(stru
+       /* Step 5 */
+       ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP);
+       /*
+-       * See section 4.3 bullet 6:
+-       * The default Max Packet size for ep0 is "8 bytes for a USB2
+-       * LS/FS/HS device or 512 bytes for a USB3 SS device"
+        * XXX: Not sure about wireless USB devices.
+        */
+-      if (udev->speed == USB_SPEED_SUPER)
++      switch (udev->speed) {
++      case USB_SPEED_SUPER:
+               ep0_ctx->ep_info2 |= MAX_PACKET(512);
+-      else
++              break;
++      case USB_SPEED_HIGH:
++      /* USB core guesses at a 64-byte max packet first for FS devices */
++      case USB_SPEED_FULL:
++              ep0_ctx->ep_info2 |= MAX_PACKET(64);
++              break;
++      case USB_SPEED_LOW:
+               ep0_ctx->ep_info2 |= MAX_PACKET(8);
++              break;
++      case USB_SPEED_VARIABLE:
++              xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
++              return -EINVAL;
++              break;
++      default:
++              /* New speed? */
++              BUG();
++      }
+       /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
+       ep0_ctx->ep_info2 |= MAX_BURST(0);
+       ep0_ctx->ep_info2 |= ERROR_COUNT(3);
diff --git a/queue-2.6.31/usb-xhci-set-eremoteio-when-xhc-gives-bad-transfer-length.patch b/queue-2.6.31/usb-xhci-set-eremoteio-when-xhc-gives-bad-transfer-length.patch
new file mode 100644 (file)
index 0000000..0598169
--- /dev/null
@@ -0,0 +1,47 @@
+From 2f697f6cbff155b3ce4053a50cdf00b5be4dda11 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 28 Aug 2009 14:28:18 -0700
+Subject: USB: xhci: Set -EREMOTEIO when xHC gives bad transfer length.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 2f697f6cbff155b3ce4053a50cdf00b5be4dda11 upstream.
+
+The xHCI hardware reports the number of bytes untransferred for a given
+transfer buffer.  If the hardware reports a bytes untransferred value
+greater than the submitted buffer size, we want to play it safe and say no
+data was transferred.  If the driver considers a short packet to be an
+error, remember to set -EREMOTEIO.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1104,6 +1104,11 @@ static int handle_tx_event(struct xhci_h
+                                                       "of %d bytes left\n",
+                                                       TRB_LEN(event->transfer_len));
+                                       td->urb->actual_length = 0;
++                                      if (td->urb->transfer_flags &
++                                                      URB_SHORT_NOT_OK)
++                                              status = -EREMOTEIO;
++                                      else
++                                              status = 0;
+                               }
+                               /* Don't overwrite a previously set error code */
+                               if (status == -EINPROGRESS) {
+@@ -1187,6 +1192,10 @@ td_cleanup:
+                                       urb->transfer_buffer_length,
+                                       urb->actual_length);
+                       urb->actual_length = 0;
++                      if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++                              status = -EREMOTEIO;
++                      else
++                              status = 0;
+               }
+               list_del(&td->td_list);
+               /* Was this TD slated to be cancelled but completed anyway? */
diff --git a/queue-2.6.31/usb-xhci-support-full-speed-devices.patch b/queue-2.6.31/usb-xhci-support-full-speed-devices.patch
new file mode 100644 (file)
index 0000000..7a6870d
--- /dev/null
@@ -0,0 +1,180 @@
+From 2d3f1fac7ee8bb4c6fad40f838488edbeabb0c50 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 7 Aug 2009 14:04:49 -0700
+Subject: USB: xhci: Support full speed devices.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 2d3f1fac7ee8bb4c6fad40f838488edbeabb0c50 upstream.
+
+Full speed devices have varying max packet sizes (8, 16, 32, or 64) for
+endpoint 0.  The xHCI hardware needs to know the real max packet size
+that the USB core discovers after it fetches the first 8 bytes of the
+device descriptor.
+
+In order to fix this without adding a new hook to host controller drivers,
+the xHCI driver looks for an updated max packet size for control
+endpoints.  If it finds an updated size, it issues an evaluate context
+command and waits for that command to finish.  This should only happen in
+the initialization and device descriptor fetching steps in the khubd
+thread, so blocking should be fine.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-hcd.c  |   88 ++++++++++++++++++++++++++++++++++++++++---
+ drivers/usb/host/xhci-ring.c |    4 +
+ drivers/usb/host/xhci.h      |    2 
+ 3 files changed, 89 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -601,6 +601,8 @@ struct xhci_ep_ctx {
+ /* bit 7 is Host Initiate Disable - for disabling stream selection */
+ #define MAX_BURST(p)  (((p)&0xff) << 8)
+ #define MAX_PACKET(p) (((p)&0xffff) << 16)
++#define MAX_PACKET_MASK               (0xffff << 16)
++#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff)
+ /**
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -601,6 +601,70 @@ int xhci_check_args(struct usb_hcd *hcd,
+       return 1;
+ }
++static int xhci_configure_endpoint(struct xhci_hcd *xhci,
++              struct usb_device *udev, struct xhci_virt_device *virt_dev,
++              bool ctx_change);
++
++/*
++ * Full speed devices may have a max packet size greater than 8 bytes, but the
++ * USB core doesn't know that until it reads the first 8 bytes of the
++ * descriptor.  If the usb_device's max packet size changes after that point,
++ * we need to issue an evaluate context command and wait on it.
++ */
++static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
++              unsigned int ep_index, struct urb *urb)
++{
++      struct xhci_container_ctx *in_ctx;
++      struct xhci_container_ctx *out_ctx;
++      struct xhci_input_control_ctx *ctrl_ctx;
++      struct xhci_ep_ctx *ep_ctx;
++      int max_packet_size;
++      int hw_max_packet_size;
++      int ret = 0;
++
++      out_ctx = xhci->devs[slot_id]->out_ctx;
++      ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
++      hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2);
++      max_packet_size = urb->dev->ep0.desc.wMaxPacketSize;
++      if (hw_max_packet_size != max_packet_size) {
++              xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n");
++              xhci_dbg(xhci, "Max packet size in usb_device = %d\n",
++                              max_packet_size);
++              xhci_dbg(xhci, "Max packet size in xHCI HW = %d\n",
++                              hw_max_packet_size);
++              xhci_dbg(xhci, "Issuing evaluate context command.\n");
++
++              /* Set up the modified control endpoint 0 */
++              xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index);
++              in_ctx = xhci->devs[slot_id]->in_ctx;
++              ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
++              ep_ctx->ep_info2 &= ~MAX_PACKET_MASK;
++              ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size);
++
++              /* Set up the input context flags for the command */
++              /* FIXME: This won't work if a non-default control endpoint
++               * changes max packet sizes.
++               */
++              ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
++              ctrl_ctx->add_flags = EP0_FLAG;
++              ctrl_ctx->drop_flags = 0;
++
++              xhci_dbg(xhci, "Slot %d input context\n", slot_id);
++              xhci_dbg_ctx(xhci, in_ctx, ep_index);
++              xhci_dbg(xhci, "Slot %d output context\n", slot_id);
++              xhci_dbg_ctx(xhci, out_ctx, ep_index);
++
++              ret = xhci_configure_endpoint(xhci, urb->dev,
++                              xhci->devs[slot_id], true);
++
++              /* Clean up the input context for later use by bandwidth
++               * functions.
++               */
++              ctrl_ctx->add_flags = SLOT_FLAG;
++      }
++      return ret;
++}
++
+ /*
+  * non-error returns are a promise to giveback() the urb later
+  * we drop ownership so next owner (or urb unlink) can get it
+@@ -612,13 +676,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+       int ret = 0;
+       unsigned int slot_id, ep_index;
++
+       if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
+               return -EINVAL;
+       slot_id = urb->dev->slot_id;
+       ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+-      spin_lock_irqsave(&xhci->lock, flags);
+       if (!xhci->devs || !xhci->devs[slot_id]) {
+               if (!in_interrupt())
+                       dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n");
+@@ -631,19 +695,33 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+               ret = -ESHUTDOWN;
+               goto exit;
+       }
+-      if (usb_endpoint_xfer_control(&urb->ep->desc))
++      if (usb_endpoint_xfer_control(&urb->ep->desc)) {
++              /* Check to see if the max packet size for the default control
++               * endpoint changed during FS device enumeration
++               */
++              if (urb->dev->speed == USB_SPEED_FULL) {
++                      ret = xhci_check_maxpacket(xhci, slot_id,
++                                      ep_index, urb);
++                      if (ret < 0)
++                              return ret;
++              }
++
+               /* We have a spinlock and interrupts disabled, so we must pass
+                * atomic context to this function, which may allocate memory.
+                */
++              spin_lock_irqsave(&xhci->lock, flags);
+               ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
+                               slot_id, ep_index);
+-      else if (usb_endpoint_xfer_bulk(&urb->ep->desc))
++              spin_unlock_irqrestore(&xhci->lock, flags);
++      } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) {
++              spin_lock_irqsave(&xhci->lock, flags);
+               ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
+                               slot_id, ep_index);
+-      else
++              spin_unlock_irqrestore(&xhci->lock, flags);
++      } else {
+               ret = -EINVAL;
++      }
+ exit:
+-      spin_unlock_irqrestore(&xhci->lock, flags);
+       return ret;
+ }
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -701,6 +701,10 @@ static void handle_cmd_completion(struct
+               xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
+               complete(&xhci->devs[slot_id]->cmd_completion);
+               break;
++      case TRB_TYPE(TRB_EVAL_CONTEXT):
++              xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
++              complete(&xhci->devs[slot_id]->cmd_completion);
++              break;
+       case TRB_TYPE(TRB_ADDR_DEV):
+               xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
+               complete(&xhci->addr_dev);
diff --git a/queue-2.6.31/usb-xhci-support-interrupt-transfers.patch b/queue-2.6.31/usb-xhci-support-interrupt-transfers.patch
new file mode 100644 (file)
index 0000000..63b8e9c
--- /dev/null
@@ -0,0 +1,132 @@
+From 624defa12f304b4d11eda309bc207fa5a1900d0f Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Wed, 2 Sep 2009 12:14:28 -0700
+Subject: USB: xhci: Support interrupt transfers.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 624defa12f304b4d11eda309bc207fa5a1900d0f upstream.
+
+Interrupt transfers are submitted to the xHCI hardware using the same TRB
+type as bulk transfers.  Re-use the bulk transfer enqueueing code to
+enqueue interrupt transfers.
+
+Interrupt transfers are a bit different than bulk transfers.  When the
+interrupt endpoint is to be serviced, the xHC will consume (at most) one
+TD.  A TD (comprised of sg list entries) can take several service
+intervals to transmit.  The important thing for device drivers to note is
+that if they use the scatter gather interface to submit interrupt
+requests, they will not get data sent from two different scatter gather
+lists in the same service interval.
+
+For now, the xHCI driver will use the service interval from the endpoint's
+descriptor (bInterval).  Drivers will need a hook to poll at a more
+frequent interval.  Set urb->interval to the interval that the xHCI
+hardware will use.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-hcd.c  |    5 ++++
+ drivers/usb/host/xhci-ring.c |   48 ++++++++++++++++++++++++++++++++++++++++++-
+ drivers/usb/host/xhci.h      |    3 ++
+ 3 files changed, 55 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -581,6 +581,7 @@ struct xhci_ep_ctx {
+ /* bit 15 is Linear Stream Array */
+ /* Interval - period between requests to an endpoint - 125u increments. */
+ #define EP_INTERVAL(p)                ((p & 0xff) << 16)
++#define EP_INTERVAL_TO_UFRAMES(p)             (1 << (((p) >> 16) & 0xff))
+ /* ep_info2 bitmasks */
+ /*
+@@ -1223,6 +1224,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+               int slot_id, unsigned int ep_index);
+ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
+               int slot_id, unsigned int ep_index);
++int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
++              int slot_id, unsigned int ep_index);
+ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+               u32 slot_id);
+ int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -727,6 +727,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+               ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
+                               slot_id, ep_index);
+               spin_unlock_irqrestore(&xhci->lock, flags);
++      } else if (usb_endpoint_xfer_int(&urb->ep->desc)) {
++              spin_lock_irqsave(&xhci->lock, flags);
++              ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb,
++                              slot_id, ep_index);
++              spin_unlock_irqrestore(&xhci->lock, flags);
+       } else {
+               ret = -EINVAL;
+       }
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1072,7 +1072,12 @@ static int handle_tx_event(struct xhci_h
+                               else
+                                       status = 0;
+                       } else {
+-                              xhci_dbg(xhci, "Successful bulk transfer!\n");
++                              if (usb_endpoint_xfer_bulk(&td->urb->ep->desc))
++                                      xhci_dbg(xhci, "Successful bulk "
++                                                      "transfer!\n");
++                              else
++                                      xhci_dbg(xhci, "Successful interrupt "
++                                                      "transfer!\n");
+                               status = 0;
+                       }
+                       break;
+@@ -1464,6 +1469,47 @@ static void giveback_first_trb(struct xh
+       ring_ep_doorbell(xhci, slot_id, ep_index);
+ }
++/*
++ * xHCI uses normal TRBs for both bulk and interrupt.  When the interrupt
++ * endpoint is to be serviced, the xHC will consume (at most) one TD.  A TD
++ * (comprised of sg list entries) can take several service intervals to
++ * transmit.
++ */
++int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
++              struct urb *urb, int slot_id, unsigned int ep_index)
++{
++      struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci,
++                      xhci->devs[slot_id]->out_ctx, ep_index);
++      int xhci_interval;
++      int ep_interval;
++
++      xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info);
++      ep_interval = urb->interval;
++      /* Convert to microframes */
++      if (urb->dev->speed == USB_SPEED_LOW ||
++                      urb->dev->speed == USB_SPEED_FULL)
++              ep_interval *= 8;
++      /* FIXME change this to a warning and a suggestion to use the new API
++       * to set the polling interval (once the API is added).
++       */
++      if (xhci_interval != ep_interval) {
++              if (!printk_ratelimit())
++                      dev_dbg(&urb->dev->dev, "Driver uses different interval"
++                                      " (%d microframe%s) than xHCI "
++                                      "(%d microframe%s)\n",
++                                      ep_interval,
++                                      ep_interval == 1 ? "" : "s",
++                                      xhci_interval,
++                                      xhci_interval == 1 ? "" : "s");
++              urb->interval = xhci_interval;
++              /* Convert back to frames for LS/FS devices */
++              if (urb->dev->speed == USB_SPEED_LOW ||
++                              urb->dev->speed == USB_SPEED_FULL)
++                      urb->interval /= 8;
++      }
++      return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
++}
++
+ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+               struct urb *urb, int slot_id, unsigned int ep_index)
+ {
diff --git a/queue-2.6.31/usb-xhci-work-around-for-chain-bit-in-link-trbs.patch b/queue-2.6.31/usb-xhci-work-around-for-chain-bit-in-link-trbs.patch
new file mode 100644 (file)
index 0000000..ffeeb8a
--- /dev/null
@@ -0,0 +1,145 @@
+From b0567b3f635db72c881a0d561cebb544ec085073 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Fri, 7 Aug 2009 14:04:36 -0700
+Subject: USB: xhci: Work around for chain bit in link TRBs.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit b0567b3f635db72c881a0d561cebb544ec085073 upstream.
+
+Different sections of the xHCI 0.95 specification had opposing
+requirements for the chain bit in a link transaction request buffer (TRB).
+The chain bit is used to designate that adjacent TRBs are all part of the
+same scatter gather list that should be sent to the device.  Link TRBs can
+be in the middle, or at the beginning or end of these chained TRBs.
+
+Sections 4.11.5.1 and 6.4.4.1 both stated the link TRB "shall have the
+chain bit set to 1", meaning it is always chained to the next TRB.
+However, section 4.6.9 on the stop endpoint command has specific cases for
+what the hardware must do for a link TRB with the chain bit set to 0.  The
+0.96 specification errata later cleared up this issue by fixing the
+4.11.5.1 and 6.4.4.1 sections to state that a link TRB can have the chain
+bit set to 1 or 0.
+
+The problem is that the xHCI cancellation code depends on the chain bit of
+the link TRB being cleared when it's at the end of a TD, and some 0.95
+xHCI hardware simply stops processing the ring when it encounters a link
+TRB with the chain bit cleared.
+
+Allow users who are testing 0.95 xHCI prototypes to set a module parameter
+(link_quirk) to turn on this link TRB work around.  Cancellation may not
+work if the ring is stopped exactly on a link TRB with chain bit set, but
+cancellation should be a relatively uncommon case.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-hcd.c  |   12 ++++++++++++
+ drivers/usb/host/xhci-mem.c  |    3 +++
+ drivers/usb/host/xhci-ring.c |   15 +++++++++++----
+ drivers/usb/host/xhci.h      |    9 +++++++++
+ 4 files changed, 35 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1058,6 +1058,8 @@ struct xhci_hcd {
+       int                     noops_submitted;
+       int                     noops_handled;
+       int                     error_bitmask;
++      unsigned int            quirks;
++#define       XHCI_LINK_TRB_QUIRK     (1 << 0)
+ };
+ /* For testing purposes */
+@@ -1136,6 +1138,13 @@ static inline void xhci_write_64(struct 
+       writel(val_hi, ptr + 1);
+ }
++static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
++{
++      u32 temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase);
++      return ((HC_VERSION(temp) == 0x95) &&
++                      (xhci->quirks & XHCI_LINK_TRB_QUIRK));
++}
++
+ /* xHCI debugging */
+ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
+ void xhci_print_registers(struct xhci_hcd *xhci);
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -22,12 +22,18 @@
+ #include <linux/irq.h>
+ #include <linux/module.h>
++#include <linux/moduleparam.h>
+ #include "xhci.h"
+ #define DRIVER_AUTHOR "Sarah Sharp"
+ #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
++/* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
++static int link_quirk;
++module_param(link_quirk, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB");
++
+ /* TODO: copied from ehci-hcd.c - can this be refactored? */
+ /*
+  * handshake - spin reading hc until handshake completes or fails
+@@ -214,6 +220,12 @@ int xhci_init(struct usb_hcd *hcd)
+       xhci_dbg(xhci, "xhci_init\n");
+       spin_lock_init(&xhci->lock);
++      if (link_quirk) {
++              xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits.\n");
++              xhci->quirks |= XHCI_LINK_TRB_QUIRK;
++      } else {
++              xhci_dbg(xhci, "xHCI has no QUIRKS\n");
++      }
+       retval = xhci_mem_init(xhci, GFP_KERNEL);
+       xhci_dbg(xhci, "Finished xhci_init\n");
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -94,6 +94,9 @@ static void xhci_link_segments(struct xh
+               val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
+               val &= ~TRB_TYPE_BITMASK;
+               val |= TRB_TYPE(TRB_LINK);
++              /* Always set the chain bit with 0.95 hardware */
++              if (xhci_link_trb_quirk(xhci))
++                      val |= TRB_CHAIN;
+               prev->trbs[TRBS_PER_SEGMENT-1].link.control = val;
+       }
+       xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n",
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -172,8 +172,9 @@ static void inc_deq(struct xhci_hcd *xhc
+  * have their chain bit cleared (so that each Link TRB is a separate TD).
+  *
+  * Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit
+- * set, but other sections talk about dealing with the chain bit set.
+- * Assume section 6.4.4.1 is wrong, and the chain bit can be set in a Link TRB.
++ * set, but other sections talk about dealing with the chain bit set.  This was
++ * fixed in the 0.96 specification errata, but we have to assume that all 0.95
++ * xHCI hardware can't handle the chain bit being cleared on a link TRB.
+  */
+ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
+ {
+@@ -191,8 +192,14 @@ static void inc_enq(struct xhci_hcd *xhc
+       while (last_trb(xhci, ring, ring->enq_seg, next)) {
+               if (!consumer) {
+                       if (ring != xhci->event_ring) {
+-                              next->link.control &= ~TRB_CHAIN;
+-                              next->link.control |= chain;
++                              /* If we're not dealing with 0.95 hardware,
++                               * carry over the chain bit of the previous TRB
++                               * (which may mean the chain bit is cleared).
++                               */
++                              if (!xhci_link_trb_quirk(xhci)) {
++                                      next->link.control &= ~TRB_CHAIN;
++                                      next->link.control |= chain;
++                              }
+                               /* Give this link TRB to the hardware */
+                               wmb();
+                               if (next->link.control & TRB_CYCLE)