]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.37 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 15 Feb 2011 20:48:03 +0000 (12:48 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 15 Feb 2011 20:48:03 +0000 (12:48 -0800)
queue-2.6.37/agp-ensure-gart-has-an-address-before-enabling-it.patch [new file with mode: 0644]
queue-2.6.37/drm-i915-only-bind-to-function-0-of-the-pci-device.patch [new file with mode: 0644]
queue-2.6.37/drm-only-set-dpms-on-when-actually-configuring-a-mode.patch [new file with mode: 0644]
queue-2.6.37/series
queue-2.6.37/usb-realloc-xhci-structures-after-a-hub-is-verified.patch [new file with mode: 0644]
queue-2.6.37/xhci-do-not-run-xhci_cleanup_msix-with-irq-disabled.patch [new file with mode: 0644]
queue-2.6.37/xhci-resume-bus-on-any-port-status-change.patch [new file with mode: 0644]
queue-2.6.37/xhci-synchronize-irq-in-xhci_suspend.patch [new file with mode: 0644]
queue-2.6.37/xhci-use-gfp_noio-during-device-reset.patch [new file with mode: 0644]

diff --git a/queue-2.6.37/agp-ensure-gart-has-an-address-before-enabling-it.patch b/queue-2.6.37/agp-ensure-gart-has-an-address-before-enabling-it.patch
new file mode 100644 (file)
index 0000000..a5958ad
--- /dev/null
@@ -0,0 +1,85 @@
+From a70b95c017e8b518e1e069853355e4e497453dbb Mon Sep 17 00:00:00 2001
+From: Stephen Kitt <steve@sk2.org>
+Date: Mon, 31 Jan 2011 14:25:43 -0800
+Subject: agp: ensure GART has an address before enabling it
+
+From: Stephen Kitt <steve@sk2.org>
+
+commit a70b95c017e8b518e1e069853355e4e497453dbb upstream.
+
+Some BIOSs (eg.  the AMI BIOS on the Asus P4P800 motherboard) don't
+initialise the GART address, and pcibios_assign_resources() can ignore it
+because it can be marked as a host bridge (see
+https://bugzilla.kernel.org/show_bug.cgi?id=24392#c5 for details).  This
+was handled correctly up to 2.6.35, but the pci_enable_device() cleanup in
+2.6.36 96576a9e1a0cdb8 ("agp: intel-agp: do not use PCI resources before
+pci_enable_device()") means that the kernel tries to enable the GART
+before assigning it an address; in such cases the GART overlaps with other
+device assignments and ends up being disabled.
+
+This patch fixes https://bugzilla.kernel.org/show_bug.cgi?id=24392
+
+Note that I imagine efficeon-agp.c probably has the same problem, but
+I can't test that and I'd like to make sure this patch is suitable for
+-stable (since 2.6.36 and 2.6.37 are affected).
+
+Signed-off-by: Stephen Kitt <steve@sk2.org>
+Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
+Cc: Maciej Rutecki <maciej.rutecki@gmail.com>
+Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
+Cc: Kulikov Vasiliy <segooon@gmail.com>
+Cc: Florian Mickler <florian@mickler.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/char/agp/intel-agp.c |   27 ++++++++++++++++-----------
+ 1 file changed, 16 insertions(+), 11 deletions(-)
+
+--- a/drivers/char/agp/intel-agp.c
++++ b/drivers/char/agp/intel-agp.c
+@@ -774,20 +774,14 @@ static int __devinit agp_intel_probe(str
+       dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
+       /*
+-      * If the device has not been properly setup, the following will catch
+-      * the problem and should stop the system from crashing.
+-      * 20030610 - hamish@zot.org
+-      */
+-      if (pci_enable_device(pdev)) {
+-              dev_err(&pdev->dev, "can't enable PCI device\n");
+-              agp_put_bridge(bridge);
+-              return -ENODEV;
+-      }
+-
+-      /*
+       * The following fixes the case where the BIOS has "forgotten" to
+       * provide an address range for the GART.
+       * 20030610 - hamish@zot.org
++      * This happens before pci_enable_device() intentionally;
++      * calling pci_enable_device() before assigning the resource
++      * will result in the GART being disabled on machines with such
++      * BIOSs (the GART ends up with a BAR starting at 0, which
++      * conflicts a lot of other devices).
+       */
+       r = &pdev->resource[0];
+       if (!r->start && r->end) {
+@@ -798,6 +792,17 @@ static int __devinit agp_intel_probe(str
+               }
+       }
++      /*
++      * If the device has not been properly setup, the following will catch
++      * the problem and should stop the system from crashing.
++      * 20030610 - hamish@zot.org
++      */
++      if (pci_enable_device(pdev)) {
++              dev_err(&pdev->dev, "can't enable PCI device\n");
++              agp_put_bridge(bridge);
++              return -ENODEV;
++      }
++
+       /* Fill in the mode register */
+       if (cap_ptr) {
+               pci_read_config_dword(pdev,
diff --git a/queue-2.6.37/drm-i915-only-bind-to-function-0-of-the-pci-device.patch b/queue-2.6.37/drm-i915-only-bind-to-function-0-of-the-pci-device.patch
new file mode 100644 (file)
index 0000000..caf51e5
--- /dev/null
@@ -0,0 +1,45 @@
+From 5fe49d86f9d01044abf687a8cd21edef636d58aa Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Tue, 1 Feb 2011 19:43:02 +0000
+Subject: drm/i915: Only bind to function 0 of the PCI device
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 5fe49d86f9d01044abf687a8cd21edef636d58aa upstream.
+
+Early chipsets (gen2/3) used function 1 as a placeholder for multi-head.
+We used to ignore these since they were not assigned to
+PCI_CLASS_DISPLAY_VGA. However with 934f992c7 we attempt to bind to all
+Intel PCI_CLASS_DISPLAY devices (and functions) to work in multi-gpu
+systems. This fails hard on gen2/3.
+
+Reported-by: Ferenc Wágner <wferi@niif.hu>
+Tested-by: Ferenc Wágner <wferi@niif.hu>
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=28012
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/i915/i915_drv.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/gpu/drm/i915/i915_drv.c
++++ b/drivers/gpu/drm/i915/i915_drv.c
+@@ -501,6 +501,14 @@ int i915_reset(struct drm_device *dev, u
+ static int __devinit
+ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ {
++      /* Only bind to function 0 of the device. Early generations
++       * used function 1 as a placeholder for multi-head. This causes
++       * us confusion instead, especially on the systems where both
++       * functions have the same PCI-ID!
++       */
++      if (PCI_FUNC(pdev->devfn))
++              return -ENODEV;
++
+       return drm_get_pci_dev(pdev, ent, &driver);
+ }
diff --git a/queue-2.6.37/drm-only-set-dpms-on-when-actually-configuring-a-mode.patch b/queue-2.6.37/drm-only-set-dpms-on-when-actually-configuring-a-mode.patch
new file mode 100644 (file)
index 0000000..d06e51c
--- /dev/null
@@ -0,0 +1,53 @@
+From 811aaa55ba21ab37407018cfc01770d6b037d3fb Mon Sep 17 00:00:00 2001
+From: Keith Packard <keithp@keithp.com>
+Date: Thu, 3 Feb 2011 16:57:28 -0800
+Subject: drm: Only set DPMS ON when actually configuring a mode
+
+From: Keith Packard <keithp@keithp.com>
+
+commit 811aaa55ba21ab37407018cfc01770d6b037d3fb upstream.
+
+In drm_crtc_helper_set_config, instead of always forcing all outputs
+to DRM_MODE_DPMS_ON, only set them if the CRTC is actually getting a
+mode set, as any mode set will turn all outputs on.
+
+This fixes https://lkml.org/lkml/2011/1/24/457
+
+Signed-off-by: Keith Packard <keithp@keithp.com>
+Reported-and-tested-by: Carlos R. Mafra <crmafra2@gmail.com>
+Tested-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/gpu/drm/drm_crtc_helper.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/gpu/drm/drm_crtc_helper.c
++++ b/drivers/gpu/drm/drm_crtc_helper.c
+@@ -654,6 +654,12 @@ int drm_crtc_helper_set_config(struct dr
+                               ret = -EINVAL;
+                               goto fail;
+                       }
++                      DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
++                      for (i = 0; i < set->num_connectors; i++) {
++                              DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
++                                            drm_get_connector_name(set->connectors[i]));
++                              set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
++                      }
+               }
+               drm_helper_disable_unused_functions(dev);
+       } else if (fb_changed) {
+@@ -670,12 +676,6 @@ int drm_crtc_helper_set_config(struct dr
+                       goto fail;
+               }
+       }
+-      DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
+-      for (i = 0; i < set->num_connectors; i++) {
+-              DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
+-                            drm_get_connector_name(set->connectors[i]));
+-              set->connectors[i]->dpms = DRM_MODE_DPMS_ON;
+-      }
+       kfree(save_connectors);
+       kfree(save_encoders);
index 3b71fea4707d2c4d70533c6e1b4537092ad1d656..399fd8576acc097f23eb1c57ed2ebd2d6638cf63 100644 (file)
@@ -262,3 +262,11 @@ drm-i915-lvds-add-aopen-i915gmm-hfs-to-the-list-of-false-positive-lvds.patch
 drm-i915-add-dependency-on-config_tmpfs.patch
 drm-i915-recognise-non-vga-display-devices.patch
 x86-mm-avoid-possible-bogus-tlb-entries-by-clearing-prev-mm_cpumask-after-switching-mm.patch
+drm-only-set-dpms-on-when-actually-configuring-a-mode.patch
+agp-ensure-gart-has-an-address-before-enabling-it.patch
+drm-i915-only-bind-to-function-0-of-the-pci-device.patch
+xhci-resume-bus-on-any-port-status-change.patch
+xhci-synchronize-irq-in-xhci_suspend.patch
+xhci-do-not-run-xhci_cleanup_msix-with-irq-disabled.patch
+usb-realloc-xhci-structures-after-a-hub-is-verified.patch
+xhci-use-gfp_noio-during-device-reset.patch
diff --git a/queue-2.6.37/usb-realloc-xhci-structures-after-a-hub-is-verified.patch b/queue-2.6.37/usb-realloc-xhci-structures-after-a-hub-is-verified.patch
new file mode 100644 (file)
index 0000000..225c698
--- /dev/null
@@ -0,0 +1,73 @@
+From 653a39d1f61bdc9f277766736d21d2e9be0391cb Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Thu, 23 Dec 2010 11:12:42 -0800
+Subject: usb: Realloc xHCI structures after a hub is verified.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 653a39d1f61bdc9f277766736d21d2e9be0391cb upstream.
+
+When there's an xHCI host power loss after a suspend from memory, the USB
+core attempts to reset and verify the USB devices that are attached to the
+system.  The xHCI driver has to reallocate those devices, since the
+hardware lost all knowledge of them during the power loss.
+
+When a hub is plugged in, and the host loses power, the xHCI hardware
+structures are not updated to say the device is a hub.  This is usually
+done in hub_configure() when the USB hub is detected.  That function is
+skipped during a reset and verify by the USB core, since the core restores
+the old configuration and alternate settings, and the hub driver has no
+idea this happened.  This bug makes the xHCI host controller reject the
+enumeration of low speed devices under the resumed hub.
+
+Therefore, make the USB core re-setup the internal xHCI hub device
+information by calling update_hub_device() when hub_activate() is called
+for a hub reset resume.  After a host power loss, all devices under the
+roothub get a reset-resume or a disconnect.
+
+This patch should be queued for the 2.6.37 stable tree.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hub.c |   21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -677,6 +677,8 @@ static void hub_init_func3(struct work_s
+ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ {
+       struct usb_device *hdev = hub->hdev;
++      struct usb_hcd *hcd;
++      int ret;
+       int port1;
+       int status;
+       bool need_debounce_delay = false;
+@@ -715,6 +717,25 @@ static void hub_activate(struct usb_hub
+                       usb_autopm_get_interface_no_resume(
+                                       to_usb_interface(hub->intfdev));
+                       return;         /* Continues at init2: below */
++              } else if (type == HUB_RESET_RESUME) {
++                      /* The internal host controller state for the hub device
++                       * may be gone after a host power loss on system resume.
++                       * Update the device's info so the HW knows it's a hub.
++                       */
++                      hcd = bus_to_hcd(hdev->bus);
++                      if (hcd->driver->update_hub_device) {
++                              ret = hcd->driver->update_hub_device(hcd, hdev,
++                                              &hub->tt, GFP_NOIO);
++                              if (ret < 0) {
++                                      dev_err(hub->intfdev, "Host not "
++                                                      "accepting hub info "
++                                                      "update.\n");
++                                      dev_err(hub->intfdev, "LS/FS devices "
++                                                      "and hubs may not work "
++                                                      "under this hub\n.");
++                              }
++                      }
++                      hub_power_on(hub, true);
+               } else {
+                       hub_power_on(hub, true);
+               }
diff --git a/queue-2.6.37/xhci-do-not-run-xhci_cleanup_msix-with-irq-disabled.patch b/queue-2.6.37/xhci-do-not-run-xhci_cleanup_msix-with-irq-disabled.patch
new file mode 100644 (file)
index 0000000..f25d270
--- /dev/null
@@ -0,0 +1,88 @@
+From 40a9fb17f32dbe54de3d636142a59288544deed7 Mon Sep 17 00:00:00 2001
+From: Zhang Rui <rui.zhang@intel.com>
+Date: Fri, 17 Dec 2010 13:17:04 -0800
+Subject: xhci: Do not run xhci_cleanup_msix with irq disabled
+
+From: Zhang Rui <rui.zhang@intel.com>
+
+commit 40a9fb17f32dbe54de3d636142a59288544deed7 upstream.
+
+when unloading xhci_hcd, I got:
+[  134.856813] xhci_hcd 0000:02:00.0: remove, state 4
+[  134.858140] usb usb3: USB disconnect, address 1
+[  134.874956] xhci_hcd 0000:02:00.0: Host controller not halted, aborting reset.
+[  134.876351] BUG: sleeping function called from invalid context at kernel/mutex.c:85
+[  134.877657] in_atomic(): 0, irqs_disabled(): 1, pid: 1451, name: modprobe
+[  134.878975] Pid: 1451, comm: modprobe Not tainted 2.6.37-rc5+ #162
+[  134.880298] Call Trace:
+[  134.881602]  [<ffffffff8104156a>] __might_sleep+0xeb/0xf0
+[  134.882921]  [<ffffffff814763dc>] mutex_lock+0x24/0x50
+[  134.884229]  [<ffffffff810a745c>] free_desc+0x2e/0x5f
+[  134.885538]  [<ffffffff810a74c8>] irq_free_descs+0x3b/0x71
+[  134.886853]  [<ffffffff8102584d>] free_irq_at+0x31/0x36
+[  134.888167]  [<ffffffff8102723f>] destroy_irq+0x69/0x71
+[  134.889486]  [<ffffffff8102747a>] native_teardown_msi_irq+0xe/0x10
+[  134.890820]  [<ffffffff8124c382>] default_teardown_msi_irqs+0x57/0x80
+[  134.892158]  [<ffffffff8124be46>] free_msi_irqs+0x8b/0xe9
+[  134.893504]  [<ffffffff8124cd46>] pci_disable_msix+0x35/0x39
+[  134.894844]  [<ffffffffa01b444a>] xhci_cleanup_msix+0x31/0x51 [xhci_hcd]
+[  134.896186]  [<ffffffffa01b4b3a>] xhci_stop+0x3a/0x80 [xhci_hcd]
+[  134.897521]  [<ffffffff81341dd4>] usb_remove_hcd+0xfd/0x14a
+[  134.898859]  [<ffffffff813500ae>] usb_hcd_pci_remove+0x5c/0xc6
+[  134.900193]  [<ffffffff8123c606>] pci_device_remove+0x3f/0x91
+[  134.901535]  [<ffffffff812e7ea4>] __device_release_driver+0x83/0xd9
+[  134.902899]  [<ffffffff812e8571>] driver_detach+0x86/0xad
+[  134.904222]  [<ffffffff812e7d56>] bus_remove_driver+0xb2/0xd8
+[  134.905540]  [<ffffffff812e8633>] driver_unregister+0x6c/0x74
+[  134.906839]  [<ffffffff8123c8e4>] pci_unregister_driver+0x44/0x89
+[  134.908121]  [<ffffffffa01b940e>] xhci_unregister_pci+0x15/0x17 [xhci_hcd]
+[  134.909396]  [<ffffffffa01bd7d2>] xhci_hcd_cleanup+0xe/0x10 [xhci_hcd]
+[  134.910652]  [<ffffffff8107fcd1>] sys_delete_module+0x1ca/0x23b
+[  134.911882]  [<ffffffff81123932>] ? path_put+0x22/0x26
+[  134.913104]  [<ffffffff8109a800>] ? audit_syscall_entry+0x2c/0x148
+[  134.914333]  [<ffffffff8100ac82>] system_call_fastpath+0x16/0x1b
+[  134.915658] xhci_hcd 0000:02:00.0: USB bus 3 deregistered
+[  134.916465] xhci_hcd 0000:02:00.0: PCI INT A disabled
+
+and the same issue when xhci_suspend is invoked.  (Note from Sarah: That's
+fixed by Andiry's patch before this, by synchronizing the irqs rather than
+freeing them on suspend.)
+
+Do not run xhci_cleanup_msix with irq disabled.
+
+This patch should be queued for the 2.6.37 stable tree.
+
+Signed-off-by: Zhang Rui <rui.zhang@intel.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -512,9 +512,10 @@ void xhci_stop(struct usb_hcd *hcd)
+       spin_lock_irq(&xhci->lock);
+       xhci_halt(xhci);
+       xhci_reset(xhci);
+-      xhci_cleanup_msix(xhci);
+       spin_unlock_irq(&xhci->lock);
++      xhci_cleanup_msix(xhci);
++
+ #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
+       /* Tell the event ring poll function not to reschedule */
+       xhci->zombie = 1;
+@@ -548,9 +549,10 @@ void xhci_shutdown(struct usb_hcd *hcd)
+       spin_lock_irq(&xhci->lock);
+       xhci_halt(xhci);
+-      xhci_cleanup_msix(xhci);
+       spin_unlock_irq(&xhci->lock);
++      xhci_cleanup_msix(xhci);
++
+       xhci_dbg(xhci, "xhci_shutdown completed - status = %x\n",
+                   xhci_readl(xhci, &xhci->op_regs->status));
+ }
diff --git a/queue-2.6.37/xhci-resume-bus-on-any-port-status-change.patch b/queue-2.6.37/xhci-resume-bus-on-any-port-status-change.patch
new file mode 100644 (file)
index 0000000..7edbac5
--- /dev/null
@@ -0,0 +1,53 @@
+From 7111ebc97ed53a32314011c85a6f235f0dab8ae8 Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 14 Dec 2010 13:24:55 -0800
+Subject: xhci: Resume bus on any port status change.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit 7111ebc97ed53a32314011c85a6f235f0dab8ae8 upstream.
+
+The original code that resumed the USB bus on a port status change would
+only do so when there was a device connected to the port.  If a device was
+just disconnected, the event would be queued for khubd, but khubd wouldn't
+run.  That would leave the connect status change (CSC) bit set.
+
+If a USB device was plugged into that same port, the xHCI host controller
+would set the current connect status (CCS) bit.  But since the CSC bit was
+already set, it would not generate an interrupt for a port status change
+event.  That would mean the user could "Safely Remove" a device, have the
+bus suspend, disconnect the device, re-plug it in, and then the device
+would never be enumerated.
+
+Plugging in a different device on another port would cause the bus to
+resume, and khubd would notice the re-connected device.  Running lsusb
+would also resume the bus, leading users to report the problem "went away"
+when using diagnostic tools.
+
+The solution is to resume the bus when a port status change event is
+received, regardless of the port status.
+
+Thank you very much to Maddog for helping me track down this Heisenbug.
+
+This patch should be queued for the 2.6.37 stable tree.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Reported-by: Jon 'maddog' Hall <maddog@li.org>
+Tested-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci-ring.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1188,7 +1188,7 @@ static void handle_port_status(struct xh
+       addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * (port_id - 1);
+       temp = xhci_readl(xhci, addr);
+-      if ((temp & PORT_CONNECT) && (hcd->state == HC_STATE_SUSPENDED)) {
++      if (hcd->state == HC_STATE_SUSPENDED) {
+               xhci_dbg(xhci, "resume root hub\n");
+               usb_hcd_resume_root_hub(hcd);
+       }
diff --git a/queue-2.6.37/xhci-synchronize-irq-in-xhci_suspend.patch b/queue-2.6.37/xhci-synchronize-irq-in-xhci_suspend.patch
new file mode 100644 (file)
index 0000000..bba3e90
--- /dev/null
@@ -0,0 +1,169 @@
+From 0029227f1bc30b6c809ae751f9e7af6cef900997 Mon Sep 17 00:00:00 2001
+From: Andiry Xu <andiry.xu@amd.com>
+Date: Mon, 27 Dec 2010 17:39:02 +0800
+Subject: xHCI: synchronize irq in xhci_suspend()
+
+From: Andiry Xu <andiry.xu@amd.com>
+
+commit 0029227f1bc30b6c809ae751f9e7af6cef900997 upstream.
+
+Synchronize the interrupts instead of free them in xhci_suspend(). This will
+prevent a double free when the host is suspended and then the card removed.
+
+Set the flag hcd->msix_enabled when using MSI-X, and check the flag in
+suspend_common(). MSI-X synchronization will be handled by xhci_suspend(),
+and MSI/INTx will be synchronized in suspend_common().
+
+This patch should be queued for the 2.6.37 stable tree.
+
+Reported-by: Matthew Garrett <mjg@redhat.com>
+Signed-off-by: Andiry Xu <andiry.xu@amd.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/core/hcd-pci.c |    7 +++++-
+ drivers/usb/host/xhci.c    |   46 ++++++++++++++-------------------------------
+ include/linux/usb/hcd.h    |    1 
+ 3 files changed, 22 insertions(+), 32 deletions(-)
+
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -406,7 +406,12 @@ static int suspend_common(struct device
+                       return retval;
+       }
+-      synchronize_irq(pci_dev->irq);
++      /* If MSI-X is enabled, the driver will have synchronized all vectors
++       * in pci_suspend(). If MSI or legacy PCI is enabled, that will be
++       * synchronized here.
++       */
++      if (!hcd->msix_enabled)
++              synchronize_irq(pci_dev->irq);
+       /* Downstream ports from this root hub should already be quiesced, so
+        * there will be no DMA activity.  Now we can shut down the upstream
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -226,7 +226,8 @@ static int xhci_setup_msi(struct xhci_hc
+ static int xhci_setup_msix(struct xhci_hcd *xhci)
+ {
+       int i, ret = 0;
+-      struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
++      struct usb_hcd *hcd = xhci_to_hcd(xhci);
++      struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+       /*
+        * calculate number of msi-x vectors supported.
+@@ -265,6 +266,7 @@ static int xhci_setup_msix(struct xhci_h
+                       goto disable_msix;
+       }
++      hcd->msix_enabled = 1;
+       return ret;
+ disable_msix:
+@@ -280,7 +282,8 @@ free_entries:
+ /* Free any IRQs and disable MSI-X */
+ static void xhci_cleanup_msix(struct xhci_hcd *xhci)
+ {
+-      struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
++      struct usb_hcd *hcd = xhci_to_hcd(xhci);
++      struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+       xhci_free_irq(xhci);
+@@ -292,6 +295,7 @@ static void xhci_cleanup_msix(struct xhc
+               pci_disable_msi(pdev);
+       }
++      hcd->msix_enabled = 0;
+       return;
+ }
+@@ -647,6 +651,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
+       int                     rc = 0;
+       struct usb_hcd          *hcd = xhci_to_hcd(xhci);
+       u32                     command;
++      int                     i;
+       spin_lock_irq(&xhci->lock);
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+@@ -677,10 +682,15 @@ int xhci_suspend(struct xhci_hcd *xhci)
+               spin_unlock_irq(&xhci->lock);
+               return -ETIMEDOUT;
+       }
+-      /* step 5: remove core well power */
+-      xhci_cleanup_msix(xhci);
+       spin_unlock_irq(&xhci->lock);
++      /* step 5: remove core well power */
++      /* synchronize irq when using MSI-X */
++      if (xhci->msix_entries) {
++              for (i = 0; i < xhci->msix_count; i++)
++                      synchronize_irq(xhci->msix_entries[i].vector);
++      }
++
+       return rc;
+ }
+@@ -694,7 +704,6 @@ int xhci_resume(struct xhci_hcd *xhci, b
+ {
+       u32                     command, temp = 0;
+       struct usb_hcd          *hcd = xhci_to_hcd(xhci);
+-      struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+       int     old_state, retval;
+       old_state = hcd->state;
+@@ -729,9 +738,8 @@ int xhci_resume(struct xhci_hcd *xhci, b
+               xhci_dbg(xhci, "Stop HCD\n");
+               xhci_halt(xhci);
+               xhci_reset(xhci);
+-              if (hibernated)
+-                      xhci_cleanup_msix(xhci);
+               spin_unlock_irq(&xhci->lock);
++              xhci_cleanup_msix(xhci);
+ #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
+               /* Tell the event ring poll function not to reschedule */
+@@ -765,30 +773,6 @@ int xhci_resume(struct xhci_hcd *xhci, b
+               return retval;
+       }
+-      spin_unlock_irq(&xhci->lock);
+-      /* Re-setup MSI-X */
+-      if (hcd->irq)
+-              free_irq(hcd->irq, hcd);
+-      hcd->irq = -1;
+-
+-      retval = xhci_setup_msix(xhci);
+-      if (retval)
+-              /* fall back to msi*/
+-              retval = xhci_setup_msi(xhci);
+-
+-      if (retval) {
+-              /* fall back to legacy interrupt*/
+-              retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
+-                                      hcd->irq_descr, hcd);
+-              if (retval) {
+-                      xhci_err(xhci, "request interrupt %d failed\n",
+-                                      pdev->irq);
+-                      return retval;
+-              }
+-              hcd->irq = pdev->irq;
+-      }
+-
+-      spin_lock_irq(&xhci->lock);
+       /* step 4: set Run/Stop bit */
+       command = xhci_readl(xhci, &xhci->op_regs->command);
+       command |= CMD_RUN;
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -112,6 +112,7 @@ struct usb_hcd {
+       /* Flags that get set only during HCD registration or removal. */
+       unsigned                rh_registered:1;/* is root hub registered? */
+       unsigned                rh_pollable:1;  /* may we poll the root hub? */
++      unsigned                msix_enabled:1; /* driver has MSI-X enabled? */
+       /* The next flag is a stopgap, to be removed when all the HCDs
+        * support the new root-hub polling mechanism. */
diff --git a/queue-2.6.37/xhci-use-gfp_noio-during-device-reset.patch b/queue-2.6.37/xhci-use-gfp_noio-during-device-reset.patch
new file mode 100644 (file)
index 0000000..2eb8c6c
--- /dev/null
@@ -0,0 +1,42 @@
+From a6d940dd759bf240d28624198660ed34582a327b Mon Sep 17 00:00:00 2001
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Date: Tue, 28 Dec 2010 13:08:42 -0800
+Subject: xhci: Use GFP_NOIO during device reset.
+
+From: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+commit a6d940dd759bf240d28624198660ed34582a327b upstream.
+
+When xhci_discover_or_reset_device() is called after a host controller
+power loss, the virtual device may need to be reallocated.  Make sure
+xhci_alloc_dev() uses GFP_NOIO.  This avoid causing a deadlock by allowing
+the kernel to flush pending I/O while reallocating memory for a virtual
+device for a USB mass storage device that's holding the backing store for
+dirty memory buffers.
+
+This patch should be queued for the 2.6.37 stable tree.
+
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/usb/host/xhci.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -2431,8 +2431,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd,
+               xhci_err(xhci, "Error while assigning device slot ID\n");
+               return 0;
+       }
+-      /* xhci_alloc_virt_device() does not touch rings; no need to lock */
+-      if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_KERNEL)) {
++      /* xhci_alloc_virt_device() does not touch rings; no need to lock.
++       * Use GFP_NOIO, since this function can be called from
++       * xhci_discover_or_reset_device(), which may be called as part of
++       * mass storage driver error handling.
++       */
++      if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_NOIO)) {
+               /* Disable slot, if we can do it without mem alloc */
+               xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
+               spin_lock_irqsave(&xhci->lock, flags);