1. 14 Jan, 2011 4 commits
    • Sarah Sharp's avatar
      usb: Realloc xHCI structures after a hub is verified. · 653a39d1
      Sarah Sharp authored
      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: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
      Cc: stable@kernel.org
      653a39d1
    • Zhang Rui's avatar
      xhci: Do not run xhci_cleanup_msix with irq disabled · 40a9fb17
      Zhang Rui authored
      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: default avatarZhang Rui <rui.zhang@intel.com>
      Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
      Cc: stable@kernel.org
      40a9fb17
    • Andiry Xu's avatar
      xHCI: synchronize irq in xhci_suspend() · 0029227f
      Andiry Xu authored
      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: default avatarMatthew Garrett <mjg@redhat.com>
      Signed-off-by: default avatarAndiry Xu <andiry.xu@amd.com>
      Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
      Cc: stable@kernel.org
      0029227f
    • Sarah Sharp's avatar
      xhci: Resume bus on any port status change. · 7111ebc9
      Sarah Sharp authored
      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: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
      Reported-by: default avatarJon 'maddog' Hall <maddog@li.org>
      Tested-by: default avatarAndiry Xu <andiry.xu@amd.com>
      Cc: stable@kernel.org
      7111ebc9
  2. 10 Jan, 2011 36 commits