Skip to content

Commit 7dd09a1

Browse files
elbeastoSarah Sharp
authored andcommitted
xhci: replace xhci_write_64() with writeq()
Function xhci_write_64() is used to write 64bit xHC registers residing in MMIO. On 32bit systems, xHC registers need to be written with 32bit accesses by writing first the lower 32bits and then the higher 32bits. The header file asm-generic/io-64-nonatomic-lo-hi.h ensures that on 32bit systems writeq() will will write 64bit registers in 32bit chunks with low-high order. Replace all calls to xhci_write_64() with calls to writeq(). This is done to reduce code duplication since 64bit low-high write logic is already implemented and to take advantage of inherent "atomic" 64bit write operations on 64bit systems. Signed-off-by: Xenia Ragiadakou <[email protected]> Signed-off-by: Sarah Sharp <[email protected]>
1 parent e8b3733 commit 7dd09a1

File tree

4 files changed

+20
-33
lines changed

4 files changed

+20
-33
lines changed

drivers/usb/host/xhci-mem.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,7 +1967,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
19671967
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
19681968
"// Write event ring dequeue pointer, "
19691969
"preserving EHB bit");
1970-
xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
1970+
writeq(((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
19711971
&xhci->ir_set->erst_dequeue);
19721972
}
19731973

@@ -2269,7 +2269,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
22692269
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
22702270
"// Device context base array address = 0x%llx (DMA), %p (virt)",
22712271
(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
2272-
xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
2272+
writeq(dma, &xhci->op_regs->dcbaa_ptr);
22732273

22742274
/*
22752275
* 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)
23182318
xhci->cmd_ring->cycle_state;
23192319
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
23202320
"// Setting command ring address to 0x%x", val);
2321-
xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
2321+
writeq(val_64, &xhci->op_regs->cmd_ring);
23222322
xhci_dbg_cmd_ptrs(xhci);
23232323

23242324
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)
23992399
val_64 = readq(&xhci->ir_set->erst_base);
24002400
val_64 &= ERST_PTR_MASK;
24012401
val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK);
2402-
xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);
2402+
writeq(val_64, &xhci->ir_set->erst_base);
24032403

24042404
/* Set the event ring dequeue address */
24052405
xhci_set_hc_event_deq(xhci);

drivers/usb/host/xhci-ring.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
319319
return 0;
320320
}
321321
xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
322-
xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
323-
&xhci->op_regs->cmd_ring);
322+
writeq(temp_64 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);
324323

325324
/* Section 4.6.1.2 of xHCI 1.0 spec says software should
326325
* time the completion od all xHCI commands, including
@@ -2872,8 +2871,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
28722871
* the event ring should be empty.
28732872
*/
28742873
temp_64 = readq(&xhci->ir_set->erst_dequeue);
2875-
xhci_write_64(xhci, temp_64 | ERST_EHB,
2876-
&xhci->ir_set->erst_dequeue);
2874+
writeq(temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
28772875
spin_unlock(&xhci->lock);
28782876

28792877
return IRQ_HANDLED;
@@ -2900,7 +2898,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
29002898

29012899
/* Clear the event handler busy flag (RW1C); event ring is empty. */
29022900
temp_64 |= ERST_EHB;
2903-
xhci_write_64(xhci, temp_64, &xhci->ir_set->erst_dequeue);
2901+
writeq(temp_64, &xhci->ir_set->erst_dequeue);
29042902

29052903
spin_unlock(&xhci->lock);
29062904

drivers/usb/host/xhci.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -762,11 +762,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)
762762
{
763763
writel(xhci->s3.command, &xhci->op_regs->command);
764764
writel(xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
765-
xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
765+
writeq(xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
766766
writel(xhci->s3.config_reg, &xhci->op_regs->config_reg);
767767
writel(xhci->s3.erst_size, &xhci->ir_set->erst_size);
768-
xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
769-
xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
768+
writeq(xhci->s3.erst_base, &xhci->ir_set->erst_base);
769+
writeq(xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
770770
writel(xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
771771
writel(xhci->s3.irq_control, &xhci->ir_set->irq_control);
772772
}
@@ -785,7 +785,7 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
785785
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
786786
"// Setting command ring address to 0x%llx",
787787
(long unsigned long) val_64);
788-
xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
788+
writeq(val_64, &xhci->op_regs->cmd_ring);
789789
}
790790

791791
/*

drivers/usb/host/xhci.h

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@
2828
#include <linux/kernel.h>
2929
#include <linux/usb/hcd.h>
3030

31+
/*
32+
* Registers should always be accessed with double word or quad word accesses.
33+
*
34+
* Some xHCI implementations may support 64-bit address pointers. Registers
35+
* with 64-bit address pointers should be written to with dword accesses by
36+
* writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
37+
* xHCI implementations that do not support 64-bit address pointers will ignore
38+
* the high dword, and write order is irrelevant.
39+
*/
3140
#include <asm-generic/io-64-nonatomic-lo-hi.h>
3241

3342
/* Code sharing between pci-quirks and xhci hcd */
@@ -1597,26 +1606,6 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
15971606
#define xhci_warn_ratelimited(xhci, fmt, args...) \
15981607
dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
15991608

1600-
/*
1601-
* Registers should always be accessed with double word or quad word accesses.
1602-
*
1603-
* Some xHCI implementations may support 64-bit address pointers. Registers
1604-
* with 64-bit address pointers should be written to with dword accesses by
1605-
* writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
1606-
* xHCI implementations that do not support 64-bit address pointers will ignore
1607-
* the high dword, and write order is irrelevant.
1608-
*/
1609-
static inline void xhci_write_64(struct xhci_hcd *xhci,
1610-
const u64 val, __le64 __iomem *regs)
1611-
{
1612-
__u32 __iomem *ptr = (__u32 __iomem *) regs;
1613-
u32 val_lo = lower_32_bits(val);
1614-
u32 val_hi = upper_32_bits(val);
1615-
1616-
writel(val_lo, ptr);
1617-
writel(val_hi, ptr + 1);
1618-
}
1619-
16201609
static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
16211610
{
16221611
return xhci->quirks & XHCI_LINK_TRB_QUIRK;

0 commit comments

Comments
 (0)