| From 74689c2344e6b0b5232b7cf167aebd2e0a4ecbf7 Mon Sep 17 00:00:00 2001 |
| From: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Date: Fri, 11 Nov 2016 15:13:16 +0200 |
| Subject: [PATCH 280/299] xhci: cleanup and refactor process_ctrl_td() |
| |
| Refactor pricess_ctrl_tx() to make it more readable |
| No functional changes |
| |
| Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit 0b6c324c8b6097b482decff8183f67c9a8a6e2a3) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/usb/host/xhci-ring.c | 103 ++++++++++++++++++------------------------- |
| 1 file changed, 45 insertions(+), 58 deletions(-) |
| |
| --- a/drivers/usb/host/xhci-ring.c |
| +++ b/drivers/usb/host/xhci-ring.c |
| @@ -1957,6 +1957,8 @@ static int process_ctrl_td(struct xhci_h |
| 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]; |
| @@ -1964,89 +1966,74 @@ static int process_ctrl_td(struct xhci_h |
| 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; |
| + *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)) |
| + ep_ctx, trb_comp_code)) |
| break; |
| - xhci_dbg(xhci, "TRB error code %u, " |
| - "halted endpoint index = %u\n", |
| - trb_comp_code, ep_index); |
| + 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); |
| + goto finish_td; |
| } |
| + |
| + /* stopped at setup stage, no data transferred */ |
| + if (event_trb == ep_ring->dequeue) |
| + goto finish_td; |
| + |
| /* |
| - * Did we transfer any data, despite the errors that might have |
| - * happened? I.e. did we get past the setup stage? |
| + * 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 (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; |
| - } |
| - } else { |
| - /* |
| - * 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. |
| - */ |
| - 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"); |
| - return 0; |
| - } |
| + if (on_data_stage) { |
| + td->urb_length_set = true; |
| + 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); |
| } |
| |