diff options
author | Andiry Xu <andiry.xu@amd.com> | 2010-07-22 18:22:55 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 17:35:41 -0400 |
commit | 4422da61550b2fe5089c5cdc374ceea33e581773 (patch) | |
tree | 66fc42663ff36fc2ab0e078f3cc36473983b45c7 | |
parent | b972302b0a13aaddc9e90da2b4b52722e5d0e776 (diff) |
USB: xHCI: handle_tx_event() refactor: finish_td
This patch moves the td universal processing part in handle_tx_event()
into a separate function finish_td().
if finish_td() returns 1, it indicates the urb can be given back.
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>
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 185 |
1 files changed, 112 insertions, 73 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index bfc99a939455..691a108295ea 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1258,6 +1258,104 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code) | |||
1258 | } | 1258 | } |
1259 | 1259 | ||
1260 | /* | 1260 | /* |
1261 | * Finish the td processing, remove the td from td list; | ||
1262 | * Return 1 if the urb can be given back. | ||
1263 | */ | ||
1264 | static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, | ||
1265 | union xhci_trb *event_trb, struct xhci_transfer_event *event, | ||
1266 | struct xhci_virt_ep *ep, int *status, bool skip) | ||
1267 | { | ||
1268 | struct xhci_virt_device *xdev; | ||
1269 | struct xhci_ring *ep_ring; | ||
1270 | unsigned int slot_id; | ||
1271 | int ep_index; | ||
1272 | struct urb *urb = NULL; | ||
1273 | struct xhci_ep_ctx *ep_ctx; | ||
1274 | int ret = 0; | ||
1275 | u32 trb_comp_code; | ||
1276 | |||
1277 | slot_id = TRB_TO_SLOT_ID(event->flags); | ||
1278 | xdev = xhci->devs[slot_id]; | ||
1279 | ep_index = TRB_TO_EP_ID(event->flags) - 1; | ||
1280 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | ||
1281 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | ||
1282 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | ||
1283 | |||
1284 | if (skip) | ||
1285 | goto td_cleanup; | ||
1286 | |||
1287 | if (trb_comp_code == COMP_STOP_INVAL || | ||
1288 | trb_comp_code == COMP_STOP) { | ||
1289 | /* The Endpoint Stop Command completion will take care of any | ||
1290 | * stopped TDs. A stopped TD may be restarted, so don't update | ||
1291 | * the ring dequeue pointer or take this TD off any lists yet. | ||
1292 | */ | ||
1293 | ep->stopped_td = td; | ||
1294 | ep->stopped_trb = event_trb; | ||
1295 | return 0; | ||
1296 | } else { | ||
1297 | if (trb_comp_code == COMP_STALL) { | ||
1298 | /* The transfer is completed from the driver's | ||
1299 | * perspective, but we need to issue a set dequeue | ||
1300 | * command for this stalled endpoint to move the dequeue | ||
1301 | * pointer past the TD. We can't do that here because | ||
1302 | * the halt condition must be cleared first. Let the | ||
1303 | * USB class driver clear the stall later. | ||
1304 | */ | ||
1305 | ep->stopped_td = td; | ||
1306 | ep->stopped_trb = event_trb; | ||
1307 | ep->stopped_stream = ep_ring->stream_id; | ||
1308 | } else if (xhci_requires_manual_halt_cleanup(xhci, | ||
1309 | ep_ctx, trb_comp_code)) { | ||
1310 | /* Other types of errors halt the endpoint, but the | ||
1311 | * class driver doesn't call usb_reset_endpoint() unless | ||
1312 | * the error is -EPIPE. Clear the halted status in the | ||
1313 | * xHCI hardware manually. | ||
1314 | */ | ||
1315 | xhci_cleanup_halted_endpoint(xhci, | ||
1316 | slot_id, ep_index, ep_ring->stream_id, | ||
1317 | td, event_trb); | ||
1318 | } else { | ||
1319 | /* Update ring dequeue pointer */ | ||
1320 | while (ep_ring->dequeue != td->last_trb) | ||
1321 | inc_deq(xhci, ep_ring, false); | ||
1322 | inc_deq(xhci, ep_ring, false); | ||
1323 | } | ||
1324 | |||
1325 | td_cleanup: | ||
1326 | /* Clean up the endpoint's TD list */ | ||
1327 | urb = td->urb; | ||
1328 | |||
1329 | /* Do one last check of the actual transfer length. | ||
1330 | * If the host controller said we transferred more data than | ||
1331 | * the buffer length, urb->actual_length will be a very big | ||
1332 | * number (since it's unsigned). Play it safe and say we didn't | ||
1333 | * transfer anything. | ||
1334 | */ | ||
1335 | if (urb->actual_length > urb->transfer_buffer_length) { | ||
1336 | xhci_warn(xhci, "URB transfer length is wrong, " | ||
1337 | "xHC issue? req. len = %u, " | ||
1338 | "act. len = %u\n", | ||
1339 | urb->transfer_buffer_length, | ||
1340 | urb->actual_length); | ||
1341 | urb->actual_length = 0; | ||
1342 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1343 | *status = -EREMOTEIO; | ||
1344 | else | ||
1345 | *status = 0; | ||
1346 | } | ||
1347 | list_del(&td->td_list); | ||
1348 | /* Was this TD slated to be cancelled but completed anyway? */ | ||
1349 | if (!list_empty(&td->cancelled_td_list)) | ||
1350 | list_del(&td->cancelled_td_list); | ||
1351 | |||
1352 | ret = 1; | ||
1353 | } | ||
1354 | |||
1355 | return ret; | ||
1356 | } | ||
1357 | |||
1358 | /* | ||
1261 | * If this function returns an error condition, it means it got a Transfer | 1359 | * If this function returns an error condition, it means it got a Transfer |
1262 | * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. | 1360 | * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. |
1263 | * At this point, the host controller is probably hosed and should be reset. | 1361 | * At this point, the host controller is probably hosed and should be reset. |
@@ -1278,6 +1376,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1278 | int status = -EINPROGRESS; | 1376 | int status = -EINPROGRESS; |
1279 | struct xhci_ep_ctx *ep_ctx; | 1377 | struct xhci_ep_ctx *ep_ctx; |
1280 | u32 trb_comp_code; | 1378 | u32 trb_comp_code; |
1379 | int ret = 0; | ||
1281 | 1380 | ||
1282 | xhci_dbg(xhci, "In %s\n", __func__); | 1381 | xhci_dbg(xhci, "In %s\n", __func__); |
1283 | slot_id = TRB_TO_SLOT_ID(event->flags); | 1382 | slot_id = TRB_TO_SLOT_ID(event->flags); |
@@ -1308,7 +1407,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1308 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", | 1407 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", |
1309 | (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); | 1408 | (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10); |
1310 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); | 1409 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); |
1311 | urb = NULL; | ||
1312 | goto cleanup; | 1410 | goto cleanup; |
1313 | } | 1411 | } |
1314 | xhci_dbg(xhci, "%s - getting list entry\n", __func__); | 1412 | xhci_dbg(xhci, "%s - getting list entry\n", __func__); |
@@ -1379,7 +1477,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1379 | break; | 1477 | break; |
1380 | } | 1478 | } |
1381 | xhci_warn(xhci, "ERROR Unknown event condition, HC probably busted\n"); | 1479 | xhci_warn(xhci, "ERROR Unknown event condition, HC probably busted\n"); |
1382 | urb = NULL; | ||
1383 | goto cleanup; | 1480 | goto cleanup; |
1384 | } | 1481 | } |
1385 | /* Now update the urb's actual_length and give back to the core */ | 1482 | /* Now update the urb's actual_length and give back to the core */ |
@@ -1427,7 +1524,10 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1427 | 1524 | ||
1428 | xhci_cleanup_halted_endpoint(xhci, | 1525 | xhci_cleanup_halted_endpoint(xhci, |
1429 | slot_id, ep_index, 0, td, event_trb); | 1526 | slot_id, ep_index, 0, td, event_trb); |
1430 | goto td_cleanup; | 1527 | |
1528 | ret = finish_td(xhci, td, event_trb, event, ep, | ||
1529 | &status, true); | ||
1530 | goto cleanup; | ||
1431 | } | 1531 | } |
1432 | /* | 1532 | /* |
1433 | * Did we transfer any data, despite the errors that might have | 1533 | * Did we transfer any data, despite the errors that might have |
@@ -1456,7 +1556,6 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1456 | td->urb->transfer_buffer_length - | 1556 | td->urb->transfer_buffer_length - |
1457 | TRB_LEN(event->transfer_len); | 1557 | TRB_LEN(event->transfer_len); |
1458 | xhci_dbg(xhci, "Waiting for status stage event\n"); | 1558 | xhci_dbg(xhci, "Waiting for status stage event\n"); |
1459 | urb = NULL; | ||
1460 | goto cleanup; | 1559 | goto cleanup; |
1461 | } | 1560 | } |
1462 | } | 1561 | } |
@@ -1558,68 +1657,16 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1558 | TRB_LEN(event->transfer_len); | 1657 | TRB_LEN(event->transfer_len); |
1559 | } | 1658 | } |
1560 | } | 1659 | } |
1561 | if (trb_comp_code == COMP_STOP_INVAL || | ||
1562 | trb_comp_code == COMP_STOP) { | ||
1563 | /* The Endpoint Stop Command completion will take care of any | ||
1564 | * stopped TDs. A stopped TD may be restarted, so don't update | ||
1565 | * the ring dequeue pointer or take this TD off any lists yet. | ||
1566 | */ | ||
1567 | ep->stopped_td = td; | ||
1568 | ep->stopped_trb = event_trb; | ||
1569 | } else { | ||
1570 | if (trb_comp_code == COMP_STALL) { | ||
1571 | /* The transfer is completed from the driver's | ||
1572 | * perspective, but we need to issue a set dequeue | ||
1573 | * command for this stalled endpoint to move the dequeue | ||
1574 | * pointer past the TD. We can't do that here because | ||
1575 | * the halt condition must be cleared first. Let the | ||
1576 | * USB class driver clear the stall later. | ||
1577 | */ | ||
1578 | ep->stopped_td = td; | ||
1579 | ep->stopped_trb = event_trb; | ||
1580 | ep->stopped_stream = ep_ring->stream_id; | ||
1581 | } else if (xhci_requires_manual_halt_cleanup(xhci, | ||
1582 | ep_ctx, trb_comp_code)) { | ||
1583 | /* Other types of errors halt the endpoint, but the | ||
1584 | * class driver doesn't call usb_reset_endpoint() unless | ||
1585 | * the error is -EPIPE. Clear the halted status in the | ||
1586 | * xHCI hardware manually. | ||
1587 | */ | ||
1588 | xhci_cleanup_halted_endpoint(xhci, | ||
1589 | slot_id, ep_index, ep_ring->stream_id, td, event_trb); | ||
1590 | } else { | ||
1591 | /* Update ring dequeue pointer */ | ||
1592 | while (ep_ring->dequeue != td->last_trb) | ||
1593 | inc_deq(xhci, ep_ring, false); | ||
1594 | inc_deq(xhci, ep_ring, false); | ||
1595 | } | ||
1596 | 1660 | ||
1597 | td_cleanup: | 1661 | ret = finish_td(xhci, td, event_trb, event, ep, &status, false); |
1598 | /* Clean up the endpoint's TD list */ | ||
1599 | urb = td->urb; | ||
1600 | /* Do one last check of the actual transfer length. | ||
1601 | * If the host controller said we transferred more data than | ||
1602 | * the buffer length, urb->actual_length will be a very big | ||
1603 | * number (since it's unsigned). Play it safe and say we didn't | ||
1604 | * transfer anything. | ||
1605 | */ | ||
1606 | if (urb->actual_length > urb->transfer_buffer_length) { | ||
1607 | xhci_warn(xhci, "URB transfer length is wrong, " | ||
1608 | "xHC issue? req. len = %u, " | ||
1609 | "act. len = %u\n", | ||
1610 | urb->transfer_buffer_length, | ||
1611 | urb->actual_length); | ||
1612 | urb->actual_length = 0; | ||
1613 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1614 | status = -EREMOTEIO; | ||
1615 | else | ||
1616 | status = 0; | ||
1617 | } | ||
1618 | list_del(&td->td_list); | ||
1619 | /* Was this TD slated to be cancelled but completed anyway? */ | ||
1620 | if (!list_empty(&td->cancelled_td_list)) | ||
1621 | list_del(&td->cancelled_td_list); | ||
1622 | 1662 | ||
1663 | cleanup: | ||
1664 | inc_deq(xhci, xhci->event_ring, true); | ||
1665 | xhci_set_hc_event_deq(xhci); | ||
1666 | |||
1667 | /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */ | ||
1668 | if (ret) { | ||
1669 | urb = td->urb; | ||
1623 | /* Leave the TD around for the reset endpoint function to use | 1670 | /* Leave the TD around for the reset endpoint function to use |
1624 | * (but only if it's not a control endpoint, since we already | 1671 | * (but only if it's not a control endpoint, since we already |
1625 | * queued the Set TR dequeue pointer command for stalled | 1672 | * queued the Set TR dequeue pointer command for stalled |
@@ -1627,17 +1674,9 @@ td_cleanup: | |||
1627 | */ | 1674 | */ |
1628 | if (usb_endpoint_xfer_control(&urb->ep->desc) || | 1675 | if (usb_endpoint_xfer_control(&urb->ep->desc) || |
1629 | (trb_comp_code != COMP_STALL && | 1676 | (trb_comp_code != COMP_STALL && |
1630 | trb_comp_code != COMP_BABBLE)) { | 1677 | trb_comp_code != COMP_BABBLE)) |
1631 | kfree(td); | 1678 | kfree(td); |
1632 | } | ||
1633 | urb->hcpriv = NULL; | ||
1634 | } | ||
1635 | cleanup: | ||
1636 | inc_deq(xhci, xhci->event_ring, true); | ||
1637 | xhci_set_hc_event_deq(xhci); | ||
1638 | 1679 | ||
1639 | /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */ | ||
1640 | if (urb) { | ||
1641 | usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb); | 1680 | usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb); |
1642 | xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n", | 1681 | xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n", |
1643 | urb, urb->actual_length, status); | 1682 | urb, urb->actual_length, status); |