]> git.ipfire.org Git - thirdparty/linux.git/blobdiff - drivers/usb/host/xhci-ring.c
Merge tag 'usb-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[thirdparty/linux.git] / drivers / usb / host / xhci-ring.c
index 4f64b814d4aa20fdd08e349e5c07324b3e105c5e..52278afea94be01b9f05c71fffaca9d3da98c936 100644 (file)
@@ -113,6 +113,12 @@ static bool last_td_in_urb(struct xhci_td *td)
        return urb_priv->num_tds_done == urb_priv->num_tds;
 }
 
+static bool unhandled_event_trb(struct xhci_ring *ring)
+{
+       return ((le32_to_cpu(ring->dequeue->event_cmd.flags) & TRB_CYCLE) ==
+               ring->cycle_state);
+}
+
 static void inc_td_cnt(struct urb *urb)
 {
        struct urb_priv *urb_priv = urb->hcpriv;
@@ -1154,6 +1160,15 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
                                break;
                        ep->ep_state &= ~EP_STOP_CMD_PENDING;
                        return;
+               case EP_STATE_STOPPED:
+                       /*
+                        * NEC uPD720200 sometimes sets this state and fails with
+                        * Context Error while continuing to process TRBs.
+                        * Be conservative and trust EP_CTX_STATE on other chips.
+                        */
+                       if (!(xhci->quirks & XHCI_NEC_HOST))
+                               break;
+                       fallthrough;
                case EP_STATE_RUNNING:
                        /* Race, HW handled stop ep cmd before ep was running */
                        xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n");
@@ -1870,7 +1885,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
        u32 port_id;
        u32 portsc, cmd_reg;
        int max_ports;
-       int slot_id;
        unsigned int hcd_portnum;
        struct xhci_bus_state *bus_state;
        bool bogus_port_status = false;
@@ -1922,9 +1936,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
 
        if (hcd->speed >= HCD_USB3 &&
            (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) {
-               slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
-               if (slot_id && xhci->devs[slot_id])
-                       xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR;
+               if (port->slot_id && xhci->devs[port->slot_id])
+                       xhci->devs[port->slot_id]->flags |= VDEV_PORT_ERROR;
        }
 
        if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
@@ -1982,9 +1995,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
                 * so the roothub behavior is consistent with external
                 * USB 3.0 hub behavior.
                 */
-               slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
-               if (slot_id && xhci->devs[slot_id])
-                       xhci_ring_device(xhci, slot_id);
+               if (port->slot_id && xhci->devs[port->slot_id])
+                       xhci_ring_device(xhci, port->slot_id);
                if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) {
                        xhci_test_and_clear_bit(xhci, port, PORT_PLC);
                        usb_wakeup_notification(hcd->self.root_hub,
@@ -2816,7 +2828,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                        td_num--;
 
                /* Is this a TRB in the currently executing TD? */
-               ep_seg = trb_in_td(xhci, ep_ring->deq_seg, ep_ring->dequeue,
+               ep_seg = trb_in_td(xhci, td->start_seg, td->first_trb,
                                td->last_trb, ep_trb_dma, false);
 
                /*
@@ -2884,9 +2896,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                                        "part of current TD ep_index %d "
                                        "comp_code %u\n", ep_index,
                                        trb_comp_code);
-                               trb_in_td(xhci, ep_ring->deq_seg,
-                                         ep_ring->dequeue, td->last_trb,
-                                         ep_trb_dma, true);
+                               trb_in_td(xhci, td->start_seg, td->first_trb,
+                                         td->last_trb, ep_trb_dma, true);
                                return -ESHUTDOWN;
                        }
                }
@@ -2962,32 +2973,18 @@ err_out:
 }
 
 /*
- * This function handles all OS-owned events on the event ring.  It may drop
+ * This function handles one OS-owned event on the event ring. It may drop
  * xhci->lock between event processing (e.g. to pass up port status changes).
- * Returns >0 for "possibly more events to process" (caller should call again),
- * otherwise 0 if done.  In future, <0 returns should indicate error code.
  */
-static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
+static int xhci_handle_event_trb(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
+                                union xhci_trb *event)
 {
-       union xhci_trb *event;
        u32 trb_type;
 
-       /* Event ring hasn't been allocated yet. */
-       if (!ir || !ir->event_ring || !ir->event_ring->dequeue) {
-               xhci_err(xhci, "ERROR interrupter not ready\n");
-               return -ENOMEM;
-       }
-
-       event = ir->event_ring->dequeue;
-       /* Does the HC or OS own the TRB? */
-       if ((le32_to_cpu(event->event_cmd.flags) & TRB_CYCLE) !=
-           ir->event_ring->cycle_state)
-               return 0;
-
        trace_xhci_handle_event(ir->event_ring, &event->generic);
 
        /*
-        * Barrier between reading the TRB_CYCLE (valid) flag above and any
+        * Barrier between reading the TRB_CYCLE (valid) flag before, and any
         * speculative reads of the event's flags/data below.
         */
        rmb();
@@ -3017,18 +3014,11 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
         * to make sure a watchdog timer didn't mark the host as non-responsive.
         */
        if (xhci->xhc_state & XHCI_STATE_DYING) {
-               xhci_dbg(xhci, "xHCI host dying, returning from "
-                               "event handler.\n");
-               return 0;
+               xhci_dbg(xhci, "xHCI host dying, returning from event handler.\n");
+               return -ENODEV;
        }
 
-       /* 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.
-        */
-       return 1;
+       return 0;
 }
 
 /*
@@ -3038,30 +3028,26 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
  */
 static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
                                     struct xhci_interrupter *ir,
-                                    union xhci_trb *event_ring_deq,
                                     bool clear_ehb)
 {
        u64 temp_64;
        dma_addr_t deq;
 
        temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
-       /* If necessary, update the HW's version of the event ring deq ptr. */
-       if (event_ring_deq != ir->event_ring->dequeue) {
-               deq = xhci_trb_virt_to_dma(ir->event_ring->deq_seg,
-                               ir->event_ring->dequeue);
-               if (deq == 0)
-                       xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n");
-               /*
-                * Per 4.9.4, Software writes to the ERDP register shall
-                * always advance the Event Ring Dequeue Pointer value.
-                */
-               if ((temp_64 & ERST_PTR_MASK) == (deq & ERST_PTR_MASK))
-                       return;
+       deq = xhci_trb_virt_to_dma(ir->event_ring->deq_seg,
+                                  ir->event_ring->dequeue);
+       if (deq == 0)
+               xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n");
+       /*
+        * Per 4.9.4, Software writes to the ERDP register shall always advance
+        * the Event Ring Dequeue Pointer value.
+        */
+       if ((temp_64 & ERST_PTR_MASK) == (deq & ERST_PTR_MASK) && !clear_ehb)
+               return;
 
-               /* Update HC event ring dequeue pointer */
-               temp_64 = ir->event_ring->deq_seg->num & ERST_DESI_MASK;
-               temp_64 |= deq & ERST_PTR_MASK;
-       }
+       /* Update HC event ring dequeue pointer */
+       temp_64 = ir->event_ring->deq_seg->num & ERST_DESI_MASK;
+       temp_64 |= deq & ERST_PTR_MASK;
 
        /* Clear the event handler busy flag (RW1C) */
        if (clear_ehb)
@@ -3069,6 +3055,76 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
        xhci_write_64(xhci, temp_64, &ir->ir_set->erst_dequeue);
 }
 
+/* Clear the interrupt pending bit for a specific interrupter. */
+static void xhci_clear_interrupt_pending(struct xhci_hcd *xhci,
+                                        struct xhci_interrupter *ir)
+{
+       if (!ir->ip_autoclear) {
+               u32 irq_pending;
+
+               irq_pending = readl(&ir->ir_set->irq_pending);
+               irq_pending |= IMAN_IP;
+               writel(irq_pending, &ir->ir_set->irq_pending);
+       }
+}
+
+/*
+ * Handle all OS-owned events on an interrupter event ring. It may drop
+ * and reaquire xhci->lock between event processing.
+ */
+static int xhci_handle_events(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
+{
+       int event_loop = 0;
+       int err;
+       u64 temp;
+
+       xhci_clear_interrupt_pending(xhci, ir);
+
+       /* Event ring hasn't been allocated yet. */
+       if (!ir->event_ring || !ir->event_ring->dequeue) {
+               xhci_err(xhci, "ERROR interrupter event ring not ready\n");
+               return -ENOMEM;
+       }
+
+       if (xhci->xhc_state & XHCI_STATE_DYING ||
+           xhci->xhc_state & XHCI_STATE_HALTED) {
+               xhci_dbg(xhci, "xHCI dying, ignoring interrupt. Shouldn't IRQs be disabled?\n");
+
+               /* Clear the event handler busy flag (RW1C) */
+               temp = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
+               xhci_write_64(xhci, temp | ERST_EHB, &ir->ir_set->erst_dequeue);
+               return -ENODEV;
+       }
+
+       /* Process all OS owned event TRBs on this event ring */
+       while (unhandled_event_trb(ir->event_ring)) {
+               err = xhci_handle_event_trb(xhci, ir, ir->event_ring->dequeue);
+
+               /*
+                * If half a segment of events have been handled in one go then
+                * update ERDP, and force isoc trbs to interrupt more often
+                */
+               if (event_loop++ > TRBS_PER_SEGMENT / 2) {
+                       xhci_update_erst_dequeue(xhci, ir, false);
+
+                       if (ir->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
+                               ir->isoc_bei_interval = ir->isoc_bei_interval / 2;
+
+                       event_loop = 0;
+               }
+
+               /* Update SW event ring dequeue pointer */
+               inc_deq(xhci, ir->event_ring);
+
+               if (err)
+                       break;
+       }
+
+       xhci_update_erst_dequeue(xhci, ir, true);
+
+       return 0;
+}
+
 /*
  * xHCI spec says we can get an interrupt, and if the HC has an error condition,
  * we might get bad data out of the event ring.  Section 4.10.2.7 has a list of
@@ -3077,12 +3133,8 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
 irqreturn_t xhci_irq(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-       union xhci_trb *event_ring_deq;
-       struct xhci_interrupter *ir;
        irqreturn_t ret = IRQ_NONE;
-       u64 temp_64;
        u32 status;
-       int event_loop = 0;
 
        spin_lock(&xhci->lock);
        /* Check if the xHC generated the interrupt, or the irq is shared */
@@ -3115,50 +3167,10 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
         */
        status |= STS_EINT;
        writel(status, &xhci->op_regs->status);
-
-       /* This is the handler of the primary interrupter */
-       ir = xhci->interrupters[0];
-       if (!hcd->msi_enabled) {
-               u32 irq_pending;
-               irq_pending = readl(&ir->ir_set->irq_pending);
-               irq_pending |= IMAN_IP;
-               writel(irq_pending, &ir->ir_set->irq_pending);
-       }
-
-       if (xhci->xhc_state & XHCI_STATE_DYING ||
-           xhci->xhc_state & XHCI_STATE_HALTED) {
-               xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
-                               "Shouldn't IRQs be disabled?\n");
-               /* Clear the event handler busy flag (RW1C);
-                * the event ring should be empty.
-                */
-               temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
-               xhci_write_64(xhci, temp_64 | ERST_EHB,
-                               &ir->ir_set->erst_dequeue);
-               ret = IRQ_HANDLED;
-               goto out;
-       }
-
-       event_ring_deq = ir->event_ring->dequeue;
-       /* FIXME this should be a delayed service routine
-        * that clears the EHB.
-        */
-       while (xhci_handle_event(xhci, ir) > 0) {
-               if (event_loop++ < TRBS_PER_SEGMENT / 2)
-                       continue;
-               xhci_update_erst_dequeue(xhci, ir, event_ring_deq, false);
-               event_ring_deq = ir->event_ring->dequeue;
-
-               /* ring is half-full, force isoc trbs to interrupt more often */
-               if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
-                       xhci->isoc_bei_interval = xhci->isoc_bei_interval / 2;
-
-               event_loop = 0;
-       }
-
-       xhci_update_erst_dequeue(xhci, ir, event_ring_deq, true);
        ret = IRQ_HANDLED;
 
+       /* This is the handler of the primary interrupter */
+       xhci_handle_events(xhci, xhci->interrupters[0]);
 out:
        spin_unlock(&xhci->lock);
 
@@ -4019,7 +4031,8 @@ static int xhci_get_isoc_frame_id(struct xhci_hcd *xhci,
 }
 
 /* Check if we should generate event interrupt for a TD in an isoc URB */
-static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i)
+static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i,
+                                struct xhci_interrupter *ir)
 {
        if (xhci->hci_version < 0x100)
                return false;
@@ -4030,8 +4043,8 @@ static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i)
         * If AVOID_BEI is set the host handles full event rings poorly,
         * generate an event at least every 8th TD to clear the event ring
         */
-       if (i && xhci->quirks & XHCI_AVOID_BEI)
-               return !!(i % xhci->isoc_bei_interval);
+       if (i && ir->isoc_bei_interval && xhci->quirks & XHCI_AVOID_BEI)
+               return !!(i % ir->isoc_bei_interval);
 
        return true;
 }
@@ -4040,6 +4053,7 @@ static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i)
 static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                struct urb *urb, int slot_id, unsigned int ep_index)
 {
+       struct xhci_interrupter *ir;
        struct xhci_ring *ep_ring;
        struct urb_priv *urb_priv;
        struct xhci_td *td;
@@ -4057,6 +4071,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
        xep = &xhci->devs[slot_id]->eps[ep_index];
        ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
+       ir = xhci->interrupters[0];
 
        num_tds = urb->number_of_packets;
        if (num_tds < 1) {
@@ -4144,7 +4159,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                td->last_trb = ep_ring->enqueue;
                                td->last_trb_seg = ep_ring->enq_seg;
                                field |= TRB_IOC;
-                               if (trb_block_event_intr(xhci, num_tds, i))
+                               if (trb_block_event_intr(xhci, num_tds, i, ir))
                                        field |= TRB_BEI;
                        }
                        /* Calculate TRB length */