Commit e8b37332 authored by Xenia Ragiadakou's avatar Xenia Ragiadakou Committed by Sarah Sharp

xhci: replace xhci_read_64() with readq()

Function xhci_read_64() is used to read 64bit xHC registers residing in MMIO.
On 32bit systems, xHC registers need to be read with 32bit accesses by
reading first the lower 32bits and then the higher 32bits.

Replace all calls to xhci_read_64() with calls to readq() and include
asm-generic/io-64-nonatomic-lo-hi.h header file, so that if the system
is not 64bit, readq() will read registers in 32bit chunks with low-high order.

This is done to reduce code duplication since 64bit low-high read logic
is already implemented and to take advantage of inherent "atomic" 64bit
read operations on 64bit systems.
Signed-off-by: default avatarXenia Ragiadakou <burzalodowa@gmail.com>
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
parent 204b7793
...@@ -203,12 +203,12 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num) ...@@ -203,12 +203,12 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, int set_num)
addr, (unsigned int)temp); addr, (unsigned int)temp);
addr = &ir_set->erst_base; addr = &ir_set->erst_base;
temp_64 = xhci_read_64(xhci, addr); temp_64 = readq(addr);
xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n", xhci_dbg(xhci, " %p: ir_set.erst_base = @%08llx\n",
addr, temp_64); addr, temp_64);
addr = &ir_set->erst_dequeue; addr = &ir_set->erst_dequeue;
temp_64 = xhci_read_64(xhci, addr); temp_64 = readq(addr);
xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n", xhci_dbg(xhci, " %p: ir_set.erst_dequeue = @%08llx\n",
addr, temp_64); addr, temp_64);
} }
...@@ -412,7 +412,7 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci) ...@@ -412,7 +412,7 @@ void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
{ {
u64 val; u64 val;
val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); val = readq(&xhci->op_regs->cmd_ring);
xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n", xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
lower_32_bits(val)); lower_32_bits(val));
xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n", 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) ...@@ -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 " xhci_warn(xhci, "WARN something wrong with SW event ring "
"dequeue ptr.\n"); "dequeue ptr.\n");
/* Update HC event ring dequeue pointer */ /* Update HC event ring dequeue pointer */
temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp = readq(&xhci->ir_set->erst_dequeue);
temp &= ERST_PTR_MASK; temp &= ERST_PTR_MASK;
/* Don't clear the EHB bit (which is RW1C) because /* Don't clear the EHB bit (which is RW1C) because
* there might be more events to service. * there might be more events to service.
...@@ -2312,7 +2312,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ...@@ -2312,7 +2312,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
(unsigned long long)xhci->cmd_ring->first_seg->dma); (unsigned long long)xhci->cmd_ring->first_seg->dma);
/* Set the address in the Command Ring Control register */ /* Set the address in the Command Ring Control register */
val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); val_64 = readq(&xhci->op_regs->cmd_ring);
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
(xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) | (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
xhci->cmd_ring->cycle_state; xhci->cmd_ring->cycle_state;
...@@ -2396,7 +2396,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) ...@@ -2396,7 +2396,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci_dbg_trace(xhci, trace_xhci_dbg_init, xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Set ERST base address for ir_set 0 = 0x%llx", "// Set ERST base address for ir_set 0 = 0x%llx",
(unsigned long long)xhci->erst.erst_dma_addr); (unsigned long long)xhci->erst.erst_dma_addr);
val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base); val_64 = readq(&xhci->ir_set->erst_base);
val_64 &= ERST_PTR_MASK; val_64 &= ERST_PTR_MASK;
val_64 |= (xhci->erst.erst_dma_addr & (u64) ~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); xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);
......
...@@ -313,7 +313,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) ...@@ -313,7 +313,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
return 0; return 0;
} }
temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); temp_64 = readq(&xhci->op_regs->cmd_ring);
if (!(temp_64 & CMD_RING_RUNNING)) { if (!(temp_64 & CMD_RING_RUNNING)) {
xhci_dbg(xhci, "Command ring had been stopped\n"); xhci_dbg(xhci, "Command ring had been stopped\n");
return 0; return 0;
...@@ -2871,7 +2871,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) ...@@ -2871,7 +2871,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
/* Clear the event handler busy flag (RW1C); /* Clear the event handler busy flag (RW1C);
* the event ring should be empty. * the event ring should be empty.
*/ */
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp_64 = readq(&xhci->ir_set->erst_dequeue);
xhci_write_64(xhci, temp_64 | ERST_EHB, xhci_write_64(xhci, temp_64 | ERST_EHB,
&xhci->ir_set->erst_dequeue); &xhci->ir_set->erst_dequeue);
spin_unlock(&xhci->lock); spin_unlock(&xhci->lock);
...@@ -2885,7 +2885,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) ...@@ -2885,7 +2885,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
*/ */
while (xhci_handle_event(xhci) > 0) {} while (xhci_handle_event(xhci) > 0) {}
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp_64 = readq(&xhci->ir_set->erst_dequeue);
/* If necessary, update the HW's version of the event ring deq ptr. */ /* If necessary, update the HW's version of the event ring deq ptr. */
if (event_ring_deq != xhci->event_ring->dequeue) { if (event_ring_deq != xhci->event_ring->dequeue) {
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
......
...@@ -604,7 +604,7 @@ int xhci_run(struct usb_hcd *hcd) ...@@ -604,7 +604,7 @@ int xhci_run(struct usb_hcd *hcd)
xhci_dbg(xhci, "Event ring:\n"); xhci_dbg(xhci, "Event ring:\n");
xhci_debug_ring(xhci, xhci->event_ring); xhci_debug_ring(xhci, xhci->event_ring);
xhci_dbg_ring_ptrs(xhci, xhci->event_ring); xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); temp_64 = readq(&xhci->ir_set->erst_dequeue);
temp_64 &= ~ERST_PTR_MASK; temp_64 &= ~ERST_PTR_MASK;
xhci_dbg_trace(xhci, trace_xhci_dbg_init, xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"ERST deq = 64'h%0lx", (long unsigned int) temp_64); "ERST deq = 64'h%0lx", (long unsigned int) temp_64);
...@@ -749,11 +749,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci) ...@@ -749,11 +749,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci)
{ {
xhci->s3.command = readl(&xhci->op_regs->command); xhci->s3.command = readl(&xhci->op_regs->command);
xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification); xhci->s3.dev_nt = readl(&xhci->op_regs->dev_notification);
xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); xhci->s3.dcbaa_ptr = readq(&xhci->op_regs->dcbaa_ptr);
xhci->s3.config_reg = readl(&xhci->op_regs->config_reg); xhci->s3.config_reg = readl(&xhci->op_regs->config_reg);
xhci->s3.erst_size = readl(&xhci->ir_set->erst_size); xhci->s3.erst_size = readl(&xhci->ir_set->erst_size);
xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base); xhci->s3.erst_base = readq(&xhci->ir_set->erst_base);
xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); xhci->s3.erst_dequeue = readq(&xhci->ir_set->erst_dequeue);
xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending); xhci->s3.irq_pending = readl(&xhci->ir_set->irq_pending);
xhci->s3.irq_control = readl(&xhci->ir_set->irq_control); xhci->s3.irq_control = readl(&xhci->ir_set->irq_control);
} }
...@@ -776,7 +776,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci) ...@@ -776,7 +776,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
u64 val_64; u64 val_64;
/* step 2: initialize command ring buffer */ /* step 2: initialize command ring buffer */
val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); val_64 = readq(&xhci->op_regs->cmd_ring);
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
(xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
xhci->cmd_ring->dequeue) & xhci->cmd_ring->dequeue) &
...@@ -3832,7 +3832,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -3832,7 +3832,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
if (ret) { if (ret) {
return ret; return ret;
} }
temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr); temp_64 = readq(&xhci->op_regs->dcbaa_ptr);
xhci_dbg_trace(xhci, trace_xhci_dbg_address, xhci_dbg_trace(xhci, trace_xhci_dbg_address,
"Op regs DCBAA ptr = %#016llx", temp_64); "Op regs DCBAA ptr = %#016llx", temp_64);
xhci_dbg_trace(xhci, trace_xhci_dbg_address, xhci_dbg_trace(xhci, trace_xhci_dbg_address,
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/usb/hcd.h> #include <linux/usb/hcd.h>
#include <asm-generic/io-64-nonatomic-lo-hi.h>
/* Code sharing between pci-quirks and xhci hcd */ /* Code sharing between pci-quirks and xhci hcd */
#include "xhci-ext-caps.h" #include "xhci-ext-caps.h"
#include "pci-quirks.h" #include "pci-quirks.h"
...@@ -1604,14 +1606,6 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) ...@@ -1604,14 +1606,6 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
* xHCI implementations that do not support 64-bit address pointers will ignore * xHCI implementations that do not support 64-bit address pointers will ignore
* the high dword, and write order is irrelevant. * 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, static inline void xhci_write_64(struct xhci_hcd *xhci,
const u64 val, __le64 __iomem *regs) const u64 val, __le64 __iomem *regs)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment