aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2010-07-30 01:12:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:44 -0400
commit9032cd52798daf4cd6314ffea5030b37b3eb34af (patch)
treeafcc0b71073b069e0ea19f4e5f4a19706964ebab /drivers/usb/host/xhci-ring.c
parent021bff9179c2d19c26599dc3e9134d04cf1c8a3a (diff)
USB: xhci: Performance - move interrupt handlers into xhci-ring.c
Most of the work for interrupt handling is done in xhci-ring.c, so it makes sense to move the functions that are first called when an interrupt happens (xhci_irq() or xhci_msi_irq()) into xhci-ring.c, so that the compiler can better optimize them. Shorten some lines to make it pass checkpatch. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 7f1c54585b63..4b50a02ba114 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2030,6 +2030,109 @@ void xhci_handle_event(struct xhci_hcd *xhci)
2030 /* Are there more items on the event ring? */ 2030 /* Are there more items on the event ring? */
2031 xhci_handle_event(xhci); 2031 xhci_handle_event(xhci);
2032} 2032}
2033/*
2034 * Called in interrupt context when there might be work
2035 * queued on the event ring
2036 *
2037 * xhci->lock must be held by caller.
2038 */
2039static void xhci_work(struct xhci_hcd *xhci)
2040{
2041 u32 temp;
2042 u64 temp_64;
2043
2044 /*
2045 * Clear the op reg interrupt status first,
2046 * so we can receive interrupts from other MSI-X interrupters.
2047 * Write 1 to clear the interrupt status.
2048 */
2049 temp = xhci_readl(xhci, &xhci->op_regs->status);
2050 temp |= STS_EINT;
2051 xhci_writel(xhci, temp, &xhci->op_regs->status);
2052 /* FIXME when MSI-X is supported and there are multiple vectors */
2053 /* Clear the MSI-X event interrupt status */
2054
2055 /* Acknowledge the interrupt */
2056 temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
2057 temp |= 0x3;
2058 xhci_writel(xhci, temp, &xhci->ir_set->irq_pending);
2059
2060 if (xhci->xhc_state & XHCI_STATE_DYING)
2061 xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
2062 "Shouldn't IRQs be disabled?\n");
2063 else
2064 /* FIXME this should be a delayed service routine
2065 * that clears the EHB.
2066 */
2067 xhci_handle_event(xhci);
2068
2069 /* Clear the event handler busy flag (RW1C); event ring is empty. */
2070 temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
2071 xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
2072 /* Flush posted writes -- FIXME is this necessary? */
2073 xhci_readl(xhci, &xhci->ir_set->irq_pending);
2074}
2075
2076/*
2077 * xHCI spec says we can get an interrupt, and if the HC has an error condition,
2078 * we might get bad data out of the event ring. Section 4.10.2.7 has a list of
2079 * indicators of an event TRB error, but we check the status *first* to be safe.
2080 */
2081irqreturn_t xhci_irq(struct usb_hcd *hcd)
2082{
2083 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
2084 u32 temp, temp2;
2085 union xhci_trb *trb;
2086
2087 spin_lock(&xhci->lock);
2088 trb = xhci->event_ring->dequeue;
2089 /* Check if the xHC generated the interrupt, or the irq is shared */
2090 temp = xhci_readl(xhci, &xhci->op_regs->status);
2091 temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending);
2092 if (temp == 0xffffffff && temp2 == 0xffffffff)
2093 goto hw_died;
2094
2095 if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) {
2096 spin_unlock(&xhci->lock);
2097 xhci_warn(xhci, "Spurious interrupt.\n");
2098 return IRQ_NONE;
2099 }
2100 xhci_dbg(xhci, "op reg status = %08x\n", temp);
2101 xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2);
2102 xhci_dbg(xhci, "Event ring dequeue ptr:\n");
2103 xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n",
2104 (unsigned long long)
2105 xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
2106 lower_32_bits(trb->link.segment_ptr),
2107 upper_32_bits(trb->link.segment_ptr),
2108 (unsigned int) trb->link.intr_target,
2109 (unsigned int) trb->link.control);
2110
2111 if (temp & STS_FATAL) {
2112 xhci_warn(xhci, "WARNING: Host System Error\n");
2113 xhci_halt(xhci);
2114hw_died:
2115 xhci_to_hcd(xhci)->state = HC_STATE_HALT;
2116 spin_unlock(&xhci->lock);
2117 return -ESHUTDOWN;
2118 }
2119
2120 xhci_work(xhci);
2121 spin_unlock(&xhci->lock);
2122
2123 return IRQ_HANDLED;
2124}
2125
2126irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd)
2127{
2128 irqreturn_t ret;
2129
2130 set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
2131
2132 ret = xhci_irq(hcd);
2133
2134 return ret;
2135}
2033 2136
2034/**** Endpoint Ring Operations ****/ 2137/**** Endpoint Ring Operations ****/
2035 2138