diff options
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 27 |
1 files changed, 12 insertions, 15 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f9c08d2fe33a..eb4b10229a05 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -2039,25 +2039,25 @@ void xhci_handle_event(struct xhci_hcd *xhci) | |||
2039 | irqreturn_t xhci_irq(struct usb_hcd *hcd) | 2039 | irqreturn_t xhci_irq(struct usb_hcd *hcd) |
2040 | { | 2040 | { |
2041 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 2041 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
2042 | u32 temp, temp2; | 2042 | u32 status, irq_pending; |
2043 | union xhci_trb *trb; | 2043 | union xhci_trb *trb; |
2044 | u64 temp_64; | 2044 | u64 temp_64; |
2045 | 2045 | ||
2046 | spin_lock(&xhci->lock); | 2046 | spin_lock(&xhci->lock); |
2047 | trb = xhci->event_ring->dequeue; | 2047 | trb = xhci->event_ring->dequeue; |
2048 | /* Check if the xHC generated the interrupt, or the irq is shared */ | 2048 | /* Check if the xHC generated the interrupt, or the irq is shared */ |
2049 | temp = xhci_readl(xhci, &xhci->op_regs->status); | 2049 | status = xhci_readl(xhci, &xhci->op_regs->status); |
2050 | temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending); | 2050 | irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending); |
2051 | if (temp == 0xffffffff && temp2 == 0xffffffff) | 2051 | if (status == 0xffffffff && irq_pending == 0xffffffff) |
2052 | goto hw_died; | 2052 | goto hw_died; |
2053 | 2053 | ||
2054 | if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) { | 2054 | if (!(status & STS_EINT) && !ER_IRQ_PENDING(irq_pending)) { |
2055 | spin_unlock(&xhci->lock); | 2055 | spin_unlock(&xhci->lock); |
2056 | xhci_warn(xhci, "Spurious interrupt.\n"); | 2056 | xhci_warn(xhci, "Spurious interrupt.\n"); |
2057 | return IRQ_NONE; | 2057 | return IRQ_NONE; |
2058 | } | 2058 | } |
2059 | xhci_dbg(xhci, "op reg status = %08x\n", temp); | 2059 | xhci_dbg(xhci, "op reg status = %08x\n", status); |
2060 | xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2); | 2060 | xhci_dbg(xhci, "ir set irq_pending = %08x\n", irq_pending); |
2061 | xhci_dbg(xhci, "Event ring dequeue ptr:\n"); | 2061 | xhci_dbg(xhci, "Event ring dequeue ptr:\n"); |
2062 | xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", | 2062 | xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n", |
2063 | (unsigned long long) | 2063 | (unsigned long long) |
@@ -2067,7 +2067,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) | |||
2067 | (unsigned int) trb->link.intr_target, | 2067 | (unsigned int) trb->link.intr_target, |
2068 | (unsigned int) trb->link.control); | 2068 | (unsigned int) trb->link.control); |
2069 | 2069 | ||
2070 | if (temp & STS_FATAL) { | 2070 | if (status & STS_FATAL) { |
2071 | xhci_warn(xhci, "WARNING: Host System Error\n"); | 2071 | xhci_warn(xhci, "WARNING: Host System Error\n"); |
2072 | xhci_halt(xhci); | 2072 | xhci_halt(xhci); |
2073 | hw_died: | 2073 | hw_died: |
@@ -2081,15 +2081,14 @@ hw_died: | |||
2081 | * so we can receive interrupts from other MSI-X interrupters. | 2081 | * so we can receive interrupts from other MSI-X interrupters. |
2082 | * Write 1 to clear the interrupt status. | 2082 | * Write 1 to clear the interrupt status. |
2083 | */ | 2083 | */ |
2084 | temp |= STS_EINT; | 2084 | status |= STS_EINT; |
2085 | xhci_writel(xhci, temp, &xhci->op_regs->status); | 2085 | xhci_writel(xhci, status, &xhci->op_regs->status); |
2086 | /* FIXME when MSI-X is supported and there are multiple vectors */ | 2086 | /* FIXME when MSI-X is supported and there are multiple vectors */ |
2087 | /* Clear the MSI-X event interrupt status */ | 2087 | /* Clear the MSI-X event interrupt status */ |
2088 | 2088 | ||
2089 | /* Acknowledge the interrupt */ | 2089 | /* Acknowledge the interrupt */ |
2090 | temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); | 2090 | irq_pending |= 0x3; |
2091 | temp |= 0x3; | 2091 | xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending); |
2092 | xhci_writel(xhci, temp, &xhci->ir_set->irq_pending); | ||
2093 | 2092 | ||
2094 | if (xhci->xhc_state & XHCI_STATE_DYING) | 2093 | if (xhci->xhc_state & XHCI_STATE_DYING) |
2095 | xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " | 2094 | xhci_dbg(xhci, "xHCI dying, ignoring interrupt. " |
@@ -2103,8 +2102,6 @@ hw_died: | |||
2103 | /* Clear the event handler busy flag (RW1C); event ring is empty. */ | 2102 | /* Clear the event handler busy flag (RW1C); event ring is empty. */ |
2104 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); | 2103 | temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue); |
2105 | xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); | 2104 | xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue); |
2106 | /* Flush posted writes -- FIXME is this necessary? */ | ||
2107 | xhci_readl(xhci, &xhci->ir_set->irq_pending); | ||
2108 | spin_unlock(&xhci->lock); | 2105 | spin_unlock(&xhci->lock); |
2109 | 2106 | ||
2110 | return IRQ_HANDLED; | 2107 | return IRQ_HANDLED; |