Loading drivers/usb/host/xhci-ring.c +45 −58 Original line number Diff line number Diff line Loading @@ -1932,6 +1932,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, int ep_index; struct xhci_ep_ctx *ep_ctx; u32 trb_comp_code; u32 remaining, requested; bool on_data_stage; slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); xdev = xhci->devs[slot_id]; Loading @@ -1939,89 +1941,74 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); requested = td->urb->transfer_buffer_length; remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); /* not setup (dequeue), or status stage means we are at data stage */ on_data_stage = (event_trb != ep_ring->dequeue && event_trb != td->last_trb); switch (trb_comp_code) { case COMP_SUCCESS: if (event_trb == ep_ring->dequeue) { xhci_warn(xhci, "WARN: Success on ctrl setup TRB " "without IOC set??\n"); *status = -ESHUTDOWN; } else if (event_trb != td->last_trb) { xhci_warn(xhci, "WARN: Success on ctrl data TRB " "without IOC set??\n"); if (event_trb != td->last_trb) { xhci_warn(xhci, "WARN: Success on ctrl %s TRB without IOC set?\n", on_data_stage ? "data" : "setup"); *status = -ESHUTDOWN; } else { *status = 0; break; } *status = 0; break; case COMP_SHORT_TX: *status = 0; break; case COMP_STOP_SHORT: if (event_trb == ep_ring->dequeue || event_trb == td->last_trb) xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n"); if (on_data_stage) td->urb->actual_length = remaining; else td->urb->actual_length = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); return finish_td(xhci, td, event_trb, event, ep, status, false); xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n"); goto finish_td; case COMP_STOP: /* Did we stop at data stage? */ if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) td->urb->actual_length = td->urb->transfer_buffer_length - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); /* fall through */ if (on_data_stage) td->urb->actual_length = requested - remaining; goto finish_td; case COMP_STOP_INVAL: return finish_td(xhci, td, event_trb, event, ep, status, false); goto finish_td; default: if (!xhci_requires_manual_halt_cleanup(xhci, ep_ctx, trb_comp_code)) break; xhci_dbg(xhci, "TRB error code %u, " "halted endpoint index = %u\n", xhci_dbg(xhci, "TRB error %u, halted endpoint index = %u\n", trb_comp_code, ep_index); /* else fall through */ case COMP_STALL: /* Did we transfer part of the data (middle) phase? */ if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) td->urb->actual_length = td->urb->transfer_buffer_length - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); if (on_data_stage) td->urb->actual_length = requested - remaining; else if (!td->urb_length_set) td->urb->actual_length = 0; return finish_td(xhci, td, event_trb, event, ep, status, false); } /* * Did we transfer any data, despite the errors that might have * happened? I.e. did we get past the setup stage? */ if (event_trb != ep_ring->dequeue) { /* The event was for the status stage */ if (event_trb == td->last_trb) { if (!td->urb_length_set) { td->urb->actual_length = td->urb->transfer_buffer_length; goto finish_td; } } else { /* stopped at setup stage, no data transferred */ if (event_trb == ep_ring->dequeue) goto finish_td; /* * Maybe the event was for the data stage? If so, update * already the actual_length of the URB and flag it as * set, so that it is not overwritten in the event for * the last TRB. * if on data stage then update the actual_length of the URB and flag it * as set, so it won't be overwritten in the event for the last TRB. */ if (on_data_stage) { td->urb_length_set = true; td->urb->actual_length = td->urb->transfer_buffer_length - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); xhci_dbg(xhci, "Waiting for status " "stage event\n"); td->urb->actual_length = requested - remaining; xhci_dbg(xhci, "Waiting for status stage event\n"); return 0; } } /* at status stage */ if (!td->urb_length_set) td->urb->actual_length = requested; finish_td: return finish_td(xhci, td, event_trb, event, ep, status, false); } Loading Loading
drivers/usb/host/xhci-ring.c +45 −58 Original line number Diff line number Diff line Loading @@ -1932,6 +1932,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, int ep_index; struct xhci_ep_ctx *ep_ctx; u32 trb_comp_code; u32 remaining, requested; bool on_data_stage; slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags)); xdev = xhci->devs[slot_id]; Loading @@ -1939,89 +1941,74 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer)); ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len)); requested = td->urb->transfer_buffer_length; remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); /* not setup (dequeue), or status stage means we are at data stage */ on_data_stage = (event_trb != ep_ring->dequeue && event_trb != td->last_trb); switch (trb_comp_code) { case COMP_SUCCESS: if (event_trb == ep_ring->dequeue) { xhci_warn(xhci, "WARN: Success on ctrl setup TRB " "without IOC set??\n"); *status = -ESHUTDOWN; } else if (event_trb != td->last_trb) { xhci_warn(xhci, "WARN: Success on ctrl data TRB " "without IOC set??\n"); if (event_trb != td->last_trb) { xhci_warn(xhci, "WARN: Success on ctrl %s TRB without IOC set?\n", on_data_stage ? "data" : "setup"); *status = -ESHUTDOWN; } else { *status = 0; break; } *status = 0; break; case COMP_SHORT_TX: *status = 0; break; case COMP_STOP_SHORT: if (event_trb == ep_ring->dequeue || event_trb == td->last_trb) xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n"); if (on_data_stage) td->urb->actual_length = remaining; else td->urb->actual_length = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); return finish_td(xhci, td, event_trb, event, ep, status, false); xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n"); goto finish_td; case COMP_STOP: /* Did we stop at data stage? */ if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) td->urb->actual_length = td->urb->transfer_buffer_length - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); /* fall through */ if (on_data_stage) td->urb->actual_length = requested - remaining; goto finish_td; case COMP_STOP_INVAL: return finish_td(xhci, td, event_trb, event, ep, status, false); goto finish_td; default: if (!xhci_requires_manual_halt_cleanup(xhci, ep_ctx, trb_comp_code)) break; xhci_dbg(xhci, "TRB error code %u, " "halted endpoint index = %u\n", xhci_dbg(xhci, "TRB error %u, halted endpoint index = %u\n", trb_comp_code, ep_index); /* else fall through */ case COMP_STALL: /* Did we transfer part of the data (middle) phase? */ if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) td->urb->actual_length = td->urb->transfer_buffer_length - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); if (on_data_stage) td->urb->actual_length = requested - remaining; else if (!td->urb_length_set) td->urb->actual_length = 0; return finish_td(xhci, td, event_trb, event, ep, status, false); } /* * Did we transfer any data, despite the errors that might have * happened? I.e. did we get past the setup stage? */ if (event_trb != ep_ring->dequeue) { /* The event was for the status stage */ if (event_trb == td->last_trb) { if (!td->urb_length_set) { td->urb->actual_length = td->urb->transfer_buffer_length; goto finish_td; } } else { /* stopped at setup stage, no data transferred */ if (event_trb == ep_ring->dequeue) goto finish_td; /* * Maybe the event was for the data stage? If so, update * already the actual_length of the URB and flag it as * set, so that it is not overwritten in the event for * the last TRB. * if on data stage then update the actual_length of the URB and flag it * as set, so it won't be overwritten in the event for the last TRB. */ if (on_data_stage) { td->urb_length_set = true; td->urb->actual_length = td->urb->transfer_buffer_length - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); xhci_dbg(xhci, "Waiting for status " "stage event\n"); td->urb->actual_length = requested - remaining; xhci_dbg(xhci, "Waiting for status stage event\n"); return 0; } } /* at status stage */ if (!td->urb_length_set) td->urb->actual_length = requested; finish_td: return finish_td(xhci, td, event_trb, event, ep, status, false); } Loading