Skip to content

Commit

Permalink
xhci: refactor transfer event errors and completion codes
Browse files Browse the repository at this point in the history
Parse the transfer event first, and remove duplicate debugging
code.

Reorder completion codes according to endpoint state.

No functional changes

We are not handling some transfer events correcly and need to
clean up this before fixing it

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Mathias Nyman authored and Greg Kroah-Hartman committed Jun 15, 2017
1 parent c5628a2 commit b336838
Showing 1 changed file with 40 additions and 38 deletions.
78 changes: 40 additions & 38 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -2298,39 +2298,26 @@ static int handle_tx_event(struct xhci_hcd *xhci,
bool handling_skipped_tds = false;

slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
ep_trb_dma = le64_to_cpu(event->buffer);

xdev = xhci->devs[slot_id];
if (!xdev) {
xhci_err(xhci, "ERROR Transfer event pointed to bad slot %u\n",
slot_id);
xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
(unsigned long long) xhci_trb_virt_to_dma(
xhci->event_ring->deq_seg,
xhci->event_ring->dequeue),
lower_32_bits(le64_to_cpu(event->buffer)),
upper_32_bits(le64_to_cpu(event->buffer)),
le32_to_cpu(event->transfer_len),
le32_to_cpu(event->flags));
return -ENODEV;
}

/* Endpoint ID is 1 based, our index is zero based */
ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
goto err_out;
}

ep = &xdev->eps[ep_index];
ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
ep_ring = xhci_dma_to_transfer_ring(ep, ep_trb_dma);
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
if (!ep_ring || GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) {

if (!ep_ring || GET_EP_CTX_STATE(ep_ctx) == EP_STATE_DISABLED) {
xhci_err(xhci,
"ERROR Transfer event for disabled endpoint slot %u ep %u or incorrect stream ring\n",
slot_id, ep_index);
xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
(unsigned long long) xhci_trb_virt_to_dma(
xhci->event_ring->deq_seg,
xhci->event_ring->dequeue),
lower_32_bits(le64_to_cpu(event->buffer)),
upper_32_bits(le64_to_cpu(event->buffer)),
le32_to_cpu(event->transfer_len),
le32_to_cpu(event->flags));
return -ENODEV;
goto err_out;
}

/* Count current td numbers if ep->skip is set */
Expand All @@ -2339,8 +2326,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
td_num++;
}

ep_trb_dma = le64_to_cpu(event->buffer);
trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
/* Look for common error cases */
switch (trb_comp_code) {
/* Skip codes that require special handling depending on
Expand All @@ -2357,6 +2342,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
slot_id, ep_index);
case COMP_SHORT_PACKET:
break;
/* Completion codes for endpoint stopped state */
case COMP_STOPPED:
xhci_dbg(xhci, "Stopped on Transfer TRB for slot %u ep %u\n",
slot_id, ep_index);
Expand All @@ -2371,18 +2357,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
"Stopped with short packet transfer detected for slot %u ep %u\n",
slot_id, ep_index);
break;
/* Completion codes for endpoint halted state */
case COMP_STALL_ERROR:
xhci_dbg(xhci, "Stalled endpoint for slot %u ep %u\n", slot_id,
ep_index);
ep->ep_state |= EP_HALTED;
status = -EPIPE;
break;
case COMP_TRB_ERROR:
xhci_warn(xhci,
"WARN: TRB error for slot %u ep %u on endpoint\n",
slot_id, ep_index);
status = -EILSEQ;
break;
case COMP_SPLIT_TRANSACTION_ERROR:
case COMP_USB_TRANSACTION_ERROR:
xhci_dbg(xhci, "Transfer error for slot %u ep %u on endpoint\n",
Expand All @@ -2394,6 +2375,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
slot_id, ep_index);
status = -EOVERFLOW;
break;
/* Completion codes for endpoint error state */
case COMP_TRB_ERROR:
xhci_warn(xhci,
"WARN: TRB error for slot %u ep %u on endpoint\n",
slot_id, ep_index);
status = -EILSEQ;
break;
/* completion codes not indicating endpoint state change */
case COMP_DATA_BUFFER_ERROR:
xhci_warn(xhci,
"WARN: HC couldn't access mem fast enough for slot %u ep %u\n",
Expand Down Expand Up @@ -2431,12 +2420,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
ep_index);
goto cleanup;
case COMP_INCOMPATIBLE_DEVICE_ERROR:
xhci_warn(xhci,
"WARN: detect an incompatible device for slot %u ep %u",
slot_id, ep_index);
status = -EPROTO;
break;
case COMP_MISSED_SERVICE_ERROR:
/*
* When encounter missed service error, one or more isoc tds
Expand All @@ -2455,6 +2438,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
"No Ping response error for slot %u ep %u, Skip one Isoc TD\n",
slot_id, ep_index);
goto cleanup;

case COMP_INCOMPATIBLE_DEVICE_ERROR:
/* needs disable slot command to recover */
xhci_warn(xhci,
"WARN: detect an incompatible device for slot %u ep %u",
slot_id, ep_index);
status = -EPROTO;
break;
default:
if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
status = 0;
Expand Down Expand Up @@ -2607,6 +2598,17 @@ static int handle_tx_event(struct xhci_hcd *xhci,
} while (handling_skipped_tds);

return 0;

err_out:
xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
(unsigned long long) xhci_trb_virt_to_dma(
xhci->event_ring->deq_seg,
xhci->event_ring->dequeue),
lower_32_bits(le64_to_cpu(event->buffer)),
upper_32_bits(le64_to_cpu(event->buffer)),
le32_to_cpu(event->transfer_len),
le32_to_cpu(event->flags));
return -ENODEV;
}

/*
Expand Down

0 comments on commit b336838

Please sign in to comment.