diff options
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 38 |
1 files changed, 11 insertions, 27 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3e5dc0723a8f..f3b5e6345858 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -144,7 +144,7 @@ static void next_trb(struct xhci_hcd *xhci, struct xhci_segment **seg, union xhci_trb **trb) { - if (trb_is_link(*trb)) { + if (trb_is_link(*trb) || last_trb_on_seg(*seg, *trb)) { *seg = (*seg)->next; *trb = ((*seg)->trbs); } else { @@ -450,8 +450,9 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) * In the future we should distinguish between -ENODEV and -ETIMEDOUT * and try to recover a -ETIMEDOUT with a host controller reset. */ - ret = xhci_handshake(&xhci->op_regs->cmd_ring, - CMD_RING_RUNNING, 0, 5 * 1000 * 1000); + ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring, + CMD_RING_RUNNING, 0, 5 * 1000 * 1000, + XHCI_STATE_REMOVING); if (ret < 0) { xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret); xhci_halt(xhci); @@ -1879,7 +1880,6 @@ static void handle_port_status(struct xhci_hcd *xhci, if ((port_id <= 0) || (port_id > max_ports)) { xhci_warn(xhci, "Port change event with invalid port ID %d\n", port_id); - inc_deq(xhci, ir->event_ring); return; } @@ -1906,7 +1906,7 @@ static void handle_port_status(struct xhci_hcd *xhci, xhci_dbg(xhci, "Port change event, %d-%d, id %d, portsc: 0x%x\n", hcd->self.busnum, hcd_portnum + 1, port_id, portsc); - trace_xhci_handle_port_status(hcd_portnum, portsc); + trace_xhci_handle_port_status(port, portsc); if (hcd->state == HC_STATE_SUSPENDED) { xhci_dbg(xhci, "resume root hub\n"); @@ -2007,8 +2007,6 @@ static void handle_port_status(struct xhci_hcd *xhci, } cleanup: - /* Update event ring dequeue pointer before dropping the lock */ - inc_deq(xhci, ir->event_ring); /* Don't make the USB core poll the roothub if we got a bad port status * change event. Besides, at that point we can't tell which roothub @@ -2884,13 +2882,6 @@ cleanup: trb_comp_code != COMP_MISSED_SERVICE_ERROR && trb_comp_code != COMP_NO_PING_RESPONSE_ERROR; - /* - * Do not update event ring dequeue pointer if we're in a loop - * processing missed tds. - */ - if (!handling_skipped_tds) - inc_deq(xhci, ir->event_ring); - /* * If ep->skip is set, it means there are missed tds on the * endpoint ring need to take care of. @@ -2922,9 +2913,7 @@ err_out: static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir) { union xhci_trb *event; - int update_ptrs = 1; u32 trb_type; - int ret; /* Event ring hasn't been allocated yet. */ if (!ir || !ir->event_ring || !ir->event_ring->dequeue) { @@ -2954,12 +2943,9 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir) break; case TRB_PORT_STATUS: handle_port_status(xhci, ir, event); - update_ptrs = 0; break; case TRB_TRANSFER: - ret = handle_tx_event(xhci, ir, &event->trans_event); - if (ret >= 0) - update_ptrs = 0; + handle_tx_event(xhci, ir, &event->trans_event); break; case TRB_DEV_NOTE: handle_device_notification(xhci, event); @@ -2979,9 +2965,8 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir) return 0; } - if (update_ptrs) - /* Update SW event ring dequeue pointer */ - inc_deq(xhci, ir->event_ring); + /* Update SW event ring dequeue pointer */ + inc_deq(xhci, ir->event_ring); /* Are there more items on the event ring? Caller will call us again to * check. @@ -3013,13 +2998,12 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, * Per 4.9.4, Software writes to the ERDP register shall * always advance the Event Ring Dequeue Pointer value. */ - if ((temp_64 & (u64) ~ERST_PTR_MASK) == - ((u64) deq & (u64) ~ERST_PTR_MASK)) + if ((temp_64 & ERST_PTR_MASK) == (deq & ERST_PTR_MASK)) return; /* Update HC event ring dequeue pointer */ - temp_64 &= ERST_DESI_MASK; - temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); + temp_64 = ir->event_ring->deq_seg->num & ERST_DESI_MASK; + temp_64 |= deq & ERST_PTR_MASK; } /* Clear the event handler busy flag (RW1C) */ |