From c1b0edff8337841b7f99116f6cb77d6e007caf90 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 15 Feb 2011 12:48:03 -0800 Subject: [PATCH] .37 patches --- ...rt-has-an-address-before-enabling-it.patch | 85 +++++++++ ...bind-to-function-0-of-the-pci-device.patch | 45 +++++ ...-on-when-actually-configuring-a-mode.patch | 53 ++++++ queue-2.6.37/series | 8 + ...i-structures-after-a-hub-is-verified.patch | 73 ++++++++ ...-xhci_cleanup_msix-with-irq-disabled.patch | 88 +++++++++ ...resume-bus-on-any-port-status-change.patch | 53 ++++++ ...xhci-synchronize-irq-in-xhci_suspend.patch | 169 ++++++++++++++++++ ...hci-use-gfp_noio-during-device-reset.patch | 42 +++++ 9 files changed, 616 insertions(+) create mode 100644 queue-2.6.37/agp-ensure-gart-has-an-address-before-enabling-it.patch create mode 100644 queue-2.6.37/drm-i915-only-bind-to-function-0-of-the-pci-device.patch create mode 100644 queue-2.6.37/drm-only-set-dpms-on-when-actually-configuring-a-mode.patch create mode 100644 queue-2.6.37/usb-realloc-xhci-structures-after-a-hub-is-verified.patch create mode 100644 queue-2.6.37/xhci-do-not-run-xhci_cleanup_msix-with-irq-disabled.patch create mode 100644 queue-2.6.37/xhci-resume-bus-on-any-port-status-change.patch create mode 100644 queue-2.6.37/xhci-synchronize-irq-in-xhci_suspend.patch create mode 100644 queue-2.6.37/xhci-use-gfp_noio-during-device-reset.patch 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 index 00000000000..a5958ad0252 --- /dev/null +++ b/queue-2.6.37/agp-ensure-gart-has-an-address-before-enabling-it.patch @@ -0,0 +1,85 @@ +From a70b95c017e8b518e1e069853355e4e497453dbb Mon Sep 17 00:00:00 2001 +From: Stephen Kitt +Date: Mon, 31 Jan 2011 14:25:43 -0800 +Subject: agp: ensure GART has an address before enabling it + +From: Stephen Kitt + +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 +Cc: Bjorn Helgaas +Cc: Maciej Rutecki +Cc: "Rafael J. Wysocki" +Cc: Kulikov Vasiliy +Cc: Florian Mickler +Signed-off-by: Andrew Morton +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..caf51e56a3f --- /dev/null +++ b/queue-2.6.37/drm-i915-only-bind-to-function-0-of-the-pci-device.patch @@ -0,0 +1,45 @@ +From 5fe49d86f9d01044abf687a8cd21edef636d58aa Mon Sep 17 00:00:00 2001 +From: Chris Wilson +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 + +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 +Tested-by: Ferenc Wágner +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=28012 +Signed-off-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d06e51c0840 --- /dev/null +++ b/queue-2.6.37/drm-only-set-dpms-on-when-actually-configuring-a-mode.patch @@ -0,0 +1,53 @@ +From 811aaa55ba21ab37407018cfc01770d6b037d3fb Mon Sep 17 00:00:00 2001 +From: Keith Packard +Date: Thu, 3 Feb 2011 16:57:28 -0800 +Subject: drm: Only set DPMS ON when actually configuring a mode + +From: Keith Packard + +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 +Reported-and-tested-by: Carlos R. Mafra +Tested-by: Takashi Iwai +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-2.6.37/series b/queue-2.6.37/series index 3b71fea4707..399fd8576ac 100644 --- a/queue-2.6.37/series +++ b/queue-2.6.37/series @@ -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 index 00000000000..225c698211f --- /dev/null +++ b/queue-2.6.37/usb-realloc-xhci-structures-after-a-hub-is-verified.patch @@ -0,0 +1,73 @@ +From 653a39d1f61bdc9f277766736d21d2e9be0391cb Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Thu, 23 Dec 2010 11:12:42 -0800 +Subject: usb: Realloc xHCI structures after a hub is verified. + +From: Sarah Sharp + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..f25d2707ce2 --- /dev/null +++ b/queue-2.6.37/xhci-do-not-run-xhci_cleanup_msix-with-irq-disabled.patch @@ -0,0 +1,88 @@ +From 40a9fb17f32dbe54de3d636142a59288544deed7 Mon Sep 17 00:00:00 2001 +From: Zhang Rui +Date: Fri, 17 Dec 2010 13:17:04 -0800 +Subject: xhci: Do not run xhci_cleanup_msix with irq disabled + +From: Zhang Rui + +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] [] __might_sleep+0xeb/0xf0 +[ 134.882921] [] mutex_lock+0x24/0x50 +[ 134.884229] [] free_desc+0x2e/0x5f +[ 134.885538] [] irq_free_descs+0x3b/0x71 +[ 134.886853] [] free_irq_at+0x31/0x36 +[ 134.888167] [] destroy_irq+0x69/0x71 +[ 134.889486] [] native_teardown_msi_irq+0xe/0x10 +[ 134.890820] [] default_teardown_msi_irqs+0x57/0x80 +[ 134.892158] [] free_msi_irqs+0x8b/0xe9 +[ 134.893504] [] pci_disable_msix+0x35/0x39 +[ 134.894844] [] xhci_cleanup_msix+0x31/0x51 [xhci_hcd] +[ 134.896186] [] xhci_stop+0x3a/0x80 [xhci_hcd] +[ 134.897521] [] usb_remove_hcd+0xfd/0x14a +[ 134.898859] [] usb_hcd_pci_remove+0x5c/0xc6 +[ 134.900193] [] pci_device_remove+0x3f/0x91 +[ 134.901535] [] __device_release_driver+0x83/0xd9 +[ 134.902899] [] driver_detach+0x86/0xad +[ 134.904222] [] bus_remove_driver+0xb2/0xd8 +[ 134.905540] [] driver_unregister+0x6c/0x74 +[ 134.906839] [] pci_unregister_driver+0x44/0x89 +[ 134.908121] [] xhci_unregister_pci+0x15/0x17 [xhci_hcd] +[ 134.909396] [] xhci_hcd_cleanup+0xe/0x10 [xhci_hcd] +[ 134.910652] [] sys_delete_module+0x1ca/0x23b +[ 134.911882] [] ? path_put+0x22/0x26 +[ 134.913104] [] ? audit_syscall_entry+0x2c/0x148 +[ 134.914333] [] 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 +Signed-off-by: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7edbac542dc --- /dev/null +++ b/queue-2.6.37/xhci-resume-bus-on-any-port-status-change.patch @@ -0,0 +1,53 @@ +From 7111ebc97ed53a32314011c85a6f235f0dab8ae8 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Tue, 14 Dec 2010 13:24:55 -0800 +Subject: xhci: Resume bus on any port status change. + +From: Sarah Sharp + +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 +Reported-by: Jon 'maddog' Hall +Tested-by: Andiry Xu +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..bba3e90e9b9 --- /dev/null +++ b/queue-2.6.37/xhci-synchronize-irq-in-xhci_suspend.patch @@ -0,0 +1,169 @@ +From 0029227f1bc30b6c809ae751f9e7af6cef900997 Mon Sep 17 00:00:00 2001 +From: Andiry Xu +Date: Mon, 27 Dec 2010 17:39:02 +0800 +Subject: xHCI: synchronize irq in xhci_suspend() + +From: Andiry Xu + +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 +Signed-off-by: Andiry Xu +Signed-off-by: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..2eb8c6cc6da --- /dev/null +++ b/queue-2.6.37/xhci-use-gfp_noio-during-device-reset.patch @@ -0,0 +1,42 @@ +From a6d940dd759bf240d28624198660ed34582a327b Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Tue, 28 Dec 2010 13:08:42 -0800 +Subject: xhci: Use GFP_NOIO during device reset. + +From: Sarah Sharp + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); -- 2.47.3