aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-11 19:14:45 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-11 19:14:45 -0400
commit625816a430dcc9c5c3ed334004e0c654f2d11cb2 (patch)
treeea69bb05dc3ac1650e899f5766e4f78217824b8e
parent22c7ef0a511795a2075fba9a1b67bea95fc3a8fa (diff)
parent638298dc66ea36623dbc2757a24fc2c4ab41b016 (diff)
Merge tag 'for-usb-linus-2013-10-09' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus
Pull xhci USB fixes from Sarah: xhci: Bug fixes and quirks for 3.12 Hi Greg, Here's four patches for 3.12. The first patch is a bug fix for the USB 2.0 Link PM registers that I sent out to the list a long time ago (August), but forgot to queue up. The second and fourth patches are quirks for xHCI hosts. These patches are marked for stable. The third patch fixes a bug uncovered with sparse. Sarah Sharp
-rw-r--r--drivers/usb/host/pci-quirks.c4
-rw-r--r--drivers/usb/host/xhci-hub.c26
-rw-r--r--drivers/usb/host/xhci-pci.c25
-rw-r--r--drivers/usb/host/xhci.c14
-rw-r--r--drivers/usb/host/xhci.h2
5 files changed, 42 insertions, 29 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 2c76ef1320ea..08ef2829a7e2 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -799,7 +799,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
799 * switchable ports. 799 * switchable ports.
800 */ 800 */
801 pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 801 pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
802 cpu_to_le32(ports_available)); 802 ports_available);
803 803
804 pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 804 pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
805 &ports_available); 805 &ports_available);
@@ -821,7 +821,7 @@ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev)
821 * host. 821 * host.
822 */ 822 */
823 pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 823 pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
824 cpu_to_le32(ports_available)); 824 ports_available);
825 825
826 pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 826 pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
827 &ports_available); 827 &ports_available);
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 773a6b28c4f1..e8b4c56dcf62 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1157,18 +1157,6 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
1157 t1 = xhci_port_state_to_neutral(t1); 1157 t1 = xhci_port_state_to_neutral(t1);
1158 if (t1 != t2) 1158 if (t1 != t2)
1159 xhci_writel(xhci, t2, port_array[port_index]); 1159 xhci_writel(xhci, t2, port_array[port_index]);
1160
1161 if (hcd->speed != HCD_USB3) {
1162 /* enable remote wake up for USB 2.0 */
1163 __le32 __iomem *addr;
1164 u32 tmp;
1165
1166 /* Get the port power control register address. */
1167 addr = port_array[port_index] + PORTPMSC;
1168 tmp = xhci_readl(xhci, addr);
1169 tmp |= PORT_RWE;
1170 xhci_writel(xhci, tmp, addr);
1171 }
1172 } 1160 }
1173 hcd->state = HC_STATE_SUSPENDED; 1161 hcd->state = HC_STATE_SUSPENDED;
1174 bus_state->next_statechange = jiffies + msecs_to_jiffies(10); 1162 bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
@@ -1247,20 +1235,6 @@ int xhci_bus_resume(struct usb_hcd *hcd)
1247 xhci_ring_device(xhci, slot_id); 1235 xhci_ring_device(xhci, slot_id);
1248 } else 1236 } else
1249 xhci_writel(xhci, temp, port_array[port_index]); 1237 xhci_writel(xhci, temp, port_array[port_index]);
1250
1251 if (hcd->speed != HCD_USB3) {
1252 /* disable remote wake up for USB 2.0 */
1253 __le32 __iomem *addr;
1254 u32 tmp;
1255
1256 /* Add one to the port status register address to get
1257 * the port power control register address.
1258 */
1259 addr = port_array[port_index] + PORTPMSC;
1260 tmp = xhci_readl(xhci, addr);
1261 tmp &= ~PORT_RWE;
1262 xhci_writel(xhci, tmp, addr);
1263 }
1264 } 1238 }
1265 1239
1266 (void) xhci_readl(xhci, &xhci->op_regs->command); 1240 (void) xhci_readl(xhci, &xhci->op_regs->command);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 236c3aabe940..b8dffd59eb25 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -35,6 +35,9 @@
35#define PCI_VENDOR_ID_ETRON 0x1b6f 35#define PCI_VENDOR_ID_ETRON 0x1b6f
36#define PCI_DEVICE_ID_ASROCK_P67 0x7023 36#define PCI_DEVICE_ID_ASROCK_P67 0x7023
37 37
38#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
39#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
40
38static const char hcd_name[] = "xhci_hcd"; 41static const char hcd_name[] = "xhci_hcd";
39 42
40/* called after powerup, by probe or system-pm "wakeup" */ 43/* called after powerup, by probe or system-pm "wakeup" */
@@ -69,6 +72,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
69 "QUIRK: Fresco Logic xHC needs configure" 72 "QUIRK: Fresco Logic xHC needs configure"
70 " endpoint cmd after reset endpoint"); 73 " endpoint cmd after reset endpoint");
71 } 74 }
75 if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
76 pdev->revision == 0x4) {
77 xhci->quirks |= XHCI_SLOW_SUSPEND;
78 xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
79 "QUIRK: Fresco Logic xHC revision %u"
80 "must be suspended extra slowly",
81 pdev->revision);
82 }
72 /* Fresco Logic confirms: all revisions of this chip do not 83 /* Fresco Logic confirms: all revisions of this chip do not
73 * support MSI, even though some of them claim to in their PCI 84 * support MSI, even though some of them claim to in their PCI
74 * capabilities. 85 * capabilities.
@@ -110,6 +121,15 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
110 xhci->quirks |= XHCI_SPURIOUS_REBOOT; 121 xhci->quirks |= XHCI_SPURIOUS_REBOOT;
111 xhci->quirks |= XHCI_AVOID_BEI; 122 xhci->quirks |= XHCI_AVOID_BEI;
112 } 123 }
124 if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
125 (pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI ||
126 pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI)) {
127 /* Workaround for occasional spurious wakeups from S5 (or
128 * any other sleep) on Haswell machines with LPT and LPT-LP
129 * with the new Intel BIOS
130 */
131 xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
132 }
113 if (pdev->vendor == PCI_VENDOR_ID_ETRON && 133 if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
114 pdev->device == PCI_DEVICE_ID_ASROCK_P67) { 134 pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
115 xhci->quirks |= XHCI_RESET_ON_RESUME; 135 xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -217,6 +237,11 @@ static void xhci_pci_remove(struct pci_dev *dev)
217 usb_put_hcd(xhci->shared_hcd); 237 usb_put_hcd(xhci->shared_hcd);
218 } 238 }
219 usb_hcd_pci_remove(dev); 239 usb_hcd_pci_remove(dev);
240
241 /* Workaround for spurious wakeups at shutdown with HSW */
242 if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
243 pci_set_power_state(dev, PCI_D3hot);
244
220 kfree(xhci); 245 kfree(xhci);
221} 246}
222 247
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1e36dbb48366..6e0d886bcce5 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -730,6 +730,9 @@ void xhci_shutdown(struct usb_hcd *hcd)
730 730
731 spin_lock_irq(&xhci->lock); 731 spin_lock_irq(&xhci->lock);
732 xhci_halt(xhci); 732 xhci_halt(xhci);
733 /* Workaround for spurious wakeups at shutdown with HSW */
734 if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
735 xhci_reset(xhci);
733 spin_unlock_irq(&xhci->lock); 736 spin_unlock_irq(&xhci->lock);
734 737
735 xhci_cleanup_msix(xhci); 738 xhci_cleanup_msix(xhci);
@@ -737,6 +740,10 @@ void xhci_shutdown(struct usb_hcd *hcd)
737 xhci_dbg_trace(xhci, trace_xhci_dbg_init, 740 xhci_dbg_trace(xhci, trace_xhci_dbg_init,
738 "xhci_shutdown completed - status = %x", 741 "xhci_shutdown completed - status = %x",
739 xhci_readl(xhci, &xhci->op_regs->status)); 742 xhci_readl(xhci, &xhci->op_regs->status));
743
744 /* Yet another workaround for spurious wakeups at shutdown with HSW */
745 if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
746 pci_set_power_state(to_pci_dev(hcd->self.controller), PCI_D3hot);
740} 747}
741 748
742#ifdef CONFIG_PM 749#ifdef CONFIG_PM
@@ -839,6 +846,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
839int xhci_suspend(struct xhci_hcd *xhci) 846int xhci_suspend(struct xhci_hcd *xhci)
840{ 847{
841 int rc = 0; 848 int rc = 0;
849 unsigned int delay = XHCI_MAX_HALT_USEC;
842 struct usb_hcd *hcd = xhci_to_hcd(xhci); 850 struct usb_hcd *hcd = xhci_to_hcd(xhci);
843 u32 command; 851 u32 command;
844 852
@@ -861,8 +869,12 @@ int xhci_suspend(struct xhci_hcd *xhci)
861 command = xhci_readl(xhci, &xhci->op_regs->command); 869 command = xhci_readl(xhci, &xhci->op_regs->command);
862 command &= ~CMD_RUN; 870 command &= ~CMD_RUN;
863 xhci_writel(xhci, command, &xhci->op_regs->command); 871 xhci_writel(xhci, command, &xhci->op_regs->command);
872
873 /* Some chips from Fresco Logic need an extraordinary delay */
874 delay *= (xhci->quirks & XHCI_SLOW_SUSPEND) ? 10 : 1;
875
864 if (xhci_handshake(xhci, &xhci->op_regs->status, 876 if (xhci_handshake(xhci, &xhci->op_regs->status,
865 STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) { 877 STS_HALT, STS_HALT, delay)) {
866 xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); 878 xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n");
867 spin_unlock_irq(&xhci->lock); 879 spin_unlock_irq(&xhci->lock);
868 return -ETIMEDOUT; 880 return -ETIMEDOUT;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 289fbfbae746..941d5f59e4dc 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1548,6 +1548,8 @@ struct xhci_hcd {
1548#define XHCI_COMP_MODE_QUIRK (1 << 14) 1548#define XHCI_COMP_MODE_QUIRK (1 << 14)
1549#define XHCI_AVOID_BEI (1 << 15) 1549#define XHCI_AVOID_BEI (1 << 15)
1550#define XHCI_PLAT (1 << 16) 1550#define XHCI_PLAT (1 << 16)
1551#define XHCI_SLOW_SUSPEND (1 << 17)
1552#define XHCI_SPURIOUS_WAKEUP (1 << 18)
1551 unsigned int num_active_eps; 1553 unsigned int num_active_eps;
1552 unsigned int limit_active_eps; 1554 unsigned int limit_active_eps;
1553 /* There are two roothubs to keep track of bus suspend info for */ 1555 /* There are two roothubs to keep track of bus suspend info for */