xhci: isoc, Intel xHCI, and suspend races.

Hi Greg,
 
 Here's some xHCI fixes that should be queued for 3.5.
 
 The first patch builds on Alan Stern's 3.4 patch to close the suspend and port
 event race conditions.  It's marked for 3.4 stable, since that's where Alan's
 patch landed.  The second patch fixes an incorrect error code that the xHCI
 driver would return when an isochronous transfer error occurred.
 
 The third and fourth patches fix issues seen on Intel xHCI host controllers.
 The third patch fixes a dead port issue that was seen on the Panther Point
 EHCI/xHCI host when CONFIG_USB_XHCI_HCD was turned off.  The ports were being
 switched over to xHCI, even though the xHCI driver was never even built.  The
 fourth patch adds support for the EHCI to xHCI port switchover for the upcoming
 Intel Lynx Point chipset.
 
 As I said, there's nothing here that's terribly urgent, and these patches can
 wait a couple weeks for the 3.5 merge window.
 
 Thanks,
 Sarah Sharp
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJPounlAAoJEBMGWMLi1Gc55twQAJm/cOCW4NI3aLfW44nsc3UM
 WFSXpu8MgaNXqQJrdaFjLAlrSWob2t2uAlI+Rr178ltpu7tOFUCBgmYp8P2eQwEF
 K6wM/464SaQYIPQjxAekTRWwxAKM9eSI6CahFHn+M6nAQY8TJkUqDuE4I/EAIHgQ
 R71OYPLvEP2w5vMi+ObkGdy6PFcIbSpDQM+trgCj3MUuaX1m0kWQjIIvgCByvdxU
 twhxOL/P6WheYCyttbr0H/PsX57jRkpV4Sjr0UJ6TdDI6aB7ZWa977+IWyf3TmUc
 mvtMBU2Kv4jts8Bkzzulz0uCKbFYQ30MihXua8nwXP/sph6dnIhwr+dYhb/HPp3a
 DrEzBiqcH1ASgBX/kvZ52UjTf4aP0vuK6nS/VsQYH7a23pO4Qd3aX41lJy/bFnt+
 u/GHeFlEQ3BmxNwMMSGHQibqAK194zvGSDs2XyPnK6PQqBiMnm77DAhzOqPP1L2f
 Z3do/dOeNRTeGknJXrgc8Eq/C4HVQ+S5MsTv3GZp/PlSTe+aGAgontH9Rj11bvs3
 FJng2S/zee/IBhuWkK9wdqud5gqZbBFw7MU3cfrGH5KzdOPsRJ6+XFfuCqLzo110
 inLhytN+urvvuZspr/gCCeW+PLDaYbYK/pw1ge0UUxWrRy0IE2spjW/Q3cdq5vL1
 brPKwwF7PsPZ6IiTY5RR
 =WrEx
 -----END PGP SIGNATURE-----

Merge tag 'for-usb-next-2012-05-03' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-next

xhci: isoc, Intel xHCI, and suspend races.

Hi Greg,

Here's some xHCI fixes that should be queued for 3.5.

The first patch builds on Alan Stern's 3.4 patch to close the suspend and port
event race conditions.  It's marked for 3.4 stable, since that's where Alan's
patch landed.  The second patch fixes an incorrect error code that the xHCI
driver would return when an isochronous transfer error occurred.

The third and fourth patches fix issues seen on Intel xHCI host controllers.
The third patch fixes a dead port issue that was seen on the Panther Point
EHCI/xHCI host when CONFIG_USB_XHCI_HCD was turned off.  The ports were being
switched over to xHCI, even though the xHCI driver was never even built.  The
fourth patch adds support for the EHCI to xHCI port switchover for the upcoming
Intel Lynx Point chipset.

As I said, there's nothing here that's terribly urgent, and these patches can
wait a couple weeks for the 3.5 merge window.

Thanks,
Sarah Sharp
This commit is contained in:
Greg Kroah-Hartman 2012-05-03 13:40:55 -07:00
commit cbad67e33d
6 changed files with 60 additions and 14 deletions

View File

@ -360,7 +360,9 @@ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == 0x1E26;
(pdev->device == 0x1E26 ||
pdev->device == 0x8C2D ||
pdev->device == 0x8C26);
}
static void ehci_enable_xhci_companion(void)

View File

@ -9,6 +9,7 @@
*/
#include <linux/types.h>
#include <linux/kconfig.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
@ -712,12 +713,28 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
return -ETIMEDOUT;
}
bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31
bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI;
}
/* The Intel Lynx Point chipset also has switchable ports. */
bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI;
}
bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
{
return usb_is_intel_ppt_switchable_xhci(pdev) ||
usb_is_intel_lpt_switchable_xhci(pdev);
}
EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
/*
@ -742,6 +759,19 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
{
u32 ports_available;
/* Don't switchover the ports if the user hasn't compiled the xHCI
* driver. Otherwise they will see "dead" USB ports that don't power
* the devices.
*/
if (!IS_ENABLED(CONFIG_USB_XHCI_HCD)) {
dev_warn(&xhci_pdev->dev,
"CONFIG_USB_XHCI_HCD is turned off, "
"defaulting to EHCI.\n");
dev_warn(&xhci_pdev->dev,
"USB 3.0 devices will work at USB 2.0 speeds.\n");
return;
}
ports_available = 0xffffffff;
/* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable
* Register, to turn on SuperSpeed terminations for all

View File

@ -558,6 +558,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
xhci_dbg(xhci, "Resume USB2 port %d\n",
wIndex + 1);
bus_state->resume_done[wIndex] = 0;
clear_bit(wIndex, &bus_state->resuming_ports);
xhci_set_link_state(xhci, port_array, wIndex,
XDEV_U0);
xhci_dbg(xhci, "set port %d resume\n",
@ -845,7 +846,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
/* Initial status is no changes */
retval = (max_ports + 8) / 8;
memset(buf, 0, retval);
status = 0;
/*
* Inform the usbcore about resume-in-progress by returning
* a non-zero value even if there are no status changes.
*/
status = bus_state->resuming_ports;
mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC;
@ -885,15 +891,11 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
spin_lock_irqsave(&xhci->lock, flags);
if (hcd->self.root_hub->do_remote_wakeup) {
port_index = max_ports;
while (port_index--) {
if (bus_state->resume_done[port_index] != 0) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "suspend failed because "
"port %d is resuming\n",
port_index + 1);
return -EBUSY;
}
if (bus_state->resuming_ports) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "suspend failed because "
"a port is resuming\n");
return -EBUSY;
}
}

View File

@ -1377,6 +1377,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
xhci_dbg(xhci, "resume HS port %d\n", port_id);
bus_state->resume_done[faked_port_index] = jiffies +
msecs_to_jiffies(20);
set_bit(faked_port_index, &bus_state->resuming_ports);
mod_timer(&hcd->rh_timer,
bus_state->resume_done[faked_port_index]);
/* Do the rest in GetPortStatus */
@ -1803,6 +1804,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
break;
case COMP_DEV_ERR:
case COMP_STALL:
case COMP_TX_ERR:
frame->status = -EPROTO;
skip_td = true;
break;

View File

@ -152,7 +152,7 @@ int xhci_reset(struct xhci_hcd *xhci)
{
u32 command;
u32 state;
int ret;
int ret, i;
state = xhci_readl(xhci, &xhci->op_regs->status);
if ((state & STS_HALT) == 0) {
@ -175,7 +175,15 @@ int xhci_reset(struct xhci_hcd *xhci)
* xHCI cannot write to any doorbells or operational registers other
* than status until the "Controller Not Ready" flag is cleared.
*/
return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
for (i = 0; i < 2; ++i) {
xhci->bus_state[i].port_c_suspend = 0;
xhci->bus_state[i].suspended_ports = 0;
xhci->bus_state[i].resuming_ports = 0;
}
return ret;
}
#ifdef CONFIG_PCI

View File

@ -1362,6 +1362,8 @@ struct xhci_bus_state {
u32 suspended_ports;
u32 port_remote_wakeup;
unsigned long resume_done[USB_MAXCHILDREN];
/* which ports have started to resume */
unsigned long resuming_ports;
};
static inline unsigned int hcd_index(struct usb_hcd *hcd)