aboutsummaryrefslogtreecommitdiffstats
path: root/usb.current
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-07-27 12:38:48 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-07-27 12:38:48 -0700
commit5ecb6c37c2cb884b005c862309fe3cf70755b536 (patch)
treeac71489a2fd01d98c52bfd01f9d2f858b40f91f0 /usb.current
parent65cf46e6d75002ca50a34ef2fefc772a23f5aa97 (diff)
downloadpatches-5ecb6c37c2cb884b005c862309fe3cf70755b536.tar.gz
xhci patches
Diffstat (limited to 'usb.current')
-rw-r--r--usb.current/usb-fix-parsing-of-superspeed-endpoint-companion-descriptor.patch108
-rw-r--r--usb.current/usb-xhci-always-align-output-device-contexts-to-64-bytes.patch287
-rw-r--r--usb.current/usb-xhci-check-if-the-host-controller-died-in-irq-handler.patch36
-rw-r--r--usb.current/usb-xhci-correct-event-handler-busy-flag-usage.patch55
-rw-r--r--usb.current/usb-xhci-deal-with-stalled-endpoints.patch219
-rw-r--r--usb.current/usb-xhci-don-t-oops-if-the-host-doesn-t-halt.patch30
-rw-r--r--usb.current/usb-xhci-fail-gracefully-if-there-s-no-ss-ep-companion-descriptor.patch36
-rw-r--r--usb.current/usb-xhci-handle-babble-errors-on-transfers.patch31
-rw-r--r--usb.current/usb-xhci-handle-short-control-packets-correctly.patch56
-rw-r--r--usb.current/usb-xhci-make-debugging-more-verbose.patch291
-rw-r--r--usb.current/usb-xhci-represent-64-bit-addresses-with-one-u64.patch744
-rw-r--r--usb.current/usb-xhci-scratchpad-buffer-allocation.patch185
-rw-r--r--usb.current/usb-xhci-set-td-size-in-transfer-trb.patch97
-rw-r--r--usb.current/usb-xhci-setup-hw-retries-correctly.patch43
-rw-r--r--usb.current/usb-xhci-stall-handling-bug-fixes.patch362
-rw-r--r--usb.current/usb-xhci-support-for-64-byte-contexts.patch925
-rw-r--r--usb.current/usb-xhci-use-gfp_atomic-while-holding-spinlocks.patch40
17 files changed, 3545 insertions, 0 deletions
diff --git a/usb.current/usb-fix-parsing-of-superspeed-endpoint-companion-descriptor.patch b/usb.current/usb-fix-parsing-of-superspeed-endpoint-companion-descriptor.patch
new file mode 100644
index 00000000000000..278cecff3d474d
--- /dev/null
+++ b/usb.current/usb-fix-parsing-of-superspeed-endpoint-companion-descriptor.patch
@@ -0,0 +1,108 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:29:49 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:04:52 -0700
+Subject: USB: Fix parsing of SuperSpeed Endpoint Companion descriptor.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190452.GA7915@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+usb_parse_ss_endpoint_companion() was supposed to allocate a structure to
+hold the SuperSpeed Endpoint Companion descriptor, and either copy the
+values the device returned, or fill in default values if the device
+descriptor did not include the companion descriptor.
+
+However, the previous code would miss the last endpoint in a configuration
+with no descriptors after it. Make usb_parse_endpoint() allocate the SS
+endpoint companion descriptor and fill it with default values, even if
+we've run out of buffer space in this configuration 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 | 48 +++++++++++++++++++++++++---------------------
+ 1 file changed, 27 insertions(+), 21 deletions(-)
+
+--- a/drivers/usb/core/config.c
++++ b/drivers/usb/core/config.c
+@@ -80,38 +80,18 @@ static int usb_parse_ss_endpoint_compani
+ int max_tx;
+ int i;
+
+- /* Allocate space for the SS endpoint companion descriptor */
+- ep->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
+- GFP_KERNEL);
+- if (!ep->ss_ep_comp)
+- return -ENOMEM;
+ desc = (struct usb_ss_ep_comp_descriptor *) buffer;
+ if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
+ dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
+ " interface %d altsetting %d ep %d: "
+ "using minimum values\n",
+ cfgno, inum, asnum, ep->desc.bEndpointAddress);
+- ep->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
+- ep->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
+- ep->ss_ep_comp->desc.bMaxBurst = 0;
+- /*
+- * Leave bmAttributes as zero, which will mean no streams for
+- * bulk, and isoc won't support multiple bursts of packets.
+- * With bursts of only one packet, and a Mult of 1, the max
+- * amount of data moved per endpoint service interval is one
+- * packet.
+- */
+- if (usb_endpoint_xfer_isoc(&ep->desc) ||
+- usb_endpoint_xfer_int(&ep->desc))
+- ep->ss_ep_comp->desc.wBytesPerInterval =
+- ep->desc.wMaxPacketSize;
+ /*
+ * The next descriptor is for an Endpoint or Interface,
+ * no extra descriptors to copy into the companion structure,
+ * and we didn't eat up any of the buffer.
+ */
+- retval = 0;
+- goto valid;
++ return 0;
+ }
+ memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE);
+ desc = &ep->ss_ep_comp->desc;
+@@ -320,6 +300,28 @@ static int usb_parse_endpoint(struct dev
+ buffer += i;
+ size -= i;
+
++ /* Allocate space for the SS endpoint companion descriptor */
++ endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
++ GFP_KERNEL);
++ if (!endpoint->ss_ep_comp)
++ return -ENOMEM;
++
++ /* Fill in some default values (may be overwritten later) */
++ endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
++ endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
++ endpoint->ss_ep_comp->desc.bMaxBurst = 0;
++ /*
++ * Leave bmAttributes as zero, which will mean no streams for
++ * bulk, and isoc won't support multiple bursts of packets.
++ * With bursts of only one packet, and a Mult of 1, the max
++ * amount of data moved per endpoint service interval is one
++ * packet.
++ */
++ if (usb_endpoint_xfer_isoc(&endpoint->desc) ||
++ usb_endpoint_xfer_int(&endpoint->desc))
++ endpoint->ss_ep_comp->desc.wBytesPerInterval =
++ endpoint->desc.wMaxPacketSize;
++
+ if (size > 0) {
+ retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
+ inum, asnum, endpoint, num_ep, buffer,
+@@ -329,6 +331,10 @@ static int usb_parse_endpoint(struct dev
+ retval = buffer - buffer0;
+ }
+ } else {
++ dev_warn(ddev, "config %d interface %d altsetting %d "
++ "endpoint 0x%X has no "
++ "SuperSpeed companion descriptor\n",
++ cfgno, inum, asnum, d->bEndpointAddress);
+ retval = buffer - buffer0;
+ }
+ } else {
diff --git a/usb.current/usb-xhci-always-align-output-device-contexts-to-64-bytes.patch b/usb.current/usb-xhci-always-align-output-device-contexts-to-64-bytes.patch
new file mode 100644
index 00000000000000..4a97a1e30f16b5
--- /dev/null
+++ b/usb.current/usb-xhci-always-align-output-device-contexts-to-64-bytes.patch
@@ -0,0 +1,287 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:31:34 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:05:08 -0700
+Subject: USB: xhci: Always align output device contexts to 64 bytes.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190508.GA7988@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+Make sure the xHCI output device context is 64-byte aligned. Previous
+code was using the same structure for both the output device context and
+the input control context. Since the structure had 32 bytes of flags
+before the device context, the output device context wouldn't be 64-byte
+aligned. Define a new structure to use for the output device context and
+clean up the debugging for these two structures.
+
+The copy of the device context in the input control context does *not*
+need to be 64-byte aligned.
+
+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 | 101 +++++++++++++++++++++++++++-----------------
+ drivers/usb/host/xhci-hcd.c | 7 ---
+ drivers/usb/host/xhci-mem.c | 15 +++---
+ drivers/usb/host/xhci.h | 19 +++++++-
+ 4 files changed, 89 insertions(+), 53 deletions(-)
+
+--- a/drivers/usb/host/xhci-dbg.c
++++ b/drivers/usb/host/xhci-dbg.c
+@@ -393,78 +393,103 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *
+ upper_32_bits(val));
+ }
+
+-void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep)
++dma_addr_t xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_slot_ctx *slot, dma_addr_t dma)
+ {
+- int i, j;
+- int last_ep_ctx = 31;
+ /* Fields are 32 bits wide, DMA addresses are in bytes */
+ int field_size = 32 / 8;
+-
+- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
+- &ctx->drop_flags, (unsigned long long)dma,
+- ctx->drop_flags);
+- dma += field_size;
+- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
+- &ctx->add_flags, (unsigned long long)dma,
+- ctx->add_flags);
+- dma += field_size;
+- for (i = 0; i < 6; ++i) {
+- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
+- &ctx->rsvd[i], (unsigned long long)dma,
+- ctx->rsvd[i], i);
+- dma += field_size;
+- }
++ int i;
+
+ xhci_dbg(xhci, "Slot Context:\n");
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n",
+- &ctx->slot.dev_info,
+- (unsigned long long)dma, ctx->slot.dev_info);
++ &slot->dev_info,
++ (unsigned long long)dma, slot->dev_info);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n",
+- &ctx->slot.dev_info2,
+- (unsigned long long)dma, ctx->slot.dev_info2);
++ &slot->dev_info2,
++ (unsigned long long)dma, slot->dev_info2);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n",
+- &ctx->slot.tt_info,
+- (unsigned long long)dma, ctx->slot.tt_info);
++ &slot->tt_info,
++ (unsigned long long)dma, slot->tt_info);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n",
+- &ctx->slot.dev_state,
+- (unsigned long long)dma, ctx->slot.dev_state);
++ &slot->dev_state,
++ (unsigned long long)dma, slot->dev_state);
+ dma += field_size;
+ for (i = 0; i < 4; ++i) {
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
+- &ctx->slot.reserved[i], (unsigned long long)dma,
+- ctx->slot.reserved[i], i);
++ &slot->reserved[i], (unsigned long long)dma,
++ slot->reserved[i], i);
+ dma += field_size;
+ }
+
++ return dma;
++}
++
++dma_addr_t xhci_dbg_ep_ctx(struct xhci_hcd *xhci, struct xhci_ep_ctx *ep, dma_addr_t dma, unsigned int last_ep)
++{
++ int i, j;
++ int last_ep_ctx = 31;
++ /* Fields are 32 bits wide, DMA addresses are in bytes */
++ int field_size = 32 / 8;
++
+ if (last_ep < 31)
+ last_ep_ctx = last_ep + 1;
+ for (i = 0; i < last_ep_ctx; ++i) {
+ xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
+- &ctx->ep[i].ep_info,
+- (unsigned long long)dma, ctx->ep[i].ep_info);
++ &ep[i].ep_info,
++ (unsigned long long)dma, ep[i].ep_info);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n",
+- &ctx->ep[i].ep_info2,
+- (unsigned long long)dma, ctx->ep[i].ep_info2);
++ &ep[i].ep_info2,
++ (unsigned long long)dma, ep[i].ep_info2);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n",
+- &ctx->ep[i].deq,
+- (unsigned long long)dma, ctx->ep[i].deq);
++ &ep[i].deq,
++ (unsigned long long)dma, ep[i].deq);
+ dma += 2*field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n",
+- &ctx->ep[i].tx_info,
+- (unsigned long long)dma, ctx->ep[i].tx_info);
++ &ep[i].tx_info,
++ (unsigned long long)dma, ep[i].tx_info);
+ dma += field_size;
+ for (j = 0; j < 3; ++j) {
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
+- &ctx->ep[i].reserved[j],
++ &ep[i].reserved[j],
+ (unsigned long long)dma,
+- ctx->ep[i].reserved[j], j);
++ ep[i].reserved[j], j);
+ dma += field_size;
+ }
+ }
++ return dma;
++}
++
++void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep)
++{
++ int i;
++ /* Fields are 32 bits wide, DMA addresses are in bytes */
++ int field_size = 32 / 8;
++
++ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
++ &ctx->drop_flags, (unsigned long long)dma,
++ ctx->drop_flags);
++ dma += field_size;
++ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
++ &ctx->add_flags, (unsigned long long)dma,
++ ctx->add_flags);
++ dma += field_size;
++ for (i = 0; i < 6; ++i) {
++ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
++ &ctx->rsvd[i], (unsigned long long)dma,
++ ctx->rsvd[i], i);
++ dma += field_size;
++ }
++ dma = xhci_dbg_slot_ctx(xhci, &ctx->slot, dma);
++ dma = xhci_dbg_ep_ctx(xhci, ctx->ep, dma, last_ep);
++}
++
++void xhci_dbg_device_ctx(struct xhci_hcd *xhci, struct xhci_device_ctx *ctx, dma_addr_t dma, unsigned int last_ep)
++{
++ dma = xhci_dbg_slot_ctx(xhci, &ctx->slot, dma);
++ dma = xhci_dbg_ep_ctx(xhci, ctx->ep, dma, last_ep);
+ }
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -584,15 +584,29 @@ struct xhci_ep_ctx {
+
+ /**
+ * struct xhci_device_control
+- * Input/Output context; see section 6.2.5.
++ * Input context; see section 6.2.5.
+ *
+ * @drop_context: set the bit of the endpoint context you want to disable
+ * @add_context: set the bit of the endpoint context you want to enable
+ */
+ struct xhci_device_control {
++ /* Input control context */
+ u32 drop_flags;
+ u32 add_flags;
+ u32 rsvd[6];
++ /* Copy of device context */
++ struct xhci_slot_ctx slot;
++ struct xhci_ep_ctx ep[31];
++};
++
++/**
++ * struct xhci_device_ctx
++ * Device context; see section 6.2.1.
++ *
++ * @slot: slot context for the device.
++ * @ep: array of endpoint contexts for the device.
++ */
++struct xhci_device_ctx {
+ struct xhci_slot_ctx slot;
+ struct xhci_ep_ctx ep[31];
+ };
+@@ -612,7 +626,7 @@ struct xhci_virt_device {
+ * track of input and output contexts separately because
+ * these commands might fail and we don't trust the hardware.
+ */
+- struct xhci_device_control *out_ctx;
++ struct xhci_device_ctx *out_ctx;
+ dma_addr_t out_ctx_dma;
+ /* Used for addressing devices and configuration changes */
+ struct xhci_device_control *in_ctx;
+@@ -1126,6 +1140,7 @@ void xhci_dbg_erst(struct xhci_hcd *xhci
+ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci);
+ void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
+ void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep);
++void xhci_dbg_device_ctx(struct xhci_hcd *xhci, struct xhci_device_ctx *ctx, dma_addr_t dma, unsigned int last_ep);
+
+ /* xHCI memory managment */
+ void xhci_mem_cleanup(struct xhci_hcd *xhci);
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -1013,7 +1013,7 @@ int xhci_check_bandwidth(struct usb_hcd
+ }
+
+ xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
+- xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma,
++ xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma,
+ LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
+
+ xhci_zero_in_ctx(virt_dev);
+@@ -1265,7 +1265,7 @@ int xhci_address_device(struct usb_hcd *
+ xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
+ xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2);
+ xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
+- xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2);
++ xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2);
+ /*
+ * USB core uses address 1 for the roothubs, so we add one to the
+ * address given back to us by the HC.
+@@ -1274,9 +1274,6 @@ int xhci_address_device(struct usb_hcd *
+ /* Zero the input context control for later use */
+ virt_dev->in_ctx->add_flags = 0;
+ virt_dev->in_ctx->drop_flags = 0;
+- /* Mirror flags in the output context for future ep enable/disable */
+- virt_dev->out_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
+- virt_dev->out_ctx->drop_flags = 0;
+
+ xhci_dbg(xhci, "Device address = %d\n", udev->devnum);
+ /* XXX Meh, not sure if anyone else but choose_address uses this. */
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -235,7 +235,10 @@ int xhci_alloc_virt_device(struct xhci_h
+ return 0;
+ dev = xhci->devs[slot_id];
+
+- /* Allocate the (output) device context that will be used in the HC */
++ /* Allocate the (output) device context that will be used in the HC.
++ * The structure is 32 bytes smaller than the input context, but that's
++ * fine.
++ */
+ dev->out_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma);
+ if (!dev->out_ctx)
+ goto fail;
+@@ -260,16 +263,12 @@ int xhci_alloc_virt_device(struct xhci_h
+
+ init_completion(&dev->cmd_completion);
+
+- /*
+- * Point to output device context in dcbaa; skip the output control
+- * context, which is eight 32 bit fields (or 32 bytes long)
+- */
+- xhci->dcbaa->dev_context_ptrs[slot_id] =
+- (u32) dev->out_ctx_dma + (32);
++ /* Point to output device context in dcbaa. */
++ xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx_dma;
+ xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
+ slot_id,
+ &xhci->dcbaa->dev_context_ptrs[slot_id],
+- (unsigned long long)dev->out_ctx_dma);
++ (unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id]);
+
+ return 1;
+ fail:
diff --git a/usb.current/usb-xhci-check-if-the-host-controller-died-in-irq-handler.patch b/usb.current/usb-xhci-check-if-the-host-controller-died-in-irq-handler.patch
new file mode 100644
index 00000000000000..88c6ebff5335e1
--- /dev/null
+++ b/usb.current/usb-xhci-check-if-the-host-controller-died-in-irq-handler.patch
@@ -0,0 +1,36 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:28:48 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:04:01 -0700
+Subject: USB: xhci: Check if the host controller died in IRQ handler.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190401.GA7765@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+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 | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -277,6 +277,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd
+ /* Check if the xHC generated the interrupt, or the irq is shared */
+ temp = xhci_readl(xhci, &xhci->op_regs->status);
+ temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending);
++ if (temp == 0xffffffff && temp2 == 0xffffffff)
++ goto hw_died;
++
+ if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) {
+ spin_unlock(&xhci->lock);
+ return IRQ_NONE;
+@@ -294,6 +297,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd
+ if (temp & STS_FATAL) {
+ xhci_warn(xhci, "WARNING: Host System Error\n");
+ xhci_halt(xhci);
++hw_died:
+ xhci_to_hcd(xhci)->state = HC_STATE_HALT;
+ spin_unlock(&xhci->lock);
+ return -ESHUTDOWN;
diff --git a/usb.current/usb-xhci-correct-event-handler-busy-flag-usage.patch b/usb.current/usb-xhci-correct-event-handler-busy-flag-usage.patch
new file mode 100644
index 00000000000000..6079ae01d04116
--- /dev/null
+++ b/usb.current/usb-xhci-correct-event-handler-busy-flag-usage.patch
@@ -0,0 +1,55 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:28:05 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:03:40 -0700
+Subject: USB: xhci: Correct Event Handler Busy flag usage.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190340.GA7653@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+The Event Handler Busy bit in the event ring dequeue pointer is write 1 to
+clear. Fix the interrupt service routine to clear that bit after the
+event handler has run.
+
+xhci_set_hc_event_deq() is designed to update the event ring dequeue pointer
+without changing any of the four reserved bits in the lower nibble. The event
+handler busy (EHB) bit is write one to clear, so the new value must always
+contain a zero in that bit in order to preserve the EHB value.
+
+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 | 4 ++--
+ drivers/usb/host/xhci-ring.c | 6 +++++-
+ 2 files changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -249,9 +249,9 @@ static void xhci_work(struct xhci_hcd *x
+ /* FIXME this should be a delayed service routine that clears the EHB */
+ xhci_handle_event(xhci);
+
+- /* Clear the event handler busy flag; the event ring should be empty. */
++ /* Clear the event handler busy flag (RW1C); the event ring should be empty. */
+ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+- xhci_write_64(xhci, temp_64 & ~ERST_EHB, &xhci->ir_set->erst_dequeue);
++ xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
+ /* Flush posted writes -- FIXME is this necessary? */
+ xhci_readl(xhci, &xhci->ir_set->irq_pending);
+ }
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -248,8 +248,12 @@ void xhci_set_hc_event_deq(struct xhci_h
+ /* Update HC event ring dequeue pointer */
+ temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+ temp &= ERST_PTR_MASK;
++ /* Don't clear the EHB bit (which is RW1C) because
++ * there might be more events to service.
++ */
++ temp &= ~ERST_EHB;
+ if (!in_interrupt())
+- xhci_dbg(xhci, "// Write event ring dequeue pointer\n");
++ xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n");
+ xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
+ &xhci->ir_set->erst_dequeue);
+ }
diff --git a/usb.current/usb-xhci-deal-with-stalled-endpoints.patch b/usb.current/usb-xhci-deal-with-stalled-endpoints.patch
new file mode 100644
index 00000000000000..cc737a0a560f0e
--- /dev/null
+++ b/usb.current/usb-xhci-deal-with-stalled-endpoints.patch
@@ -0,0 +1,219 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:23:41 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:03:15 -0700
+Subject: USB: xhci: Deal with stalled endpoints.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190315.GA7497@gamba.jf.intel.com>
+
+
+When an endpoint on a device under an xHCI host controller stalls, the
+host controller driver must let the hardware know that the USB core has
+successfully cleared the halt condition. The HCD submits a Reset Endpoint
+Command, which will clear the toggle bit for USB 2.0 devices, and set the
+sequence number to zero for USB 3.0 devices.
+
+The xHCI urb_enqueue will accept new URBs while the endpoint is halted,
+and will queue them to the hardware rings. However, the endpoint doorbell
+will not be rung until the Reset Endpoint Command completes.
+
+Don't queue a reset endpoint command for root hubs. khubd clears halt
+conditions on the roothub during the initialization process, but the roothub
+isn't a real device, so the xHCI host controller doesn't need to know about the
+cleared halt.
+
+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 | 44 ++++++++++++++++++++++++++++++++++++++++++-
+ drivers/usb/host/xhci-pci.c | 1
+ drivers/usb/host/xhci-ring.c | 36 ++++++++++++++++++++++++++++++++++-
+ drivers/usb/host/xhci.h | 8 +++++--
+ 4 files changed, 85 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -848,8 +848,8 @@ union xhci_trb {
+ #define TRB_CONFIG_EP 12
+ /* Evaluate Context Command */
+ #define TRB_EVAL_CONTEXT 13
+-/* Reset Transfer Ring Command */
+-#define TRB_RESET_RING 14
++/* Reset Endpoint Command */
++#define TRB_RESET_EP 14
+ /* Stop Transfer Ring Command */
+ #define TRB_STOP_RING 15
+ /* Set Transfer Ring Dequeue Pointer Command */
+@@ -929,6 +929,7 @@ struct xhci_ring {
+ unsigned int cancels_pending;
+ unsigned int state;
+ #define SET_DEQ_PENDING (1 << 0)
++#define EP_HALTED (1 << 1)
+ /* The TRB that was last reported in a stopped endpoint ring */
+ union xhci_trb *stopped_trb;
+ struct xhci_td *stopped_td;
+@@ -1128,6 +1129,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
+ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
+ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
++void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
+ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
+ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
+
+@@ -1148,6 +1150,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_reset_ep(struct xhci_hcd *xhci, int slot_id,
++ unsigned int ep_index);
+
+ /* 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
+@@ -787,8 +787,11 @@ int xhci_add_endpoint(struct usb_hcd *hc
+ int ret = 0;
+
+ ret = xhci_check_args(hcd, udev, ep, 1, __func__);
+- if (ret <= 0)
++ if (ret <= 0) {
++ /* So we won't queue a reset ep command for a root hub */
++ ep->hcpriv = NULL;
+ return ret;
++ }
+ xhci = hcd_to_xhci(hcd);
+
+ added_ctxs = xhci_get_endpoint_flag(&ep->desc);
+@@ -851,6 +854,9 @@ int xhci_add_endpoint(struct usb_hcd *hc
+ }
+ new_slot_info = in_ctx->slot.dev_info;
+
++ /* Store the usb_device pointer for later use */
++ ep->hcpriv = udev;
++
+ xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n",
+ (unsigned int) ep->desc.bEndpointAddress,
+ udev->slot_id,
+@@ -1026,6 +1032,42 @@ void xhci_reset_bandwidth(struct usb_hcd
+ xhci_zero_in_ctx(virt_dev);
+ }
+
++/* 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
++ * zero after the halt condition is cleared.
++ * Context: in_interrupt
++ */
++void xhci_endpoint_reset(struct usb_hcd *hcd,
++ struct usb_host_endpoint *ep)
++{
++ struct xhci_hcd *xhci;
++ struct usb_device *udev;
++ unsigned int ep_index;
++ unsigned long flags;
++ int ret;
++
++ xhci = hcd_to_xhci(hcd);
++ udev = (struct usb_device *) ep->hcpriv;
++ /* Called with a root hub endpoint (or an endpoint that wasn't added
++ * with xhci_add_endpoint()
++ */
++ if (!ep->hcpriv)
++ return;
++ ep_index = xhci_get_endpoint_index(&ep->desc);
++
++ xhci_dbg(xhci, "Queueing reset endpoint command\n");
++ spin_lock_irqsave(&xhci->lock, flags);
++ ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index);
++ if (!ret) {
++ xhci_ring_cmd_db(xhci);
++ }
++ spin_unlock_irqrestore(&xhci->lock, flags);
++
++ if (ret)
++ xhci_warn(xhci, "FIXME allocate a new ring segment\n");
++}
++
+ /*
+ * At this point, the struct usb_device is about to go away, the device has
+ * disconnected, and all traffic has been stopped and the endpoints have been
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -117,6 +117,7 @@ static const struct hc_driver xhci_pci_h
+ .free_dev = xhci_free_dev,
+ .add_endpoint = xhci_add_endpoint,
+ .drop_endpoint = xhci_drop_endpoint,
++ .endpoint_reset = xhci_endpoint_reset,
+ .check_bandwidth = xhci_check_bandwidth,
+ .reset_bandwidth = xhci_reset_bandwidth,
+ .address_device = xhci_address_device,
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -279,7 +279,8 @@ static void ring_ep_doorbell(struct xhci
+ /* Don't ring the doorbell for this endpoint if there are pending
+ * cancellations because the we don't want to interrupt processing.
+ */
+- if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)) {
++ if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)
++ && !(ep_ring->state & EP_HALTED)) {
+ field = xhci_readl(xhci, db_addr) & DB_MASK;
+ xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr);
+ /* Flush PCI posted writes - FIXME Matthew Wilcox says this
+@@ -603,6 +604,25 @@ static void handle_set_deq_completion(st
+ ring_ep_doorbell(xhci, slot_id, ep_index);
+ }
+
++static void handle_reset_ep_completion(struct xhci_hcd *xhci,
++ struct xhci_event_cmd *event,
++ union xhci_trb *trb)
++{
++ int slot_id;
++ unsigned int ep_index;
++
++ slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
++ ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
++ /* 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);
++}
+
+ static void handle_cmd_completion(struct xhci_hcd *xhci,
+ struct xhci_event_cmd *event)
+@@ -653,6 +673,9 @@ static void handle_cmd_completion(struct
+ case TRB_TYPE(TRB_CMD_NOOP):
+ ++xhci->noops_handled;
+ break;
++ case TRB_TYPE(TRB_RESET_EP):
++ handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue);
++ break;
+ default:
+ /* Skip over unknown commands on the event ring */
+ xhci->error_bitmask |= 1 << 6;
+@@ -823,6 +846,7 @@ static int handle_tx_event(struct xhci_h
+ break;
+ case COMP_STALL:
+ xhci_warn(xhci, "WARN: Stalled endpoint\n");
++ ep_ring->state |= EP_HALTED;
+ status = -EPIPE;
+ break;
+ case COMP_TRB_ERR:
+@@ -1656,3 +1680,13 @@ static int queue_set_tr_deq(struct xhci_
+ return queue_command(xhci, (u32) addr | cycle_state, 0, 0,
+ trb_slot_id | trb_ep_index | type);
+ }
++
++int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
++ unsigned int ep_index)
++{
++ u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
++ u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
++ u32 type = TRB_TYPE(TRB_RESET_EP);
++
++ return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type);
++}
diff --git a/usb.current/usb-xhci-don-t-oops-if-the-host-doesn-t-halt.patch b/usb.current/usb-xhci-don-t-oops-if-the-host-doesn-t-halt.patch
new file mode 100644
index 00000000000000..4464332d0ee9c2
--- /dev/null
+++ b/usb.current/usb-xhci-don-t-oops-if-the-host-doesn-t-halt.patch
@@ -0,0 +1,30 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:28:35 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:03:50 -0700
+Subject: USB: xhci: Don't oops if the host doesn't halt.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190350.GA7729@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+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 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -103,7 +103,10 @@ int xhci_reset(struct xhci_hcd *xhci)
+ u32 state;
+
+ state = xhci_readl(xhci, &xhci->op_regs->status);
+- BUG_ON((state & STS_HALT) == 0);
++ if ((state & STS_HALT) == 0) {
++ xhci_warn(xhci, "Host controller not halted, aborting reset.\n");
++ return 0;
++ }
+
+ xhci_dbg(xhci, "// Reset the HC\n");
+ command = xhci_readl(xhci, &xhci->op_regs->command);
diff --git a/usb.current/usb-xhci-fail-gracefully-if-there-s-no-ss-ep-companion-descriptor.patch b/usb.current/usb-xhci-fail-gracefully-if-there-s-no-ss-ep-companion-descriptor.patch
new file mode 100644
index 00000000000000..c6cffaeb9b46fe
--- /dev/null
+++ b/usb.current/usb-xhci-fail-gracefully-if-there-s-no-ss-ep-companion-descriptor.patch
@@ -0,0 +1,36 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:29:33 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:04:38 -0700
+Subject: USB: xhci: Fail gracefully if there's no SS ep companion descriptor.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190438.GA7879@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+This is a work around for a bug in the SuperSpeed Endpoint Companion Descriptor
+parsing code. It fails in some corner cases, which means ep->ss_ep_comp may be
+NULL.
+
+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 | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -496,7 +496,12 @@ int xhci_endpoint_init(struct xhci_hcd *
+ max_packet = ep->desc.wMaxPacketSize;
+ ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
+ /* dig out max burst from ep companion desc */
+- max_packet = ep->ss_ep_comp->desc.bMaxBurst;
++ if (!ep->ss_ep_comp) {
++ xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n");
++ max_packet = 0;
++ } else {
++ max_packet = ep->ss_ep_comp->desc.bMaxBurst;
++ }
+ ep_ctx->ep_info2 |= MAX_BURST(max_packet);
+ break;
+ case USB_SPEED_HIGH:
diff --git a/usb.current/usb-xhci-handle-babble-errors-on-transfers.patch b/usb.current/usb-xhci-handle-babble-errors-on-transfers.patch
new file mode 100644
index 00000000000000..84abb604c3f519
--- /dev/null
+++ b/usb.current/usb-xhci-handle-babble-errors-on-transfers.patch
@@ -0,0 +1,31 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:29:18 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:04:32 -0700
+Subject: USB: xhci: Handle babble errors on transfers.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190432.GA7838@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+Pass back a babble error when this error code is seen in the transfer event TRB.
+
+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 | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -876,6 +876,10 @@ static int handle_tx_event(struct xhci_h
+ xhci_warn(xhci, "WARN: transfer error on endpoint\n");
+ status = -EPROTO;
+ break;
++ case COMP_BABBLE:
++ xhci_warn(xhci, "WARN: babble error on endpoint\n");
++ status = -EOVERFLOW;
++ break;
+ case COMP_DB_ERR:
+ xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n");
+ status = -ENOSR;
diff --git a/usb.current/usb-xhci-handle-short-control-packets-correctly.patch b/usb.current/usb-xhci-handle-short-control-packets-correctly.patch
new file mode 100644
index 00000000000000..bae4254b985ad0
--- /dev/null
+++ b/usb.current/usb-xhci-handle-short-control-packets-correctly.patch
@@ -0,0 +1,56 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:27:20 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:03:36 -0700
+Subject: USB: xhci: Handle short control packets correctly.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190336.GA7615@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+When there is a short packet on a control transfer, the xHCI host controller
+hardware will generate two events. The first event will be for the data stage
+TD with a completion code for a short packet. The second event will be for the
+status stage with a successful completion code. Before this patch, the xHCI
+driver would giveback the short control URB when it received the event for the
+data stage TD. Then it would become confused when it saw a status stage event
+for the endpoint for an URB it had already finished processing.
+
+Change the xHCI host controller driver to wait for the status stage event when
+it receives a short transfer completion code for a data stage TD.
+
+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 | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -892,15 +892,23 @@ static int handle_tx_event(struct xhci_h
+ if (event_trb != ep_ring->dequeue) {
+ /* The event was for the status stage */
+ if (event_trb == td->last_trb) {
+- td->urb->actual_length =
+- td->urb->transfer_buffer_length;
++ /* Did we already see a short data stage? */
++ if (td->urb->actual_length != 0)
++ status = -EREMOTEIO;
++ else
++ td->urb->actual_length =
++ td->urb->transfer_buffer_length;
+ } else {
+ /* Maybe the event was for the data stage? */
+- if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL)
++ if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
+ /* We didn't stop on a link TRB in the middle */
+ td->urb->actual_length =
+ td->urb->transfer_buffer_length -
+ TRB_LEN(event->transfer_len);
++ xhci_dbg(xhci, "Waiting for status stage event\n");
++ urb = NULL;
++ goto cleanup;
++ }
+ }
+ }
+ } else {
diff --git a/usb.current/usb-xhci-make-debugging-more-verbose.patch b/usb.current/usb-xhci-make-debugging-more-verbose.patch
new file mode 100644
index 00000000000000..1aa6c98a669921
--- /dev/null
+++ b/usb.current/usb-xhci-make-debugging-more-verbose.patch
@@ -0,0 +1,291 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:28:17 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:03:46 -0700
+Subject: USB: xhci: Make debugging more verbose.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190346.GA7692@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+Add more debugging to the irq handler, slot context initialization, ring
+operations, URB cancellation, and MMIO writes.
+
+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 | 47 ++++++++++++++++++++++++++++++-------------
+ drivers/usb/host/xhci-ring.c | 35 ++++++++++++++++++++++++++++++--
+ drivers/usb/host/xhci.h | 14 +++++-------
+ 3 files changed, 72 insertions(+), 24 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1065,10 +1065,9 @@ static inline unsigned int xhci_readl(co
+ static inline void xhci_writel(struct xhci_hcd *xhci,
+ const unsigned int val, __u32 __iomem *regs)
+ {
+- if (!in_interrupt())
+- xhci_dbg(xhci,
+- "`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
+- regs, val);
++ xhci_dbg(xhci,
++ "`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
++ regs, val);
+ writel(val, regs);
+ }
+
+@@ -1096,10 +1095,9 @@ static inline void xhci_write_64(struct
+ u32 val_lo = lower_32_bits(val);
+ u32 val_hi = upper_32_bits(val);
+
+- if (!in_interrupt())
+- xhci_dbg(xhci,
+- "`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n",
+- regs, (long unsigned int) val);
++ xhci_dbg(xhci,
++ "`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n",
++ regs, (long unsigned int) val);
+ writel(val_lo, ptr);
+ writel(val_hi, ptr + 1);
+ }
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -267,8 +267,10 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd
+ {
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ u32 temp, temp2;
++ union xhci_trb *trb;
+
+ spin_lock(&xhci->lock);
++ trb = xhci->event_ring->dequeue;
+ /* Check if the xHC generated the interrupt, or the irq is shared */
+ temp = xhci_readl(xhci, &xhci->op_regs->status);
+ temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+@@ -276,6 +278,15 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd
+ spin_unlock(&xhci->lock);
+ return IRQ_NONE;
+ }
++ xhci_dbg(xhci, "op reg status = %08x\n", temp);
++ xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2);
++ xhci_dbg(xhci, "Event ring dequeue ptr:\n");
++ xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n",
++ (unsigned long long)xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
++ lower_32_bits(trb->link.segment_ptr),
++ upper_32_bits(trb->link.segment_ptr),
++ (unsigned int) trb->link.intr_target,
++ (unsigned int) trb->link.control);
+
+ if (temp & STS_FATAL) {
+ xhci_warn(xhci, "WARNING: Host System Error\n");
+@@ -385,6 +396,20 @@ int xhci_run(struct usb_hcd *hcd)
+ add_timer(&xhci->event_ring_timer);
+ #endif
+
++ xhci_dbg(xhci, "Command ring memory map follows:\n");
++ xhci_debug_ring(xhci, xhci->cmd_ring);
++ xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
++ xhci_dbg_cmd_ptrs(xhci);
++
++ xhci_dbg(xhci, "ERST memory map follows:\n");
++ xhci_dbg_erst(xhci, &xhci->erst);
++ xhci_dbg(xhci, "Event ring:\n");
++ xhci_debug_ring(xhci, xhci->event_ring);
++ xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
++ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
++ temp_64 &= ~ERST_PTR_MASK;
++ xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
++
+ xhci_dbg(xhci, "// Set the interrupt modulation register\n");
+ temp = xhci_readl(xhci, &xhci->ir_set->irq_control);
+ temp &= ~ER_IRQ_INTERVAL_MASK;
+@@ -409,20 +434,6 @@ int xhci_run(struct usb_hcd *hcd)
+ if (NUM_TEST_NOOPS > 0)
+ doorbell = xhci_setup_one_noop(xhci);
+
+- xhci_dbg(xhci, "Command ring memory map follows:\n");
+- xhci_debug_ring(xhci, xhci->cmd_ring);
+- xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+- xhci_dbg_cmd_ptrs(xhci);
+-
+- xhci_dbg(xhci, "ERST memory map follows:\n");
+- xhci_dbg_erst(xhci, &xhci->erst);
+- xhci_dbg(xhci, "Event ring:\n");
+- xhci_debug_ring(xhci, xhci->event_ring);
+- xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
+- temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+- temp_64 &= ~ERST_PTR_MASK;
+- xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
+-
+ temp = xhci_readl(xhci, &xhci->op_regs->command);
+ temp |= (CMD_RUN);
+ xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
+@@ -665,8 +676,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
+ goto done;
+
+ xhci_dbg(xhci, "Cancel URB %p\n", urb);
++ xhci_dbg(xhci, "Event ring:\n");
++ xhci_debug_ring(xhci, xhci->event_ring);
+ ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+ ep_ring = xhci->devs[urb->dev->slot_id]->ep_rings[ep_index];
++ xhci_dbg(xhci, "Endpoint ring:\n");
++ xhci_debug_ring(xhci, ep_ring);
+ td = (struct xhci_td *) urb->hcpriv;
+
+ ep_ring->cancels_pending++;
+@@ -1178,6 +1193,8 @@ int xhci_address_device(struct usb_hcd *
+ if (!udev->config)
+ xhci_setup_addressable_virt_dev(xhci, udev);
+ /* Otherwise, assume the core has the device configured how it wants */
++ xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
++ xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2);
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ ret = xhci_queue_address_device(xhci, virt_dev->in_ctx_dma,
+@@ -1221,6 +1238,8 @@ int xhci_address_device(struct usb_hcd *
+ default:
+ xhci_err(xhci, "ERROR: unexpected command completion "
+ "code 0x%x.\n", virt_dev->cmd_status);
++ xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
++ xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2);
+ ret = -EINVAL;
+ break;
+ }
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -135,6 +135,7 @@ static void next_trb(struct xhci_hcd *xh
+ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
+ {
+ union xhci_trb *next = ++(ring->dequeue);
++ unsigned long long addr;
+
+ ring->deq_updates++;
+ /* Update the dequeue pointer further if that was a link TRB or we're at
+@@ -152,6 +153,13 @@ static void inc_deq(struct xhci_hcd *xhc
+ ring->dequeue = ring->deq_seg->trbs;
+ next = ring->dequeue;
+ }
++ addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
++ if (ring == xhci->event_ring)
++ xhci_dbg(xhci, "Event ring deq = 0x%llx (DMA)\n", addr);
++ else if (ring == xhci->cmd_ring)
++ xhci_dbg(xhci, "Command ring deq = 0x%llx (DMA)\n", addr);
++ else
++ xhci_dbg(xhci, "Ring deq = 0x%llx (DMA)\n", addr);
+ }
+
+ /*
+@@ -171,6 +179,7 @@ static void inc_enq(struct xhci_hcd *xhc
+ {
+ u32 chain;
+ union xhci_trb *next;
++ unsigned long long addr;
+
+ chain = ring->enqueue->generic.field[3] & TRB_CHAIN;
+ next = ++(ring->enqueue);
+@@ -204,6 +213,13 @@ static void inc_enq(struct xhci_hcd *xhc
+ ring->enqueue = ring->enq_seg->trbs;
+ next = ring->enqueue;
+ }
++ addr = (unsigned long long) xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
++ if (ring == xhci->event_ring)
++ xhci_dbg(xhci, "Event ring enq = 0x%llx (DMA)\n", addr);
++ else if (ring == xhci->cmd_ring)
++ xhci_dbg(xhci, "Command ring enq = 0x%llx (DMA)\n", addr);
++ else
++ xhci_dbg(xhci, "Ring enq = 0x%llx (DMA)\n", addr);
+ }
+
+ /*
+@@ -252,8 +268,7 @@ void xhci_set_hc_event_deq(struct xhci_h
+ * there might be more events to service.
+ */
+ temp &= ~ERST_EHB;
+- if (!in_interrupt())
+- xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n");
++ xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n");
+ xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
+ &xhci->ir_set->erst_dequeue);
+ }
+@@ -781,6 +796,7 @@ static int handle_tx_event(struct xhci_h
+ struct urb *urb = 0;
+ int status = -EINPROGRESS;
+
++ xhci_dbg(xhci, "In %s\n", __func__);
+ xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)];
+ if (!xdev) {
+ xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
+@@ -789,6 +805,7 @@ static int handle_tx_event(struct xhci_h
+
+ /* Endpoint ID is 1 based, our index is zero based */
+ ep_index = TRB_TO_EP_ID(event->flags) - 1;
++ xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index);
+ ep_ring = xdev->ep_rings[ep_index];
+ if (!ep_ring || (xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
+ xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n");
+@@ -797,6 +814,7 @@ static int handle_tx_event(struct xhci_h
+
+ event_dma = event->buffer;
+ /* This TRB should be in the TD at the head of this ring's TD list */
++ xhci_dbg(xhci, "%s - checking for list empty\n", __func__);
+ if (list_empty(&ep_ring->td_list)) {
+ xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
+ TRB_TO_SLOT_ID(event->flags), ep_index);
+@@ -806,11 +824,14 @@ static int handle_tx_event(struct xhci_h
+ urb = NULL;
+ goto cleanup;
+ }
++ xhci_dbg(xhci, "%s - getting list entry\n", __func__);
+ td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
+
+ /* Is this a TRB in the currently executing TD? */
++ xhci_dbg(xhci, "%s - looking for TD\n", __func__);
+ event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
+ td->last_trb, event_dma);
++ xhci_dbg(xhci, "%s - found event_seg = %p\n", __func__, event_seg);
+ if (!event_seg) {
+ /* HC is busted, give up! */
+ xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n");
+@@ -1027,6 +1048,8 @@ cleanup:
+ /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */
+ 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);
+ spin_unlock(&xhci->lock);
+ usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
+ spin_lock(&xhci->lock);
+@@ -1044,6 +1067,7 @@ void xhci_handle_event(struct xhci_hcd *
+ int update_ptrs = 1;
+ int ret;
+
++ xhci_dbg(xhci, "In %s\n", __func__);
+ if (!xhci->event_ring || !xhci->event_ring->dequeue) {
+ xhci->error_bitmask |= 1 << 1;
+ return;
+@@ -1056,18 +1080,25 @@ void xhci_handle_event(struct xhci_hcd *
+ xhci->error_bitmask |= 1 << 2;
+ return;
+ }
++ xhci_dbg(xhci, "%s - OS owns TRB\n", __func__);
+
+ /* FIXME: Handle more event types. */
+ switch ((event->event_cmd.flags & TRB_TYPE_BITMASK)) {
+ case TRB_TYPE(TRB_COMPLETION):
++ xhci_dbg(xhci, "%s - calling handle_cmd_completion\n", __func__);
+ handle_cmd_completion(xhci, &event->event_cmd);
++ xhci_dbg(xhci, "%s - returned from handle_cmd_completion\n", __func__);
+ break;
+ case TRB_TYPE(TRB_PORT_STATUS):
++ xhci_dbg(xhci, "%s - calling handle_port_status\n", __func__);
+ handle_port_status(xhci, event);
++ xhci_dbg(xhci, "%s - returned from handle_port_status\n", __func__);
+ update_ptrs = 0;
+ break;
+ case TRB_TYPE(TRB_TRANSFER):
++ xhci_dbg(xhci, "%s - calling handle_tx_event\n", __func__);
+ ret = handle_tx_event(xhci, &event->trans_event);
++ xhci_dbg(xhci, "%s - returned from handle_tx_event\n", __func__);
+ if (ret < 0)
+ xhci->error_bitmask |= 1 << 9;
+ else
diff --git a/usb.current/usb-xhci-represent-64-bit-addresses-with-one-u64.patch b/usb.current/usb-xhci-represent-64-bit-addresses-with-one-u64.patch
new file mode 100644
index 00000000000000..d64bf41fcecbd4
--- /dev/null
+++ b/usb.current/usb-xhci-represent-64-bit-addresses-with-one-u64.patch
@@ -0,0 +1,744 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:24:11 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:03:31 -0700
+Subject: USB: xhci: Represent 64-bit addresses with one u64.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190331.GA7575@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+There are several xHCI data structures that use two 32-bit fields to
+represent a 64-bit address. Since some architectures don't support 64-bit
+PCI writes, the fields need to be written in two 32-bit writes. The xHCI
+specification says that if a platform is incapable of generating 64-bit
+writes, software must write the low 32-bits first, then the high 32-bits.
+Hardware that supports 64-bit addressing will wait for the high 32-bit
+write before reading the revised value, and hardware that only supports
+32-bit writes will ignore the high 32-bit write.
+
+Previous xHCI code represented 64-bit addresses with two u32 values. This
+lead to buggy code that would write the 32-bits in the wrong order, or
+forget to write the upper 32-bits. Change the two u32s to one u64 and
+create a function call to write all 64-bit addresses in the proper order.
+This new function could be modified in the future if all platforms support
+64-bit writes.
+
+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 | 69 ++++++++++++++++---------------------------
+ drivers/usb/host/xhci-hcd.c | 43 +++++++++++---------------
+ drivers/usb/host/xhci-mem.c | 61 ++++++++++++++------------------------
+ drivers/usb/host/xhci-ring.c | 49 ++++++++++++++----------------
+ drivers/usb/host/xhci.h | 65 ++++++++++++++++++++++++++++------------
+ 5 files changed, 138 insertions(+), 149 deletions(-)
+
+--- a/drivers/usb/host/xhci-dbg.c
++++ b/drivers/usb/host/xhci-dbg.c
+@@ -173,6 +173,7 @@ void xhci_print_ir_set(struct xhci_hcd *
+ {
+ void *addr;
+ u32 temp;
++ u64 temp_64;
+
+ addr = &ir_set->irq_pending;
+ temp = xhci_readl(xhci, addr);
+@@ -200,25 +201,15 @@ void xhci_print_ir_set(struct xhci_hcd *
+ xhci_dbg(xhci, " WARN: %p: ir_set.rsvd = 0x%x\n",
+ addr, (unsigned int)temp);
+
+- addr = &ir_set->erst_base[0];
+- temp = xhci_readl(xhci, addr);
+- xhci_dbg(xhci, " %p: ir_set.erst_base[0] = 0x%x\n",
+- addr, (unsigned int) temp);
+-
+- addr = &ir_set->erst_base[1];
+- temp = xhci_readl(xhci, addr);
+- xhci_dbg(xhci, " %p: ir_set.erst_base[1] = 0x%x\n",
+- addr, (unsigned int) temp);
+-
+- addr = &ir_set->erst_dequeue[0];
+- temp = xhci_readl(xhci, addr);
+- xhci_dbg(xhci, " %p: ir_set.erst_dequeue[0] = 0x%x\n",
+- addr, (unsigned int) temp);
+-
+- addr = &ir_set->erst_dequeue[1];
+- temp = xhci_readl(xhci, addr);
+- xhci_dbg(xhci, " %p: ir_set.erst_dequeue[1] = 0x%x\n",
+- addr, (unsigned int) temp);
++ addr = &ir_set->erst_base;
++ temp_64 = xhci_read_64(xhci, addr);
++ xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n",
++ addr, temp_64);
++
++ addr = &ir_set->erst_dequeue;
++ temp_64 = xhci_read_64(xhci, addr);
++ xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n",
++ addr, temp_64);
+ }
+
+ void xhci_print_run_regs(struct xhci_hcd *xhci)
+@@ -268,8 +259,7 @@ void xhci_debug_trb(struct xhci_hcd *xhc
+ xhci_dbg(xhci, "Link TRB:\n");
+ xhci_print_trb_offsets(xhci, trb);
+
+- address = trb->link.segment_ptr[0] +
+- (((u64) trb->link.segment_ptr[1]) << 32);
++ address = trb->link.segment_ptr;
+ xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);
+
+ xhci_dbg(xhci, "Interrupter target = 0x%x\n",
+@@ -282,8 +272,7 @@ void xhci_debug_trb(struct xhci_hcd *xhc
+ (unsigned int) (trb->link.control & TRB_NO_SNOOP));
+ break;
+ case TRB_TYPE(TRB_TRANSFER):
+- address = trb->trans_event.buffer[0] +
+- (((u64) trb->trans_event.buffer[1]) << 32);
++ address = trb->trans_event.buffer;
+ /*
+ * FIXME: look at flags to figure out if it's an address or if
+ * the data is directly in the buffer field.
+@@ -291,8 +280,7 @@ void xhci_debug_trb(struct xhci_hcd *xhc
+ xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
+ break;
+ case TRB_TYPE(TRB_COMPLETION):
+- address = trb->event_cmd.cmd_trb[0] +
+- (((u64) trb->event_cmd.cmd_trb[1]) << 32);
++ address = trb->event_cmd.cmd_trb;
+ xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
+ xhci_dbg(xhci, "Completion status = %u\n",
+ (unsigned int) GET_COMP_CODE(trb->event_cmd.status));
+@@ -328,8 +316,8 @@ void xhci_debug_segment(struct xhci_hcd
+ for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
+ trb = &seg->trbs[i];
+ xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
+- (unsigned int) trb->link.segment_ptr[0],
+- (unsigned int) trb->link.segment_ptr[1],
++ lower_32_bits(trb->link.segment_ptr),
++ upper_32_bits(trb->link.segment_ptr),
+ (unsigned int) trb->link.intr_target,
+ (unsigned int) trb->link.control);
+ addr += sizeof(*trb);
+@@ -386,8 +374,8 @@ void xhci_dbg_erst(struct xhci_hcd *xhci
+ entry = &erst->entries[i];
+ xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
+ (unsigned int) addr,
+- (unsigned int) entry->seg_addr[0],
+- (unsigned int) entry->seg_addr[1],
++ lower_32_bits(entry->seg_addr),
++ upper_32_bits(entry->seg_addr),
+ (unsigned int) entry->seg_size,
+ (unsigned int) entry->rsvd);
+ addr += sizeof(*entry);
+@@ -396,12 +384,13 @@ void xhci_dbg_erst(struct xhci_hcd *xhci
+
+ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
+ {
+- u32 val;
++ u64 val;
+
+- val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]);
+- xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = 0x%x\n", val);
+- val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[1]);
+- xhci_dbg(xhci, "// xHC command ring deq ptr high bits = 0x%x\n", val);
++ val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
++ xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
++ lower_32_bits(val));
++ xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n",
++ upper_32_bits(val));
+ }
+
+ void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep)
+@@ -462,14 +451,10 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
+ &ctx->ep[i].ep_info2,
+ (unsigned long long)dma, ctx->ep[i].ep_info2);
+ dma += field_size;
+- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[0]\n",
+- &ctx->ep[i].deq[0],
+- (unsigned long long)dma, ctx->ep[i].deq[0]);
+- dma += field_size;
+- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[1]\n",
+- &ctx->ep[i].deq[1],
+- (unsigned long long)dma, ctx->ep[i].deq[1]);
+- dma += field_size;
++ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n",
++ &ctx->ep[i].deq,
++ (unsigned long long)dma, ctx->ep[i].deq);
++ dma += 2*field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n",
+ &ctx->ep[i].tx_info,
+ (unsigned long long)dma, ctx->ep[i].tx_info);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -25,6 +25,7 @@
+
+ #include <linux/usb.h>
+ #include <linux/timer.h>
++#include <linux/kernel.h>
+
+ #include "../core/hcd.h"
+ /* Code sharing between pci-quirks and xhci hcd */
+@@ -42,14 +43,6 @@
+ * xHCI register interface.
+ * This corresponds to the eXtensible Host Controller Interface (xHCI)
+ * Revision 0.95 specification
+- *
+- * Registers should always be accessed with double word or quad word accesses.
+- *
+- * Some xHCI implementations may support 64-bit address pointers. Registers
+- * with 64-bit address pointers should be written to with dword accesses by
+- * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
+- * xHCI implementations that do not support 64-bit address pointers will ignore
+- * the high dword, and write order is irrelevant.
+ */
+
+ /**
+@@ -166,10 +159,10 @@ struct xhci_op_regs {
+ u32 reserved1;
+ u32 reserved2;
+ u32 dev_notification;
+- u32 cmd_ring[2];
++ u64 cmd_ring;
+ /* rsvd: offset 0x20-2F */
+ u32 reserved3[4];
+- u32 dcbaa_ptr[2];
++ u64 dcbaa_ptr;
+ u32 config_reg;
+ /* rsvd: offset 0x3C-3FF */
+ u32 reserved4[241];
+@@ -254,7 +247,7 @@ struct xhci_op_regs {
+ #define CMD_RING_RUNNING (1 << 3)
+ /* bits 4:5 reserved and should be preserved */
+ /* Command Ring pointer - bit mask for the lower 32 bits. */
+-#define CMD_RING_ADDR_MASK (0xffffffc0)
++#define CMD_RING_RSVD_BITS (0x3f)
+
+ /* CONFIG - Configure Register - config_reg bitmasks */
+ /* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */
+@@ -382,8 +375,8 @@ struct xhci_intr_reg {
+ u32 irq_control;
+ u32 erst_size;
+ u32 rsvd;
+- u32 erst_base[2];
+- u32 erst_dequeue[2];
++ u64 erst_base;
++ u64 erst_dequeue;
+ };
+
+ /* irq_pending bitmasks */
+@@ -538,7 +531,7 @@ struct xhci_slot_ctx {
+ struct xhci_ep_ctx {
+ u32 ep_info;
+ u32 ep_info2;
+- u32 deq[2];
++ u64 deq;
+ u32 tx_info;
+ /* offset 0x14 - 0x1f reserved for HC internal use */
+ u32 reserved[3];
+@@ -641,7 +634,7 @@ struct xhci_virt_device {
+ */
+ struct xhci_device_context_array {
+ /* 64-bit device addresses; we only write 32-bit addresses */
+- u32 dev_context_ptrs[2*MAX_HC_SLOTS];
++ u64 dev_context_ptrs[MAX_HC_SLOTS];
+ /* private xHCD pointers */
+ dma_addr_t dma;
+ };
+@@ -654,7 +647,7 @@ struct xhci_device_context_array {
+
+ struct xhci_stream_ctx {
+ /* 64-bit stream ring address, cycle state, and stream type */
+- u32 stream_ring[2];
++ u64 stream_ring;
+ /* offset 0x14 - 0x1f reserved for HC internal use */
+ u32 reserved[2];
+ };
+@@ -662,7 +655,7 @@ struct xhci_stream_ctx {
+
+ struct xhci_transfer_event {
+ /* 64-bit buffer address, or immediate data */
+- u32 buffer[2];
++ u64 buffer;
+ u32 transfer_len;
+ /* This field is interpreted differently based on the type of TRB */
+ u32 flags;
+@@ -744,7 +737,7 @@ struct xhci_transfer_event {
+
+ struct xhci_link_trb {
+ /* 64-bit segment pointer*/
+- u32 segment_ptr[2];
++ u64 segment_ptr;
+ u32 intr_target;
+ u32 control;
+ };
+@@ -755,7 +748,7 @@ struct xhci_link_trb {
+ /* Command completion event TRB */
+ struct xhci_event_cmd {
+ /* Pointer to command TRB, or the value passed by the event data trb */
+- u32 cmd_trb[2];
++ u64 cmd_trb;
+ u32 status;
+ u32 flags;
+ };
+@@ -943,7 +936,7 @@ struct xhci_ring {
+
+ struct xhci_erst_entry {
+ /* 64-bit event ring segment address */
+- u32 seg_addr[2];
++ u64 seg_addr;
+ u32 seg_size;
+ /* Set to zero */
+ u32 rsvd;
+@@ -1079,6 +1072,38 @@ static inline void xhci_writel(struct xh
+ writel(val, regs);
+ }
+
++/*
++ * Registers should always be accessed with double word or quad word accesses.
++ *
++ * Some xHCI implementations may support 64-bit address pointers. Registers
++ * with 64-bit address pointers should be written to with dword accesses by
++ * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
++ * xHCI implementations that do not support 64-bit address pointers will ignore
++ * the high dword, and write order is irrelevant.
++ */
++static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
++ __u64 __iomem *regs)
++{
++ __u32 __iomem *ptr = (__u32 __iomem *) regs;
++ u64 val_lo = readl(ptr);
++ u64 val_hi = readl(ptr + 1);
++ return val_lo + (val_hi << 32);
++}
++static inline void xhci_write_64(struct xhci_hcd *xhci,
++ const u64 val, __u64 __iomem *regs)
++{
++ __u32 __iomem *ptr = (__u32 __iomem *) regs;
++ u32 val_lo = lower_32_bits(val);
++ u32 val_hi = upper_32_bits(val);
++
++ if (!in_interrupt())
++ xhci_dbg(xhci,
++ "`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n",
++ regs, (long unsigned int) val);
++ writel(val_lo, ptr);
++ writel(val_hi, ptr + 1);
++}
++
+ /* 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
+@@ -226,6 +226,7 @@ int xhci_init(struct usb_hcd *hcd)
+ static void xhci_work(struct xhci_hcd *xhci)
+ {
+ u32 temp;
++ u64 temp_64;
+
+ /*
+ * Clear the op reg interrupt status first,
+@@ -249,8 +250,8 @@ static void xhci_work(struct xhci_hcd *x
+ xhci_handle_event(xhci);
+
+ /* Clear the event handler busy flag; the event ring should be empty. */
+- temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
+- xhci_writel(xhci, temp & ~ERST_EHB, &xhci->ir_set->erst_dequeue[0]);
++ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
++ xhci_write_64(xhci, temp_64 & ~ERST_EHB, &xhci->ir_set->erst_dequeue);
+ /* Flush posted writes -- FIXME is this necessary? */
+ xhci_readl(xhci, &xhci->ir_set->irq_pending);
+ }
+@@ -295,6 +296,7 @@ void xhci_event_ring_work(unsigned long
+ {
+ unsigned long flags;
+ int temp;
++ u64 temp_64;
+ struct xhci_hcd *xhci = (struct xhci_hcd *) arg;
+ int i, j;
+
+@@ -311,9 +313,9 @@ void xhci_event_ring_work(unsigned long
+ xhci_dbg(xhci, "Event ring:\n");
+ xhci_debug_segment(xhci, xhci->event_ring->deq_seg);
+ xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
+- temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
+- temp &= ERST_PTR_MASK;
+- xhci_dbg(xhci, "ERST deq = 0x%x\n", temp);
++ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
++ temp_64 &= ~ERST_PTR_MASK;
++ xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
+ xhci_dbg(xhci, "Command ring:\n");
+ xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg);
+ xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+@@ -356,6 +358,7 @@ void xhci_event_ring_work(unsigned long
+ int xhci_run(struct usb_hcd *hcd)
+ {
+ u32 temp;
++ u64 temp_64;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ void (*doorbell)(struct xhci_hcd *) = NULL;
+
+@@ -416,11 +419,9 @@ int xhci_run(struct usb_hcd *hcd)
+ xhci_dbg(xhci, "Event ring:\n");
+ xhci_debug_ring(xhci, xhci->event_ring);
+ xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
+- temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
+- temp &= ERST_PTR_MASK;
+- xhci_dbg(xhci, "ERST deq = 0x%x\n", temp);
+- temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[1]);
+- xhci_dbg(xhci, "ERST deq upper = 0x%x\n", temp);
++ temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
++ temp_64 &= ~ERST_PTR_MASK;
++ xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
+
+ temp = xhci_readl(xhci, &xhci->op_regs->command);
+ temp |= (CMD_RUN);
+@@ -888,8 +889,7 @@ static void xhci_zero_in_ctx(struct xhci
+ ep_ctx = &virt_dev->in_ctx->ep[i];
+ ep_ctx->ep_info = 0;
+ ep_ctx->ep_info2 = 0;
+- ep_ctx->deq[0] = 0;
+- ep_ctx->deq[1] = 0;
++ ep_ctx->deq = 0;
+ ep_ctx->tx_info = 0;
+ }
+ }
+@@ -1165,7 +1165,7 @@ int xhci_address_device(struct usb_hcd *
+ struct xhci_virt_device *virt_dev;
+ int ret = 0;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+- u32 temp;
++ u64 temp_64;
+
+ if (!udev->slot_id) {
+ xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id);
+@@ -1227,18 +1227,13 @@ int xhci_address_device(struct usb_hcd *
+ if (ret) {
+ return ret;
+ }
+- temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[0]);
+- xhci_dbg(xhci, "Op regs DCBAA ptr[0] = %#08x\n", temp);
+- temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[1]);
+- xhci_dbg(xhci, "Op regs DCBAA ptr[1] = %#08x\n", temp);
+- xhci_dbg(xhci, "Slot ID %d dcbaa entry[0] @%p = %#08x\n",
+- udev->slot_id,
+- &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id],
+- xhci->dcbaa->dev_context_ptrs[2*udev->slot_id]);
+- xhci_dbg(xhci, "Slot ID %d dcbaa entry[1] @%p = %#08x\n",
++ temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
++ xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64);
++ xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n",
+ udev->slot_id,
+- &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1],
+- xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1]);
++ &xhci->dcbaa->dev_context_ptrs[udev->slot_id],
++ (unsigned long long)
++ xhci->dcbaa->dev_context_ptrs[udev->slot_id]);
+ xhci_dbg(xhci, "Output Context DMA address = %#08llx\n",
+ (unsigned long long)virt_dev->out_ctx_dma);
+ xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -88,7 +88,7 @@ static void xhci_link_segments(struct xh
+ return;
+ prev->next = next;
+ if (link_trbs) {
+- prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr[0] = next->dma;
++ prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = next->dma;
+
+ /* Set the last TRB in the segment to have a TRB type ID of Link TRB */
+ val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
+@@ -200,8 +200,7 @@ void xhci_free_virt_device(struct xhci_h
+ return;
+
+ dev = xhci->devs[slot_id];
+- xhci->dcbaa->dev_context_ptrs[2*slot_id] = 0;
+- xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0;
++ xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
+ if (!dev)
+ return;
+
+@@ -265,13 +264,12 @@ int xhci_alloc_virt_device(struct xhci_h
+ * Point to output device context in dcbaa; skip the output control
+ * context, which is eight 32 bit fields (or 32 bytes long)
+ */
+- xhci->dcbaa->dev_context_ptrs[2*slot_id] =
++ xhci->dcbaa->dev_context_ptrs[slot_id] =
+ (u32) dev->out_ctx_dma + (32);
+ xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
+ slot_id,
+- &xhci->dcbaa->dev_context_ptrs[2*slot_id],
++ &xhci->dcbaa->dev_context_ptrs[slot_id],
+ (unsigned long long)dev->out_ctx_dma);
+- xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0;
+
+ return 1;
+ fail:
+@@ -360,10 +358,9 @@ int xhci_setup_addressable_virt_dev(stru
+ ep0_ctx->ep_info2 |= MAX_BURST(0);
+ ep0_ctx->ep_info2 |= ERROR_COUNT(3);
+
+- ep0_ctx->deq[0] =
++ ep0_ctx->deq =
+ dev->ep_rings[0]->first_seg->dma;
+- ep0_ctx->deq[0] |= dev->ep_rings[0]->cycle_state;
+- ep0_ctx->deq[1] = 0;
++ ep0_ctx->deq |= dev->ep_rings[0]->cycle_state;
+
+ /* Steps 7 and 8 were done in xhci_alloc_virt_device() */
+
+@@ -477,8 +474,7 @@ int xhci_endpoint_init(struct xhci_hcd *
+ if (!virt_dev->new_ep_rings[ep_index])
+ return -ENOMEM;
+ ep_ring = virt_dev->new_ep_rings[ep_index];
+- ep_ctx->deq[0] = ep_ring->first_seg->dma | ep_ring->cycle_state;
+- ep_ctx->deq[1] = 0;
++ ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
+
+ ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
+
+@@ -535,8 +531,7 @@ void xhci_endpoint_zero(struct xhci_hcd
+
+ ep_ctx->ep_info = 0;
+ ep_ctx->ep_info2 = 0;
+- ep_ctx->deq[0] = 0;
+- ep_ctx->deq[1] = 0;
++ ep_ctx->deq = 0;
+ ep_ctx->tx_info = 0;
+ /* Don't free the endpoint ring until the set interface or configuration
+ * request succeeds.
+@@ -551,10 +546,8 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+
+ /* Free the Event Ring Segment Table and the actual Event Ring */
+ xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
+- xhci_writel(xhci, 0, &xhci->ir_set->erst_base[0]);
+- xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
+- xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[0]);
+- xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
++ xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
++ xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
+ size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
+ if (xhci->erst.entries)
+ pci_free_consistent(pdev, size,
+@@ -566,8 +559,7 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+ xhci->event_ring = NULL;
+ xhci_dbg(xhci, "Freed event ring\n");
+
+- xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[0]);
+- xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[1]);
++ xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
+ if (xhci->cmd_ring)
+ xhci_ring_free(xhci, xhci->cmd_ring);
+ xhci->cmd_ring = NULL;
+@@ -586,8 +578,7 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+ xhci->device_pool = NULL;
+ xhci_dbg(xhci, "Freed device context pool\n");
+
+- xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]);
+- xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]);
++ xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
+ if (xhci->dcbaa)
+ pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
+ xhci->dcbaa, xhci->dcbaa->dma);
+@@ -602,6 +593,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ dma_addr_t dma;
+ struct device *dev = xhci_to_hcd(xhci)->self.controller;
+ unsigned int val, val2;
++ u64 val_64;
+ struct xhci_segment *seg;
+ u32 page_size;
+ int i;
+@@ -647,8 +639,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ xhci->dcbaa->dma = dma;
+ xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n",
+ (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
+- xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]);
+- xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]);
++ xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
+
+ /*
+ * Initialize the ring segment pool. The ring must be a contiguous
+@@ -675,14 +666,12 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ (unsigned long long)xhci->cmd_ring->first_seg->dma);
+
+ /* Set the address in the Command Ring Control register */
+- val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]);
+- val = (val & ~CMD_RING_ADDR_MASK) |
+- (xhci->cmd_ring->first_seg->dma & CMD_RING_ADDR_MASK) |
++ val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
++ val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
++ (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
+ xhci->cmd_ring->cycle_state;
+- xhci_dbg(xhci, "// Setting command ring address low bits to 0x%x\n", val);
+- xhci_writel(xhci, val, &xhci->op_regs->cmd_ring[0]);
+- xhci_dbg(xhci, "// Setting command ring address high bits to 0x0\n");
+- xhci_writel(xhci, (u32) 0, &xhci->op_regs->cmd_ring[1]);
++ xhci_dbg(xhci, "// Setting command ring address to 0x%x\n", val);
++ xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+ xhci_dbg_cmd_ptrs(xhci);
+
+ val = xhci_readl(xhci, &xhci->cap_regs->db_off);
+@@ -722,8 +711,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ /* set ring base address and size for each segment table entry */
+ for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) {
+ struct xhci_erst_entry *entry = &xhci->erst.entries[val];
+- entry->seg_addr[0] = seg->dma;
+- entry->seg_addr[1] = 0;
++ entry->seg_addr = seg->dma;
+ entry->seg_size = TRBS_PER_SEGMENT;
+ entry->rsvd = 0;
+ seg = seg->next;
+@@ -741,11 +729,10 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ /* set the segment table base address */
+ xhci_dbg(xhci, "// Set ERST base address for ir_set 0 = 0x%llx\n",
+ (unsigned long long)xhci->erst.erst_dma_addr);
+- val = xhci_readl(xhci, &xhci->ir_set->erst_base[0]);
+- val &= ERST_PTR_MASK;
+- val |= (xhci->erst.erst_dma_addr & ~ERST_PTR_MASK);
+- xhci_writel(xhci, val, &xhci->ir_set->erst_base[0]);
+- xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
++ val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base);
++ val_64 &= ERST_PTR_MASK;
++ val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK);
++ xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);
+
+ /* Set the event ring dequeue address */
+ xhci_set_hc_event_deq(xhci);
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -237,7 +237,7 @@ static int room_on_ring(struct xhci_hcd
+
+ void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
+ {
+- u32 temp;
++ u64 temp;
+ dma_addr_t deq;
+
+ deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
+@@ -246,13 +246,12 @@ void xhci_set_hc_event_deq(struct xhci_h
+ xhci_warn(xhci, "WARN something wrong with SW event ring "
+ "dequeue ptr.\n");
+ /* Update HC event ring dequeue pointer */
+- temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
++ temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+ temp &= ERST_PTR_MASK;
+ if (!in_interrupt())
+ xhci_dbg(xhci, "// Write event ring dequeue pointer\n");
+- xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
+- xhci_writel(xhci, (deq & ~ERST_PTR_MASK) | temp,
+- &xhci->ir_set->erst_dequeue[0]);
++ xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
++ &xhci->ir_set->erst_dequeue);
+ }
+
+ /* Ring the host controller doorbell after placing a command on the ring */
+@@ -352,7 +351,7 @@ static void find_new_dequeue_state(struc
+ if (!state->new_deq_seg)
+ BUG();
+ /* Dig out the cycle state saved by the xHC during the stop ep cmd */
+- state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq[0];
++ state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq;
+
+ state->new_deq_ptr = cur_td->last_trb;
+ state->new_deq_seg = find_trb_seg(state->new_deq_seg,
+@@ -594,10 +593,8 @@ static void handle_set_deq_completion(st
+ * cancelling URBs, which might not be an error...
+ */
+ } else {
+- xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq[0] = 0x%x, "
+- "deq[1] = 0x%x.\n",
+- dev->out_ctx->ep[ep_index].deq[0],
+- dev->out_ctx->ep[ep_index].deq[1]);
++ xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
++ dev->out_ctx->ep[ep_index].deq);
+ }
+
+ ep_ring->state &= ~SET_DEQ_PENDING;
+@@ -631,7 +628,7 @@ static void handle_cmd_completion(struct
+ u64 cmd_dma;
+ dma_addr_t cmd_dequeue_dma;
+
+- cmd_dma = (((u64) event->cmd_trb[1]) << 32) + event->cmd_trb[0];
++ cmd_dma = event->cmd_trb;
+ cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+ xhci->cmd_ring->dequeue);
+ /* Is the command ring deq ptr out of sync with the deq seg ptr? */
+@@ -794,10 +791,7 @@ static int handle_tx_event(struct xhci_h
+ return -ENODEV;
+ }
+
+- event_dma = event->buffer[0];
+- if (event->buffer[1] != 0)
+- xhci_warn(xhci, "WARN ignoring upper 32-bits of 64-bit TRB dma address\n");
+-
++ event_dma = event->buffer;
+ /* This TRB should be in the TD at the head of this ring's TD list */
+ if (list_empty(&ep_ring->td_list)) {
+ xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
+@@ -821,10 +815,10 @@ static int handle_tx_event(struct xhci_h
+ event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
+ xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+ (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
+- xhci_dbg(xhci, "Offset 0x00 (buffer[0]) = 0x%x\n",
+- (unsigned int) event->buffer[0]);
+- xhci_dbg(xhci, "Offset 0x04 (buffer[0]) = 0x%x\n",
+- (unsigned int) event->buffer[1]);
++ xhci_dbg(xhci, "Offset 0x00 (buffer lo) = 0x%x\n",
++ lower_32_bits(event->buffer));
++ xhci_dbg(xhci, "Offset 0x04 (buffer hi) = 0x%x\n",
++ upper_32_bits(event->buffer));
+ xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n",
+ (unsigned int) event->transfer_len);
+ xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n",
+@@ -1343,8 +1337,8 @@ static int queue_bulk_sg_tx(struct xhci_
+ TD_REMAINDER(urb->transfer_buffer_length - running_total) |
+ TRB_INTR_TARGET(0);
+ queue_trb(xhci, ep_ring, false,
+- (u32) addr,
+- (u32) ((u64) addr >> 32),
++ lower_32_bits(addr),
++ upper_32_bits(addr),
+ length_field,
+ /* We always want to know if the TRB was short,
+ * or we won't get an event when it completes.
+@@ -1475,8 +1469,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ TD_REMAINDER(urb->transfer_buffer_length - running_total) |
+ TRB_INTR_TARGET(0);
+ queue_trb(xhci, ep_ring, false,
+- (u32) addr,
+- (u32) ((u64) addr >> 32),
++ lower_32_bits(addr),
++ upper_32_bits(addr),
+ length_field,
+ /* We always want to know if the TRB was short,
+ * or we won't get an event when it completes.
+@@ -1637,7 +1631,8 @@ int xhci_queue_slot_control(struct xhci_
+ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+ u32 slot_id)
+ {
+- return queue_command(xhci, in_ctx_ptr, 0, 0,
++ return queue_command(xhci, lower_32_bits(in_ctx_ptr),
++ upper_32_bits(in_ctx_ptr), 0,
+ TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id));
+ }
+
+@@ -1645,7 +1640,8 @@ int xhci_queue_address_device(struct xhc
+ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
+ u32 slot_id)
+ {
+- return queue_command(xhci, in_ctx_ptr, 0, 0,
++ return queue_command(xhci, lower_32_bits(in_ctx_ptr),
++ upper_32_bits(in_ctx_ptr), 0,
+ TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
+ }
+
+@@ -1677,7 +1673,8 @@ static int queue_set_tr_deq(struct xhci_
+ xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
+ xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n",
+ deq_seg, deq_ptr);
+- return queue_command(xhci, (u32) addr | cycle_state, 0, 0,
++ return queue_command(xhci, lower_32_bits(addr) | cycle_state,
++ upper_32_bits(addr), 0,
+ trb_slot_id | trb_ep_index | type);
+ }
+
diff --git a/usb.current/usb-xhci-scratchpad-buffer-allocation.patch b/usb.current/usb-xhci-scratchpad-buffer-allocation.patch
new file mode 100644
index 00000000000000..3b13823ff71af3
--- /dev/null
+++ b/usb.current/usb-xhci-scratchpad-buffer-allocation.patch
@@ -0,0 +1,185 @@
+From johnyoun@synopsys.com Mon Jul 27 12:30:05 2009
+From: John Youn <johnyoun@synopsys.com>
+Date: Mon, 27 Jul 2009 12:05:03 -0700
+Subject: USB: xhci: Scratchpad buffer allocation
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>, John Youn <johnyoun@synopsys.com>
+Message-ID: <20090727190503.GA7953@gamba.jf.intel.com>
+
+
+From: John Youn <johnyoun@synopsys.com>
+
+Allocates and initializes the scratchpad buffer array (XHCI 4.20). This is an
+array of 64-bit DMA addresses to scratch pages that the controller may use
+during operation. The number of pages is specified in the "Max Scratchpad
+Buffers" field of HCSPARAMS2. The DMA address of this array is written into
+slot 0 of the DCBAA.
+
+Signed-off-by: John Youn <johnyoun@synopsys.com>
+Acked-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c | 102 ++++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/xhci.h | 11 ++++
+ 2 files changed, 113 insertions(+)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -89,6 +89,7 @@ struct xhci_cap_regs {
+ #define HCS_ERST_MAX(p) (((p) >> 4) & 0xf)
+ /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
+ /* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */
++#define HCS_MAX_SCRATCHPAD(p) (((p) >> 27) & 0x1f)
+
+ /* HCSPARAMS3 - hcs_params3 - bitmasks */
+ /* bits 0:7, Max U1 to U0 latency for the roothub ports */
+@@ -951,6 +952,13 @@ struct xhci_erst {
+ unsigned int erst_size;
+ };
+
++struct xhci_scratchpad {
++ u64 *sp_array;
++ dma_addr_t sp_dma;
++ void **sp_buffers;
++ dma_addr_t *sp_dma_buffers;
++};
++
+ /*
+ * Each segment table entry is 4*32bits long. 1K seems like an ok size:
+ * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
+@@ -1005,6 +1013,9 @@ struct xhci_hcd {
+ struct xhci_ring *cmd_ring;
+ struct xhci_ring *event_ring;
+ struct xhci_erst erst;
++ /* Scratchpad */
++ struct xhci_scratchpad *scratchpad;
++
+ /* slot enabling and address device helpers */
+ struct completion addr_dev;
+ int slot_id;
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -545,6 +545,103 @@ void xhci_endpoint_zero(struct xhci_hcd
+ */
+ }
+
++/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */
++static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
++{
++ int i;
++ struct device *dev = xhci_to_hcd(xhci)->self.controller;
++ int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2);
++
++ xhci_dbg(xhci, "Allocating %d scratchpad buffers\n", num_sp);
++
++ if (!num_sp)
++ return 0;
++
++ xhci->scratchpad = kzalloc(sizeof(*xhci->scratchpad), flags);
++ if (!xhci->scratchpad)
++ goto fail_sp;
++
++ xhci->scratchpad->sp_array =
++ pci_alloc_consistent(to_pci_dev(dev),
++ num_sp * sizeof(u64),
++ &xhci->scratchpad->sp_dma);
++ if (!xhci->scratchpad->sp_array)
++ goto fail_sp2;
++
++ xhci->scratchpad->sp_buffers = kzalloc(sizeof(void *) * num_sp, flags);
++ if (!xhci->scratchpad->sp_buffers)
++ goto fail_sp3;
++
++ xhci->scratchpad->sp_dma_buffers =
++ kzalloc(sizeof(dma_addr_t) * num_sp, flags);
++
++ if (!xhci->scratchpad->sp_dma_buffers)
++ goto fail_sp4;
++
++ xhci->dcbaa->dev_context_ptrs[0] = xhci->scratchpad->sp_dma;
++ for (i = 0; i < num_sp; i++) {
++ dma_addr_t dma;
++ void *buf = pci_alloc_consistent(to_pci_dev(dev),
++ xhci->page_size, &dma);
++ if (!buf)
++ goto fail_sp5;
++
++ xhci->scratchpad->sp_array[i] = dma;
++ xhci->scratchpad->sp_buffers[i] = buf;
++ xhci->scratchpad->sp_dma_buffers[i] = dma;
++ }
++
++ return 0;
++
++ fail_sp5:
++ for (i = i - 1; i >= 0; i--) {
++ pci_free_consistent(to_pci_dev(dev), xhci->page_size,
++ xhci->scratchpad->sp_buffers[i],
++ xhci->scratchpad->sp_dma_buffers[i]);
++ }
++ kfree(xhci->scratchpad->sp_dma_buffers);
++
++ fail_sp4:
++ kfree(xhci->scratchpad->sp_buffers);
++
++ fail_sp3:
++ pci_free_consistent(to_pci_dev(dev), num_sp * sizeof(u64),
++ xhci->scratchpad->sp_array,
++ xhci->scratchpad->sp_dma);
++
++ fail_sp2:
++ kfree(xhci->scratchpad);
++ xhci->scratchpad = NULL;
++
++ fail_sp:
++ return -ENOMEM;
++}
++
++static void scratchpad_free(struct xhci_hcd *xhci)
++{
++ int num_sp;
++ int i;
++ struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
++
++ if (!xhci->scratchpad)
++ return;
++
++ num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2);
++
++ for (i = 0; i < num_sp; i++) {
++ pci_free_consistent(pdev, xhci->page_size,
++ xhci->scratchpad->sp_buffers[i],
++ xhci->scratchpad->sp_dma_buffers[i]);
++ }
++ kfree(xhci->scratchpad->sp_dma_buffers);
++ kfree(xhci->scratchpad->sp_buffers);
++ pci_free_consistent(pdev, num_sp * sizeof(u64),
++ xhci->scratchpad->sp_array,
++ xhci->scratchpad->sp_dma);
++ kfree(xhci->scratchpad);
++ xhci->scratchpad = NULL;
++}
++
+ void xhci_mem_cleanup(struct xhci_hcd *xhci)
+ {
+ struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
+@@ -593,6 +690,7 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+
+ xhci->page_size = 0;
+ xhci->page_shift = 0;
++ scratchpad_free(xhci);
+ }
+
+ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
+@@ -755,7 +853,11 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ for (i = 0; i < MAX_HC_SLOTS; ++i)
+ xhci->devs[i] = 0;
+
++ if (scratchpad_alloc(xhci, flags))
++ goto fail;
++
+ return 0;
++
+ fail:
+ xhci_warn(xhci, "Couldn't initialize memory\n");
+ xhci_mem_cleanup(xhci);
diff --git a/usb.current/usb-xhci-set-td-size-in-transfer-trb.patch b/usb.current/usb-xhci-set-td-size-in-transfer-trb.patch
new file mode 100644
index 00000000000000..25f509e28ce03e
--- /dev/null
+++ b/usb.current/usb-xhci-set-td-size-in-transfer-trb.patch
@@ -0,0 +1,97 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:23:20 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:03:07 -0700
+Subject: USB: xhci: Set TD size in transfer TRB.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190307.GA7455@gamba.jf.intel.com>
+
+
+The 0.95 xHCI specification requires software to set the "TD size" field
+in each transaction request block (TRB). This field gives the host
+controller an indication of how much data is remaining in the TD
+(including the buffer in the current TRB). Set this field in bulk TRBs
+and data stage TRBs for control transfers.
+
+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 | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1285,6 +1285,7 @@ static int queue_bulk_sg_tx(struct xhci_
+ /* Queue the first TRB, even if it's zero-length */
+ do {
+ u32 field = 0;
++ u32 length_field = 0;
+
+ /* Don't change the cycle bit of the first TRB until later */
+ if (first_trb)
+@@ -1314,10 +1315,13 @@ static int queue_bulk_sg_tx(struct xhci_
+ (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1),
+ (unsigned int) addr + trb_buff_len);
+ }
++ length_field = TRB_LEN(trb_buff_len) |
++ TD_REMAINDER(urb->transfer_buffer_length - running_total) |
++ TRB_INTR_TARGET(0);
+ queue_trb(xhci, ep_ring, false,
+ (u32) addr,
+ (u32) ((u64) addr >> 32),
+- TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0),
++ length_field,
+ /* We always want to know if the TRB was short,
+ * or we won't get an event when it completes.
+ * (Unless we use event data TRBs, which are a
+@@ -1365,7 +1369,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ struct xhci_generic_trb *start_trb;
+ bool first_trb;
+ int start_cycle;
+- u32 field;
++ u32 field, length_field;
+
+ int running_total, trb_buff_len, ret;
+ u64 addr;
+@@ -1443,10 +1447,13 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
+ td->last_trb = ep_ring->enqueue;
+ field |= TRB_IOC;
+ }
++ length_field = TRB_LEN(trb_buff_len) |
++ TD_REMAINDER(urb->transfer_buffer_length - running_total) |
++ TRB_INTR_TARGET(0);
+ queue_trb(xhci, ep_ring, false,
+ (u32) addr,
+ (u32) ((u64) addr >> 32),
+- TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0),
++ length_field,
+ /* We always want to know if the TRB was short,
+ * or we won't get an event when it completes.
+ * (Unless we use event data TRBs, which are a
+@@ -1478,7 +1485,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+ struct usb_ctrlrequest *setup;
+ struct xhci_generic_trb *start_trb;
+ int start_cycle;
+- u32 field;
++ u32 field, length_field;
+ struct xhci_td *td;
+
+ ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
+@@ -1528,13 +1535,16 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *
+
+ /* If there's data, queue data TRBs */
+ field = 0;
++ length_field = TRB_LEN(urb->transfer_buffer_length) |
++ TD_REMAINDER(urb->transfer_buffer_length) |
++ TRB_INTR_TARGET(0);
+ if (urb->transfer_buffer_length > 0) {
+ if (setup->bRequestType & USB_DIR_IN)
+ field |= TRB_DIR_IN;
+ queue_trb(xhci, ep_ring, false,
+ lower_32_bits(urb->transfer_dma),
+ upper_32_bits(urb->transfer_dma),
+- TRB_LEN(urb->transfer_buffer_length) | TRB_INTR_TARGET(0),
++ length_field,
+ /* Event on short tx */
+ field | TRB_ISP | TRB_TYPE(TRB_DATA) | ep_ring->cycle_state);
+ }
diff --git a/usb.current/usb-xhci-setup-hw-retries-correctly.patch b/usb.current/usb-xhci-setup-hw-retries-correctly.patch
new file mode 100644
index 00000000000000..fd3331c7bb09fe
--- /dev/null
+++ b/usb.current/usb-xhci-setup-hw-retries-correctly.patch
@@ -0,0 +1,43 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:29:05 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:04:27 -0700
+Subject: USB: xhci: Setup HW retries correctly.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190427.GA7800@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+The xHCI host controller can be programmed to retry a transfer a certain number
+of times per endpoint before it passes back an error condition to the host
+controller driver. The xHC will return an error code when the error count
+transitions from 1 to 0. Programming an error count of 3 means the xHC tries
+the transfer 3 times, programming it with a 1 means it tries to transfer once,
+and programming it with 0 means the HW tries the transfer infinitely.
+
+We want isochronous transfers to only be tried once, so set the error count to
+one.
+
+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 | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -480,11 +480,13 @@ int xhci_endpoint_init(struct xhci_hcd *
+
+ /* FIXME dig Mult and streams info out of ep companion desc */
+
+- /* Allow 3 retries for everything but isoc */
++ /* Allow 3 retries for everything but isoc;
++ * error count = 0 means infinite retries.
++ */
+ if (!usb_endpoint_xfer_isoc(&ep->desc))
+ ep_ctx->ep_info2 = ERROR_COUNT(3);
+ else
+- ep_ctx->ep_info2 = ERROR_COUNT(0);
++ ep_ctx->ep_info2 = ERROR_COUNT(1);
+
+ ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep);
+
diff --git a/usb.current/usb-xhci-stall-handling-bug-fixes.patch b/usb.current/usb-xhci-stall-handling-bug-fixes.patch
new file mode 100644
index 00000000000000..b854e1524e5484
--- /dev/null
+++ b/usb.current/usb-xhci-stall-handling-bug-fixes.patch
@@ -0,0 +1,362 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:32:25 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:05:21 -0700
+Subject: USB: xhci: Stall handling bug fixes.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190521.GA8067@gamba.jf.intel.com>
+
+
+Correct the xHCI code to handle stalls on USB endpoints. We need to move
+the endpoint ring's dequeue pointer past the stalled transfer, or the HW
+will try to restart the transfer the next time the doorbell is rung.
+
+Don't attempt to clear a halt on an endpoint if we haven't seen a stalled
+transfer for it. The USB core will attempt to clear a halt on all
+endpoints when it selects a new configuration.
+
+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 | 24 +++++++
+ drivers/usb/host/xhci-ring.c | 133 +++++++++++++++++++++++++++----------------
+ drivers/usb/host/xhci.h | 12 +++
+ 3 files changed, 120 insertions(+), 49 deletions(-)
+
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -952,6 +952,12 @@ 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;
+@@ -1203,6 +1209,12 @@ int xhci_queue_configure_endpoint(struct
+ 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,
++ unsigned int slot_id, unsigned int ep_index,
++ struct xhci_td *cur_td, struct xhci_dequeue_state *state);
++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);
+
+ /* 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
+@@ -1089,6 +1089,8 @@ 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);
+ udev = (struct usb_device *) ep->hcpriv;
+@@ -1098,11 +1100,33 @@ void xhci_endpoint_reset(struct usb_hcd
+ if (!ep->hcpriv)
+ return;
+ ep_index = xhci_get_endpoint_index(&ep->desc);
++ ep_ring = xhci->devs[udev->slot_id]->ep_rings[ep_index];
++ if (!ep_ring->stopped_td) {
++ xhci_dbg(xhci, "Endpoint 0x%x not halted, refusing to reset.\n",
++ ep->desc.bEndpointAddress);
++ return;
++ }
+
+ xhci_dbg(xhci, "Queueing reset endpoint command\n");
+ spin_lock_irqsave(&xhci->lock, flags);
+ ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index);
++ /*
++ * Can't change the ring dequeue pointer until it's transitioned to the
++ * stopped state, which is only upon a successful reset endpoint
++ * 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);
++ kfree(ep_ring->stopped_td);
+ xhci_ring_cmd_db(xhci);
+ }
+ spin_unlock_irqrestore(&xhci->lock, flags);
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -335,12 +335,6 @@ static struct xhci_segment *find_trb_seg
+ return cur_seg;
+ }
+
+-struct dequeue_state {
+- struct xhci_segment *new_deq_seg;
+- union xhci_trb *new_deq_ptr;
+- int new_cycle_state;
+-};
+-
+ /*
+ * Move the xHC's endpoint ring dequeue pointer past cur_td.
+ * Record the new state of the xHC's endpoint ring dequeue segment,
+@@ -355,26 +349,30 @@ struct dequeue_state {
+ * - Finally we move the dequeue state one TRB further, toggling the cycle bit
+ * if we've moved it past a link TRB with the toggle cycle bit set.
+ */
+-static void find_new_dequeue_state(struct xhci_hcd *xhci,
++void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
+ unsigned int slot_id, unsigned int ep_index,
+- struct xhci_td *cur_td, struct dequeue_state *state)
++ struct xhci_td *cur_td, struct xhci_dequeue_state *state)
+ {
+ struct xhci_virt_device *dev = xhci->devs[slot_id];
+ struct xhci_ring *ep_ring = dev->ep_rings[ep_index];
+ struct xhci_generic_trb *trb;
+ struct xhci_ep_ctx *ep_ctx;
++ dma_addr_t addr;
+
+ state->new_cycle_state = 0;
++ xhci_dbg(xhci, "Finding segment containing stopped TRB.\n");
+ state->new_deq_seg = find_trb_seg(cur_td->start_seg,
+ ep_ring->stopped_trb,
+ &state->new_cycle_state);
+ if (!state->new_deq_seg)
+ BUG();
+ /* Dig out the cycle state saved by the xHC during the stop ep cmd */
++ xhci_dbg(xhci, "Finding endpoint context\n");
+ ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
+ state->new_cycle_state = 0x1 & ep_ctx->deq;
+
+ state->new_deq_ptr = cur_td->last_trb;
++ xhci_dbg(xhci, "Finding segment containing last TRB in TD.\n");
+ state->new_deq_seg = find_trb_seg(state->new_deq_seg,
+ state->new_deq_ptr,
+ &state->new_cycle_state);
+@@ -388,6 +386,12 @@ static void find_new_dequeue_state(struc
+ next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
+
+ /* Don't update the ring cycle state for the producer (us). */
++ xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n",
++ state->new_deq_seg);
++ addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
++ xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n",
++ (unsigned long long) addr);
++ xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n");
+ ep_ring->dequeue = state->new_deq_ptr;
+ ep_ring->deq_seg = state->new_deq_seg;
+ }
+@@ -437,6 +441,30 @@ static int queue_set_tr_deq(struct xhci_
+ unsigned int ep_index, struct xhci_segment *deq_seg,
+ union xhci_trb *deq_ptr, u32 cycle_state);
+
++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)
++{
++ xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
++ "new deq ptr = %p (0x%llx dma), new cycle = %u\n",
++ deq_state->new_deq_seg,
++ (unsigned long long)deq_state->new_deq_seg->dma,
++ deq_state->new_deq_ptr,
++ (unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
++ deq_state->new_cycle_state);
++ queue_set_tr_deq(xhci, slot_id, ep_index,
++ deq_state->new_deq_seg,
++ deq_state->new_deq_ptr,
++ (u32) deq_state->new_cycle_state);
++ /* Stop the TD queueing code from ringing the doorbell until
++ * this command completes. The HC won't set the dequeue pointer
++ * if the ring is running, and ringing the doorbell starts the
++ * ring running.
++ */
++ ep_ring->state |= SET_DEQ_PENDING;
++ xhci_ring_cmd_db(xhci);
++}
++
+ /*
+ * When we get a command completion for a Stop Endpoint Command, we need to
+ * unlink any cancelled TDs from the ring. There are two ways to do that:
+@@ -457,7 +485,7 @@ static void handle_stopped_endpoint(stru
+ struct xhci_td *cur_td = 0;
+ struct xhci_td *last_unlinked_td;
+
+- struct dequeue_state deq_state;
++ struct xhci_dequeue_state deq_state;
+ #ifdef CONFIG_USB_HCD_STAT
+ ktime_t stop_time = ktime_get();
+ #endif
+@@ -485,7 +513,7 @@ static void handle_stopped_endpoint(stru
+ * move the xHC endpoint ring dequeue pointer past this TD.
+ */
+ if (cur_td == ep_ring->stopped_td)
+- find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
++ xhci_find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
+ &deq_state);
+ else
+ td_to_noop(xhci, ep_ring, cur_td);
+@@ -501,24 +529,8 @@ static void handle_stopped_endpoint(stru
+
+ /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
+ if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
+- xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
+- "new deq ptr = %p (0x%llx dma), new cycle = %u\n",
+- deq_state.new_deq_seg,
+- (unsigned long long)deq_state.new_deq_seg->dma,
+- deq_state.new_deq_ptr,
+- (unsigned long long)xhci_trb_virt_to_dma(deq_state.new_deq_seg, deq_state.new_deq_ptr),
+- deq_state.new_cycle_state);
+- queue_set_tr_deq(xhci, slot_id, ep_index,
+- deq_state.new_deq_seg,
+- deq_state.new_deq_ptr,
+- (u32) deq_state.new_cycle_state);
+- /* Stop the TD queueing code from ringing the doorbell until
+- * this command completes. The HC won't set the dequeue pointer
+- * if the ring is running, and ringing the doorbell starts the
+- * ring running.
+- */
+- ep_ring->state |= SET_DEQ_PENDING;
+- xhci_ring_cmd_db(xhci);
++ xhci_queue_new_dequeue_state(xhci, ep_ring,
++ slot_id, ep_index, &deq_state);
+ } else {
+ /* Otherwise just ring the doorbell to restart the ring */
+ ring_ep_doorbell(xhci, slot_id, ep_index);
+@@ -929,12 +941,15 @@ static int handle_tx_event(struct xhci_h
+ if (event_trb != ep_ring->dequeue) {
+ /* The event was for the status stage */
+ if (event_trb == td->last_trb) {
+- /* Did we already see a short data stage? */
+- if (td->urb->actual_length != 0)
+- status = -EREMOTEIO;
+- else
++ if (td->urb->actual_length != 0) {
++ /* Don't overwrite a previously set error code */
++ if (status == -EINPROGRESS || status == 0)
++ /* Did we already see a short data stage? */
++ status = -EREMOTEIO;
++ } else {
+ td->urb->actual_length =
+ td->urb->transfer_buffer_length;
++ }
+ } else {
+ /* Maybe the event was for the data stage? */
+ if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
+@@ -992,16 +1007,20 @@ static int handle_tx_event(struct xhci_h
+ 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) {
++ if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
++ status = -EREMOTEIO;
++ else
++ status = 0;
++ }
+ } else {
+ td->urb->actual_length = td->urb->transfer_buffer_length;
+ /* Ignore a short packet completion if the
+ * untransferred length was zero.
+ */
+- status = 0;
++ if (status == -EREMOTEIO)
++ status = 0;
+ }
+ } else {
+ /* Slow path - walk the list, starting from the dequeue
+@@ -1028,19 +1047,30 @@ static int handle_tx_event(struct xhci_h
+ TRB_LEN(event->transfer_len);
+ }
+ }
+- /* 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.
+- */
+ if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL ||
+ GET_COMP_CODE(event->transfer_len) == 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.
++ */
+ ep_ring->stopped_td = td;
+ ep_ring->stopped_trb = event_trb;
+ } else {
+- /* Update ring dequeue pointer */
+- while (ep_ring->dequeue != td->last_trb)
++ if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) {
++ /* 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
++ * pointer past the TD. We can't do that here because
++ * the halt condition must be cleared first.
++ */
++ ep_ring->stopped_td = td;
++ ep_ring->stopped_trb = event_trb;
++ } else {
++ /* Update ring dequeue pointer */
++ while (ep_ring->dequeue != td->last_trb)
++ inc_deq(xhci, ep_ring, false);
+ inc_deq(xhci, ep_ring, false);
+- inc_deq(xhci, ep_ring, false);
++ }
+
+ /* Clean up the endpoint's TD list */
+ urb = td->urb;
+@@ -1050,7 +1080,10 @@ static int handle_tx_event(struct xhci_h
+ list_del(&td->cancelled_td_list);
+ ep_ring->cancels_pending--;
+ }
+- kfree(td);
++ /* Leave the TD around for the reset endpoint function to use */
++ if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
++ kfree(td);
++ }
+ urb->hcpriv = NULL;
+ }
+ cleanup:
+@@ -1166,13 +1199,13 @@ static int prepare_ring(struct xhci_hcd
+ */
+ xhci_warn(xhci, "WARN urb submitted to disabled ep\n");
+ return -ENOENT;
+- case EP_STATE_HALTED:
+ case EP_STATE_ERROR:
+- xhci_warn(xhci, "WARN waiting for halt or error on ep "
+- "to be cleared\n");
++ xhci_warn(xhci, "WARN waiting for error on ep to be cleared\n");
+ /* FIXME event handling code for error needs to clear it */
+ /* XXX not sure if this should be -ENOENT or not */
+ return -EINVAL;
++ case EP_STATE_HALTED:
++ xhci_dbg(xhci, "WARN halted endpoint, queueing URB anyway.\n");
+ case EP_STATE_STOPPED:
+ case EP_STATE_RUNNING:
+ break;
+@@ -1724,10 +1757,12 @@ static int queue_set_tr_deq(struct xhci_
+ u32 type = TRB_TYPE(TRB_SET_DEQ);
+
+ addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
+- if (addr == 0)
++ if (addr == 0) {
+ xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
+ xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n",
+ deq_seg, deq_ptr);
++ return 0;
++ }
+ return queue_command(xhci, lower_32_bits(addr) | cycle_state,
+ upper_32_bits(addr), 0,
+ trb_slot_id | trb_ep_index | type);
diff --git a/usb.current/usb-xhci-support-for-64-byte-contexts.patch b/usb.current/usb-xhci-support-for-64-byte-contexts.patch
new file mode 100644
index 00000000000000..82fcd510775790
--- /dev/null
+++ b/usb.current/usb-xhci-support-for-64-byte-contexts.patch
@@ -0,0 +1,925 @@
+From johnyoun@synopsys.com Mon Jul 27 12:32:02 2009
+From: John Youn <johnyoun@synopsys.com>
+Date: Mon, 27 Jul 2009 12:05:15 -0700
+Subject: USB: xhci: Support for 64-byte contexts
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>, John Youn <johnyoun@synopsys.com>
+Message-ID: <20090727190515.GA8030@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+From: John Youn <johnyoun@synopsys.com>
+
+Adds support for controllers that use 64-byte contexts. The following context
+data structures are affected by this: Device, Input, Input Control, Endpoint,
+and Slot. To accommodate the use of either 32 or 64-byte contexts, a Device or
+Input context can only be accessed through functions which look-up and return
+pointers to their contained contexts.
+
+Signed-off-by: John Youn <johnyoun@synopsys.com>
+Acked-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-dbg.c | 125 +++++++++++++++++++++++++++----------------
+ drivers/usb/host/xhci-hcd.c | 121 ++++++++++++++++++++++++-----------------
+ drivers/usb/host/xhci-mem.c | 121 +++++++++++++++++++++++++++++------------
+ drivers/usb/host/xhci-ring.c | 22 +++++--
+ drivers/usb/host/xhci.h | 61 +++++++++++---------
+ 5 files changed, 287 insertions(+), 163 deletions(-)
+
+--- a/drivers/usb/host/xhci-dbg.c
++++ b/drivers/usb/host/xhci-dbg.c
+@@ -393,103 +393,138 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *
+ upper_32_bits(val));
+ }
+
+-dma_addr_t xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_slot_ctx *slot, dma_addr_t dma)
++/* Print the last 32 bytes for 64-byte contexts */
++static void dbg_rsvd64(struct xhci_hcd *xhci, u64 *ctx, dma_addr_t dma)
++{
++ int i;
++ for (i = 0; i < 4; ++i) {
++ xhci_dbg(xhci, "@%p (virt) @%08llx "
++ "(dma) %#08llx - rsvd64[%d]\n",
++ &ctx[4 + i], (unsigned long long)dma,
++ ctx[4 + i], i);
++ dma += 8;
++ }
++}
++
++void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
+ {
+ /* Fields are 32 bits wide, DMA addresses are in bytes */
+ int field_size = 32 / 8;
+ 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);
++ int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
++
+ xhci_dbg(xhci, "Slot Context:\n");
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n",
+- &slot->dev_info,
+- (unsigned long long)dma, slot->dev_info);
++ &slot_ctx->dev_info,
++ (unsigned long long)dma, slot_ctx->dev_info);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n",
+- &slot->dev_info2,
+- (unsigned long long)dma, slot->dev_info2);
++ &slot_ctx->dev_info2,
++ (unsigned long long)dma, slot_ctx->dev_info2);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n",
+- &slot->tt_info,
+- (unsigned long long)dma, slot->tt_info);
++ &slot_ctx->tt_info,
++ (unsigned long long)dma, slot_ctx->tt_info);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n",
+- &slot->dev_state,
+- (unsigned long long)dma, slot->dev_state);
++ &slot_ctx->dev_state,
++ (unsigned long long)dma, slot_ctx->dev_state);
+ dma += field_size;
+ for (i = 0; i < 4; ++i) {
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
+- &slot->reserved[i], (unsigned long long)dma,
+- slot->reserved[i], i);
++ &slot_ctx->reserved[i], (unsigned long long)dma,
++ slot_ctx->reserved[i], i);
+ dma += field_size;
+ }
+
+- return dma;
++ if (csz)
++ dbg_rsvd64(xhci, (u64 *)slot_ctx, dma);
+ }
+
+-dma_addr_t xhci_dbg_ep_ctx(struct xhci_hcd *xhci, struct xhci_ep_ctx *ep, dma_addr_t dma, unsigned int last_ep)
++void xhci_dbg_ep_ctx(struct xhci_hcd *xhci,
++ struct xhci_container_ctx *ctx,
++ unsigned int last_ep)
+ {
+ int i, j;
+ int last_ep_ctx = 31;
+ /* Fields are 32 bits wide, DMA addresses are in bytes */
+ int field_size = 32 / 8;
++ int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
+
+ if (last_ep < 31)
+ last_ep_ctx = last_ep + 1;
+ 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);
++
+ xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
+- &ep[i].ep_info,
+- (unsigned long long)dma, ep[i].ep_info);
++ &ep_ctx->ep_info,
++ (unsigned long long)dma, ep_ctx->ep_info);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n",
+- &ep[i].ep_info2,
+- (unsigned long long)dma, ep[i].ep_info2);
++ &ep_ctx->ep_info2,
++ (unsigned long long)dma, ep_ctx->ep_info2);
+ dma += field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n",
+- &ep[i].deq,
+- (unsigned long long)dma, ep[i].deq);
++ &ep_ctx->deq,
++ (unsigned long long)dma, ep_ctx->deq);
+ dma += 2*field_size;
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n",
+- &ep[i].tx_info,
+- (unsigned long long)dma, ep[i].tx_info);
++ &ep_ctx->tx_info,
++ (unsigned long long)dma, ep_ctx->tx_info);
+ dma += field_size;
+ for (j = 0; j < 3; ++j) {
+ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
+- &ep[i].reserved[j],
++ &ep_ctx->reserved[j],
+ (unsigned long long)dma,
+- ep[i].reserved[j], j);
++ ep_ctx->reserved[j], j);
+ dma += field_size;
+ }
++
++ if (csz)
++ dbg_rsvd64(xhci, (u64 *)ep_ctx, dma);
+ }
+- return dma;
+ }
+
+-void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep)
++void xhci_dbg_ctx(struct xhci_hcd *xhci,
++ struct xhci_container_ctx *ctx,
++ unsigned int last_ep)
+ {
+ int i;
+ /* Fields are 32 bits wide, DMA addresses are in bytes */
+ int field_size = 32 / 8;
+-
+- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
+- &ctx->drop_flags, (unsigned long long)dma,
+- ctx->drop_flags);
+- dma += field_size;
+- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
+- &ctx->add_flags, (unsigned long long)dma,
+- ctx->add_flags);
+- dma += field_size;
+- for (i = 0; i < 6; ++i) {
+- xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
+- &ctx->rsvd[i], (unsigned long long)dma,
+- ctx->rsvd[i], i);
++ struct xhci_slot_ctx *slot_ctx;
++ dma_addr_t dma = ctx->dma;
++ int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
++
++ if (ctx->type == XHCI_CTX_TYPE_INPUT) {
++ struct xhci_input_control_ctx *ctrl_ctx =
++ xhci_get_input_control_ctx(xhci, ctx);
++ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
++ &ctrl_ctx->drop_flags, (unsigned long long)dma,
++ ctrl_ctx->drop_flags);
+ dma += field_size;
++ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
++ &ctrl_ctx->add_flags, (unsigned long long)dma,
++ ctrl_ctx->add_flags);
++ dma += field_size;
++ for (i = 0; i < 6; ++i) {
++ xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n",
++ &ctrl_ctx->rsvd2[i], (unsigned long long)dma,
++ ctrl_ctx->rsvd2[i], i);
++ dma += field_size;
++ }
++
++ if (csz)
++ dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
+ }
+- dma = xhci_dbg_slot_ctx(xhci, &ctx->slot, dma);
+- dma = xhci_dbg_ep_ctx(xhci, ctx->ep, dma, last_ep);
+-}
+
+-void xhci_dbg_device_ctx(struct xhci_hcd *xhci, struct xhci_device_ctx *ctx, dma_addr_t dma, unsigned int last_ep)
+-{
+- dma = xhci_dbg_slot_ctx(xhci, &ctx->slot, dma);
+- dma = xhci_dbg_ep_ctx(xhci, ctx->ep, dma, last_ep);
++ slot_ctx = xhci_get_slot_ctx(xhci, ctx);
++ xhci_dbg_slot_ctx(xhci, ctx);
++ xhci_dbg_ep_ctx(xhci, ctx, last_ep);
+ }
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -447,6 +447,27 @@ struct xhci_doorbell_array {
+
+
+ /**
++ * struct xhci_container_ctx
++ * @type: Type of context. Used to calculated offsets to contained contexts.
++ * @size: Size of the context data
++ * @bytes: The raw context data given to HW
++ * @dma: dma address of the bytes
++ *
++ * Represents either a Device or Input context. Holds a pointer to the raw
++ * memory used for the context (bytes) and dma address of it (dma).
++ */
++struct xhci_container_ctx {
++ unsigned type;
++#define XHCI_CTX_TYPE_DEVICE 0x1
++#define XHCI_CTX_TYPE_INPUT 0x2
++
++ int size;
++
++ u8 *bytes;
++ dma_addr_t dma;
++};
++
++/**
+ * struct xhci_slot_ctx
+ * @dev_info: Route string, device speed, hub info, and last valid endpoint
+ * @dev_info2: Max exit latency for device number, root hub port number
+@@ -583,32 +604,16 @@ struct xhci_ep_ctx {
+
+
+ /**
+- * struct xhci_device_control
+- * Input context; see section 6.2.5.
++ * struct xhci_input_control_context
++ * Input control context; see section 6.2.5.
+ *
+ * @drop_context: set the bit of the endpoint context you want to disable
+ * @add_context: set the bit of the endpoint context you want to enable
+ */
+-struct xhci_device_control {
+- /* Input control context */
++struct xhci_input_control_ctx {
+ u32 drop_flags;
+ u32 add_flags;
+- u32 rsvd[6];
+- /* Copy of device context */
+- struct xhci_slot_ctx slot;
+- struct xhci_ep_ctx ep[31];
+-};
+-
+-/**
+- * struct xhci_device_ctx
+- * Device context; see section 6.2.1.
+- *
+- * @slot: slot context for the device.
+- * @ep: array of endpoint contexts for the device.
+- */
+-struct xhci_device_ctx {
+- struct xhci_slot_ctx slot;
+- struct xhci_ep_ctx ep[31];
++ u32 rsvd2[6];
+ };
+
+ /* drop context bitmasks */
+@@ -616,7 +621,6 @@ struct xhci_device_ctx {
+ /* add context bitmasks */
+ #define ADD_EP(x) (0x1 << x)
+
+-
+ struct xhci_virt_device {
+ /*
+ * Commands to the hardware are passed an "input context" that
+@@ -626,11 +630,10 @@ struct xhci_virt_device {
+ * track of input and output contexts separately because
+ * these commands might fail and we don't trust the hardware.
+ */
+- struct xhci_device_ctx *out_ctx;
+- dma_addr_t out_ctx_dma;
++ struct xhci_container_ctx *out_ctx;
+ /* Used for addressing devices and configuration changes */
+- struct xhci_device_control *in_ctx;
+- dma_addr_t in_ctx_dma;
++ struct xhci_container_ctx *in_ctx;
++
+ /* FIXME when stream support is added */
+ struct xhci_ring *ep_rings[31];
+ /* Temporary storage in case the configure endpoint command fails and we
+@@ -1139,8 +1142,7 @@ void xhci_debug_ring(struct xhci_hcd *xh
+ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst);
+ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci);
+ void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
+-void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep);
+-void xhci_dbg_device_ctx(struct xhci_hcd *xhci, struct xhci_device_ctx *ctx, dma_addr_t dma, unsigned int last_ep);
++void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep);
+
+ /* xHCI memory managment */
+ void xhci_mem_cleanup(struct xhci_hcd *xhci);
+@@ -1207,4 +1209,9 @@ int xhci_hub_control(struct usb_hcd *hcd
+ char *buf, u16 wLength);
+ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
+
++/* xHCI contexts */
++struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
++struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
++struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index);
++
+ #endif /* __LINUX_XHCI_HCD_H */
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -722,7 +722,9 @@ int xhci_drop_endpoint(struct usb_hcd *h
+ struct usb_host_endpoint *ep)
+ {
+ struct xhci_hcd *xhci;
+- struct xhci_device_control *in_ctx;
++ struct xhci_container_ctx *in_ctx, *out_ctx;
++ struct xhci_input_control_ctx *ctrl_ctx;
++ struct xhci_slot_ctx *slot_ctx;
+ unsigned int last_ctx;
+ unsigned int ep_index;
+ struct xhci_ep_ctx *ep_ctx;
+@@ -750,31 +752,34 @@ int xhci_drop_endpoint(struct usb_hcd *h
+ }
+
+ in_ctx = xhci->devs[udev->slot_id]->in_ctx;
++ out_ctx = xhci->devs[udev->slot_id]->out_ctx;
++ ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+ ep_index = xhci_get_endpoint_index(&ep->desc);
+- ep_ctx = &xhci->devs[udev->slot_id]->out_ctx->ep[ep_index];
++ ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
+ /* If the HC already knows the endpoint is disabled,
+ * or the HCD has noted it is disabled, ignore this request
+ */
+ if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED ||
+- in_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
++ ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
+ xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
+ __func__, ep);
+ return 0;
+ }
+
+- in_ctx->drop_flags |= drop_flag;
+- new_drop_flags = in_ctx->drop_flags;
++ ctrl_ctx->drop_flags |= drop_flag;
++ new_drop_flags = ctrl_ctx->drop_flags;
+
+- in_ctx->add_flags = ~drop_flag;
+- new_add_flags = in_ctx->add_flags;
++ ctrl_ctx->add_flags = ~drop_flag;
++ new_add_flags = ctrl_ctx->add_flags;
+
+- last_ctx = xhci_last_valid_endpoint(in_ctx->add_flags);
++ last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
++ slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
+ /* Update the last valid endpoint context, if we deleted the last one */
+- if ((in_ctx->slot.dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
+- in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
+- in_ctx->slot.dev_info |= LAST_CTX(last_ctx);
++ if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
++ slot_ctx->dev_info &= ~LAST_CTX_MASK;
++ slot_ctx->dev_info |= LAST_CTX(last_ctx);
+ }
+- new_slot_info = in_ctx->slot.dev_info;
++ new_slot_info = slot_ctx->dev_info;
+
+ xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
+
+@@ -804,9 +809,11 @@ int xhci_add_endpoint(struct usb_hcd *hc
+ struct usb_host_endpoint *ep)
+ {
+ struct xhci_hcd *xhci;
+- struct xhci_device_control *in_ctx;
++ struct xhci_container_ctx *in_ctx, *out_ctx;
+ unsigned int ep_index;
+ struct xhci_ep_ctx *ep_ctx;
++ struct xhci_slot_ctx *slot_ctx;
++ struct xhci_input_control_ctx *ctrl_ctx;
+ u32 added_ctxs;
+ unsigned int last_ctx;
+ u32 new_add_flags, new_drop_flags, new_slot_info;
+@@ -839,12 +846,14 @@ int xhci_add_endpoint(struct usb_hcd *hc
+ }
+
+ in_ctx = xhci->devs[udev->slot_id]->in_ctx;
++ out_ctx = xhci->devs[udev->slot_id]->out_ctx;
++ ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+ ep_index = xhci_get_endpoint_index(&ep->desc);
+- ep_ctx = &xhci->devs[udev->slot_id]->out_ctx->ep[ep_index];
++ ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
+ /* If the HCD has already noted the endpoint is enabled,
+ * ignore this request.
+ */
+- if (in_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
++ if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
+ xhci_warn(xhci, "xHCI %s called with enabled ep %p\n",
+ __func__, ep);
+ return 0;
+@@ -862,8 +871,8 @@ int xhci_add_endpoint(struct usb_hcd *hc
+ return -ENOMEM;
+ }
+
+- in_ctx->add_flags |= added_ctxs;
+- new_add_flags = in_ctx->add_flags;
++ ctrl_ctx->add_flags |= added_ctxs;
++ new_add_flags = ctrl_ctx->add_flags;
+
+ /* If xhci_endpoint_disable() was called for this endpoint, but the
+ * xHC hasn't been notified yet through the check_bandwidth() call,
+@@ -871,14 +880,15 @@ int xhci_add_endpoint(struct usb_hcd *hc
+ * descriptors. We must drop and re-add this endpoint, so we leave the
+ * drop flags alone.
+ */
+- new_drop_flags = in_ctx->drop_flags;
++ new_drop_flags = ctrl_ctx->drop_flags;
+
++ slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
+ /* Update the last valid endpoint context, if we just added one past */
+- if ((in_ctx->slot.dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
+- in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
+- in_ctx->slot.dev_info |= LAST_CTX(last_ctx);
++ if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
++ slot_ctx->dev_info &= ~LAST_CTX_MASK;
++ slot_ctx->dev_info |= LAST_CTX(last_ctx);
+ }
+- new_slot_info = in_ctx->slot.dev_info;
++ new_slot_info = slot_ctx->dev_info;
+
+ /* Store the usb_device pointer for later use */
+ ep->hcpriv = udev;
+@@ -892,9 +902,11 @@ int xhci_add_endpoint(struct usb_hcd *hc
+ return 0;
+ }
+
+-static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev)
++static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev)
+ {
++ struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_ep_ctx *ep_ctx;
++ struct xhci_slot_ctx *slot_ctx;
+ int i;
+
+ /* When a device's add flag and drop flag are zero, any subsequent
+@@ -902,13 +914,15 @@ static void xhci_zero_in_ctx(struct xhci
+ * untouched. Make sure we don't leave any old state in the input
+ * endpoint contexts.
+ */
+- virt_dev->in_ctx->drop_flags = 0;
+- virt_dev->in_ctx->add_flags = 0;
+- virt_dev->in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
++ ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
++ ctrl_ctx->drop_flags = 0;
++ ctrl_ctx->add_flags = 0;
++ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
++ slot_ctx->dev_info &= ~LAST_CTX_MASK;
+ /* Endpoint 0 is always valid */
+- virt_dev->in_ctx->slot.dev_info |= LAST_CTX(1);
++ slot_ctx->dev_info |= LAST_CTX(1);
+ for (i = 1; i < 31; ++i) {
+- ep_ctx = &virt_dev->in_ctx->ep[i];
++ ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i);
+ ep_ctx->ep_info = 0;
+ ep_ctx->ep_info2 = 0;
+ ep_ctx->deq = 0;
+@@ -934,6 +948,8 @@ int xhci_check_bandwidth(struct usb_hcd
+ unsigned long flags;
+ struct xhci_hcd *xhci;
+ struct xhci_virt_device *virt_dev;
++ struct xhci_input_control_ctx *ctrl_ctx;
++ struct xhci_slot_ctx *slot_ctx;
+
+ ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
+ if (ret <= 0)
+@@ -949,16 +965,18 @@ int xhci_check_bandwidth(struct usb_hcd
+ virt_dev = xhci->devs[udev->slot_id];
+
+ /* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
+- virt_dev->in_ctx->add_flags |= SLOT_FLAG;
+- virt_dev->in_ctx->add_flags &= ~EP0_FLAG;
+- virt_dev->in_ctx->drop_flags &= ~SLOT_FLAG;
+- virt_dev->in_ctx->drop_flags &= ~EP0_FLAG;
++ ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
++ ctrl_ctx->add_flags |= SLOT_FLAG;
++ ctrl_ctx->add_flags &= ~EP0_FLAG;
++ ctrl_ctx->drop_flags &= ~SLOT_FLAG;
++ ctrl_ctx->drop_flags &= ~EP0_FLAG;
+ xhci_dbg(xhci, "New Input Control Context:\n");
+- xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma,
+- LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
++ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
++ 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,
++ ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
+ udev->slot_id);
+ if (ret < 0) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+@@ -1013,10 +1031,10 @@ int xhci_check_bandwidth(struct usb_hcd
+ }
+
+ xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
+- xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma,
+- LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
++ xhci_dbg_ctx(xhci, virt_dev->out_ctx,
++ LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
+
+- xhci_zero_in_ctx(virt_dev);
++ xhci_zero_in_ctx(xhci, virt_dev);
+ /* Free any old rings */
+ for (i = 1; i < 31; ++i) {
+ if (virt_dev->new_ep_rings[i]) {
+@@ -1054,7 +1072,7 @@ void xhci_reset_bandwidth(struct usb_hcd
+ virt_dev->new_ep_rings[i] = NULL;
+ }
+ }
+- xhci_zero_in_ctx(virt_dev);
++ xhci_zero_in_ctx(xhci, virt_dev);
+ }
+
+ /* Deal with stalled endpoints. The core should have sent the control message
+@@ -1187,6 +1205,8 @@ int xhci_address_device(struct usb_hcd *
+ struct xhci_virt_device *virt_dev;
+ int ret = 0;
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
++ struct xhci_slot_ctx *slot_ctx;
++ struct xhci_input_control_ctx *ctrl_ctx;
+ u64 temp_64;
+
+ if (!udev->slot_id) {
+@@ -1201,11 +1221,11 @@ int xhci_address_device(struct usb_hcd *
+ xhci_setup_addressable_virt_dev(xhci, udev);
+ /* Otherwise, assume the core has the device configured how it wants */
+ xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
+- xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2);
++ xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
+
+ spin_lock_irqsave(&xhci->lock, flags);
+- ret = xhci_queue_address_device(xhci, virt_dev->in_ctx_dma,
+- udev->slot_id);
++ ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
++ udev->slot_id);
+ if (ret) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
+@@ -1246,7 +1266,7 @@ int xhci_address_device(struct usb_hcd *
+ xhci_err(xhci, "ERROR: unexpected command completion "
+ "code 0x%x.\n", virt_dev->cmd_status);
+ xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
+- xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2);
++ xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
+ ret = -EINVAL;
+ break;
+ }
+@@ -1261,19 +1281,21 @@ int xhci_address_device(struct usb_hcd *
+ (unsigned long long)
+ xhci->dcbaa->dev_context_ptrs[udev->slot_id]);
+ xhci_dbg(xhci, "Output Context DMA address = %#08llx\n",
+- (unsigned long long)virt_dev->out_ctx_dma);
++ (unsigned long long)virt_dev->out_ctx->dma);
+ xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
+- xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2);
++ xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
+ xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
+- xhci_dbg_device_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2);
++ xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
+ /*
+ * USB core uses address 1 for the roothubs, so we add one to the
+ * address given back to us by the HC.
+ */
+- udev->devnum = (virt_dev->out_ctx->slot.dev_state & DEV_ADDR_MASK) + 1;
++ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
++ udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
+ /* Zero the input context control for later use */
+- virt_dev->in_ctx->add_flags = 0;
+- virt_dev->in_ctx->drop_flags = 0;
++ ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
++ ctrl_ctx->add_flags = 0;
++ ctrl_ctx->drop_flags = 0;
+
+ xhci_dbg(xhci, "Device address = %d\n", udev->devnum);
+ /* XXX Meh, not sure if anyone else but choose_address uses this. */
+@@ -1315,7 +1337,6 @@ static int __init xhci_hcd_init(void)
+ /* xhci_device_control has eight fields, and also
+ * embeds one xhci_slot_ctx and 31 xhci_ep_ctx
+ */
+- BUILD_BUG_ON(sizeof(struct xhci_device_control) != (8+8+8*31)*32/8);
+ BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8);
+ BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8);
+ BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8);
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -189,6 +189,63 @@ fail:
+ return 0;
+ }
+
++#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
++
++struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
++ int type, gfp_t flags)
++{
++ struct xhci_container_ctx *ctx = kzalloc(sizeof(*ctx), flags);
++ if (!ctx)
++ return NULL;
++
++ BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT));
++ ctx->type = type;
++ ctx->size = HCC_64BYTE_CONTEXT(xhci->hcc_params) ? 2048 : 1024;
++ if (type == XHCI_CTX_TYPE_INPUT)
++ ctx->size += CTX_SIZE(xhci->hcc_params);
++
++ ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma);
++ memset(ctx->bytes, 0, ctx->size);
++ return ctx;
++}
++
++void xhci_free_container_ctx(struct xhci_hcd *xhci,
++ struct xhci_container_ctx *ctx)
++{
++ dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma);
++ kfree(ctx);
++}
++
++struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci,
++ struct xhci_container_ctx *ctx)
++{
++ BUG_ON(ctx->type != XHCI_CTX_TYPE_INPUT);
++ return (struct xhci_input_control_ctx *)ctx->bytes;
++}
++
++struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci,
++ struct xhci_container_ctx *ctx)
++{
++ if (ctx->type == XHCI_CTX_TYPE_DEVICE)
++ return (struct xhci_slot_ctx *)ctx->bytes;
++
++ return (struct xhci_slot_ctx *)
++ (ctx->bytes + CTX_SIZE(xhci->hcc_params));
++}
++
++struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci,
++ struct xhci_container_ctx *ctx,
++ unsigned int ep_index)
++{
++ /* increment ep index by offset of start of ep ctx array */
++ ep_index++;
++ if (ctx->type == XHCI_CTX_TYPE_INPUT)
++ ep_index++;
++
++ return (struct xhci_ep_ctx *)
++ (ctx->bytes + (ep_index * CTX_SIZE(xhci->hcc_params)));
++}
++
+ /* All the xhci_tds in the ring's TD list should be freed at this point */
+ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
+ {
+@@ -209,11 +266,10 @@ void xhci_free_virt_device(struct xhci_h
+ xhci_ring_free(xhci, dev->ep_rings[i]);
+
+ if (dev->in_ctx)
+- dma_pool_free(xhci->device_pool,
+- dev->in_ctx, dev->in_ctx_dma);
++ xhci_free_container_ctx(xhci, dev->in_ctx);
+ if (dev->out_ctx)
+- dma_pool_free(xhci->device_pool,
+- dev->out_ctx, dev->out_ctx_dma);
++ xhci_free_container_ctx(xhci, dev->out_ctx);
++
+ kfree(xhci->devs[slot_id]);
+ xhci->devs[slot_id] = 0;
+ }
+@@ -221,7 +277,6 @@ void xhci_free_virt_device(struct xhci_h
+ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
+ struct usb_device *udev, gfp_t flags)
+ {
+- dma_addr_t dma;
+ struct xhci_virt_device *dev;
+
+ /* Slot ID 0 is reserved */
+@@ -235,26 +290,21 @@ int xhci_alloc_virt_device(struct xhci_h
+ return 0;
+ dev = xhci->devs[slot_id];
+
+- /* Allocate the (output) device context that will be used in the HC.
+- * The structure is 32 bytes smaller than the input context, but that's
+- * fine.
+- */
+- dev->out_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma);
++ /* Allocate the (output) device context that will be used in the HC. */
++ dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags);
+ if (!dev->out_ctx)
+ goto fail;
+- dev->out_ctx_dma = dma;
++
+ xhci_dbg(xhci, "Slot %d output ctx = 0x%llx (dma)\n", slot_id,
+- (unsigned long long)dma);
+- memset(dev->out_ctx, 0, sizeof(*dev->out_ctx));
++ (unsigned long long)dev->out_ctx->dma);
+
+ /* Allocate the (input) device context for address device command */
+- dev->in_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma);
++ dev->in_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, flags);
+ if (!dev->in_ctx)
+ goto fail;
+- dev->in_ctx_dma = dma;
++
+ xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id,
+- (unsigned long long)dma);
+- memset(dev->in_ctx, 0, sizeof(*dev->in_ctx));
++ (unsigned long long)dev->in_ctx->dma);
+
+ /* Allocate endpoint 0 ring */
+ dev->ep_rings[0] = xhci_ring_alloc(xhci, 1, true, flags);
+@@ -264,7 +314,7 @@ int xhci_alloc_virt_device(struct xhci_h
+ init_completion(&dev->cmd_completion);
+
+ /* Point to output device context in dcbaa. */
+- xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx_dma;
++ xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
+ xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
+ slot_id,
+ &xhci->dcbaa->dev_context_ptrs[slot_id],
+@@ -282,6 +332,8 @@ int xhci_setup_addressable_virt_dev(stru
+ struct xhci_virt_device *dev;
+ struct xhci_ep_ctx *ep0_ctx;
+ struct usb_device *top_dev;
++ struct xhci_slot_ctx *slot_ctx;
++ struct xhci_input_control_ctx *ctrl_ctx;
+
+ dev = xhci->devs[udev->slot_id];
+ /* Slot ID 0 is reserved */
+@@ -290,27 +342,29 @@ int xhci_setup_addressable_virt_dev(stru
+ udev->slot_id);
+ return -EINVAL;
+ }
+- ep0_ctx = &dev->in_ctx->ep[0];
++ ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0);
++ ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx);
++ slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
+
+ /* 2) New slot context and endpoint 0 context are valid*/
+- dev->in_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
++ ctrl_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
+
+ /* 3) Only the control endpoint is valid - one endpoint context */
+- dev->in_ctx->slot.dev_info |= LAST_CTX(1);
++ slot_ctx->dev_info |= LAST_CTX(1);
+
+ switch (udev->speed) {
+ case USB_SPEED_SUPER:
+- dev->in_ctx->slot.dev_info |= (u32) udev->route;
+- dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_SS;
++ slot_ctx->dev_info |= (u32) udev->route;
++ slot_ctx->dev_info |= (u32) SLOT_SPEED_SS;
+ break;
+ case USB_SPEED_HIGH:
+- dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_HS;
++ slot_ctx->dev_info |= (u32) SLOT_SPEED_HS;
+ break;
+ case USB_SPEED_FULL:
+- dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_FS;
++ slot_ctx->dev_info |= (u32) SLOT_SPEED_FS;
+ break;
+ case USB_SPEED_LOW:
+- dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_LS;
++ slot_ctx->dev_info |= (u32) SLOT_SPEED_LS;
+ break;
+ case USB_SPEED_VARIABLE:
+ xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
+@@ -324,7 +378,7 @@ int xhci_setup_addressable_virt_dev(stru
+ for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
+ top_dev = top_dev->parent)
+ /* Found device below root hub */;
+- dev->in_ctx->slot.dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
++ slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
+ xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum);
+
+ /* Is this a LS/FS device under a HS hub? */
+@@ -334,8 +388,8 @@ int xhci_setup_addressable_virt_dev(stru
+ */
+ if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) &&
+ udev->tt) {
+- dev->in_ctx->slot.tt_info = udev->tt->hub->slot_id;
+- dev->in_ctx->slot.tt_info |= udev->ttport << 8;
++ slot_ctx->tt_info = udev->tt->hub->slot_id;
++ slot_ctx->tt_info |= udev->ttport << 8;
+ }
+ xhci_dbg(xhci, "udev->tt = %p\n", udev->tt);
+ xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport);
+@@ -466,7 +520,7 @@ int xhci_endpoint_init(struct xhci_hcd *
+ unsigned int max_burst;
+
+ ep_index = xhci_get_endpoint_index(&ep->desc);
+- ep_ctx = &virt_dev->in_ctx->ep[ep_index];
++ ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
+
+ /* Set up the endpoint ring */
+ virt_dev->new_ep_rings[ep_index] = xhci_ring_alloc(xhci, 1, true, mem_flags);
+@@ -533,7 +587,7 @@ void xhci_endpoint_zero(struct xhci_hcd
+ struct xhci_ep_ctx *ep_ctx;
+
+ ep_index = xhci_get_endpoint_index(&ep->desc);
+- ep_ctx = &virt_dev->in_ctx->ep[ep_index];
++ ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
+
+ ep_ctx->ep_info = 0;
+ ep_ctx->ep_info2 = 0;
+@@ -753,11 +807,10 @@ int xhci_mem_init(struct xhci_hcd *xhci,
+ */
+ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
+ SEGMENT_SIZE, 64, xhci->page_size);
++
+ /* See Table 46 and Note on Figure 55 */
+- /* FIXME support 64-byte contexts */
+ xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
+- sizeof(struct xhci_device_control),
+- 64, xhci->page_size);
++ 2112, 64, xhci->page_size);
+ if (!xhci->segment_pool || !xhci->device_pool)
+ goto fail;
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -362,6 +362,7 @@ static void find_new_dequeue_state(struc
+ struct xhci_virt_device *dev = xhci->devs[slot_id];
+ struct xhci_ring *ep_ring = dev->ep_rings[ep_index];
+ struct xhci_generic_trb *trb;
++ struct xhci_ep_ctx *ep_ctx;
+
+ state->new_cycle_state = 0;
+ state->new_deq_seg = find_trb_seg(cur_td->start_seg,
+@@ -370,7 +371,8 @@ static void find_new_dequeue_state(struc
+ if (!state->new_deq_seg)
+ BUG();
+ /* Dig out the cycle state saved by the xHC during the stop ep cmd */
+- state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq;
++ ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
++ state->new_cycle_state = 0x1 & ep_ctx->deq;
+
+ state->new_deq_ptr = cur_td->last_trb;
+ state->new_deq_seg = find_trb_seg(state->new_deq_seg,
+@@ -570,11 +572,15 @@ static void handle_set_deq_completion(st
+ unsigned int ep_index;
+ struct xhci_ring *ep_ring;
+ struct xhci_virt_device *dev;
++ struct xhci_ep_ctx *ep_ctx;
++ struct xhci_slot_ctx *slot_ctx;
+
+ slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
+ ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
+ dev = xhci->devs[slot_id];
+ ep_ring = dev->ep_rings[ep_index];
++ ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
++ slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
+
+ if (GET_COMP_CODE(event->status) != COMP_SUCCESS) {
+ unsigned int ep_state;
+@@ -588,9 +594,9 @@ static void handle_set_deq_completion(st
+ case COMP_CTX_STATE:
+ xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due "
+ "to incorrect slot or ep state.\n");
+- ep_state = dev->out_ctx->ep[ep_index].ep_info;
++ ep_state = ep_ctx->ep_info;
+ ep_state &= EP_STATE_MASK;
+- slot_state = dev->out_ctx->slot.dev_state;
++ slot_state = slot_ctx->dev_state;
+ slot_state = GET_SLOT_STATE(slot_state);
+ xhci_dbg(xhci, "Slot state = %u, EP state = %u\n",
+ slot_state, ep_state);
+@@ -613,7 +619,7 @@ static void handle_set_deq_completion(st
+ */
+ } else {
+ xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
+- dev->out_ctx->ep[ep_index].deq);
++ ep_ctx->deq);
+ }
+
+ ep_ring->state &= ~SET_DEQ_PENDING;
+@@ -795,6 +801,7 @@ static int handle_tx_event(struct xhci_h
+ union xhci_trb *event_trb;
+ struct urb *urb = 0;
+ int status = -EINPROGRESS;
++ struct xhci_ep_ctx *ep_ctx;
+
+ xhci_dbg(xhci, "In %s\n", __func__);
+ xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)];
+@@ -807,7 +814,8 @@ static int handle_tx_event(struct xhci_h
+ ep_index = TRB_TO_EP_ID(event->flags) - 1;
+ xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index);
+ ep_ring = xdev->ep_rings[ep_index];
+- if (!ep_ring || (xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
++ ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
++ if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
+ xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n");
+ return -ENODEV;
+ }
+@@ -1193,9 +1201,9 @@ static int prepare_transfer(struct xhci_
+ gfp_t mem_flags)
+ {
+ int ret;
+-
++ struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+ ret = prepare_ring(xhci, xdev->ep_rings[ep_index],
+- xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK,
++ ep_ctx->ep_info & EP_STATE_MASK,
+ num_trbs, mem_flags);
+ if (ret)
+ return ret;
diff --git a/usb.current/usb-xhci-use-gfp_atomic-while-holding-spinlocks.patch b/usb.current/usb-xhci-use-gfp_atomic-while-holding-spinlocks.patch
new file mode 100644
index 00000000000000..66db17780f1932
--- /dev/null
+++ b/usb.current/usb-xhci-use-gfp_atomic-while-holding-spinlocks.patch
@@ -0,0 +1,40 @@
+From sarah.a.sharp@linux.intel.com Mon Jul 27 12:23:57 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Mon, 27 Jul 2009 12:03:23 -0700
+Subject: USB: xhci: Use GFP_ATOMIC while holding spinlocks.
+Cc: linux-usb@vger.kernel.org, Greg KH <greg@kroah.com>
+Message-ID: <20090727190323.GA7537@gamba.jf.intel.com>
+Content-Disposition: inline
+
+
+The xHCI functions to queue an URB onto the hardware rings must be called
+with the xhci spinlock held. Those functions will allocate memory, and
+take a gfp_t memory flags argument. We must pass them the GFP_ATOMIC
+flag, since we don't want the memory allocation to attempt to sleep while
+waiting for more memory to become available.
+
+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 | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-hcd.c
++++ b/drivers/usb/host/xhci-hcd.c
+@@ -601,10 +601,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd
+ goto exit;
+ }
+ if (usb_endpoint_xfer_control(&urb->ep->desc))
+- ret = xhci_queue_ctrl_tx(xhci, mem_flags, urb,
++ /* We have a spinlock and interrupts disabled, so we must pass
++ * atomic context to this function, which may allocate memory.
++ */
++ ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
+ slot_id, ep_index);
+ else if (usb_endpoint_xfer_bulk(&urb->ep->desc))
+- ret = xhci_queue_bulk_tx(xhci, mem_flags, urb,
++ ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
+ slot_id, ep_index);
+ else
+ ret = -EINVAL;