--- /dev/null
+From dc332fdf9f373a87b1e2f423b5b004b2a3c37e1a Mon Sep 17 00:00:00 2001
+From: Jonathan Nieder <jrnieder@gmail.com>
+Date: Sun, 8 Jul 2012 21:55:14 +0200
+Subject: ACPI / PM: Leave Bus Master Arbitration enabled for suspend/resume
+
+From: Jonathan Nieder <jrnieder@gmail.com>
+
+commit dc332fdf9f373a87b1e2f423b5b004b2a3c37e1a upstream.
+
+This is an old suspend/resume lockup fix:
+
+ commit 2780cc4660e1
+ Author: Len Brown <len.brown@intel.com>
+ Date: Thu Dec 23 13:43:30 2004 -0500
+
+ [ACPI] Fix suspend/resume lockup issue
+ by leaving Bus Master Arbitration enabled.
+ The ACPI spec mandates it be disabled only for C3.
+
+ http://bugzilla.kernel.org/show_bug.cgi?id=3599
+
+ Signed-off-by: David Shaohua Li <shaohua.li@intel.com>
+ Signed-off-by: Len Brown <len.brown@intel.com>
+
+The bug snuck back in in commit 2feec47d4c5f (ACPICA: ACPI 5: Support
+for new FADT SleepStatus, SleepControl registers, 2012-02-14),
+presumably by copy/pasting a copy of the code without that fix for the
+legacy case.
+
+On affected machines, after that commit, the machine locks up hard on
+resume from suspend. The same fix as seven years ago still works.
+
+Addresses <https://bugzilla.kernel.org/show_bug.cgi?id=43641>.
+
+Reported-bisected-and-tested-by: Octavio Alvarez <alvarezp@alvarezp.com>
+Reported-by: Adrian Knoth <adi@drcomp.erfurt.thur.de>
+Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/acpica/hwsleep.c | 22 ----------------------
+ 1 file changed, 22 deletions(-)
+
+--- a/drivers/acpi/acpica/hwsleep.c
++++ b/drivers/acpi/acpica/hwsleep.c
+@@ -95,18 +95,6 @@ acpi_status acpi_hw_legacy_sleep(u8 slee
+ return_ACPI_STATUS(status);
+ }
+
+- if (sleep_state != ACPI_STATE_S5) {
+- /*
+- * Disable BM arbitration. This feature is contained within an
+- * optional register (PM2 Control), so ignore a BAD_ADDRESS
+- * exception.
+- */
+- status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
+- if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
+- return_ACPI_STATUS(status);
+- }
+- }
+-
+ /*
+ * 1) Disable/Clear all GPEs
+ * 2) Enable all wakeup GPEs
+@@ -364,16 +352,6 @@ acpi_status acpi_hw_legacy_wake(u8 sleep
+ [ACPI_EVENT_POWER_BUTTON].
+ status_register_id, ACPI_CLEAR_STATUS);
+
+- /*
+- * Enable BM arbitration. This feature is contained within an
+- * optional register (PM2 Control), so ignore a BAD_ADDRESS
+- * exception.
+- */
+- status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
+- if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) {
+- return_ACPI_STATUS(status);
+- }
+-
+ acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
+ return_ACPI_STATUS(status);
+ }
--- /dev/null
+From dbf0e4c7257f8d684ec1a3c919853464293de66e Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Mon, 9 Jul 2012 11:09:21 -0400
+Subject: PCI: EHCI: fix crash during suspend on ASUS computers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit dbf0e4c7257f8d684ec1a3c919853464293de66e upstream.
+
+Quite a few ASUS computers experience a nasty problem, related to the
+EHCI controllers, when going into system suspend. It was observed
+that the problem didn't occur if the controllers were not put into the
+D3 power state before starting the suspend, and commit
+151b61284776be2d6f02d48c23c3625678960b97 (USB: EHCI: fix crash during
+suspend on ASUS computers) was created to do this.
+
+It turned out this approach messed up other computers that didn't have
+the problem -- it prevented USB wakeup from working. Consequently
+commit c2fb8a3fa25513de8fedb38509b1f15a5bbee47b (USB: add
+NO_D3_DURING_SLEEP flag and revert 151b61284776be2) was merged; it
+reverted the earlier commit and added a whitelist of known good board
+names.
+
+Now we know the actual cause of the problem. Thanks to AceLan Kao for
+tracking it down.
+
+According to him, an engineer at ASUS explained that some of their
+BIOSes contain a bug that was added in an attempt to work around a
+problem in early versions of Windows. When the computer goes into S3
+suspend, the BIOS tries to verify that the EHCI controllers were first
+quiesced by the OS. Nothing's wrong with this, but the BIOS does it
+by checking that the PCI COMMAND registers contain 0 without checking
+the controllers' power state. If the register isn't 0, the BIOS
+assumes the controller needs to be quiesced and tries to do so. This
+involves making various MMIO accesses to the controller, which don't
+work very well if the controller is already in D3. The end result is
+a system hang or memory corruption.
+
+Since the value in the PCI COMMAND register doesn't matter once the
+controller has been suspended, and since the value will be restored
+anyway when the controller is resumed, we can work around the BIOS bug
+simply by setting the register to 0 during system suspend. This patch
+(as1590) does so and also reverts the second commit mentioned above,
+which is now unnecessary.
+
+In theory we could do this for every PCI device. However to avoid
+introducing new problems, the patch restricts itself to EHCI host
+controllers.
+
+Finally the affected systems can suspend with USB wakeup working
+properly.
+
+Reference: https://bugzilla.kernel.org/show_bug.cgi?id=37632
+Reference: https://bugzilla.kernel.org/show_bug.cgi?id=42728
+Based-on-patch-by: AceLan Kao <acelan.kao@canonical.com>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Tested-by: Dâniel Fraga <fragabr@gmail.com>
+Tested-by: Javier Marcet <jmarcet@gmail.com>
+Tested-by: Andrey Rahmatullin <wrar@wrar.name>
+Tested-by: Oleksij Rempel <bug-track@fisher-privat.net>
+Tested-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Rafael J. Wysocki <rjw@sisk.pl>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/pci-driver.c | 12 ++++++++++++
+ drivers/pci/pci.c | 5 -----
+ drivers/pci/quirks.c | 26 --------------------------
+ include/linux/pci.h | 2 --
+ 4 files changed, 12 insertions(+), 33 deletions(-)
+
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -742,6 +742,18 @@ static int pci_pm_suspend_noirq(struct d
+
+ pci_pm_set_unknown_state(pci_dev);
+
++ /*
++ * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's
++ * PCI COMMAND register isn't 0, the BIOS assumes that the controller
++ * hasn't been quiesced and tries to turn it off. If the controller
++ * is already in D3, this can hang or cause memory corruption.
++ *
++ * Since the value of the COMMAND register doesn't matter once the
++ * device has been suspended, we can safely set it to 0 here.
++ */
++ if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI)
++ pci_write_config_word(pci_dev, PCI_COMMAND, 0);
++
+ return 0;
+ }
+
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -1743,11 +1743,6 @@ int pci_prepare_to_sleep(struct pci_dev
+ if (target_state == PCI_POWER_ERROR)
+ return -EIO;
+
+- /* Some devices mustn't be in D3 during system sleep */
+- if (target_state == PCI_D3hot &&
+- (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP))
+- return 0;
+-
+ pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
+
+ error = pci_set_power_state(dev, target_state);
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -2917,32 +2917,6 @@ static void __devinit disable_igfx_irq(s
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
+
+-/*
+- * The Intel 6 Series/C200 Series chipset's EHCI controllers on many
+- * ASUS motherboards will cause memory corruption or a system crash
+- * if they are in D3 while the system is put into S3 sleep.
+- */
+-static void __devinit asus_ehci_no_d3(struct pci_dev *dev)
+-{
+- const char *sys_info;
+- static const char good_Asus_board[] = "P8Z68-V";
+-
+- if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)
+- return;
+- if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)
+- return;
+- sys_info = dmi_get_system_info(DMI_BOARD_NAME);
+- if (sys_info && memcmp(sys_info, good_Asus_board,
+- sizeof(good_Asus_board) - 1) == 0)
+- return;
+-
+- dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n");
+- dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP;
+- device_set_wakeup_capable(&dev->dev, false);
+-}
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3);
+-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3);
+-
+ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
+ struct pci_fixup *end)
+ {
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -176,8 +176,6 @@ enum pci_dev_flags {
+ PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2,
+ /* Provide indication device is assigned by a Virtual Machine Manager */
+ PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4,
+- /* Device causes system crash if in D3 during S3 sleep */
+- PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8,
+ };
+
+ enum pci_irq_reroute_variant {
--- /dev/null
+From 222a806af830fda34ad1f6bc991cd226916de060 Mon Sep 17 00:00:00 2001
+From: Mark Rustad <mark.d.rustad@intel.com>
+Date: Thu, 21 Jun 2012 12:23:42 -0700
+Subject: SCSI: Fix NULL dereferences in scsi_cmd_to_driver
+
+From: Mark Rustad <mark.d.rustad@intel.com>
+
+commit 222a806af830fda34ad1f6bc991cd226916de060 upstream.
+
+Avoid crashing if the private_data pointer happens to be NULL. This has
+been seen sometimes when a host reset happens, notably when there are
+many LUNs:
+
+host3: Assigned Port ID 0c1601
+scsi host3: libfc: Host reset succeeded on port (0c1601)
+BUG: unable to handle kernel NULL pointer dereference at 0000000000000350
+IP: [<ffffffff81352bb8>] scsi_send_eh_cmnd+0x58/0x3a0
+<snip>
+Process scsi_eh_3 (pid: 4144, threadinfo ffff88030920c000, task ffff880326b160c0)
+Stack:
+ 000000010372e6ba 0000000000000282 000027100920dca0 ffffffffa0038ee0
+ 0000000000000000 0000000000030003 ffff88030920dc80 ffff88030920dc80
+ 00000002000e0000 0000000a00004000 ffff8803242f7760 ffff88031326ed80
+Call Trace:
+ [<ffffffff8105b590>] ? lock_timer_base+0x70/0x70
+ [<ffffffff81352fbe>] scsi_eh_tur+0x3e/0xc0
+ [<ffffffff81353a36>] scsi_eh_test_devices+0x76/0x170
+ [<ffffffff81354125>] scsi_eh_host_reset+0x85/0x160
+ [<ffffffff81354291>] scsi_eh_ready_devs+0x91/0x110
+ [<ffffffff813543fd>] scsi_unjam_host+0xed/0x1f0
+ [<ffffffff813546a8>] scsi_error_handler+0x1a8/0x200
+ [<ffffffff81354500>] ? scsi_unjam_host+0x1f0/0x1f0
+ [<ffffffff8106ec3e>] kthread+0x9e/0xb0
+ [<ffffffff81509264>] kernel_thread_helper+0x4/0x10
+ [<ffffffff8106eba0>] ? kthread_freezable_should_stop+0x70/0x70
+ [<ffffffff81509260>] ? gs_change+0x13/0x13
+Code: 25 28 00 00 00 48 89 45 c8 31 c0 48 8b 87 80 00 00 00 48 8d b5 60 ff ff ff 89 d1 48 89 fb 41 89 d6 4c 89 fa 48 8b 80 b8 00 00 00
+ <48> 8b 80 50 03 00 00 48 8b 00 48 89 85 38 ff ff ff 48 8b 07 4c
+RIP [<ffffffff81352bb8>] scsi_send_eh_cmnd+0x58/0x3a0
+ RSP <ffff88030920dc50>
+CR2: 0000000000000350
+
+
+Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
+Tested-by: Marcus Dennis <marcusx.e.dennis@intel.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/scsi/scsi_cmnd.h | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/include/scsi/scsi_cmnd.h
++++ b/include/scsi/scsi_cmnd.h
+@@ -134,10 +134,16 @@ struct scsi_cmnd {
+
+ static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
+ {
++ struct scsi_driver **sdp;
++
+ if (!cmd->request->rq_disk)
+ return NULL;
+
+- return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
++ sdp = (struct scsi_driver **)cmd->request->rq_disk->private_data;
++ if (!sdp)
++ return NULL;
++
++ return *sdp;
+ }
+
+ extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
--- /dev/null
+From 6ef1b512f4e6f936d89aa20be3d97a7ec7c290ac Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 22 Jun 2012 10:52:34 -0700
+Subject: SCSI: libsas: fix taskfile corruption in sas_ata_qc_fill_rtf
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit 6ef1b512f4e6f936d89aa20be3d97a7ec7c290ac upstream.
+
+fill_result_tf() grabs the taskfile flags from the originating qc which
+sas_ata_qc_fill_rtf() promptly overwrites. The presence of an
+ata_taskfile in the sata_device makes it tempting to just copy the full
+contents in sas_ata_qc_fill_rtf(). However, libata really only wants
+the fis contents and expects the other portions of the taskfile to not
+be touched by ->qc_fill_rtf. To that end store a fis buffer in the
+sata_device and use ata_tf_from_fis() like every other ->qc_fill_rtf()
+implementation.
+
+Reported-by: Praveen Murali <pmurali@logicube.com>
+Tested-by: Praveen Murali <pmurali@logicube.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: James Bottomley <JBottomley@Parallels.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/aic94xx/aic94xx_task.c | 2 +-
+ drivers/scsi/libsas/sas_ata.c | 12 ++++++------
+ include/scsi/libsas.h | 6 ++++--
+ 3 files changed, 11 insertions(+), 9 deletions(-)
+
+--- a/drivers/scsi/aic94xx/aic94xx_task.c
++++ b/drivers/scsi/aic94xx/aic94xx_task.c
+@@ -201,7 +201,7 @@ static void asd_get_response_tasklet(str
+
+ if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) {
+ resp->frame_len = le16_to_cpu(*(__le16 *)(r+6));
+- memcpy(&resp->ending_fis[0], r+16, 24);
++ memcpy(&resp->ending_fis[0], r+16, ATA_RESP_FIS_SIZE);
+ ts->buf_valid_size = sizeof(*resp);
+ }
+ }
+--- a/drivers/scsi/libsas/sas_ata.c
++++ b/drivers/scsi/libsas/sas_ata.c
+@@ -139,12 +139,12 @@ static void sas_ata_task_done(struct sas
+ if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
+ ((stat->stat == SAM_STAT_CHECK_CONDITION &&
+ dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
+- ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
++ memcpy(dev->sata_dev.fis, resp->ending_fis, ATA_RESP_FIS_SIZE);
+
+ if (!link->sactive) {
+- qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
++ qc->err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
+ } else {
+- link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command);
++ link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.fis[2]);
+ if (unlikely(link->eh_info.err_mask))
+ qc->flags |= ATA_QCFLAG_FAILED;
+ }
+@@ -161,8 +161,8 @@ static void sas_ata_task_done(struct sas
+ qc->flags |= ATA_QCFLAG_FAILED;
+ }
+
+- dev->sata_dev.tf.feature = 0x04; /* status err */
+- dev->sata_dev.tf.command = ATA_ERR;
++ dev->sata_dev.fis[3] = 0x04; /* status err */
++ dev->sata_dev.fis[2] = ATA_ERR;
+ }
+ }
+
+@@ -269,7 +269,7 @@ static bool sas_ata_qc_fill_rtf(struct a
+ {
+ struct domain_device *dev = qc->ap->private_data;
+
+- memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf));
++ ata_tf_from_fis(dev->sata_dev.fis, &qc->result_tf);
+ return true;
+ }
+
+--- a/include/scsi/libsas.h
++++ b/include/scsi/libsas.h
+@@ -163,6 +163,8 @@ enum ata_command_set {
+ ATAPI_COMMAND_SET = 1,
+ };
+
++#define ATA_RESP_FIS_SIZE 24
++
+ struct sata_device {
+ enum ata_command_set command_set;
+ struct smp_resp rps_resp; /* report_phy_sata_resp */
+@@ -171,7 +173,7 @@ struct sata_device {
+
+ struct ata_port *ap;
+ struct ata_host ata_host;
+- struct ata_taskfile tf;
++ u8 fis[ATA_RESP_FIS_SIZE];
+ };
+
+ enum {
+@@ -537,7 +539,7 @@ enum exec_status {
+ */
+ struct ata_task_resp {
+ u16 frame_len;
+- u8 ending_fis[24]; /* dev to host or data-in */
++ u8 ending_fis[ATA_RESP_FIS_SIZE]; /* dev to host or data-in */
+ };
+
+ #define SAS_STATUS_BUF_SIZE 96
e1000e-test-for-valid-check_reset_block-function-pointer.patch
hid-hid-multitouch-fix-wrong-protocol-detection.patch
acpi-pm-make-acpi_pm_device_sleep_state-follow-the-specification.patch
+scsi-fix-null-dereferences-in-scsi_cmd_to_driver.patch
+scsi-libsas-fix-taskfile-corruption-in-sas_ata_qc_fill_rtf.patch
+acpi-pm-leave-bus-master-arbitration-enabled-for-suspend-resume.patch
+usb-metro-usb-fix-tty_flip_buffer_push-use.patch
+usb-cdc-wdm-fix-lockup-on-error-in-wdm_read.patch
+usb-option-add-zte-mf60.patch
+usb-option-add-mediatek-product-ids.patch
+usb-add-support-for-root-hub-port-status-cas.patch
+xhci-fix-hang-on-back-to-back-set-tr-deq-ptr-commands.patch
+pci-ehci-fix-crash-during-suspend-on-asus-computers.patch
--- /dev/null
+From 8bea2bd37df08aaa599aa361a9f8b836ba98e554 Mon Sep 17 00:00:00 2001
+From: Stanislaw Ledwon <staszek.ledwon@linux.jf.intel.com>
+Date: Mon, 18 Jun 2012 15:20:00 +0200
+Subject: usb: Add support for root hub port status CAS
+
+From: Stanislaw Ledwon <staszek.ledwon@linux.jf.intel.com>
+
+commit 8bea2bd37df08aaa599aa361a9f8b836ba98e554 upstream.
+
+The host controller port status register supports CAS (Cold Attach
+Status) bit. This bit could be set when USB3.0 device is connected
+when system is in Sx state. When the system wakes to S0 this port
+status with CAS bit is reported and this port can't be used by any
+device.
+
+When CAS bit is set the port should be reset by warm reset. This
+was not supported by xhci driver.
+
+The issue was found when pendrive was connected to suspended
+platform. The link state of "Compliance Mode" was reported together
+with CAS bit. This link state was also not supported by xhci and
+core/hub.c.
+
+The CAS bit is defined only for xhci root hub port and it is
+not supported on regular hubs. The link status is used to force
+warm reset on port. Make the USB core issue a warm reset when port
+is in ether the 'inactive' or 'compliance mode'. Change the xHCI driver
+to report 'compliance mode' when the CAS is set. This force warm reset
+on the root hub port.
+
+This patch should be backported to stable kernels as old as 3.2, that
+contain the commit 10d674a82e553cb8a1f41027bb3c3e309b3f6804 "USB: When
+hot reset for USB3 fails, try warm reset."
+
+Signed-off-by: Stanislaw Ledwon <staszek.ledwon@linux.intel.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Acked-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/hub.c | 18 ++++++++++--------
+ drivers/usb/host/xhci-hub.c | 44 ++++++++++++++++++++++++++++++++++++++------
+ drivers/usb/host/xhci.h | 6 +++++-
+ 3 files changed, 53 insertions(+), 15 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -2102,12 +2102,16 @@ static unsigned hub_is_wusb(struct usb_h
+ static int hub_port_reset(struct usb_hub *hub, int port1,
+ struct usb_device *udev, unsigned int delay, bool warm);
+
+-/* Is a USB 3.0 port in the Inactive state? */
+-static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus)
++/* Is a USB 3.0 port in the Inactive or Complinance Mode state?
++ * Port worm reset is required to recover
++ */
++static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
+ {
+ return hub_is_superspeed(hub->hdev) &&
+- (portstatus & USB_PORT_STAT_LINK_STATE) ==
+- USB_SS_PORT_LS_SS_INACTIVE;
++ (((portstatus & USB_PORT_STAT_LINK_STATE) ==
++ USB_SS_PORT_LS_SS_INACTIVE) ||
++ ((portstatus & USB_PORT_STAT_LINK_STATE) ==
++ USB_SS_PORT_LS_COMP_MOD)) ;
+ }
+
+ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
+@@ -2143,7 +2147,7 @@ static int hub_port_wait_reset(struct us
+ *
+ * See https://bugzilla.kernel.org/show_bug.cgi?id=41752
+ */
+- if (hub_port_inactive(hub, portstatus)) {
++ if (hub_port_warm_reset_required(hub, portstatus)) {
+ int ret;
+
+ if ((portchange & USB_PORT_STAT_C_CONNECTION))
+@@ -3757,9 +3761,7 @@ static void hub_events(void)
+ /* Warm reset a USB3 protocol port if it's in
+ * SS.Inactive state.
+ */
+- if (hub_is_superspeed(hub->hdev) &&
+- (portstatus & USB_PORT_STAT_LINK_STATE)
+- == USB_SS_PORT_LS_SS_INACTIVE) {
++ if (hub_port_warm_reset_required(hub, portstatus)) {
+ dev_dbg(hub_dev, "warm reset port %d\n", i);
+ hub_port_reset(hub, i, NULL,
+ HUB_BH_RESET_TIME, true);
+--- a/drivers/usb/host/xhci-hub.c
++++ b/drivers/usb/host/xhci-hub.c
+@@ -462,6 +462,42 @@ void xhci_test_and_clear_bit(struct xhci
+ }
+ }
+
++/* Updates Link Status for super Speed port */
++static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
++{
++ u32 pls = status_reg & PORT_PLS_MASK;
++
++ /* resume state is a xHCI internal state.
++ * Do not report it to usb core.
++ */
++ if (pls == XDEV_RESUME)
++ return;
++
++ /* When the CAS bit is set then warm reset
++ * should be performed on port
++ */
++ if (status_reg & PORT_CAS) {
++ /* The CAS bit can be set while the port is
++ * in any link state.
++ * Only roothubs have CAS bit, so we
++ * pretend to be in compliance mode
++ * unless we're already in compliance
++ * or the inactive state.
++ */
++ if (pls != USB_SS_PORT_LS_COMP_MOD &&
++ pls != USB_SS_PORT_LS_SS_INACTIVE) {
++ pls = USB_SS_PORT_LS_COMP_MOD;
++ }
++ /* Return also connection bit -
++ * hub state machine resets port
++ * when this bit is set.
++ */
++ pls |= USB_PORT_STAT_CONNECTION;
++ }
++ /* update status field */
++ *status |= pls;
++}
++
+ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buf, u16 wLength)
+ {
+@@ -605,13 +641,9 @@ int xhci_hub_control(struct usb_hcd *hcd
+ else
+ status |= USB_PORT_STAT_POWER;
+ }
+- /* Port Link State */
++ /* Update Port Link State for super speed ports*/
+ if (hcd->speed == HCD_USB3) {
+- /* resume state is a xHCI internal state.
+- * Do not report it to usb core.
+- */
+- if ((temp & PORT_PLS_MASK) != XDEV_RESUME)
+- status |= (temp & PORT_PLS_MASK);
++ xhci_hub_report_link_state(&status, temp);
+ }
+ if (bus_state->port_c_suspend & (1 << wIndex))
+ status |= 1 << USB_PORT_FEAT_C_SUSPEND;
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -341,7 +341,11 @@ struct xhci_op_regs {
+ #define PORT_PLC (1 << 22)
+ /* port configure error change - port failed to configure its link partner */
+ #define PORT_CEC (1 << 23)
+-/* bit 24 reserved */
++/* Cold Attach Status - xHC can set this bit to report device attached during
++ * Sx state. Warm port reset should be perfomed to clear this bit and move port
++ * to connected state.
++ */
++#define PORT_CAS (1 << 24)
+ /* wake on connect (enable) */
+ #define PORT_WKCONN_E (1 << 25)
+ /* wake on disconnect (enable) */
--- /dev/null
+From b086b6b10d9f182cd8d2f0dcfd7fd11edba93fc9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Mon, 2 Jul 2012 10:33:14 +0200
+Subject: USB: cdc-wdm: fix lockup on error in wdm_read
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+
+commit b086b6b10d9f182cd8d2f0dcfd7fd11edba93fc9 upstream.
+
+Clear the WDM_READ flag on empty reads to avoid running
+forever in an infinite tight loop, causing lockups:
+
+Jul 1 21:58:11 nemi kernel: [ 3658.898647] qmi_wwan 2-1:1.2: Unexpected error -71
+Jul 1 21:58:36 nemi kernel: [ 3684.072021] BUG: soft lockup - CPU#0 stuck for 23s! [qmi.pl:12235]
+Jul 1 21:58:36 nemi kernel: [ 3684.072212] CPU 0
+Jul 1 21:58:36 nemi kernel: [ 3684.072355]
+Jul 1 21:58:36 nemi kernel: [ 3684.072367] Pid: 12235, comm: qmi.pl Tainted: P O 3.5.0-rc2+ #13 LENOVO 2776LEG/2776LEG
+Jul 1 21:58:36 nemi kernel: [ 3684.072383] RIP: 0010:[<ffffffffa0635008>] [<ffffffffa0635008>] spin_unlock_irq+0x8/0xc [cdc_wdm]
+Jul 1 21:58:36 nemi kernel: [ 3684.072388] RSP: 0018:ffff88022dca1e70 EFLAGS: 00000282
+Jul 1 21:58:36 nemi kernel: [ 3684.072393] RAX: ffff88022fc3f650 RBX: ffffffff811c56f7 RCX: 00000001000ce8c1
+Jul 1 21:58:36 nemi kernel: [ 3684.072398] RDX: 0000000000000010 RSI: 000000000267d810 RDI: ffff88022fc3f650
+Jul 1 21:58:36 nemi kernel: [ 3684.072403] RBP: ffff88022dca1eb0 R08: ffffffffa063578e R09: 0000000000000000
+Jul 1 21:58:36 nemi kernel: [ 3684.072407] R10: 0000000000000008 R11: 0000000000000246 R12: 0000000000000002
+Jul 1 21:58:36 nemi kernel: [ 3684.072412] R13: 0000000000000246 R14: ffffffff00000002 R15: ffff8802281d8c88
+Jul 1 21:58:36 nemi kernel: [ 3684.072418] FS: 00007f666a260700(0000) GS:ffff88023bc00000(0000) knlGS:0000000000000000
+Jul 1 21:58:36 nemi kernel: [ 3684.072423] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+Jul 1 21:58:36 nemi kernel: [ 3684.072428] CR2: 000000000270d9d8 CR3: 000000022e865000 CR4: 00000000000007f0
+Jul 1 21:58:36 nemi kernel: [ 3684.072433] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+Jul 1 21:58:36 nemi kernel: [ 3684.072438] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+Jul 1 21:58:36 nemi kernel: [ 3684.072444] Process qmi.pl (pid: 12235, threadinfo ffff88022dca0000, task ffff88022ff76380)
+Jul 1 21:58:36 nemi kernel: [ 3684.072448] Stack:
+Jul 1 21:58:36 nemi kernel: [ 3684.072458] ffffffffa063592e 0000000100020000 ffff88022fc3f650 ffff88022fc3f6a8
+Jul 1 21:58:36 nemi kernel: [ 3684.072466] 0000000000000200 0000000100000000 000000000267d810 0000000000000000
+Jul 1 21:58:36 nemi kernel: [ 3684.072475] 0000000000000000 ffff880212cfb6d0 0000000000000200 ffff880212cfb6c0
+Jul 1 21:58:36 nemi kernel: [ 3684.072479] Call Trace:
+Jul 1 21:58:36 nemi kernel: [ 3684.072489] [<ffffffffa063592e>] ? wdm_read+0x1a0/0x263 [cdc_wdm]
+Jul 1 21:58:36 nemi kernel: [ 3684.072500] [<ffffffff8110adb7>] ? vfs_read+0xa1/0xfb
+Jul 1 21:58:36 nemi kernel: [ 3684.072509] [<ffffffff81040589>] ? alarm_setitimer+0x35/0x64
+Jul 1 21:58:36 nemi kernel: [ 3684.072517] [<ffffffff8110aec7>] ? sys_read+0x45/0x6e
+Jul 1 21:58:36 nemi kernel: [ 3684.072525] [<ffffffff813725f9>] ? system_call_fastpath+0x16/0x1b
+Jul 1 21:58:36 nemi kernel: [ 3684.072557] Code: <66> 66 90 c3 83 ff ed 89 f8 74 16 7f 06 83 ff a1 75 0a c3 83 ff f4
+
+The WDM_READ flag is normally cleared by wdm_int_callback
+before resubmitting the read urb, and set by wdm_in_callback
+when this urb returns with data or an error. But a crashing
+device may cause both a read error and cancelling all urbs.
+Make sure that the flag is cleared by wdm_read if the buffer
+is empty.
+
+We don't clear the flag on errors, as there may be pending
+data in the buffer which should be processed. The flag will
+instead be cleared on the next wdm_read call.
+
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Acked-by: Oliver Neukum <oneukum@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-wdm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -497,6 +497,8 @@ retry:
+ goto retry;
+ }
+ if (!desc->reslength) { /* zero length read */
++ dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
++ clear_bit(WDM_READ, &desc->flags);
+ spin_unlock_irq(&desc->iuspin);
+ goto retry;
+ }
--- /dev/null
+From b7d28e32c93801d60c1a7a817f774a02b7bdde43 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 2 Jul 2012 12:34:24 +0200
+Subject: USB: metro-usb: fix tty_flip_buffer_push use
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit b7d28e32c93801d60c1a7a817f774a02b7bdde43 upstream.
+
+Do not set low_latency flag at open as tty_flip_buffer_push must not be
+called in IRQ context with low_latency set.
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/metro-usb.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/drivers/usb/serial/metro-usb.c
++++ b/drivers/usb/serial/metro-usb.c
+@@ -171,14 +171,6 @@ static int metrousb_open(struct tty_stru
+ metro_priv->throttled = 0;
+ spin_unlock_irqrestore(&metro_priv->lock, flags);
+
+- /*
+- * Force low_latency on so that our tty_push actually forces the data
+- * through, otherwise it is scheduled, and with high data rates (like
+- * with OHCI) data can get lost.
+- */
+- if (tty)
+- tty->low_latency = 1;
+-
+ /* Clear the urb pipe. */
+ usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe);
+
--- /dev/null
+From aacef9c561a693341566a6850c451ce3df68cb9a Mon Sep 17 00:00:00 2001
+From: Gaosen Zhang <gaosen.zhang@mediatek.com>
+Date: Thu, 5 Jul 2012 21:49:00 +0800
+Subject: USB: option: Add MEDIATEK product ids
+
+From: Gaosen Zhang <gaosen.zhang@mediatek.com>
+
+commit aacef9c561a693341566a6850c451ce3df68cb9a upstream.
+
+Signed-off-by: Gaosen Zhang <gaosen.zhang@mediatek.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -497,6 +497,15 @@ static void option_instat_callback(struc
+
+ /* MediaTek products */
+ #define MEDIATEK_VENDOR_ID 0x0e8d
++#define MEDIATEK_PRODUCT_DC_1COM 0x00a0
++#define MEDIATEK_PRODUCT_DC_4COM 0x00a5
++#define MEDIATEK_PRODUCT_DC_5COM 0x00a4
++#define MEDIATEK_PRODUCT_7208_1COM 0x7101
++#define MEDIATEK_PRODUCT_7208_2COM 0x7102
++#define MEDIATEK_PRODUCT_FP_1COM 0x0003
++#define MEDIATEK_PRODUCT_FP_2COM 0x0023
++#define MEDIATEK_PRODUCT_FPDC_1COM 0x0043
++#define MEDIATEK_PRODUCT_FPDC_2COM 0x0033
+
+ /* Cellient products */
+ #define CELLIENT_VENDOR_ID 0x2692
+@@ -1246,6 +1255,17 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_1COM, 0x0a, 0x00, 0x00) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x02, 0x01) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x00, 0x00) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x02, 0x01) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x00, 0x00) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_1COM, 0x02, 0x00, 0x00) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_2COM, 0x02, 0x02, 0x01) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_1COM, 0x0a, 0x00, 0x00) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) },
+ { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
+ { } /* Terminating entry */
+ };
--- /dev/null
+From 8e16e33c168a6efd0c9f7fa9dd4c1e1db9a74553 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Mon, 2 Jul 2012 19:53:55 +0200
+Subject: USB: option: add ZTE MF60
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+
+commit 8e16e33c168a6efd0c9f7fa9dd4c1e1db9a74553 upstream.
+
+Switches into a composite device by ejecting the initial
+driver CD. The four interfaces are: QCDM, AT, QMI/wwan
+and mass storage. Let this driver manage the two serial
+interfaces:
+
+T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 28 Spd=480 MxCh= 0
+D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
+P: Vendor=19d2 ProdID=1402 Rev= 0.00
+S: Manufacturer=ZTE,Incorporated
+S: Product=ZTE WCDMA Technologies MSM
+S: SerialNumber=xxxxx
+C:* #Ifs= 4 Cfg#= 1 Atr=c0 MxPwr=500mA
+I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
+E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
+E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
+I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
+E: Ad=83(I) Atr=03(Int.) MxPS= 64 Ivl=2ms
+E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
+I:* If#= 3 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
+E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -554,6 +554,10 @@ static const struct option_blacklist_inf
+ .reserved = BIT(1),
+ };
+
++static const struct option_blacklist_info net_intf2_blacklist = {
++ .reserved = BIT(2),
++};
++
+ static const struct option_blacklist_info net_intf3_blacklist = {
+ .reserved = BIT(3),
+ };
+@@ -1099,6 +1103,8 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
+ 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
--- /dev/null
+From 0d9f78a92ef5e97d9fe51d9215ebe22f6f0d289d Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 21 Jun 2012 16:28:30 -0700
+Subject: xhci: Fix hang on back-to-back Set TR Deq Ptr commands.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 0d9f78a92ef5e97d9fe51d9215ebe22f6f0d289d upstream.
+
+The Microsoft LifeChat 3000 USB headset was causing a very reproducible
+hang whenever it was plugged in. At first, I thought the host
+controller was producing bad transfer events, because the log was filled
+with errors like:
+
+xhci_hcd 0000:00:14.0: ERROR Transfer event TRB DMA ptr not part of current TD
+
+However, it turned out to be an xHCI driver bug in the ring expansion
+patches. The bug is triggered When there are two ring segments, and a
+TD that ends just before a link TRB, like so:
+
+ ______________ _____________
+| | ---> | setup TRB B |
+ ______________ | _____________
+| | | | data TRB B |
+ ______________ | _____________
+| setup TRB A | <-- deq | | data TRB B |
+ ______________ | _____________
+| data TRB A | | | | <-- enq, deq''
+ ______________ | _____________
+| status TRB A | | | |
+ ______________ | _____________
+| link TRB |--------------- | link TRB |
+ _____________ <--- deq' _____________
+
+TD A (the first control transfer) stalls on the data phase. That halts
+the ring. The xHCI driver moves the hardware dequeue pointer to the
+first TRB after the stalled transfer, which happens to be the link TRB.
+
+Once the Set TR dequeue pointer command completes, the function
+update_ring_for_set_deq_completion runs. That function is supposed to
+update the xHCI driver's dequeue pointer to match the internal hardware
+dequeue pointer. On the first call this would work fine, and the
+software dequeue pointer would move to deq'.
+
+However, if the transfer immediately after that stalled (TD B in this
+case), another Set TR Dequeue command would be issued. That would move
+the hardware dequeue pointer to deq''. Once that command completed,
+update_ring_for_set_deq_completion would run again.
+
+The original code would unconditionally increment the software dequeue
+pointer, which moved the pointer off the ring segment into la-la-land.
+The while loop would happy increment the dequeue pointer (possibly
+wrapping it) until it matched the hardware pointer value.
+
+The while loop would also access all the memory in between the first
+ring segment and the second ring segment to determine if it was a link
+TRB. This could cause general protection faults, although it was
+unlikely because the ring segments came from a DMA pool, and would often
+have consecutive memory addresses.
+
+If nothing in that space looked like a link TRB, the deq_seg pointer for
+the ring would remain on the first segment. Thus, the deq_seg and the
+software dequeue pointer would get out of sync.
+
+When the next transfer event came in after the stalled transfer, the
+xHCI driver code would attempt to convert the software dequeue pointer
+into a DMA address in order to compare the DMA address for the completed
+transfer. Since the deq_seg and the dequeue pointer were out of sync,
+xhci_trb_virt_to_dma would return NULL.
+
+The transfer event would get ignored, the transfer would eventually
+timeout, and we would mistakenly convert the finished transfer to no-op
+TRBs. Some kernel driver (maybe xHCI?) would then get stuck in an
+infinite loop in interrupt context, and the whole machine would hang.
+
+This patch should be backported to kernels as old as 3.4, that contain
+the commit b008df60c6369ba0290fa7daa177375407a12e07 "xHCI: count free
+TRBs on transfer ring"
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Cc: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -885,6 +885,17 @@ static void update_ring_for_set_deq_comp
+ num_trbs_free_temp = ep_ring->num_trbs_free;
+ dequeue_temp = ep_ring->dequeue;
+
++ /* If we get two back-to-back stalls, and the first stalled transfer
++ * ends just before a link TRB, the dequeue pointer will be left on
++ * the link TRB by the code in the while loop. So we have to update
++ * the dequeue pointer one segment further, or we'll jump off
++ * the segment into la-la-land.
++ */
++ if (last_trb(xhci, ep_ring, ep_ring->deq_seg, ep_ring->dequeue)) {
++ ep_ring->deq_seg = ep_ring->deq_seg->next;
++ ep_ring->dequeue = ep_ring->deq_seg->trbs;
++ }
++
+ while (ep_ring->dequeue != dev->eps[ep_index].queued_deq_ptr) {
+ /* We have more usable TRBs */
+ ep_ring->num_trbs_free++;