Revert "xhci: replace xhci_write_64() with writeq()"

This reverts commit 7dd09a1af2.

Many xHCI host controllers can only handle 32-bit addresses, and writing
64-bits at a time causes them to fail.  Rafał reports that USB devices
simply do not enumerate, and reverting this patch helps.  Branimir
reports that his host controller doesn't respond to an Enable Slot
command and dies:

[   75.576160] xhci_hcd 0000:03:00.0: Timeout while waiting for a slot
[   88.991634] xhci_hcd 0000:03:00.0: Stopped the command ring failed, maybe the host is dead
[   88.991748] xhci_hcd 0000:03:00.0: Abort command ring failed
[   88.991845] xhci_hcd 0000:03:00.0: HC died; cleaning up
[   93.985489] xhci_hcd 0000:03:00.0: Timeout while waiting for a slot
[   93.985494] xhci_hcd 0000:03:00.0: Abort the command ring, but the xHCI is dead.
[   98.982586] xhci_hcd 0000:03:00.0: Timeout while waiting for a slot
[   98.982591] xhci_hcd 0000:03:00.0: Abort the command ring, but the xHCI is dead.
[  103.979696] xhci_hcd 0000:03:00.0: Timeout while waiting for a slot
[  103.979702] xhci_hcd 0000:03:00.0: Abort the command ring, but the xHCI is dead

Signed-off-by: Sarah Sharp <sarah.a.sharp@intel.com>
Reported-by: Rafał Miłecki <zajec5@gmail.com>
Reported-by: Branimir Maksimovic <branimir.maksimovic@gmail.com>
Cc: Xenia Ragiadakou <burzalodowa@gmail.com>
This commit is contained in:
Sarah Sharp 2014-01-29 14:02:00 -08:00
parent 140e3026a5
commit 477632dff5
4 changed files with 33 additions and 20 deletions

View File

@ -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
@ -2318,7 +2318,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
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);
@ -2399,7 +2399,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
val_64 = readq(&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);

View File

@ -313,7 +313,8 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
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
@ -2865,7 +2866,8 @@ hw_died:
* the event ring should be empty.
*/
temp_64 = readq(&xhci->ir_set->erst_dequeue);
writeq(temp_64 | ERST_EHB, &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;
@ -2892,7 +2894,7 @@ hw_died:
/* 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);

View File

@ -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);
}
@ -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);
}
/*

View File

@ -28,15 +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 */
@ -1614,6 +1605,26 @@ 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 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;