diff options
author | Andiry Xu <andiry.xu@amd.com> | 2010-07-22 18:23:08 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 17:35:41 -0400 |
commit | 22405ed2e1bd8d2676cb45c578bdd05527ce25b9 (patch) | |
tree | 50fc29c7f4957cccdcd2ed02b8ecd43fc17b0f76 /drivers/usb/host | |
parent | 8af56be185a94e39c80ce90fc9f83f3058a3ce80 (diff) |
USB xHCI: handle_tx_event() refactor: process_bulk_intr_td
This patch moves the bulk and interrupt td processing part in
handle_tx_event() into a separate function process_bulk_intr_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')
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 216 |
1 files changed, 115 insertions, 101 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index e28cfd15e1a6..83580cf794d1 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1459,6 +1459,117 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, | |||
1459 | } | 1459 | } |
1460 | 1460 | ||
1461 | /* | 1461 | /* |
1462 | * Process bulk and interrupt tds, update urb status and actual_length. | ||
1463 | */ | ||
1464 | static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, | ||
1465 | union xhci_trb *event_trb, struct xhci_transfer_event *event, | ||
1466 | struct xhci_virt_ep *ep, int *status) | ||
1467 | { | ||
1468 | struct xhci_ring *ep_ring; | ||
1469 | union xhci_trb *cur_trb; | ||
1470 | struct xhci_segment *cur_seg; | ||
1471 | u32 trb_comp_code; | ||
1472 | |||
1473 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | ||
1474 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | ||
1475 | |||
1476 | switch (trb_comp_code) { | ||
1477 | case COMP_SUCCESS: | ||
1478 | /* Double check that the HW transferred everything. */ | ||
1479 | if (event_trb != td->last_trb) { | ||
1480 | xhci_warn(xhci, "WARN Successful completion " | ||
1481 | "on short TX\n"); | ||
1482 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1483 | *status = -EREMOTEIO; | ||
1484 | else | ||
1485 | *status = 0; | ||
1486 | } else { | ||
1487 | if (usb_endpoint_xfer_bulk(&td->urb->ep->desc)) | ||
1488 | xhci_dbg(xhci, "Successful bulk " | ||
1489 | "transfer!\n"); | ||
1490 | else | ||
1491 | xhci_dbg(xhci, "Successful interrupt " | ||
1492 | "transfer!\n"); | ||
1493 | *status = 0; | ||
1494 | } | ||
1495 | break; | ||
1496 | case COMP_SHORT_TX: | ||
1497 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1498 | *status = -EREMOTEIO; | ||
1499 | else | ||
1500 | *status = 0; | ||
1501 | break; | ||
1502 | default: | ||
1503 | /* Others already handled above */ | ||
1504 | break; | ||
1505 | } | ||
1506 | dev_dbg(&td->urb->dev->dev, | ||
1507 | "ep %#x - asked for %d bytes, " | ||
1508 | "%d bytes untransferred\n", | ||
1509 | td->urb->ep->desc.bEndpointAddress, | ||
1510 | td->urb->transfer_buffer_length, | ||
1511 | TRB_LEN(event->transfer_len)); | ||
1512 | /* Fast path - was this the last TRB in the TD for this URB? */ | ||
1513 | if (event_trb == td->last_trb) { | ||
1514 | if (TRB_LEN(event->transfer_len) != 0) { | ||
1515 | td->urb->actual_length = | ||
1516 | td->urb->transfer_buffer_length - | ||
1517 | TRB_LEN(event->transfer_len); | ||
1518 | if (td->urb->transfer_buffer_length < | ||
1519 | td->urb->actual_length) { | ||
1520 | xhci_warn(xhci, "HC gave bad length " | ||
1521 | "of %d bytes left\n", | ||
1522 | TRB_LEN(event->transfer_len)); | ||
1523 | td->urb->actual_length = 0; | ||
1524 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1525 | *status = -EREMOTEIO; | ||
1526 | else | ||
1527 | *status = 0; | ||
1528 | } | ||
1529 | /* Don't overwrite a previously set error code */ | ||
1530 | if (*status == -EINPROGRESS) { | ||
1531 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1532 | *status = -EREMOTEIO; | ||
1533 | else | ||
1534 | *status = 0; | ||
1535 | } | ||
1536 | } else { | ||
1537 | td->urb->actual_length = | ||
1538 | td->urb->transfer_buffer_length; | ||
1539 | /* Ignore a short packet completion if the | ||
1540 | * untransferred length was zero. | ||
1541 | */ | ||
1542 | if (*status == -EREMOTEIO) | ||
1543 | *status = 0; | ||
1544 | } | ||
1545 | } else { | ||
1546 | /* Slow path - walk the list, starting from the dequeue | ||
1547 | * pointer, to get the actual length transferred. | ||
1548 | */ | ||
1549 | td->urb->actual_length = 0; | ||
1550 | for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg; | ||
1551 | cur_trb != event_trb; | ||
1552 | next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { | ||
1553 | if ((cur_trb->generic.field[3] & | ||
1554 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) && | ||
1555 | (cur_trb->generic.field[3] & | ||
1556 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK)) | ||
1557 | td->urb->actual_length += | ||
1558 | TRB_LEN(cur_trb->generic.field[2]); | ||
1559 | } | ||
1560 | /* If the ring didn't stop on a Link or No-op TRB, add | ||
1561 | * in the actual bytes transferred from the Normal TRB | ||
1562 | */ | ||
1563 | if (trb_comp_code != COMP_STOP_INVAL) | ||
1564 | td->urb->actual_length += | ||
1565 | TRB_LEN(cur_trb->generic.field[2]) - | ||
1566 | TRB_LEN(event->transfer_len); | ||
1567 | } | ||
1568 | |||
1569 | return finish_td(xhci, td, event_trb, event, ep, status, false); | ||
1570 | } | ||
1571 | |||
1572 | /* | ||
1462 | * If this function returns an error condition, it means it got a Transfer | 1573 | * If this function returns an error condition, it means it got a Transfer |
1463 | * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. | 1574 | * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. |
1464 | * At this point, the host controller is probably hosed and should be reset. | 1575 | * At this point, the host controller is probably hosed and should be reset. |
@@ -1584,109 +1695,12 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1584 | } | 1695 | } |
1585 | /* Now update the urb's actual_length and give back to the core */ | 1696 | /* Now update the urb's actual_length and give back to the core */ |
1586 | /* Was this a control transfer? */ | 1697 | /* Was this a control transfer? */ |
1587 | if (usb_endpoint_xfer_control(&td->urb->ep->desc)) { | 1698 | if (usb_endpoint_xfer_control(&td->urb->ep->desc)) |
1588 | ret = process_ctrl_td(xhci, td, event_trb, event, ep, | 1699 | ret = process_ctrl_td(xhci, td, event_trb, event, ep, |
1589 | &status); | 1700 | &status); |
1590 | goto cleanup; | 1701 | else |
1591 | } else { | 1702 | ret = process_bulk_intr_td(xhci, td, event_trb, event, ep, |
1592 | switch (trb_comp_code) { | 1703 | &status); |
1593 | case COMP_SUCCESS: | ||
1594 | /* Double check that the HW transferred everything. */ | ||
1595 | if (event_trb != td->last_trb) { | ||
1596 | xhci_warn(xhci, "WARN Successful completion " | ||
1597 | "on short TX\n"); | ||
1598 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1599 | status = -EREMOTEIO; | ||
1600 | else | ||
1601 | status = 0; | ||
1602 | } else { | ||
1603 | if (usb_endpoint_xfer_bulk(&td->urb->ep->desc)) | ||
1604 | xhci_dbg(xhci, "Successful bulk " | ||
1605 | "transfer!\n"); | ||
1606 | else | ||
1607 | xhci_dbg(xhci, "Successful interrupt " | ||
1608 | "transfer!\n"); | ||
1609 | status = 0; | ||
1610 | } | ||
1611 | break; | ||
1612 | case COMP_SHORT_TX: | ||
1613 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1614 | status = -EREMOTEIO; | ||
1615 | else | ||
1616 | status = 0; | ||
1617 | break; | ||
1618 | default: | ||
1619 | /* Others already handled above */ | ||
1620 | break; | ||
1621 | } | ||
1622 | dev_dbg(&td->urb->dev->dev, | ||
1623 | "ep %#x - asked for %d bytes, " | ||
1624 | "%d bytes untransferred\n", | ||
1625 | td->urb->ep->desc.bEndpointAddress, | ||
1626 | td->urb->transfer_buffer_length, | ||
1627 | TRB_LEN(event->transfer_len)); | ||
1628 | /* Fast path - was this the last TRB in the TD for this URB? */ | ||
1629 | if (event_trb == td->last_trb) { | ||
1630 | if (TRB_LEN(event->transfer_len) != 0) { | ||
1631 | td->urb->actual_length = | ||
1632 | td->urb->transfer_buffer_length - | ||
1633 | TRB_LEN(event->transfer_len); | ||
1634 | if (td->urb->transfer_buffer_length < | ||
1635 | td->urb->actual_length) { | ||
1636 | xhci_warn(xhci, "HC gave bad length " | ||
1637 | "of %d bytes left\n", | ||
1638 | TRB_LEN(event->transfer_len)); | ||
1639 | td->urb->actual_length = 0; | ||
1640 | if (td->urb->transfer_flags & | ||
1641 | URB_SHORT_NOT_OK) | ||
1642 | status = -EREMOTEIO; | ||
1643 | else | ||
1644 | status = 0; | ||
1645 | } | ||
1646 | /* Don't overwrite a previously set error code */ | ||
1647 | if (status == -EINPROGRESS) { | ||
1648 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1649 | status = -EREMOTEIO; | ||
1650 | else | ||
1651 | status = 0; | ||
1652 | } | ||
1653 | } else { | ||
1654 | td->urb->actual_length = td->urb->transfer_buffer_length; | ||
1655 | /* Ignore a short packet completion if the | ||
1656 | * untransferred length was zero. | ||
1657 | */ | ||
1658 | if (status == -EREMOTEIO) | ||
1659 | status = 0; | ||
1660 | } | ||
1661 | } else { | ||
1662 | /* Slow path - walk the list, starting from the dequeue | ||
1663 | * pointer, to get the actual length transferred. | ||
1664 | */ | ||
1665 | union xhci_trb *cur_trb; | ||
1666 | struct xhci_segment *cur_seg; | ||
1667 | |||
1668 | td->urb->actual_length = 0; | ||
1669 | for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg; | ||
1670 | cur_trb != event_trb; | ||
1671 | next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) { | ||
1672 | if ((cur_trb->generic.field[3] & | ||
1673 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) && | ||
1674 | (cur_trb->generic.field[3] & | ||
1675 | TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK)) | ||
1676 | td->urb->actual_length += | ||
1677 | TRB_LEN(cur_trb->generic.field[2]); | ||
1678 | } | ||
1679 | /* If the ring didn't stop on a Link or No-op TRB, add | ||
1680 | * in the actual bytes transferred from the Normal TRB | ||
1681 | */ | ||
1682 | if (trb_comp_code != COMP_STOP_INVAL) | ||
1683 | td->urb->actual_length += | ||
1684 | TRB_LEN(cur_trb->generic.field[2]) - | ||
1685 | TRB_LEN(event->transfer_len); | ||
1686 | } | ||
1687 | } | ||
1688 | |||
1689 | ret = finish_td(xhci, td, event_trb, event, ep, &status, false); | ||
1690 | 1704 | ||
1691 | cleanup: | 1705 | cleanup: |
1692 | inc_deq(xhci, xhci->event_ring, true); | 1706 | inc_deq(xhci, xhci->event_ring, true); |