aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
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
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')
-rw-r--r--drivers/usb/host/xhci-ring.c103
-rw-r--r--drivers/usb/host/xhci.c103
-rw-r--r--drivers/usb/host/xhci.h1
3 files changed, 104 insertions, 103 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
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index f5e0b00cbb83..d5c550ea3e68 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -172,17 +172,6 @@ int xhci_reset(struct xhci_hcd *xhci)
172 return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); 172 return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
173} 173}
174 174
175static irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd)
176{
177 irqreturn_t ret;
178
179 set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
180
181 ret = xhci_irq(hcd);
182
183 return ret;
184}
185
186/* 175/*
187 * Free IRQs 176 * Free IRQs
188 * free all IRQs request 177 * free all IRQs request
@@ -332,100 +321,8 @@ int xhci_init(struct usb_hcd *hcd)
332 return retval; 321 return retval;
333} 322}
334 323
335/*
336 * Called in interrupt context when there might be work
337 * queued on the event ring
338 *
339 * xhci->lock must be held by caller.
340 */
341static void xhci_work(struct xhci_hcd *xhci)
342{
343 u32 temp;
344 u64 temp_64;
345
346 /*
347 * Clear the op reg interrupt status first,
348 * so we can receive interrupts from other MSI-X interrupters.
349 * Write 1 to clear the interrupt status.
350 */
351 temp = xhci_readl(xhci, &xhci->op_regs->status);
352 temp |= STS_EINT;
353 xhci_writel(xhci, temp, &xhci->op_regs->status);
354 /* FIXME when MSI-X is supported and there are multiple vectors */
355 /* Clear the MSI-X event interrupt status */
356
357 /* Acknowledge the interrupt */
358 temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
359 temp |= 0x3;
360 xhci_writel(xhci, temp, &xhci->ir_set->irq_pending);
361 /* Flush posted writes */
362 xhci_readl(xhci, &xhci->ir_set->irq_pending);
363
364 if (xhci->xhc_state & XHCI_STATE_DYING)
365 xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
366 "Shouldn't IRQs be disabled?\n");
367 else
368 /* FIXME this should be a delayed service routine
369 * that clears the EHB.
370 */
371 xhci_handle_event(xhci);
372
373 /* Clear the event handler busy flag (RW1C); the event ring should be empty. */
374 temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
375 xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
376 /* Flush posted writes -- FIXME is this necessary? */
377 xhci_readl(xhci, &xhci->ir_set->irq_pending);
378}
379
380/*-------------------------------------------------------------------------*/ 324/*-------------------------------------------------------------------------*/
381 325
382/*
383 * xHCI spec says we can get an interrupt, and if the HC has an error condition,
384 * we might get bad data out of the event ring. Section 4.10.2.7 has a list of
385 * indicators of an event TRB error, but we check the status *first* to be safe.
386 */
387irqreturn_t xhci_irq(struct usb_hcd *hcd)
388{
389 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
390 u32 temp, temp2;
391 union xhci_trb *trb;
392
393 spin_lock(&xhci->lock);
394 trb = xhci->event_ring->dequeue;
395 /* Check if the xHC generated the interrupt, or the irq is shared */
396 temp = xhci_readl(xhci, &xhci->op_regs->status);
397 temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending);
398 if (temp == 0xffffffff && temp2 == 0xffffffff)
399 goto hw_died;
400
401 if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) {
402 spin_unlock(&xhci->lock);
403 return IRQ_NONE;
404 }
405 xhci_dbg(xhci, "op reg status = %08x\n", temp);
406 xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2);
407 xhci_dbg(xhci, "Event ring dequeue ptr:\n");
408 xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n",
409 (unsigned long long)xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
410 lower_32_bits(trb->link.segment_ptr),
411 upper_32_bits(trb->link.segment_ptr),
412 (unsigned int) trb->link.intr_target,
413 (unsigned int) trb->link.control);
414
415 if (temp & STS_FATAL) {
416 xhci_warn(xhci, "WARNING: Host System Error\n");
417 xhci_halt(xhci);
418hw_died:
419 xhci_to_hcd(xhci)->state = HC_STATE_HALT;
420 spin_unlock(&xhci->lock);
421 return -ESHUTDOWN;
422 }
423
424 xhci_work(xhci);
425 spin_unlock(&xhci->lock);
426
427 return IRQ_HANDLED;
428}
429 326
430#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING 327#ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
431void xhci_event_ring_work(unsigned long arg) 328void xhci_event_ring_work(unsigned long arg)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 9fe95c4e2a56..6d829c41d963 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1371,6 +1371,7 @@ void xhci_stop(struct usb_hcd *hcd);
1371void xhci_shutdown(struct usb_hcd *hcd); 1371void xhci_shutdown(struct usb_hcd *hcd);
1372int xhci_get_frame(struct usb_hcd *hcd); 1372int xhci_get_frame(struct usb_hcd *hcd);
1373irqreturn_t xhci_irq(struct usb_hcd *hcd); 1373irqreturn_t xhci_irq(struct usb_hcd *hcd);
1374irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd);
1374int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); 1375int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev);
1375void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); 1376void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
1376int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, 1377int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,