From 477632dff5c7deaa165701f441e9a4bd33e22b18 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 29 Jan 2014 14:02:00 -0800 Subject: Revert "xhci: replace xhci_write_64() with writeq()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7dd09a1af2c7150269350aaa567a11b06e831003. 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 Reported-by: Rafał Miłecki Reported-by: Branimir Maksimovic Cc: Xenia Ragiadakou --- drivers/usb/host/xhci-mem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/usb/host/xhci-mem.c') diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 873c272b3ef5..4b87026f8a5a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -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); -- cgit v1.2.3 From f7b2e4032d52deff480e0c303fbd9180276f8dfc Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Thu, 30 Jan 2014 13:27:49 -0800 Subject: Revert "xhci: replace xhci_read_64() with readq()" This reverts commit e8b373326d8efcaf9ec1da8b618556c89bd5ffc4. Many xHCI host controllers can only handle 32-bit addresses, and writing 64-bits at a time causes them to fail. Reading 64-bits at a time may also cause them to return 0xffffffff, so revert this commit as well. Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-dbg.c | 6 +++--- drivers/usb/host/xhci-mem.c | 6 +++--- drivers/usb/host/xhci-ring.c | 6 +++--- drivers/usb/host/xhci.c | 12 ++++++------ drivers/usb/host/xhci.h | 10 ++++++++-- 5 files changed, 23 insertions(+), 17 deletions(-) (limited to 'drivers/usb/host/xhci-mem.c') diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index b016d38199f2..eb009a457fb5 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -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", diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 4b87026f8a5a..bce4391a0e7d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -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. @@ -2312,7 +2312,7 @@ 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; @@ -2396,7 +2396,7 @@ 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); xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index e19fae964f76..909b32a4412f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -307,7 +307,7 @@ 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; @@ -2865,7 +2865,7 @@ hw_died: /* Clear the event handler busy flag (RW1C); * the event ring should be empty. */ - temp_64 = readq(&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); @@ -2879,7 +2879,7 @@ hw_died: */ 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, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ebbe52cafaa1..3712359d18ba 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -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); } @@ -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) & @@ -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, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 60def15d129c..9154fd6cf24c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -28,8 +28,6 @@ #include #include -#include - /* Code sharing between pci-quirks and xhci hcd */ #include "xhci-ext-caps.h" #include "pci-quirks.h" @@ -1614,6 +1612,14 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) * 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) { -- cgit v1.2.3