From 543eb12ecd91df324554b8abc8d52e965bd4922b Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 21 Jul 2020 10:46:02 +0200 Subject: [PATCH 1/4] usb: xhci: Add missing endian conversions (cpu_to_leXX / leXX_to_cpu) While trying to use the U-Boot xHCI driver on the MIPS Octeon platform, which is big endian, I noticed that the driver is missing a few endian conversion calls. This patch adds these missing endian conversion calls. Signed-off-by: Stefan Roese Reviewed-by: Bin Meng Tested-by: Bin Meng Cc: Bin Meng Cc: Marek Vasut --- drivers/usb/host/xhci-mem.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 108f4bd8cf..2c92c53808 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -110,7 +110,7 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl) ctrl->dcbaa->dev_context_ptrs[0] = 0; - free((void *)(uintptr_t)ctrl->scratchpad->sp_array[0]); + free((void *)(uintptr_t)le64_to_cpu(ctrl->scratchpad->sp_array[0])); free(ctrl->scratchpad->sp_array); free(ctrl->scratchpad); ctrl->scratchpad = NULL; @@ -227,7 +227,8 @@ static void xhci_link_segments(struct xhci_segment *prev, prev->next = next; if (link_trbs) { val_64 = (uintptr_t)next->trbs; - prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = val_64; + prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = + cpu_to_le64(val_64); /* * Set the last TRB in the segment to @@ -491,7 +492,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes); /* Point to output device context in dcbaa. */ - ctrl->dcbaa->dev_context_ptrs[slot_id] = byte_64; + ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64); xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[slot_id], sizeof(__le64)); @@ -773,7 +774,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, debug("route string %x\n", route); #endif - slot_ctx->dev_info |= route; + slot_ctx->dev_info |= cpu_to_le32(route); switch (speed) { case USB_SPEED_SUPER: From 61a1acb55e8e1da71c1c9a0046942b4a945e444c Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 21 Jul 2020 10:46:03 +0200 Subject: [PATCH 2/4] usb: xhci: xhci_mem_init: Use cpu_to_le64() and not xhci_writeq() xhci_writeq() makes the CPU->LE swapping only when addressing registers in the xHCI controller address range and not in the local memory (RAM). We need to use cpu_to_le64() here to ensure that the conversion is done correctly. Signed-off-by: Stefan Roese Reviewed-by: Bin Meng Tested-by: Bin Meng Cc: Bin Meng Cc: Marek Vasut --- drivers/usb/host/xhci-mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 2c92c53808..bf60a9c256 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -567,7 +567,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, trb_64 = 0; trb_64 = (uintptr_t)seg->trbs; struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; - xhci_writeq(&entry->seg_addr, trb_64); + entry->seg_addr = cpu_to_le64(trb_64); entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); entry->rsvd = 0; seg = seg->next; From d96f6e1c0b49eb94f78b662e828e557ba943ee54 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 21 Jul 2020 10:46:04 +0200 Subject: [PATCH 3/4] usb: usb-uclass.c: Drop le16_to_cpu() as values are already swapped These values are already swapped to CPU endianess, so swapping them again is a bug. Let's remove the swap here instead. Signed-off-by: Stefan Roese Reviewed-by: Bin Meng Tested-by: Bin Meng Cc: Bin Meng Cc: Marek Vasut --- drivers/usb/host/usb-uclass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index f42c0625cb..e5dda79b94 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -416,21 +416,21 @@ static int usb_match_device(const struct usb_device_descriptor *desc, const struct usb_device_id *id) { if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && - id->idVendor != le16_to_cpu(desc->idVendor)) + id->idVendor != desc->idVendor) return 0; if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && - id->idProduct != le16_to_cpu(desc->idProduct)) + id->idProduct != desc->idProduct) return 0; /* No need to test id->bcdDevice_lo != 0, since 0 is never greater than any unsigned number. */ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && - (id->bcdDevice_lo > le16_to_cpu(desc->bcdDevice))) + (id->bcdDevice_lo > desc->bcdDevice)) return 0; if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && - (id->bcdDevice_hi < le16_to_cpu(desc->bcdDevice))) + (id->bcdDevice_hi < desc->bcdDevice)) return 0; if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && From b5152a653d36c67a34b54c4c1e9eb182e7e5b9d6 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 21 Jul 2020 10:46:05 +0200 Subject: [PATCH 4/4] usb: xhci: Add virt_to_phys() to support mapped platforms Some platforms, like MIPS Octeon, use mapped addresses (virtual address != physical address). On these platforms we need to make sure, that the local virtual addresses are converted to physical (DMA) addresses for the xHCI controller. This patch adds the missing virt_to_phys() calls, so that the correct addresses are used. Signed-off-by: Stefan Roese Reviewed-by: Bin Meng Tested-by: Bin Meng Cc: Bin Meng Cc: Marek Vasut --- drivers/usb/host/xhci-mem.c | 19 +++++++++---------- drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 3 +-- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index bf60a9c256..1da0524aa0 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -226,7 +226,7 @@ static void xhci_link_segments(struct xhci_segment *prev, return; prev->next = next; if (link_trbs) { - val_64 = (uintptr_t)next->trbs; + val_64 = virt_to_phys(next->trbs); prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = cpu_to_le64(val_64); @@ -489,7 +489,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id) /* Allocate endpoint 0 ring */ virt_dev->eps[0].ring = xhci_ring_alloc(1, true); - byte_64 = (uintptr_t)(virt_dev->out_ctx->bytes); + byte_64 = virt_to_phys(virt_dev->out_ctx->bytes); /* Point to output device context in dcbaa. */ ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64); @@ -514,7 +514,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, uint64_t val_64; uint64_t trb_64; uint32_t val; - unsigned long deq; + uint64_t deq; int i; struct xhci_segment *seg; @@ -526,7 +526,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, return -ENOMEM; } - val_64 = (uintptr_t)ctrl->dcbaa; + val_64 = virt_to_phys(ctrl->dcbaa); /* Set the pointer in DCBAA register */ xhci_writeq(&hcor->or_dcbaap, val_64); @@ -534,7 +534,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, ctrl->cmd_ring = xhci_ring_alloc(1, true); /* Set the address in the Command Ring Control register */ - trb_64 = (uintptr_t)ctrl->cmd_ring->first_seg->trbs; + trb_64 = virt_to_phys(ctrl->cmd_ring->first_seg->trbs); val_64 = xhci_readq(&hcor->or_crcr); val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) | (trb_64 & (u64) ~CMD_RING_RSVD_BITS) | @@ -564,8 +564,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, for (val = 0, seg = ctrl->event_ring->first_seg; val < ERST_NUM_SEGS; val++) { - trb_64 = 0; - trb_64 = (uintptr_t)seg->trbs; + trb_64 = virt_to_phys(seg->trbs); struct xhci_erst_entry *entry = &ctrl->erst.entries[val]; entry->seg_addr = cpu_to_le64(trb_64); entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT); @@ -575,7 +574,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, xhci_flush_cache((uintptr_t)ctrl->erst.entries, ERST_NUM_SEGS * sizeof(struct xhci_erst_entry)); - deq = (unsigned long)ctrl->event_ring->dequeue; + deq = virt_to_phys(ctrl->event_ring->dequeue); /* Update HC event ring dequeue pointer */ xhci_writeq(&ctrl->ir_set->erst_dequeue, @@ -590,7 +589,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr, /* this is the event ring segment table pointer */ val_64 = xhci_readq(&ctrl->ir_set->erst_base); val_64 &= ERST_PTR_MASK; - val_64 |= ((uintptr_t)(ctrl->erst.entries) & ~ERST_PTR_MASK); + val_64 |= virt_to_phys(ctrl->erst.entries) & ~ERST_PTR_MASK; xhci_writeq(&ctrl->ir_set->erst_base, val_64); @@ -858,7 +857,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, cpu_to_le32(((0 & MAX_BURST_MASK) << MAX_BURST_SHIFT) | ((3 & ERROR_COUNT_MASK) << ERROR_COUNT_SHIFT)); - trb_64 = (uintptr_t)virt_dev->eps[0].ring->first_seg->trbs; + trb_64 = virt_to_phys(virt_dev->eps[0].ring->first_seg->trbs); ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state); /* diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 86aeaab412..092ed6eaf1 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -275,7 +275,7 @@ void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, u32 slot_id, u32 ep_index, trb_type cmd) { u32 fields[4]; - u64 val_64 = (uintptr_t)ptr; + u64 val_64 = virt_to_phys(ptr); BUG_ON(prepare_ring(ctrl, ctrl->cmd_ring, EP_STATE_RUNNING)); @@ -399,7 +399,7 @@ void xhci_acknowledge_event(struct xhci_ctrl *ctrl) /* Inform the hardware */ xhci_writeq(&ctrl->ir_set->erst_dequeue, - (uintptr_t)ctrl->event_ring->dequeue | ERST_EHB); + virt_to_phys(ctrl->event_ring->dequeue) | ERST_EHB); } /** @@ -577,7 +577,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, u64 addr; int ret; u32 trb_fields[4]; - u64 val_64 = (uintptr_t)buffer; + u64 val_64 = virt_to_phys(buffer); debug("dev=%p, pipe=%lx, buffer=%p, length=%d\n", udev, pipe, buffer, length); @@ -876,7 +876,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, if (length > 0) { if (req->requesttype & USB_DIR_IN) field |= TRB_DIR_IN; - buf_64 = (uintptr_t)buffer; + buf_64 = virt_to_phys(buffer); trb_fields[0] = lower_32_bits(buf_64); trb_fields[1] = upper_32_bits(buf_64); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f635bb39f6..126dabc11b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -631,8 +631,7 @@ static int xhci_set_configuration(struct usb_device *udev) cpu_to_le32(MAX_BURST(max_burst) | ERROR_COUNT(err_count)); - trb_64 = (uintptr_t) - virt_dev->eps[ep_index].ring->enqueue; + trb_64 = virt_to_phys(virt_dev->eps[ep_index].ring->enqueue); ep_ctx[ep_index]->deq = cpu_to_le64(trb_64 | virt_dev->eps[ep_index].ring->cycle_state);