diff options
author | Andiry Xu <andiry.xu@amd.com> | 2010-07-22 18:23:20 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 17:35:41 -0400 |
commit | 986a92d44810cad915279fdc942e2fd2c2857499 (patch) | |
tree | 25acf06086d9c57048eabdc089a408d5decdd8e9 /drivers/usb/host/xhci-ring.c | |
parent | 7fec3253edeb62ab7fc1a82d246196e72e9afdac (diff) |
USB: xHCI: adds new cases to trb_comp_code switch
This patch adds new cases to trb_comp_code switch, and moves
the switch judgment ahead of fetching td.
Signed-off-by: Andiry Xu <andiry.xu@amd.com>
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.c | 76 |
1 files changed, 52 insertions, 24 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 44730eca5fd9..5bb12fed9d2d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1605,36 +1605,16 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1605 | ep = &xdev->eps[ep_index]; | 1605 | ep = &xdev->eps[ep_index]; |
1606 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | 1606 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); |
1607 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | 1607 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); |
1608 | if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { | 1608 | if (!ep_ring || |
1609 | (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { | ||
1609 | xhci_err(xhci, "ERROR Transfer event for disabled endpoint " | 1610 | xhci_err(xhci, "ERROR Transfer event for disabled endpoint " |
1610 | "or incorrect stream ring\n"); | 1611 | "or incorrect stream ring\n"); |
1611 | return -ENODEV; | 1612 | return -ENODEV; |
1612 | } | 1613 | } |
1613 | 1614 | ||
1614 | event_dma = event->buffer; | 1615 | event_dma = event->buffer; |
1615 | /* This TRB should be in the TD at the head of this ring's TD list */ | ||
1616 | if (list_empty(&ep_ring->td_list)) { | ||
1617 | xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", | ||
1618 | TRB_TO_SLOT_ID(event->flags), ep_index); | ||
1619 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", | ||
1620 | (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); | ||
1621 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); | ||
1622 | goto cleanup; | ||
1623 | } | ||
1624 | td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list); | ||
1625 | |||
1626 | /* Is this a TRB in the currently executing TD? */ | ||
1627 | event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, | ||
1628 | td->last_trb, event_dma); | ||
1629 | if (!event_seg) { | ||
1630 | /* HC is busted, give up! */ | ||
1631 | xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n"); | ||
1632 | return -ESHUTDOWN; | ||
1633 | } | ||
1634 | event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)]; | ||
1635 | |||
1636 | /* Look for common error cases */ | ||
1637 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | 1616 | trb_comp_code = GET_COMP_CODE(event->transfer_len); |
1617 | /* Look for common error cases */ | ||
1638 | switch (trb_comp_code) { | 1618 | switch (trb_comp_code) { |
1639 | /* Skip codes that require special handling depending on | 1619 | /* Skip codes that require special handling depending on |
1640 | * transfer type | 1620 | * transfer type |
@@ -1670,14 +1650,62 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1670 | xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n"); | 1650 | xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n"); |
1671 | status = -ENOSR; | 1651 | status = -ENOSR; |
1672 | break; | 1652 | break; |
1653 | case COMP_BW_OVER: | ||
1654 | xhci_warn(xhci, "WARN: bandwidth overrun event on endpoint\n"); | ||
1655 | break; | ||
1656 | case COMP_BUFF_OVER: | ||
1657 | xhci_warn(xhci, "WARN: buffer overrun event on endpoint\n"); | ||
1658 | break; | ||
1659 | case COMP_UNDERRUN: | ||
1660 | /* | ||
1661 | * When the Isoch ring is empty, the xHC will generate | ||
1662 | * a Ring Overrun Event for IN Isoch endpoint or Ring | ||
1663 | * Underrun Event for OUT Isoch endpoint. | ||
1664 | */ | ||
1665 | xhci_dbg(xhci, "underrun event on endpoint\n"); | ||
1666 | if (!list_empty(&ep_ring->td_list)) | ||
1667 | xhci_dbg(xhci, "Underrun Event for slot %d ep %d " | ||
1668 | "still with TDs queued?\n", | ||
1669 | TRB_TO_SLOT_ID(event->flags), ep_index); | ||
1670 | goto cleanup; | ||
1671 | case COMP_OVERRUN: | ||
1672 | xhci_dbg(xhci, "overrun event on endpoint\n"); | ||
1673 | if (!list_empty(&ep_ring->td_list)) | ||
1674 | xhci_dbg(xhci, "Overrun Event for slot %d ep %d " | ||
1675 | "still with TDs queued?\n", | ||
1676 | TRB_TO_SLOT_ID(event->flags), ep_index); | ||
1677 | goto cleanup; | ||
1673 | default: | 1678 | default: |
1674 | if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { | 1679 | if (xhci_is_vendor_info_code(xhci, trb_comp_code)) { |
1675 | status = 0; | 1680 | status = 0; |
1676 | break; | 1681 | break; |
1677 | } | 1682 | } |
1678 | xhci_warn(xhci, "ERROR Unknown event condition, HC probably busted\n"); | 1683 | xhci_warn(xhci, "ERROR Unknown event condition, HC probably " |
1684 | "busted\n"); | ||
1685 | goto cleanup; | ||
1686 | } | ||
1687 | |||
1688 | /* This TRB should be in the TD at the head of this ring's TD list */ | ||
1689 | if (list_empty(&ep_ring->td_list)) { | ||
1690 | xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", | ||
1691 | TRB_TO_SLOT_ID(event->flags), ep_index); | ||
1692 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", | ||
1693 | (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); | ||
1694 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); | ||
1679 | goto cleanup; | 1695 | goto cleanup; |
1680 | } | 1696 | } |
1697 | td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list); | ||
1698 | |||
1699 | /* Is this a TRB in the currently executing TD? */ | ||
1700 | event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue, | ||
1701 | td->last_trb, event_dma); | ||
1702 | if (!event_seg) { | ||
1703 | /* HC is busted, give up! */ | ||
1704 | xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n"); | ||
1705 | return -ESHUTDOWN; | ||
1706 | } | ||
1707 | event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)]; | ||
1708 | |||
1681 | /* Now update the urb's actual_length and give back to the core */ | 1709 | /* Now update the urb's actual_length and give back to the core */ |
1682 | /* Was this a control transfer? */ | 1710 | /* Was this a control transfer? */ |
1683 | if (usb_endpoint_xfer_control(&td->urb->ep->desc)) | 1711 | if (usb_endpoint_xfer_control(&td->urb->ep->desc)) |