diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2010-07-30 01:12:29 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 17:35:44 -0400 |
commit | 9032cd52798daf4cd6314ffea5030b37b3eb34af (patch) | |
tree | afcc0b71073b069e0ea19f4e5f4a19706964ebab /drivers/usb/host/xhci.c | |
parent | 021bff9179c2d19c26599dc3e9134d04cf1c8a3a (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.c')
-rw-r--r-- | drivers/usb/host/xhci.c | 103 |
1 files changed, 0 insertions, 103 deletions
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 | ||
175 | static 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 | */ | ||
341 | static 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 | */ | ||
387 | irqreturn_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); | ||
418 | hw_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 |
431 | void xhci_event_ring_work(unsigned long arg) | 328 | void xhci_event_ring_work(unsigned long arg) |