Commit 28ccd296 authored by Matt Evans's avatar Matt Evans Committed by Sarah Sharp

xhci: Make xHCI driver endian-safe

This patch changes the struct members defining access to xHCI device-visible
memory to use __le32/__le64 where appropriate, and then adds swaps where
required.  Checked with sparse that all accesses are correct.

MMIO accesses use readl/writel so already are performed LE, but prototypes
now reflect this with __le*.

There were a couple of (debug) instances of DMA pointers being truncated to
32bits which have been fixed too.
Signed-off-by: default avatarMatt Evans <matt@ozlabs.org>
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
parent 7fc2a616
......@@ -147,7 +147,7 @@ static void xhci_print_op_regs(struct xhci_hcd *xhci)
static void xhci_print_ports(struct xhci_hcd *xhci)
{
u32 __iomem *addr;
__le32 __iomem *addr;
int i, j;
int ports;
char *names[NUM_PORT_REGS] = {
......@@ -253,27 +253,27 @@ void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb)
void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
{
u64 address;
u32 type = xhci_readl(xhci, &trb->link.control) & TRB_TYPE_BITMASK;
u32 type = le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK;
switch (type) {
case TRB_TYPE(TRB_LINK):
xhci_dbg(xhci, "Link TRB:\n");
xhci_print_trb_offsets(xhci, trb);
address = trb->link.segment_ptr;
address = le64_to_cpu(trb->link.segment_ptr);
xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);
xhci_dbg(xhci, "Interrupter target = 0x%x\n",
GET_INTR_TARGET(trb->link.intr_target));
GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target)));
xhci_dbg(xhci, "Cycle bit = %u\n",
(unsigned int) (trb->link.control & TRB_CYCLE));
(unsigned int) (le32_to_cpu(trb->link.control) & TRB_CYCLE));
xhci_dbg(xhci, "Toggle cycle bit = %u\n",
(unsigned int) (trb->link.control & LINK_TOGGLE));
(unsigned int) (le32_to_cpu(trb->link.control) & LINK_TOGGLE));
xhci_dbg(xhci, "No Snoop bit = %u\n",
(unsigned int) (trb->link.control & TRB_NO_SNOOP));
(unsigned int) (le32_to_cpu(trb->link.control) & TRB_NO_SNOOP));
break;
case TRB_TYPE(TRB_TRANSFER):
address = trb->trans_event.buffer;
address = le64_to_cpu(trb->trans_event.buffer);
/*
* FIXME: look at flags to figure out if it's an address or if
* the data is directly in the buffer field.
......@@ -281,11 +281,12 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
break;
case TRB_TYPE(TRB_COMPLETION):
address = trb->event_cmd.cmd_trb;
address = le64_to_cpu(trb->event_cmd.cmd_trb);
xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
xhci_dbg(xhci, "Completion status = %u\n",
(unsigned int) GET_COMP_CODE(trb->event_cmd.status));
xhci_dbg(xhci, "Flags = 0x%x\n", (unsigned int) trb->event_cmd.flags);
(unsigned int) GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
xhci_dbg(xhci, "Flags = 0x%x\n",
(unsigned int) le32_to_cpu(trb->event_cmd.flags));
break;
default:
xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n",
......@@ -311,16 +312,16 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
{
int i;
u32 addr = (u32) seg->dma;
u64 addr = seg->dma;
union xhci_trb *trb = seg->trbs;
for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
trb = &seg->trbs[i];
xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
lower_32_bits(trb->link.segment_ptr),
upper_32_bits(trb->link.segment_ptr),
(unsigned int) trb->link.intr_target,
(unsigned int) trb->link.control);
xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr,
(u32)lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
(u32)upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
(unsigned int) le32_to_cpu(trb->link.intr_target),
(unsigned int) le32_to_cpu(trb->link.control));
addr += sizeof(*trb);
}
}
......@@ -391,18 +392,18 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
{
u32 addr = (u32) erst->erst_dma_addr;
u64 addr = erst->erst_dma_addr;
int i;
struct xhci_erst_entry *entry;
for (i = 0; i < erst->num_entries; ++i) {
entry = &erst->entries[i];
xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
(unsigned int) addr,
lower_32_bits(entry->seg_addr),
upper_32_bits(entry->seg_addr),
(unsigned int) entry->seg_size,
(unsigned int) entry->rsvd);
xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n",
addr,
lower_32_bits(le64_to_cpu(entry->seg_addr)),
upper_32_bits(le64_to_cpu(entry->seg_addr)),
(unsigned int) le32_to_cpu(entry->seg_size),
(unsigned int) le32_to_cpu(entry->rsvd));
addr += sizeof(*entry);
}
}
......@@ -436,7 +437,7 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci,
{
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
switch (GET_SLOT_STATE(slot_ctx->dev_state)) {
switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) {
case 0:
return "enabled/disabled";
case 1:
......
......@@ -50,7 +50,7 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
temp |= 0x0008;
/* Bits 6:5 - no TTs in root ports */
/* Bit 7 - no port indicators */
desc->wHubCharacteristics = (__force __u16) cpu_to_le16(temp);
desc->wHubCharacteristics = cpu_to_le16(temp);
}
/* Fill in the USB 2.0 roothub descriptor */
......@@ -314,7 +314,7 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
}
static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
u16 wIndex, u32 __iomem *addr, u32 port_status)
u16 wIndex, __le32 __iomem *addr, u32 port_status)
{
/* Don't allow the USB core to disable SuperSpeed ports. */
if (hcd->speed == HCD_USB3) {
......@@ -331,7 +331,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
}
static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
u16 wIndex, u32 __iomem *addr, u32 port_status)
u16 wIndex, __le32 __iomem *addr, u32 port_status)
{
char *port_change_bit;
u32 status;
......@@ -376,7 +376,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
unsigned long flags;
u32 temp, temp1, status;
int retval = 0;
u32 __iomem **port_array;
__le32 __iomem **port_array;
int slot_id;
struct xhci_bus_state *bus_state;
......@@ -664,7 +664,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
int i, retval;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int ports;
u32 __iomem **port_array;
__le32 __iomem **port_array;
struct xhci_bus_state *bus_state;
if (hcd->speed == HCD_USB3) {
......@@ -709,7 +709,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int max_ports, port_index;
u32 __iomem **port_array;
__le32 __iomem **port_array;
struct xhci_bus_state *bus_state;
unsigned long flags;
......@@ -779,7 +779,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
if (DEV_HIGHSPEED(t1)) {
/* enable remote wake up for USB 2.0 */
u32 __iomem *addr;
__le32 __iomem *addr;
u32 tmp;
/* Add one to the port status register address to get
......@@ -801,7 +801,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int max_ports, port_index;
u32 __iomem **port_array;
__le32 __iomem **port_array;
struct xhci_bus_state *bus_state;
u32 temp;
unsigned long flags;
......@@ -875,7 +875,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
if (DEV_HIGHSPEED(temp)) {
/* disable remote wake up for USB 2.0 */
u32 __iomem *addr;
__le32 __iomem *addr;
u32 tmp;
/* Add one to the port status register address to get
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -57,13 +57,13 @@
* @run_regs_off: RTSOFF - Runtime register space offset
*/
struct xhci_cap_regs {
u32 hc_capbase;
u32 hcs_params1;
u32 hcs_params2;
u32 hcs_params3;
u32 hcc_params;
u32 db_off;
u32 run_regs_off;
__le32 hc_capbase;
__le32 hcs_params1;
__le32 hcs_params2;
__le32 hcs_params3;
__le32 hcc_params;
__le32 db_off;
__le32 run_regs_off;
/* Reserved up to (CAPLENGTH - 0x1C) */
};
......@@ -155,26 +155,26 @@ struct xhci_cap_regs {
* devices.
*/
struct xhci_op_regs {
u32 command;
u32 status;
u32 page_size;
u32 reserved1;
u32 reserved2;
u32 dev_notification;
u64 cmd_ring;
__le32 command;
__le32 status;
__le32 page_size;
__le32 reserved1;
__le32 reserved2;
__le32 dev_notification;
__le64 cmd_ring;
/* rsvd: offset 0x20-2F */
u32 reserved3[4];
u64 dcbaa_ptr;
u32 config_reg;
__le32 reserved3[4];
__le64 dcbaa_ptr;
__le32 config_reg;
/* rsvd: offset 0x3C-3FF */
u32 reserved4[241];
__le32 reserved4[241];
/* port 1 registers, which serve as a base address for other ports */
u32 port_status_base;
u32 port_power_base;
u32 port_link_base;
u32 reserved5;
__le32 port_status_base;
__le32 port_power_base;
__le32 port_link_base;
__le32 reserved5;
/* registers for ports 2-255 */
u32 reserved6[NUM_PORT_REGS*254];
__le32 reserved6[NUM_PORT_REGS*254];
};
/* USBCMD - USB command - command bitmasks */
......@@ -382,12 +382,12 @@ struct xhci_op_regs {
* updates the dequeue pointer.
*/
struct xhci_intr_reg {
u32 irq_pending;
u32 irq_control;
u32 erst_size;
u32 rsvd;
u64 erst_base;
u64 erst_dequeue;
__le32 irq_pending;
__le32 irq_control;
__le32 erst_size;
__le32 rsvd;
__le64 erst_base;
__le64 erst_dequeue;
};
/* irq_pending bitmasks */
......@@ -432,8 +432,8 @@ struct xhci_intr_reg {
* or larger accesses"
*/
struct xhci_run_regs {
u32 microframe_index;
u32 rsvd[7];
__le32 microframe_index;
__le32 rsvd[7];
struct xhci_intr_reg ir_set[128];
};
......@@ -447,7 +447,7 @@ struct xhci_run_regs {
* Section 5.6
*/
struct xhci_doorbell_array {
u32 doorbell[256];
__le32 doorbell[256];
};
#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16))
......@@ -504,12 +504,12 @@ struct xhci_container_ctx {
* reserved at the end of the slot context for HC internal use.
*/
struct xhci_slot_ctx {
u32 dev_info;
u32 dev_info2;
u32 tt_info;
u32 dev_state;
__le32 dev_info;
__le32 dev_info2;
__le32 tt_info;
__le32 dev_state;
/* offset 0x10 to 0x1f reserved for HC internal use */
u32 reserved[4];
__le32 reserved[4];
};
/* dev_info bitmasks */
......@@ -580,12 +580,12 @@ struct xhci_slot_ctx {
* reserved at the end of the endpoint context for HC internal use.
*/
struct xhci_ep_ctx {
u32 ep_info;
u32 ep_info2;
u64 deq;
u32 tx_info;
__le32 ep_info;
__le32 ep_info2;
__le64 deq;
__le32 tx_info;
/* offset 0x14 - 0x1f reserved for HC internal use */
u32 reserved[3];
__le32 reserved[3];
};
/* ep_info bitmasks */
......@@ -660,9 +660,9 @@ struct xhci_ep_ctx {
* @add_context: set the bit of the endpoint context you want to enable
*/
struct xhci_input_control_ctx {
u32 drop_flags;
u32 add_flags;
u32 rsvd2[6];
__le32 drop_flags;
__le32 add_flags;
__le32 rsvd2[6];
};
/* Represents everything that is needed to issue a command on the command ring.
......@@ -688,9 +688,9 @@ struct xhci_command {
struct xhci_stream_ctx {
/* 64-bit stream ring address, cycle state, and stream type */
u64 stream_ring;
__le64 stream_ring;
/* offset 0x14 - 0x1f reserved for HC internal use */
u32 reserved[2];
__le32 reserved[2];
};
/* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */
......@@ -803,7 +803,7 @@ struct xhci_virt_device {
*/
struct xhci_device_context_array {
/* 64-bit device addresses; we only write 32-bit addresses */
u64 dev_context_ptrs[MAX_HC_SLOTS];
__le64 dev_context_ptrs[MAX_HC_SLOTS];
/* private xHCD pointers */
dma_addr_t dma;
};
......@@ -816,10 +816,10 @@ struct xhci_device_context_array {
struct xhci_transfer_event {
/* 64-bit buffer address, or immediate data */
u64 buffer;
u32 transfer_len;
__le64 buffer;
__le32 transfer_len;
/* This field is interpreted differently based on the type of TRB */
u32 flags;
__le32 flags;
};
/** Transfer Event bit fields **/
......@@ -898,9 +898,9 @@ struct xhci_transfer_event {
struct xhci_link_trb {
/* 64-bit segment pointer*/
u64 segment_ptr;
u32 intr_target;
u32 control;
__le64 segment_ptr;
__le32 intr_target;
__le32 control;
};
/* control bitfields */
......@@ -909,9 +909,9 @@ struct xhci_link_trb {
/* Command completion event TRB */
struct xhci_event_cmd {
/* Pointer to command TRB, or the value passed by the event data trb */
u64 cmd_trb;
u32 status;
u32 flags;
__le64 cmd_trb;
__le32 status;
__le32 flags;
};
/* flags bitmasks */
......@@ -970,7 +970,7 @@ struct xhci_event_cmd {
#define TRB_SIA (1<<31)
struct xhci_generic_trb {
u32 field[4];
__le32 field[4];
};
union xhci_trb {
......@@ -1118,10 +1118,10 @@ struct xhci_ring {
struct xhci_erst_entry {
/* 64-bit event ring segment address */
u64 seg_addr;
u32 seg_size;
__le64 seg_addr;
__le32 seg_size;
/* Set to zero */
u32 rsvd;
__le32 rsvd;
};
struct xhci_erst {
......@@ -1286,10 +1286,10 @@ struct xhci_hcd {
/* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
u8 *port_array;
/* Array of pointers to USB 3.0 PORTSC registers */
u32 __iomem **usb3_ports;
__le32 __iomem **usb3_ports;
unsigned int num_usb3_ports;
/* Array of pointers to USB 2.0 PORTSC registers */
u32 __iomem **usb2_ports;
__le32 __iomem **usb2_ports;
unsigned int num_usb2_ports;
};
......@@ -1322,12 +1322,12 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
/* TODO: copied from ehci.h - can be refactored? */
/* xHCI spec says all registers are little endian */
static inline unsigned int xhci_readl(const struct xhci_hcd *xhci,
__u32 __iomem *regs)
__le32 __iomem *regs)
{
return readl(regs);
}
static inline void xhci_writel(struct xhci_hcd *xhci,
const unsigned int val, __u32 __iomem *regs)
const unsigned int val, __le32 __iomem *regs)
{
xhci_dbg(xhci,
"`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
......@@ -1345,7 +1345,7 @@ static inline void xhci_writel(struct xhci_hcd *xhci,
* the high dword, and write order is irrelevant.
*/
static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
__u64 __iomem *regs)
__le64 __iomem *regs)
{
__u32 __iomem *ptr = (__u32 __iomem *) regs;
u64 val_lo = readl(ptr);
......@@ -1353,7 +1353,7 @@ static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
return val_lo + (val_hi << 32);
}
static inline void xhci_write_64(struct xhci_hcd *xhci,
const u64 val, __u64 __iomem *regs)
const u64 val, __le64 __iomem *regs)
{
__u32 __iomem *ptr = (__u32 __iomem *) regs;
u32 val_lo = lower_32_bits(val);
......
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