USB: xhci: Fix register write order.
The 0.95 xHCI spec says that if the xHCI HW support 64-bit addressing, you must write the whole 64-bit address as one atomic operation, or write the low 32 bits, and then the high 32 bits. I had the register writes swapped in some places. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
045f123d9c
commit
3841d56ebb
@@ -416,11 +416,11 @@ 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 = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[1]);
|
|
||||||
xhci_dbg(xhci, "ERST deq upper = 0x%x\n", temp);
|
|
||||||
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
|
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
|
||||||
temp &= ERST_PTR_MASK;
|
temp &= ERST_PTR_MASK;
|
||||||
xhci_dbg(xhci, "ERST deq = 0x%x\n", temp);
|
xhci_dbg(xhci, "ERST deq = 0x%x\n", temp);
|
||||||
|
temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[1]);
|
||||||
|
xhci_dbg(xhci, "ERST deq upper = 0x%x\n", temp);
|
||||||
|
|
||||||
temp = xhci_readl(xhci, &xhci->op_regs->command);
|
temp = xhci_readl(xhci, &xhci->op_regs->command);
|
||||||
temp |= (CMD_RUN);
|
temp |= (CMD_RUN);
|
||||||
|
@@ -475,8 +475,8 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
|||||||
if (!virt_dev->new_ep_rings[ep_index])
|
if (!virt_dev->new_ep_rings[ep_index])
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
ep_ring = virt_dev->new_ep_rings[ep_index];
|
ep_ring = virt_dev->new_ep_rings[ep_index];
|
||||||
ep_ctx->deq[1] = 0;
|
|
||||||
ep_ctx->deq[0] = ep_ring->first_seg->dma | ep_ring->cycle_state;
|
ep_ctx->deq[0] = ep_ring->first_seg->dma | ep_ring->cycle_state;
|
||||||
|
ep_ctx->deq[1] = 0;
|
||||||
|
|
||||||
ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
|
ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
|
||||||
|
|
||||||
@@ -533,8 +533,8 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
|
|||||||
|
|
||||||
ep_ctx->ep_info = 0;
|
ep_ctx->ep_info = 0;
|
||||||
ep_ctx->ep_info2 = 0;
|
ep_ctx->ep_info2 = 0;
|
||||||
ep_ctx->deq[1] = 0;
|
|
||||||
ep_ctx->deq[0] = 0;
|
ep_ctx->deq[0] = 0;
|
||||||
|
ep_ctx->deq[1] = 0;
|
||||||
ep_ctx->tx_info = 0;
|
ep_ctx->tx_info = 0;
|
||||||
/* Don't free the endpoint ring until the set interface or configuration
|
/* Don't free the endpoint ring until the set interface or configuration
|
||||||
* request succeeds.
|
* request succeeds.
|
||||||
@@ -549,10 +549,10 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||||||
|
|
||||||
/* Free the Event Ring Segment Table and the actual Event Ring */
|
/* Free the Event Ring Segment Table and the actual Event Ring */
|
||||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
|
xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
|
||||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
|
|
||||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[0]);
|
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[0]);
|
||||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
|
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
|
||||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[0]);
|
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[0]);
|
||||||
|
xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
|
||||||
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
|
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
|
||||||
if (xhci->erst.entries)
|
if (xhci->erst.entries)
|
||||||
pci_free_consistent(pdev, size,
|
pci_free_consistent(pdev, size,
|
||||||
@@ -564,8 +564,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||||||
xhci->event_ring = NULL;
|
xhci->event_ring = NULL;
|
||||||
xhci_dbg(xhci, "Freed event ring\n");
|
xhci_dbg(xhci, "Freed event ring\n");
|
||||||
|
|
||||||
xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[1]);
|
|
||||||
xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[0]);
|
xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[0]);
|
||||||
|
xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[1]);
|
||||||
if (xhci->cmd_ring)
|
if (xhci->cmd_ring)
|
||||||
xhci_ring_free(xhci, xhci->cmd_ring);
|
xhci_ring_free(xhci, xhci->cmd_ring);
|
||||||
xhci->cmd_ring = NULL;
|
xhci->cmd_ring = NULL;
|
||||||
@@ -584,8 +584,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|||||||
xhci->device_pool = NULL;
|
xhci->device_pool = NULL;
|
||||||
xhci_dbg(xhci, "Freed device context pool\n");
|
xhci_dbg(xhci, "Freed device context pool\n");
|
||||||
|
|
||||||
xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]);
|
|
||||||
xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]);
|
xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]);
|
||||||
|
xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]);
|
||||||
if (xhci->dcbaa)
|
if (xhci->dcbaa)
|
||||||
pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
|
pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
|
||||||
xhci->dcbaa, xhci->dcbaa->dma);
|
xhci->dcbaa, xhci->dcbaa->dma);
|
||||||
@@ -645,8 +645,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||||||
xhci->dcbaa->dma = dma;
|
xhci->dcbaa->dma = dma;
|
||||||
xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n",
|
xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n",
|
||||||
(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
|
(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
|
||||||
xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]);
|
|
||||||
xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]);
|
xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]);
|
||||||
|
xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the ring segment pool. The ring must be a contiguous
|
* Initialize the ring segment pool. The ring must be a contiguous
|
||||||
@@ -677,10 +677,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||||||
val = (val & ~CMD_RING_ADDR_MASK) |
|
val = (val & ~CMD_RING_ADDR_MASK) |
|
||||||
(xhci->cmd_ring->first_seg->dma & CMD_RING_ADDR_MASK) |
|
(xhci->cmd_ring->first_seg->dma & CMD_RING_ADDR_MASK) |
|
||||||
xhci->cmd_ring->cycle_state;
|
xhci->cmd_ring->cycle_state;
|
||||||
xhci_dbg(xhci, "// Setting command ring address high bits to 0x0\n");
|
|
||||||
xhci_writel(xhci, (u32) 0, &xhci->op_regs->cmd_ring[1]);
|
|
||||||
xhci_dbg(xhci, "// Setting command ring address low bits to 0x%x\n", val);
|
xhci_dbg(xhci, "// Setting command ring address low bits to 0x%x\n", val);
|
||||||
xhci_writel(xhci, val, &xhci->op_regs->cmd_ring[0]);
|
xhci_writel(xhci, val, &xhci->op_regs->cmd_ring[0]);
|
||||||
|
xhci_dbg(xhci, "// Setting command ring address high bits to 0x0\n");
|
||||||
|
xhci_writel(xhci, (u32) 0, &xhci->op_regs->cmd_ring[1]);
|
||||||
xhci_dbg_cmd_ptrs(xhci);
|
xhci_dbg_cmd_ptrs(xhci);
|
||||||
|
|
||||||
val = xhci_readl(xhci, &xhci->cap_regs->db_off);
|
val = xhci_readl(xhci, &xhci->cap_regs->db_off);
|
||||||
@@ -720,8 +720,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||||||
/* set ring base address and size for each segment table entry */
|
/* set ring base address and size for each segment table entry */
|
||||||
for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) {
|
for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) {
|
||||||
struct xhci_erst_entry *entry = &xhci->erst.entries[val];
|
struct xhci_erst_entry *entry = &xhci->erst.entries[val];
|
||||||
entry->seg_addr[1] = 0;
|
|
||||||
entry->seg_addr[0] = seg->dma;
|
entry->seg_addr[0] = seg->dma;
|
||||||
|
entry->seg_addr[1] = 0;
|
||||||
entry->seg_size = TRBS_PER_SEGMENT;
|
entry->seg_size = TRBS_PER_SEGMENT;
|
||||||
entry->rsvd = 0;
|
entry->rsvd = 0;
|
||||||
seg = seg->next;
|
seg = seg->next;
|
||||||
@@ -739,11 +739,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
|
|||||||
/* set the segment table base address */
|
/* set the segment table base address */
|
||||||
xhci_dbg(xhci, "// Set ERST base address for ir_set 0 = 0x%llx\n",
|
xhci_dbg(xhci, "// Set ERST base address for ir_set 0 = 0x%llx\n",
|
||||||
(unsigned long long)xhci->erst.erst_dma_addr);
|
(unsigned long long)xhci->erst.erst_dma_addr);
|
||||||
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
|
|
||||||
val = xhci_readl(xhci, &xhci->ir_set->erst_base[0]);
|
val = xhci_readl(xhci, &xhci->ir_set->erst_base[0]);
|
||||||
val &= ERST_PTR_MASK;
|
val &= ERST_PTR_MASK;
|
||||||
val |= (xhci->erst.erst_dma_addr & ~ERST_PTR_MASK);
|
val |= (xhci->erst.erst_dma_addr & ~ERST_PTR_MASK);
|
||||||
xhci_writel(xhci, val, &xhci->ir_set->erst_base[0]);
|
xhci_writel(xhci, val, &xhci->ir_set->erst_base[0]);
|
||||||
|
xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
|
||||||
|
|
||||||
/* Set the event ring dequeue address */
|
/* Set the event ring dequeue address */
|
||||||
set_hc_event_deq(xhci);
|
set_hc_event_deq(xhci);
|
||||||
|
Reference in New Issue
Block a user