aboutsummaryrefslogtreecommitdiffstats
path: root/usb.current
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-11-05 10:59:25 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2009-11-05 10:59:25 -0800
commitf878c4f193b7327244af8f7de8cf8bc61fb78fe1 (patch)
tree0d95465d5a6a8f13259bc149b249f29501e7fb75 /usb.current
parent39874450fa07821078746db7b99cc931ca9478cc (diff)
downloadpatches-f878c4f193b7327244af8f7de8cf8bc61fb78fe1.tar.gz
some bugfixes for .32
Diffstat (limited to 'usb.current')
-rw-r--r--usb.current/usb-cdc_acm-fix-memory-leak-after-hangup.patch90
-rw-r--r--usb.current/usb-cdc_acm-fix-race-condition-when-opening-tty.patch35
-rw-r--r--usb.current/usb-ohci-quirk-amd-prefetch-for-usb-1.1-iso-transfer.patch151
-rw-r--r--usb.current/usb-option.c-add-support-for-d-link-dwm-162-u5.patch45
-rw-r--r--usb.current/usb-usbmon-fix-bug-in-mon_buff_area_shrink.patch68
-rw-r--r--usb.current/usb-xhci-fix-bug-memory-free-after-failed-initialization.patch39
-rw-r--r--usb.current/usb-xhci-fix-scratchpad-deallocation.patch37
-rw-r--r--usb.current/usb-xhci-fix-trb-physical-to-virtual-address-translation.patch65
8 files changed, 530 insertions, 0 deletions
diff --git a/usb.current/usb-cdc_acm-fix-memory-leak-after-hangup.patch b/usb.current/usb-cdc_acm-fix-memory-leak-after-hangup.patch
new file mode 100644
index 00000000000000..432907a3e4b641
--- /dev/null
+++ b/usb.current/usb-cdc_acm-fix-memory-leak-after-hangup.patch
@@ -0,0 +1,90 @@
+From francescolavra@interfree.it Thu Nov 5 10:09:43 2009
+From: Francesco Lavra <francescolavra@interfree.it>
+Date: Tue, 3 Nov 2009 10:53:07 +0000 (UTC)
+Subject: USB: cdc_acm: Fix memory leak after hangup
+Message-ID: <loom.20091103T113446-408@post.gmane.org>
+
+
+Am Donnerstag, 10. September 2009 15:43:53 schrieb Dietmar Hilbrich:
+> Hello,
+>
+> i have the following problem with the cdc-acm - driver:
+>
+> I'm using the driver with an "Ericsson F3507G" on a Thinkpad T400.
+>
+> If a disable the device (with the RFKill-Switch) while it is used by a
+> programm like ppp, the driver doesn't seem to correctly clean up the tty,
+> even after the program has been closed)
+>
+> The tty is still active (e.g. there still exists an entry in
+> /sys/dev/char/166:0 if ttyACM0 was used) and if a reacticate the device,
+> this device entry will be skipped and the Device-Nodes ttyACM1, ttyACM2
+> and ttyACM3 will be used.
+>
+> This problem was introduced with the commit
+> 10077d4a6674f535abdbe25cdecb1202af7948f1 (before 2.6.31-rc1) and still
+> exists in 2.6.31.
+>
+> I was able the fix this problem with the following patch:
+>
+> diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
+> index 2bfc41e..0970d2f 100644
+> --- a/drivers/usb/class/cdc-acm.c
+> +++ b/drivers/usb/class/cdc-acm.c
+> @@ -676,6 +676,7 @@ static void acm_tty_hangup(struct tty_struct *tty)
+> struct acm *acm = tty->driver_data;
+> tty_port_hangup(&acm->port);
+> acm_port_down(acm, 0);
+> + acm_tty_unregister(acm);
+> }
+
+I have the same problem with cdc-acm (I'm using a Samsung SGH-U900): when I
+unplug it from the USB port during a PPP connection, the ppp daemon gets the
+hangup correctly (and closes the device), but the struct acm corresponding to
+the device disconnected is not freed. Hence reconnecting the device results in
+creation of /dev/ttyACM(x+1). The same happens when the system is hibernated
+during a PPP connection.
+
+This memory leak is due to the fact that when the tty is hung up,
+tty_port_close_start() returns always zero, and acm_tty_close() never reaches
+the point where acm_tty_unregister() is called.
+
+Here is a fix for this.
+
+Signed-off-by: Francesco Lavra <francescolavra@interfree.it>
+Acked-by: Oliver Neukum <oliver@neukum.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-acm.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -686,15 +686,21 @@ static void acm_tty_close(struct tty_str
+
+ /* Perform the closing process and see if we need to do the hardware
+ shutdown */
+- if (!acm || tty_port_close_start(&acm->port, tty, filp) == 0)
++ if (!acm)
++ return;
++ if (tty_port_close_start(&acm->port, tty, filp) == 0) {
++ mutex_lock(&open_mutex);
++ if (!acm->dev) {
++ tty_port_tty_set(&acm->port, NULL);
++ acm_tty_unregister(acm);
++ tty->driver_data = NULL;
++ }
++ mutex_unlock(&open_mutex);
+ return;
++ }
+ acm_port_down(acm, 0);
+ tty_port_close_end(&acm->port, tty);
+- mutex_lock(&open_mutex);
+ tty_port_tty_set(&acm->port, NULL);
+- if (!acm->dev)
+- acm_tty_unregister(acm);
+- mutex_unlock(&open_mutex);
+ }
+
+ static int acm_tty_write(struct tty_struct *tty,
diff --git a/usb.current/usb-cdc_acm-fix-race-condition-when-opening-tty.patch b/usb.current/usb-cdc_acm-fix-race-condition-when-opening-tty.patch
new file mode 100644
index 00000000000000..8e8d2d2b760959
--- /dev/null
+++ b/usb.current/usb-cdc_acm-fix-race-condition-when-opening-tty.patch
@@ -0,0 +1,35 @@
+From hsggebhardt@googlemail.com Thu Nov 5 10:08:03 2009
+From: Henry Gebhardt <hsggebhardt@googlemail.com>
+Date: Wed, 4 Nov 2009 11:19:28 +0100
+Subject: USB: cdc_acm: Fix race condition when opening tty
+To: Oliver Neukum <oliver@neukum.org>
+Cc: greg@kroah.com
+Message-ID: <1bd893420911040219vbfe58a1redb8c8ed934760bd@mail.gmail.com>
+
+From: Henry Gebhardt <gebhardt@astro.uni-tuebingen.de>
+
+If acm_rx_tasklet() gets called before tty_port_block_til_ready()
+returns, then bulk IN urbs may not be sent. This fixes it.
+
+Signed-off-by: Henry Gebhardt <gebhardt@astro.uni-tuebingen.de>
+Acked-by: Oliver Neukum <oliver@neukum.org>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/class/cdc-acm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -609,9 +609,9 @@ static int acm_tty_open(struct tty_struc
+
+ acm->throttle = 0;
+
+- tasklet_schedule(&acm->urb_task);
+ set_bit(ASYNCB_INITIALIZED, &acm->port.flags);
+ rv = tty_port_block_til_ready(&acm->port, tty, filp);
++ tasklet_schedule(&acm->urb_task);
+ done:
+ mutex_unlock(&acm->mutex);
+ err_out:
diff --git a/usb.current/usb-ohci-quirk-amd-prefetch-for-usb-1.1-iso-transfer.patch b/usb.current/usb-ohci-quirk-amd-prefetch-for-usb-1.1-iso-transfer.patch
new file mode 100644
index 00000000000000..f613d1c43f765c
--- /dev/null
+++ b/usb.current/usb-ohci-quirk-amd-prefetch-for-usb-1.1-iso-transfer.patch
@@ -0,0 +1,151 @@
+From libin.yang@amd.com Thu Nov 5 10:03:20 2009
+From: Libin Yang <libin.yang@amd.com>
+Date: Wed, 4 Nov 2009 14:55:18 +0800
+Subject: USB: ohci: quirk AMD prefetch for USB 1.1 ISO transfer
+To: gregkh@suse.de, david-b@pacbell.net, stern@rowland.harvard.edu
+Cc: linux-usb@vger.kernel.org, oliver@neukum.org, "Yang, Libin" <Libin.Yang@amd.com>, "Xu, Andiry" <Andiry.Xu@amd.com>
+Message-ID: <1257317719.4833.27.camel@younglee-desktop>
+
+From: Libin Yang <libin.yang@amd.com>
+
+
+The following patch in the driver is required to avoid USB 1.1 device
+failures that may occur due to requests from USB OHCI controllers may
+be overwritten if the latency for any pending request by the USB
+controller is very long (in the range of milliseconds).
+
+Signed-off-by: Libin Yang <libin.yang@amd.com>
+Cc: David Brownell <dbrownell@users.sourceforge.net>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/host/ohci-hcd.c | 5 +++++
+ drivers/usb/host/ohci-pci.c | 20 ++++++++++++++++++++
+ drivers/usb/host/ohci-q.c | 18 ++++++++++++------
+ drivers/usb/host/ohci.h | 9 +++++++++
+ 4 files changed, 46 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -402,6 +402,7 @@ struct ohci_hcd {
+ #define OHCI_QUIRK_FRAME_NO 0x80 /* no big endian frame_no shift */
+ #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */
+ #define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/
++#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
+ // there are also chip quirks/bugs in init logic
+
+ struct work_struct nec_work; /* Worker for NEC quirk */
+@@ -433,6 +434,10 @@ static inline int quirk_amdiso(struct oh
+ {
+ return ohci->flags & OHCI_QUIRK_AMD_ISO;
+ }
++static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
++{
++ return ohci->flags & OHCI_QUIRK_AMD_PREFETCH;
++}
+ #else
+ static inline int quirk_nec(struct ohci_hcd *ohci)
+ {
+@@ -446,6 +451,10 @@ static inline int quirk_amdiso(struct oh
+ {
+ return 0;
+ }
++static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
++{
++ return 0;
++}
+ #endif
+
+ /* convert between an hcd pointer and the corresponding ohci_hcd */
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -87,6 +87,7 @@ static int ohci_restart (struct ohci_hcd
+ #ifdef CONFIG_PCI
+ static void quirk_amd_pll(int state);
+ static void amd_iso_dev_put(void);
++static void sb800_prefetch(struct ohci_hcd *ohci, int on);
+ #else
+ static inline void quirk_amd_pll(int state)
+ {
+@@ -96,6 +97,10 @@ static inline void amd_iso_dev_put(void)
+ {
+ return;
+ }
++static inline void sb800_prefetch(struct ohci_hcd *ohci, int on)
++{
++ return;
++}
+ #endif
+
+
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -177,6 +177,13 @@ static int ohci_quirk_amd700(struct usb_
+ return 0;
+
+ pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
++
++ /* SB800 needs pre-fetch fix */
++ if ((rev >= 0x40) && (rev <= 0x4f)) {
++ ohci->flags |= OHCI_QUIRK_AMD_PREFETCH;
++ ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
++ }
++
+ if ((rev > 0x3b) || (rev < 0x30)) {
+ pci_dev_put(amd_smbus_dev);
+ amd_smbus_dev = NULL;
+@@ -262,6 +269,19 @@ static void amd_iso_dev_put(void)
+
+ }
+
++static void sb800_prefetch(struct ohci_hcd *ohci, int on)
++{
++ struct pci_dev *pdev;
++ u16 misc;
++
++ pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller);
++ pci_read_config_word(pdev, 0x50, &misc);
++ if (on == 0)
++ pci_write_config_word(pdev, 0x50, misc & 0xfcff);
++ else
++ pci_write_config_word(pdev, 0x50, misc | 0x0300);
++}
++
+ /* List of quirks for OHCI */
+ static const struct pci_device_id ohci_pci_quirks[] = {
+ {
+--- a/drivers/usb/host/ohci-q.c
++++ b/drivers/usb/host/ohci-q.c
+@@ -49,9 +49,12 @@ __acquires(ohci->lock)
+ switch (usb_pipetype (urb->pipe)) {
+ case PIPE_ISOCHRONOUS:
+ ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
+- if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
+- && quirk_amdiso(ohci))
+- quirk_amd_pll(1);
++ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
++ if (quirk_amdiso(ohci))
++ quirk_amd_pll(1);
++ if (quirk_amdprefetch(ohci))
++ sb800_prefetch(ohci, 0);
++ }
+ break;
+ case PIPE_INTERRUPT:
+ ohci_to_hcd(ohci)->self.bandwidth_int_reqs--;
+@@ -680,9 +683,12 @@ static void td_submit_urb (
+ data + urb->iso_frame_desc [cnt].offset,
+ urb->iso_frame_desc [cnt].length, urb, cnt);
+ }
+- if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
+- && quirk_amdiso(ohci))
+- quirk_amd_pll(0);
++ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
++ if (quirk_amdiso(ohci))
++ quirk_amd_pll(0);
++ if (quirk_amdprefetch(ohci))
++ sb800_prefetch(ohci, 1);
++ }
+ periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0
+ && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0;
+ break;
diff --git a/usb.current/usb-option.c-add-support-for-d-link-dwm-162-u5.patch b/usb.current/usb-option.c-add-support-for-d-link-dwm-162-u5.patch
new file mode 100644
index 00000000000000..6244c8671facec
--- /dev/null
+++ b/usb.current/usb-option.c-add-support-for-d-link-dwm-162-u5.patch
@@ -0,0 +1,45 @@
+From r0bertz@gentoo.org Thu Nov 5 10:19:05 2009
+From: Zhang Le <r0bertz@gentoo.org>
+Date: Wed, 4 Nov 2009 23:22:59 +0800
+Subject: USB: option.c: add support for D-Link DWM-162-U5
+To: gregkh@suse.de
+Cc: smurf@smurf.noris.de, Zhang Le <r0bertz@gentoo.org>
+Message-ID: <1257348179-20430-1-git-send-email-r0bertz@gentoo.org>
+
+
+Add D-Link DWM-162-U5 device id 1e0e:ce16 into option driver. The device
+has 4 interfaces, of which 1 is handled by storage and the other 3 by
+option driver.
+
+The device appears first as CD-only 05c6:2100 device and must be
+switched to 1e0e:ce16 mode either by using "eject CD" or usb_modeswitch.
+
+The MessageContent for usb_modeswitch.conf is:
+"55534243e0c26a85000000000000061b000000020000000000000000000000"
+
+Signed-off-by: Zhang Le <r0bertz@gentoo.org>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/serial/option.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -308,6 +308,7 @@ static int option_resume(struct usb_ser
+
+ #define DLINK_VENDOR_ID 0x1186
+ #define DLINK_PRODUCT_DWM_652 0x3e04
++#define DLINK_PRODUCT_DWM_652_U5 0xce16
+
+ #define QISDA_VENDOR_ID 0x1da5
+ #define QISDA_PRODUCT_H21_4512 0x4512
+@@ -586,6 +587,7 @@ static struct usb_device_id option_ids[]
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
+ { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
++ { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
+ { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
diff --git a/usb.current/usb-usbmon-fix-bug-in-mon_buff_area_shrink.patch b/usb.current/usb-usbmon-fix-bug-in-mon_buff_area_shrink.patch
new file mode 100644
index 00000000000000..89c262ec024a8a
--- /dev/null
+++ b/usb.current/usb-usbmon-fix-bug-in-mon_buff_area_shrink.patch
@@ -0,0 +1,68 @@
+From stern@rowland.harvard.edu Thu Nov 5 10:18:37 2009
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 4 Nov 2009 11:35:53 -0500 (EST)
+Subject: USB: usbmon: fix bug in mon_buff_area_shrink
+To: Greg KH <greg@kroah.com>, Pete Zaitcev <zaitcev@redhat.com>
+Message-ID: <Pine.LNX.4.44L0.0911041133570.2968-100000@iolanthe.rowland.org>
+
+This patch (as1299b) fixes a bug in an error-handling path of usbmon's
+binary interface. The storage area for URB data is divided into
+fixed-size blocks. If an URB's data can't be copied, the area
+reserved for it should be decreased to the size of the truncated
+information (rounded up to a block boundary). Rounding up the amount
+to be removed and subtracting it from the reserved size is definitely
+the wrong thing to do.
+
+Also, when the data for an isochronous URB can't be copied, we can
+still copy the isoc packet descriptors. In fact the current code does
+copy the descriptors, but then sets the capture length to 0 so they
+remain inaccessible. The capture length should be reduced to the
+length of the descriptors, not set to 0.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Acked-by: Pete Zaitcev <zaitcev@redhat.com>
+CC: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/mon/mon_bin.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/mon/mon_bin.c
++++ b/drivers/usb/mon/mon_bin.c
+@@ -348,12 +348,12 @@ static unsigned int mon_buff_area_alloc_
+
+ /*
+ * Return a few (kilo-)bytes to the head of the buffer.
+- * This is used if a DMA fetch fails.
++ * This is used if a data fetch fails.
+ */
+ static void mon_buff_area_shrink(struct mon_reader_bin *rp, unsigned int size)
+ {
+
+- size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
++ /* size &= ~(PKT_ALIGN-1); -- we're called with aligned size */
+ rp->b_cnt -= size;
+ if (rp->b_in < size)
+ rp->b_in += rp->b_size;
+@@ -433,6 +433,7 @@ static void mon_bin_event(struct mon_rea
+ unsigned int urb_length;
+ unsigned int offset;
+ unsigned int length;
++ unsigned int delta;
+ unsigned int ndesc, lendesc;
+ unsigned char dir;
+ struct mon_bin_hdr *ep;
+@@ -537,8 +538,10 @@ static void mon_bin_event(struct mon_rea
+ if (length != 0) {
+ ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
+ if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */
+- ep->len_cap = 0;
+- mon_buff_area_shrink(rp, length);
++ delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
++ ep->len_cap -= length;
++ delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
++ mon_buff_area_shrink(rp, delta);
+ }
+ } else {
+ ep->flag_data = data_tag;
diff --git a/usb.current/usb-xhci-fix-bug-memory-free-after-failed-initialization.patch b/usb.current/usb-xhci-fix-bug-memory-free-after-failed-initialization.patch
new file mode 100644
index 00000000000000..beede6576509d1
--- /dev/null
+++ b/usb.current/usb-xhci-fix-bug-memory-free-after-failed-initialization.patch
@@ -0,0 +1,39 @@
+From sarah.a.sharp@linux.intel.com Thu Nov 5 10:15:20 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 3 Nov 2009 22:02:22 -0800
+Subject: USB: xhci: Fix bug memory free after failed initialization.
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org
+Message-ID: <20091104060222.GA25309@xanatos>
+Content-Disposition: inline
+
+
+If the xHCI driver fails during the memory initialization, xhci->ir_set
+may not be a valid pointer. Check that it points to valid DMA'able memory
+before writing to that address during the memory freeing process.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -802,9 +802,11 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+ int i;
+
+ /* Free the Event Ring Segment Table and the actual Event Ring */
+- xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
+- xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
+- xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
++ if (xhci->ir_set) {
++ xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
++ 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,
diff --git a/usb.current/usb-xhci-fix-scratchpad-deallocation.patch b/usb.current/usb-xhci-fix-scratchpad-deallocation.patch
new file mode 100644
index 00000000000000..5058d23cda14e7
--- /dev/null
+++ b/usb.current/usb-xhci-fix-scratchpad-deallocation.patch
@@ -0,0 +1,37 @@
+From sarah.a.sharp@linux.intel.com Thu Nov 5 10:18:01 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Wed, 4 Nov 2009 11:22:19 -0800
+Subject: USB: xhci: Fix scratchpad deallocation.
+To: Greg KH <gregkh@suse.de>
+Cc: John Youn <John.Youn@synopsys.com>, linux-usb@vger.kernel.org
+Message-ID: <20091104192219.GA5081@xanatos>
+Content-Disposition: inline
+
+
+The scratchpad_free() function uses xhci->page_size to free some memory
+with pci_free_consistent(). However, the page_size is set to zero before
+the call, causing kernel oopses on driver unload. Call scratchpad_free()
+before setting xhci->page_size to zero.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Acked-by: John Youn <John.Youn@synopsys.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-mem.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -843,9 +843,9 @@ void xhci_mem_cleanup(struct xhci_hcd *x
+ xhci->dcbaa, xhci->dcbaa->dma);
+ xhci->dcbaa = NULL;
+
++ scratchpad_free(xhci);
+ xhci->page_size = 0;
+ xhci->page_shift = 0;
+- scratchpad_free(xhci);
+ }
+
+ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
diff --git a/usb.current/usb-xhci-fix-trb-physical-to-virtual-address-translation.patch b/usb.current/usb-xhci-fix-trb-physical-to-virtual-address-translation.patch
new file mode 100644
index 00000000000000..8a4e4673f604ba
--- /dev/null
+++ b/usb.current/usb-xhci-fix-trb-physical-to-virtual-address-translation.patch
@@ -0,0 +1,65 @@
+From sarah.a.sharp@linux.intel.com Thu Nov 5 10:15:34 2009
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 3 Nov 2009 22:02:24 -0800
+Subject: USB: xhci: Fix TRB physical to virtual address translation.
+To: Greg KH <gregkh@suse.de>
+Cc: linux-usb@vger.kernel.org
+Message-ID: <20091104060224.GA24973@xanatos>
+Content-Disposition: inline
+
+
+The trb_in_td() function in the xHCI driver is supposed to translate a
+physical transfer buffer request (TRB) into a virtual pointer to the ring
+segment that TRB is in.
+
+Unfortunately, a mistake in this function may cause endless loops as the
+driver searches through the linked list of ring segments over and over
+again. Fix a couple bugs that may lead to loops or bad output:
+
+1. Bail out if we get a NULL pointer when translating the segment's
+private structure and the starting DMA address of the segment chunk. If
+this happens, we've been handed a starting TRB pointer from a different
+ring.
+
+2. Make sure the function works when there's multiple segments in the
+ring. In the while loop to search through the ring segments, use the
+current segment variable (cur_seg), rather than the starting segment
+variable (start_seg) that is passed in.
+
+3. Stop searching the ring if we've run through all the segments in the
+ring.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -864,9 +864,11 @@ static struct xhci_segment *trb_in_td(
+ cur_seg = start_seg;
+
+ do {
++ if (start_dma == 0)
++ return 0;
+ /* We may get an event for a Link TRB in the middle of a TD */
+ end_seg_dma = xhci_trb_virt_to_dma(cur_seg,
+- &start_seg->trbs[TRBS_PER_SEGMENT - 1]);
++ &cur_seg->trbs[TRBS_PER_SEGMENT - 1]);
+ /* If the end TRB isn't in this segment, this is set to 0 */
+ end_trb_dma = xhci_trb_virt_to_dma(cur_seg, end_trb);
+
+@@ -893,8 +895,9 @@ static struct xhci_segment *trb_in_td(
+ }
+ cur_seg = cur_seg->next;
+ start_dma = xhci_trb_virt_to_dma(cur_seg, &cur_seg->trbs[0]);
+- } while (1);
++ } while (cur_seg != start_seg);
+
++ return 0;
+ }
+
+ /*