diff options
author | Andiry Xu <andiry.xu@amd.com> | 2010-07-22 18:23:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 17:35:41 -0400 |
commit | 8af56be185a94e39c80ce90fc9f83f3058a3ce80 (patch) | |
tree | 9904122b745b067b10ce067d689ff52d9f3105d9 /drivers/usb/host | |
parent | 4422da61550b2fe5089c5cdc374ceea33e581773 (diff) |
USB: xHCI: handle_tx_event() refactor: process_ctrl_td
This patch moves the ctrl td processing part in handle_tx_event()
into a separate function process_ctrl_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 | 184 |
1 files changed, 106 insertions, 78 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 691a108295ea..e28cfd15e1a6 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1356,6 +1356,109 @@ td_cleanup: | |||
1356 | } | 1356 | } |
1357 | 1357 | ||
1358 | /* | 1358 | /* |
1359 | * Process control tds, update urb status and actual_length. | ||
1360 | */ | ||
1361 | static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, | ||
1362 | union xhci_trb *event_trb, struct xhci_transfer_event *event, | ||
1363 | struct xhci_virt_ep *ep, int *status) | ||
1364 | { | ||
1365 | struct xhci_virt_device *xdev; | ||
1366 | struct xhci_ring *ep_ring; | ||
1367 | unsigned int slot_id; | ||
1368 | int ep_index; | ||
1369 | struct xhci_ep_ctx *ep_ctx; | ||
1370 | u32 trb_comp_code; | ||
1371 | |||
1372 | slot_id = TRB_TO_SLOT_ID(event->flags); | ||
1373 | xdev = xhci->devs[slot_id]; | ||
1374 | ep_index = TRB_TO_EP_ID(event->flags) - 1; | ||
1375 | ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); | ||
1376 | ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); | ||
1377 | trb_comp_code = GET_COMP_CODE(event->transfer_len); | ||
1378 | |||
1379 | xhci_debug_trb(xhci, xhci->event_ring->dequeue); | ||
1380 | switch (trb_comp_code) { | ||
1381 | case COMP_SUCCESS: | ||
1382 | if (event_trb == ep_ring->dequeue) { | ||
1383 | xhci_warn(xhci, "WARN: Success on ctrl setup TRB " | ||
1384 | "without IOC set??\n"); | ||
1385 | *status = -ESHUTDOWN; | ||
1386 | } else if (event_trb != td->last_trb) { | ||
1387 | xhci_warn(xhci, "WARN: Success on ctrl data TRB " | ||
1388 | "without IOC set??\n"); | ||
1389 | *status = -ESHUTDOWN; | ||
1390 | } else { | ||
1391 | xhci_dbg(xhci, "Successful control transfer!\n"); | ||
1392 | *status = 0; | ||
1393 | } | ||
1394 | break; | ||
1395 | case COMP_SHORT_TX: | ||
1396 | xhci_warn(xhci, "WARN: short transfer on control ep\n"); | ||
1397 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1398 | *status = -EREMOTEIO; | ||
1399 | else | ||
1400 | *status = 0; | ||
1401 | break; | ||
1402 | default: | ||
1403 | if (!xhci_requires_manual_halt_cleanup(xhci, | ||
1404 | ep_ctx, trb_comp_code)) | ||
1405 | break; | ||
1406 | xhci_dbg(xhci, "TRB error code %u, " | ||
1407 | "halted endpoint index = %u\n", | ||
1408 | trb_comp_code, ep_index); | ||
1409 | /* else fall through */ | ||
1410 | case COMP_STALL: | ||
1411 | /* Did we transfer part of the data (middle) phase? */ | ||
1412 | if (event_trb != ep_ring->dequeue && | ||
1413 | event_trb != td->last_trb) | ||
1414 | td->urb->actual_length = | ||
1415 | td->urb->transfer_buffer_length | ||
1416 | - TRB_LEN(event->transfer_len); | ||
1417 | else | ||
1418 | td->urb->actual_length = 0; | ||
1419 | |||
1420 | xhci_cleanup_halted_endpoint(xhci, | ||
1421 | slot_id, ep_index, 0, td, event_trb); | ||
1422 | return finish_td(xhci, td, event_trb, event, ep, status, true); | ||
1423 | } | ||
1424 | /* | ||
1425 | * Did we transfer any data, despite the errors that might have | ||
1426 | * happened? I.e. did we get past the setup stage? | ||
1427 | */ | ||
1428 | if (event_trb != ep_ring->dequeue) { | ||
1429 | /* The event was for the status stage */ | ||
1430 | if (event_trb == td->last_trb) { | ||
1431 | if (td->urb->actual_length != 0) { | ||
1432 | /* Don't overwrite a previously set error code | ||
1433 | */ | ||
1434 | if ((*status == -EINPROGRESS || *status == 0) && | ||
1435 | (td->urb->transfer_flags | ||
1436 | & URB_SHORT_NOT_OK)) | ||
1437 | /* Did we already see a short data | ||
1438 | * stage? */ | ||
1439 | *status = -EREMOTEIO; | ||
1440 | } else { | ||
1441 | td->urb->actual_length = | ||
1442 | td->urb->transfer_buffer_length; | ||
1443 | } | ||
1444 | } else { | ||
1445 | /* Maybe the event was for the data stage? */ | ||
1446 | if (trb_comp_code != COMP_STOP_INVAL) { | ||
1447 | /* We didn't stop on a link TRB in the middle */ | ||
1448 | td->urb->actual_length = | ||
1449 | td->urb->transfer_buffer_length - | ||
1450 | TRB_LEN(event->transfer_len); | ||
1451 | xhci_dbg(xhci, "Waiting for status " | ||
1452 | "stage event\n"); | ||
1453 | return 0; | ||
1454 | } | ||
1455 | } | ||
1456 | } | ||
1457 | |||
1458 | return finish_td(xhci, td, event_trb, event, ep, status, false); | ||
1459 | } | ||
1460 | |||
1461 | /* | ||
1359 | * If this function returns an error condition, it means it got a Transfer | 1462 | * If this function returns an error condition, it means it got a Transfer |
1360 | * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. | 1463 | * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. |
1361 | * At this point, the host controller is probably hosed and should be reset. | 1464 | * At this point, the host controller is probably hosed and should be reset. |
@@ -1482,84 +1585,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
1482 | /* Now update the urb's actual_length and give back to the core */ | 1585 | /* Now update the urb's actual_length and give back to the core */ |
1483 | /* Was this a control transfer? */ | 1586 | /* Was this a control transfer? */ |
1484 | if (usb_endpoint_xfer_control(&td->urb->ep->desc)) { | 1587 | if (usb_endpoint_xfer_control(&td->urb->ep->desc)) { |
1485 | xhci_debug_trb(xhci, xhci->event_ring->dequeue); | 1588 | ret = process_ctrl_td(xhci, td, event_trb, event, ep, |
1486 | switch (trb_comp_code) { | 1589 | &status); |
1487 | case COMP_SUCCESS: | 1590 | goto cleanup; |
1488 | if (event_trb == ep_ring->dequeue) { | ||
1489 | xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n"); | ||
1490 | status = -ESHUTDOWN; | ||
1491 | } else if (event_trb != td->last_trb) { | ||
1492 | xhci_warn(xhci, "WARN: Success on ctrl data TRB without IOC set??\n"); | ||
1493 | status = -ESHUTDOWN; | ||
1494 | } else { | ||
1495 | xhci_dbg(xhci, "Successful control transfer!\n"); | ||
1496 | status = 0; | ||
1497 | } | ||
1498 | break; | ||
1499 | case COMP_SHORT_TX: | ||
1500 | xhci_warn(xhci, "WARN: short transfer on control ep\n"); | ||
1501 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1502 | status = -EREMOTEIO; | ||
1503 | else | ||
1504 | status = 0; | ||
1505 | break; | ||
1506 | |||
1507 | default: | ||
1508 | if (!xhci_requires_manual_halt_cleanup(xhci, | ||
1509 | ep_ctx, trb_comp_code)) | ||
1510 | break; | ||
1511 | xhci_dbg(xhci, "TRB error code %u, " | ||
1512 | "halted endpoint index = %u\n", | ||
1513 | trb_comp_code, ep_index); | ||
1514 | /* else fall through */ | ||
1515 | case COMP_STALL: | ||
1516 | /* Did we transfer part of the data (middle) phase? */ | ||
1517 | if (event_trb != ep_ring->dequeue && | ||
1518 | event_trb != td->last_trb) | ||
1519 | td->urb->actual_length = | ||
1520 | td->urb->transfer_buffer_length | ||
1521 | - TRB_LEN(event->transfer_len); | ||
1522 | else | ||
1523 | td->urb->actual_length = 0; | ||
1524 | |||
1525 | xhci_cleanup_halted_endpoint(xhci, | ||
1526 | slot_id, ep_index, 0, td, event_trb); | ||
1527 | |||
1528 | ret = finish_td(xhci, td, event_trb, event, ep, | ||
1529 | &status, true); | ||
1530 | goto cleanup; | ||
1531 | } | ||
1532 | /* | ||
1533 | * Did we transfer any data, despite the errors that might have | ||
1534 | * happened? I.e. did we get past the setup stage? | ||
1535 | */ | ||
1536 | if (event_trb != ep_ring->dequeue) { | ||
1537 | /* The event was for the status stage */ | ||
1538 | if (event_trb == td->last_trb) { | ||
1539 | if (td->urb->actual_length != 0) { | ||
1540 | /* Don't overwrite a previously set error code */ | ||
1541 | if ((status == -EINPROGRESS || | ||
1542 | status == 0) && | ||
1543 | (td->urb->transfer_flags | ||
1544 | & URB_SHORT_NOT_OK)) | ||
1545 | /* Did we already see a short data stage? */ | ||
1546 | status = -EREMOTEIO; | ||
1547 | } else { | ||
1548 | td->urb->actual_length = | ||
1549 | td->urb->transfer_buffer_length; | ||
1550 | } | ||
1551 | } else { | ||
1552 | /* Maybe the event was for the data stage? */ | ||
1553 | if (trb_comp_code != COMP_STOP_INVAL) { | ||
1554 | /* We didn't stop on a link TRB in the middle */ | ||
1555 | td->urb->actual_length = | ||
1556 | td->urb->transfer_buffer_length - | ||
1557 | TRB_LEN(event->transfer_len); | ||
1558 | xhci_dbg(xhci, "Waiting for status stage event\n"); | ||
1559 | goto cleanup; | ||
1560 | } | ||
1561 | } | ||
1562 | } | ||
1563 | } else { | 1591 | } else { |
1564 | switch (trb_comp_code) { | 1592 | switch (trb_comp_code) { |
1565 | case COMP_SUCCESS: | 1593 | case COMP_SUCCESS: |