Only receive TD can have a transfer length less than the transfer size, so rename COMP_SHORT_TX to COMP_SHORT_RX, XHCI_TRUST_TX_LENGTH to XHCI_TRUST_RX_LENGTH. handle_tx_event() is called for both receive and transmit completions so rename to handle_data_event(). In process_bulk_intr_td(): - Only trace unexpected short completions if XHCI_TRUST_RX_LENGTH isn't set, ratelimit the trace (as is done elsewhere). - Only debug trace short receives if URB_SHORT_NOT_OK isn't set. --- I hope this isn't mangled! --- drivers/usb/host/xhci-pci.c | 4 +-- drivers/usb/host/xhci-ring.c | 62 +++++++++++++++++++++----------------------- drivers/usb/host/xhci.h | 4 +-- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index b8dffd5..97b3edc 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -89,7 +89,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) "QUIRK: Fresco Logic revision %u " "has broken MSI implementation", pdev->revision); - xhci->quirks |= XHCI_TRUST_TX_LENGTH; + xhci->quirks |= XHCI_TRUST_RX_LENGTH; } if (pdev->vendor == PCI_VENDOR_ID_NEC) @@ -135,7 +135,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_RESET_ON_RESUME; xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "QUIRK: Resetting on resume"); - xhci->quirks |= XHCI_TRUST_TX_LENGTH; + xhci->quirks |= XHCI_TRUST_RX_LENGTH; } if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 6bfbd80..e38abc2 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2071,7 +2071,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, *status = 0; } break; - case COMP_SHORT_TX: + case COMP_SHORT_RX: if (td->urb->transfer_flags & URB_SHORT_NOT_OK) *status = -EREMOTEIO; else @@ -2166,9 +2166,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, frame->status = 0; break; } - if ((xhci->quirks & XHCI_TRUST_TX_LENGTH)) - trb_comp_code = COMP_SHORT_TX; - case COMP_SHORT_TX: + if ((xhci->quirks & XHCI_TRUST_RX_LENGTH)) + trb_comp_code = COMP_SHORT_RX; + case COMP_SHORT_RX: frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ? -EREMOTEIO : 0; break; @@ -2264,36 +2264,34 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, switch (trb_comp_code) { case COMP_SUCCESS: /* Double check that the HW transferred everything. */ - if (event_trb != td->last_trb || - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { - xhci_warn(xhci, "WARN Successful completion " - "on short TX\n"); - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - *status = -EREMOTEIO; - else - *status = 0; - if ((xhci->quirks & XHCI_TRUST_TX_LENGTH)) - trb_comp_code = COMP_SHORT_TX; - } else { + if (event_trb == td->last_trb && + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { *status = 0; + break; } - break; - case COMP_SHORT_TX: - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - *status = -EREMOTEIO; + if (xhci->quirks & XHCI_TRUST_RX_LENGTH) + trb_comp_code = COMP_SHORT_RX; else + xhci_warn_ratelimited(xhci, + "WARN Successful completion on short RX: needs XHCI_TRUST_RX_LENGTH quirk?\n"); + /* FALLTHROUGH */ + case COMP_SHORT_RX: + if (td->urb->transfer_flags & URB_SHORT_NOT_OK) { + xhci_dbg(xhci, "ep %#x - asked for %d bytes, " + "%d bytes untransferred\n", + td->urb->ep->desc.bEndpointAddress, + td->urb->transfer_buffer_length, + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); + *status = -EREMOTEIO; + } else { *status = 0; + } break; default: /* Others already handled above */ break; } - if (trb_comp_code == COMP_SHORT_TX) - xhci_dbg(xhci, "ep %#x - asked for %d bytes, " - "%d bytes untransferred\n", - td->urb->ep->desc.bEndpointAddress, - td->urb->transfer_buffer_length, - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); + /* Fast path - was this the last TRB in the TD for this URB? */ if (event_trb == td->last_trb) { if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { @@ -2357,7 +2355,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, * event with a corrupted Slot ID, Endpoint ID, or TRB DMA address. * At this point, the host controller is probably hosed and should be reset. */ -static int handle_tx_event(struct xhci_hcd *xhci, +static int handle_data_event(struct xhci_hcd *xhci, struct xhci_transfer_event *event) __releases(&xhci->lock) __acquires(&xhci->lock) @@ -2436,12 +2434,12 @@ static int handle_tx_event(struct xhci_hcd *xhci, case COMP_SUCCESS: if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) break; - if (xhci->quirks & XHCI_TRUST_TX_LENGTH) - trb_comp_code = COMP_SHORT_TX; + if (xhci->quirks & XHCI_TRUST_RX_LENGTH) + trb_comp_code = COMP_SHORT_RX; else xhci_warn_ratelimited(xhci, - "WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n"); - case COMP_SHORT_TX: + "WARN Successful completion on short RX: needs XHCI_TRUST_RX_LENGTH quirk?\n"); + case COMP_SHORT_RX: break; case COMP_STOP: xhci_dbg(xhci, "Stopped on Transfer TRB\n"); @@ -2604,7 +2602,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, ret = skip_isoc_td(xhci, td, event, ep, &status); goto cleanup; } - if (trb_comp_code == COMP_SHORT_TX) + if (trb_comp_code == COMP_SHORT_RX) ep_ring->last_td_was_short = true; else ep_ring->last_td_was_short = false; @@ -2737,7 +2735,7 @@ static int xhci_handle_event(struct xhci_hcd *xhci) update_ptrs = 0; break; case TRB_TYPE(TRB_TRANSFER): - ret = handle_tx_event(xhci, &event->trans_event); + ret = handle_data_event(xhci, &event->trans_event); if (ret < 0) xhci->error_bitmask |= 1 << 9; else diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 941d5f5..72ad988 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1032,7 +1032,7 @@ struct xhci_transfer_event { /* Endpoint Not Enabled Error */ #define COMP_EBADEP 12 /* Short Packet */ -#define COMP_SHORT_TX 13 +#define COMP_SHORT_RX 13 /* Ring Underrun - doorbell rung for an empty isoc OUT ep ring */ #define COMP_UNDERRUN 14 /* Ring Overrun - isoc IN ep ring is empty when ep is scheduled to RX */ @@ -1541,7 +1541,7 @@ struct xhci_hcd { #define XHCI_RESET_ON_RESUME (1 << 7) #define XHCI_SW_BW_CHECKING (1 << 8) #define XHCI_AMD_0x96_HOST (1 << 9) -#define XHCI_TRUST_TX_LENGTH (1 << 10) +#define XHCI_TRUST_RX_LENGTH (1 << 10) #define XHCI_LPM_SUPPORT (1 << 11) #define XHCI_INTEL_HOST (1 << 12) #define XHCI_SPURIOUS_REBOOT (1 << 13) -- 1.8.1.2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html