mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
xhci: Fix some regressions introduced in 3.14.
Hi Greg, Here's four patches for 3.14. One of them adds an xHCI host quirk, and the other three of them fix regressions introduced in 3.14. One regression causes USB 3.0 Link PM to be enabled on all xHCI hosts (even those that may not support it), which causes some USB 3.0 devices to not enumerate. A second regression causes some xHCI hosts that don't support 64-bit addressing to stop responding to commands and die. Note, these patches don't fix the recent usbfs regression that was caused by commit35773dac5f
"usb: xhci: Link TRB must not occur within a USB payload burst". I'm waiting for those patches to be tested. Please pull usb-linus into usb-next, as I have feature patches that rely on140e3026a5
Revert "usbcore: set lpm_capable field for LPM capable root hubs" Sarah Sharp -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJS8UyYAAoJEBMGWMLi1Gc5G9AP/jTLQoh/9ILE3fPN9UeXHr7x TR3sWrB2JB6HzO53FJqoIWdnyei+GQRHRYKFZbJRMIXSdfI7EiJ9ZaFvGKYkOjyg FblD2WqYn5jY2yiW8roxOebDzDadxxqafwtrqIGx88sV9o9yKInhBq5NqxD1ZC/X QM9Dbgxed4TX6OVVE8hvUbzr1gldYiUr8rKfvN8X6RDBEi6wh6HV0B/7T96vw6Hp hFDIgIdwgVYsnah2QjS007tpNFfWQtoi3sq+Jcq0S6QVpCrTPjPB6MqHJM/MQtG+ 8JkmZRPA8jjwaPvow8Kx3bmt89H5Q/hWKlUPZmaShOO4OKN3xOQNh+FNbvqs1pPZ XpL3/dv/w/zzQ7sqD2IaT9HiDfzeYfspdiv9QsSJg7XlfiulgdCggrhIGvta6p51 bR0JEHMxSuI/Aqe/fr5Prf4YyeWS+fDKIwRsaNXG143pd7hFJxoyT91QE3FCxAdD qmw/YdeDT7J+3TB55OCPIxuaOTEjJQ9GyKXP/TKaSrTVWcH8/N0wNMa7IPSplysN fgeNNDtZ0A7P4XyyMNxaQpbRcM39eV/yGaVR6yDqjJ4RlEZTTTOMfNSaVoCXIb74 3km6DVSqEQ0xPq08nrIcWbPqor+hShbw/bbUJCQBITKJp6oDeImacCvZw7RaYhfs cx7UuQPKmv7iYaG1Vmcm =sPwW -----END PGP SIGNATURE----- Merge tag 'for-usb-linus-2014-02-04' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-linus Sarah writes: xhci: Fix some regressions introduced in 3.14. Hi Greg, Here's four patches for 3.14. One of them adds an xHCI host quirk, and the other three of them fix regressions introduced in 3.14. One regression causes USB 3.0 Link PM to be enabled on all xHCI hosts (even those that may not support it), which causes some USB 3.0 devices to not enumerate. A second regression causes some xHCI hosts that don't support 64-bit addressing to stop responding to commands and die. Note, these patches don't fix the recent usbfs regression that was caused by commit35773dac5f
"usb: xhci: Link TRB must not occur within a USB payload burst". I'm waiting for those patches to be tested. Please pull usb-linus into usb-next, as I have feature patches that rely on140e3026a5
Revert "usbcore: set lpm_capable field for LPM capable root hubs" Sarah Sharp
This commit is contained in:
commit
5c2740280f
9 changed files with 62 additions and 45 deletions
|
@ -1032,7 +1032,6 @@ static int register_root_hub(struct usb_hcd *hcd)
|
|||
dev_name(&usb_dev->dev), retval);
|
||||
return retval;
|
||||
}
|
||||
usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);
|
||||
}
|
||||
|
||||
retval = usb_new_device (usb_dev);
|
||||
|
|
|
@ -128,7 +128,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
|
|||
return usb_get_intfdata(hdev->actconfig->interface[0]);
|
||||
}
|
||||
|
||||
int usb_device_supports_lpm(struct usb_device *udev)
|
||||
static int usb_device_supports_lpm(struct usb_device *udev)
|
||||
{
|
||||
/* USB 2.1 (and greater) devices indicate LPM support through
|
||||
* their USB 2.0 Extended Capabilities BOS descriptor.
|
||||
|
@ -149,11 +149,6 @@ int usb_device_supports_lpm(struct usb_device *udev)
|
|||
"Power management will be impacted.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* udev is root hub */
|
||||
if (!udev->parent)
|
||||
return 1;
|
||||
|
||||
if (udev->parent->lpm_capable)
|
||||
return 1;
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
|
|||
unsigned int size);
|
||||
extern int usb_get_bos_descriptor(struct usb_device *dev);
|
||||
extern void usb_release_bos_descriptor(struct usb_device *dev);
|
||||
extern int usb_device_supports_lpm(struct usb_device *udev);
|
||||
extern char *usb_cache_string(struct usb_device *udev, int index);
|
||||
extern int usb_set_configuration(struct usb_device *dev, int configuration);
|
||||
extern int usb_choose_configuration(struct usb_device *udev);
|
||||
|
|
|
@ -203,12 +203,12 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num)
|
|||
addr, (unsigned int)temp);
|
||||
|
||||
addr = &ir_set->erst_base;
|
||||
temp_64 = readq(addr);
|
||||
temp_64 = xhci_read_64(xhci, addr);
|
||||
xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n",
|
||||
addr, temp_64);
|
||||
|
||||
addr = &ir_set->erst_dequeue;
|
||||
temp_64 = readq(addr);
|
||||
temp_64 = xhci_read_64(xhci, addr);
|
||||
xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n",
|
||||
addr, temp_64);
|
||||
}
|
||||
|
@ -412,7 +412,7 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
|
|||
{
|
||||
u64 val;
|
||||
|
||||
val = readq(&xhci->op_regs->cmd_ring);
|
||||
val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
|
||||
xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
|
||||
lower_32_bits(val));
|
||||
xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n",
|
||||
|
|
|
@ -1958,7 +1958,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
|
|||
xhci_warn(xhci, "WARN something wrong with SW event ring "
|
||||
"dequeue ptr.\n");
|
||||
/* Update HC event ring dequeue pointer */
|
||||
temp = readq(&xhci->ir_set->erst_dequeue);
|
||||
temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
temp &= ERST_PTR_MASK;
|
||||
/* Don't clear the EHB bit (which is RW1C) because
|
||||
* there might be more events to service.
|
||||
|
@ -1967,7 +1967,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
|
|||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"// Write event ring dequeue pointer, "
|
||||
"preserving EHB bit");
|
||||
writeq(((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
|
||||
xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
|
||||
&xhci->ir_set->erst_dequeue);
|
||||
}
|
||||
|
||||
|
@ -2269,7 +2269,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"// Device context base array address = 0x%llx (DMA), %p (virt)",
|
||||
(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
|
||||
writeq(dma, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
|
||||
|
||||
/*
|
||||
* Initialize the ring segment pool. The ring must be a contiguous
|
||||
|
@ -2312,13 +2312,13 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
(unsigned long long)xhci->cmd_ring->first_seg->dma);
|
||||
|
||||
/* Set the address in the Command Ring Control register */
|
||||
val_64 = readq(&xhci->op_regs->cmd_ring);
|
||||
val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
|
||||
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
|
||||
(xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
|
||||
xhci->cmd_ring->cycle_state;
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"// Setting command ring address to 0x%x", val);
|
||||
writeq(val_64, &xhci->op_regs->cmd_ring);
|
||||
xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
|
||||
xhci_dbg_cmd_ptrs(xhci);
|
||||
|
||||
xhci->lpm_command = xhci_alloc_command(xhci, true, true, flags);
|
||||
|
@ -2396,10 +2396,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"// Set ERST base address for ir_set 0 = 0x%llx",
|
||||
(unsigned long long)xhci->erst.erst_dma_addr);
|
||||
val_64 = readq(&xhci->ir_set->erst_base);
|
||||
val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base);
|
||||
val_64 &= ERST_PTR_MASK;
|
||||
val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK);
|
||||
writeq(val_64, &xhci->ir_set->erst_base);
|
||||
xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);
|
||||
|
||||
/* Set the event ring dequeue address */
|
||||
xhci_set_hc_event_deq(xhci);
|
||||
|
|
|
@ -142,6 +142,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
|||
"QUIRK: Resetting on resume");
|
||||
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
|
||||
}
|
||||
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
|
||||
pdev->device == 0x0015 &&
|
||||
pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG &&
|
||||
pdev->subsystem_device == 0xc0cd)
|
||||
xhci->quirks |= XHCI_RESET_ON_RESUME;
|
||||
if (pdev->vendor == PCI_VENDOR_ID_VIA)
|
||||
xhci->quirks |= XHCI_RESET_ON_RESUME;
|
||||
}
|
||||
|
|
|
@ -307,13 +307,14 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
|
|||
return 0;
|
||||
}
|
||||
|
||||
temp_64 = readq(&xhci->op_regs->cmd_ring);
|
||||
temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
|
||||
if (!(temp_64 & CMD_RING_RUNNING)) {
|
||||
xhci_dbg(xhci, "Command ring had been stopped\n");
|
||||
return 0;
|
||||
}
|
||||
xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
|
||||
writeq(temp_64 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);
|
||||
xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
|
||||
&xhci->op_regs->cmd_ring);
|
||||
|
||||
/* Section 4.6.1.2 of xHCI 1.0 spec says software should
|
||||
* time the completion od all xHCI commands, including
|
||||
|
@ -2864,8 +2865,9 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
|
|||
/* Clear the event handler busy flag (RW1C);
|
||||
* the event ring should be empty.
|
||||
*/
|
||||
temp_64 = readq(&xhci->ir_set->erst_dequeue);
|
||||
writeq(temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
|
||||
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
xhci_write_64(xhci, temp_64 | ERST_EHB,
|
||||
&xhci->ir_set->erst_dequeue);
|
||||
spin_unlock(&xhci->lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -2877,7 +2879,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
|
|||
*/
|
||||
while (xhci_handle_event(xhci) > 0) {}
|
||||
|
||||
temp_64 = readq(&xhci->ir_set->erst_dequeue);
|
||||
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
/* If necessary, update the HW's version of the event ring deq ptr. */
|
||||
if (event_ring_deq != xhci->event_ring->dequeue) {
|
||||
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
|
||||
|
@ -2892,7 +2894,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
|
|||
|
||||
/* Clear the event handler busy flag (RW1C); event ring is empty. */
|
||||
temp_64 |= ERST_EHB;
|
||||
writeq(temp_64, &xhci->ir_set->erst_dequeue);
|
||||
xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
|
||||
|
||||
spin_unlock(&xhci->lock);
|
||||
|
||||
|
|
|
@ -611,7 +611,7 @@ int xhci_run(struct usb_hcd *hcd)
|
|||
xhci_dbg(xhci, "Event ring:\n");
|
||||
xhci_debug_ring(xhci, xhci->event_ring);
|
||||
xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
|
||||
temp_64 = readq(&xhci->ir_set->erst_dequeue);
|
||||
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
temp_64 &= ~ERST_PTR_MASK;
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"ERST deq = 64'h%0lx", (long unsigned int) temp_64);
|
||||
|
@ -756,11 +756,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci)
|
|||
{
|
||||
xhci->s3.command = readl(&xhci->op_regs->command);
|
||||
xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification);
|
||||
xhci->s3.dcbaa_ptr = readq(&xhci->op_regs->dcbaa_ptr);
|
||||
xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci->s3.config_reg = readl(&xhci->op_regs->config_reg);
|
||||
xhci->s3.erst_size = readl(&xhci->ir_set->erst_size);
|
||||
xhci->s3.erst_base = readq(&xhci->ir_set->erst_base);
|
||||
xhci->s3.erst_dequeue = readq(&xhci->ir_set->erst_dequeue);
|
||||
xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
|
||||
xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
|
||||
xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending);
|
||||
xhci->s3.irq_control = readl(&xhci->ir_set->irq_control);
|
||||
}
|
||||
|
@ -769,11 +769,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)
|
|||
{
|
||||
writel(xhci->s3.command, &xhci->op_regs->command);
|
||||
writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
|
||||
writeq(xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
|
||||
writel(xhci->s3.config_reg, &xhci->op_regs->config_reg);
|
||||
writel(xhci->s3.erst_size, &xhci->ir_set->erst_size);
|
||||
writeq(xhci->s3.erst_base, &xhci->ir_set->erst_base);
|
||||
writeq(xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
|
||||
xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
|
||||
xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
|
||||
writel(xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
|
||||
writel(xhci->s3.irq_control, &xhci->ir_set->irq_control);
|
||||
}
|
||||
|
@ -783,7 +783,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
|
|||
u64 val_64;
|
||||
|
||||
/* step 2: initialize command ring buffer */
|
||||
val_64 = readq(&xhci->op_regs->cmd_ring);
|
||||
val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
|
||||
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
|
||||
(xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
|
||||
xhci->cmd_ring->dequeue) &
|
||||
|
@ -792,7 +792,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
|
|||
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
|
||||
"// Setting command ring address to 0x%llx",
|
||||
(long unsigned long) val_64);
|
||||
writeq(val_64, &xhci->op_regs->cmd_ring);
|
||||
xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3842,7 +3842,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
|
|||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
temp_64 = readq(&xhci->op_regs->dcbaa_ptr);
|
||||
temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
|
||||
"Op regs DCBAA ptr = %#016llx", temp_64);
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
|
||||
|
|
|
@ -28,17 +28,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/usb/hcd.h>
|
||||
|
||||
/*
|
||||
* Registers should always be accessed with double word or quad word accesses.
|
||||
*
|
||||
* Some xHCI implementations may support 64-bit address pointers. Registers
|
||||
* with 64-bit address pointers should be written to with dword accesses by
|
||||
* writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
|
||||
* xHCI implementations that do not support 64-bit address pointers will ignore
|
||||
* the high dword, and write order is irrelevant.
|
||||
*/
|
||||
#include <asm-generic/io-64-nonatomic-lo-hi.h>
|
||||
|
||||
/* Code sharing between pci-quirks and xhci hcd */
|
||||
#include "xhci-ext-caps.h"
|
||||
#include "pci-quirks.h"
|
||||
|
@ -1614,6 +1603,34 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
|
|||
#define xhci_warn_ratelimited(xhci, fmt, args...) \
|
||||
dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
|
||||
|
||||
/*
|
||||
* Registers should always be accessed with double word or quad word accesses.
|
||||
*
|
||||
* Some xHCI implementations may support 64-bit address pointers. Registers
|
||||
* with 64-bit address pointers should be written to with dword accesses by
|
||||
* writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
|
||||
* xHCI implementations that do not support 64-bit address pointers will ignore
|
||||
* the high dword, and write order is irrelevant.
|
||||
*/
|
||||
static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
|
||||
__le64 __iomem *regs)
|
||||
{
|
||||
__u32 __iomem *ptr = (__u32 __iomem *) regs;
|
||||
u64 val_lo = readl(ptr);
|
||||
u64 val_hi = readl(ptr + 1);
|
||||
return val_lo + (val_hi << 32);
|
||||
}
|
||||
static inline void xhci_write_64(struct xhci_hcd *xhci,
|
||||
const u64 val, __le64 __iomem *regs)
|
||||
{
|
||||
__u32 __iomem *ptr = (__u32 __iomem *) regs;
|
||||
u32 val_lo = lower_32_bits(val);
|
||||
u32 val_hi = upper_32_bits(val);
|
||||
|
||||
writel(val_lo, ptr);
|
||||
writel(val_hi, ptr + 1);
|
||||
}
|
||||
|
||||
static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
|
||||
{
|
||||
return xhci->quirks & XHCI_LINK_TRB_QUIRK;
|
||||
|
|
Loading…
Reference in a new issue