| From 1eb94a825e9c0bb4890e2c8c4154b8b7f371b954 Mon Sep 17 00:00:00 2001 |
| From: Felipe Balbi <felipe.balbi@linux.intel.com> |
| Date: Mon, 23 Jan 2017 14:20:11 +0200 |
| Subject: [PATCH 198/255] usb: host: xhci: introduce xhci_td_cleanup() |
| |
| By extracting xhci_td_cleanup() from finish_td(), code before clearer |
| and easier to follow. |
| |
| There are no functional changes with this patch. It's merely a cleanup. |
| |
| Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> |
| Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit 55fa4396b24db2adbcf5659ce3d7397c31e6b51c) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/usb/host/xhci-ring.c | 92 +++++++++++++++++++++++-------------------- |
| 1 file changed, 50 insertions(+), 42 deletions(-) |
| |
| --- a/drivers/usb/host/xhci-ring.c |
| +++ b/drivers/usb/host/xhci-ring.c |
| @@ -1825,6 +1825,55 @@ int xhci_is_vendor_info_code(struct xhci |
| return 0; |
| } |
| |
| +static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td, |
| + struct xhci_ring *ep_ring, int *status) |
| +{ |
| + struct urb_priv *urb_priv; |
| + struct urb *urb = NULL; |
| + |
| + /* Clean up the endpoint's TD list */ |
| + urb = td->urb; |
| + urb_priv = urb->hcpriv; |
| + |
| + /* if a bounce buffer was used to align this td then unmap it */ |
| + if (td->bounce_seg) |
| + xhci_unmap_td_bounce_buffer(xhci, ep_ring, td); |
| + |
| + /* Do one last check of the actual transfer length. |
| + * If the host controller said we transferred more data than the buffer |
| + * length, urb->actual_length will be a very big number (since it's |
| + * unsigned). Play it safe and say we didn't transfer anything. |
| + */ |
| + if (urb->actual_length > urb->transfer_buffer_length) { |
| + xhci_warn(xhci, "URB req %u and actual %u transfer length mismatch\n", |
| + urb->transfer_buffer_length, urb->actual_length); |
| + urb->actual_length = 0; |
| + *status = 0; |
| + } |
| + list_del_init(&td->td_list); |
| + /* Was this TD slated to be cancelled but completed anyway? */ |
| + if (!list_empty(&td->cancelled_td_list)) |
| + list_del_init(&td->cancelled_td_list); |
| + |
| + inc_td_cnt(urb); |
| + /* Giveback the urb when all the tds are completed */ |
| + if (last_td_in_urb(td)) { |
| + if ((urb->actual_length != urb->transfer_buffer_length && |
| + (urb->transfer_flags & URB_SHORT_NOT_OK)) || |
| + (*status != 0 && !usb_endpoint_xfer_isoc(&urb->ep->desc))) |
| + xhci_dbg(xhci, "Giveback URB %p, len = %d, expected = %d, status = %d\n", |
| + urb, urb->actual_length, |
| + urb->transfer_buffer_length, *status); |
| + |
| + /* set isoc urb status to 0 just as EHCI, UHCI, and OHCI */ |
| + if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) |
| + *status = 0; |
| + xhci_giveback_urb_in_irq(xhci, td, *status); |
| + } |
| + |
| + return 0; |
| +} |
| + |
| static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td, |
| union xhci_trb *ep_trb, struct xhci_transfer_event *event, |
| struct xhci_virt_ep *ep, int *status, bool skip) |
| @@ -1832,8 +1881,6 @@ static int finish_td(struct xhci_hcd *xh |
| struct xhci_virt_device *xdev; |
| struct xhci_ep_ctx *ep_ctx; |
| struct xhci_ring *ep_ring; |
| - struct urb_priv *urb_priv; |
| - struct urb *urb = NULL; |
| unsigned int slot_id; |
| u32 trb_comp_code; |
| int ep_index; |
| @@ -1876,46 +1923,7 @@ static int finish_td(struct xhci_hcd *xh |
| } |
| |
| td_cleanup: |
| - /* Clean up the endpoint's TD list */ |
| - urb = td->urb; |
| - urb_priv = urb->hcpriv; |
| - |
| - /* if a bounce buffer was used to align this td then unmap it */ |
| - if (td->bounce_seg) |
| - xhci_unmap_td_bounce_buffer(xhci, ep_ring, td); |
| - |
| - /* Do one last check of the actual transfer length. |
| - * If the host controller said we transferred more data than the buffer |
| - * length, urb->actual_length will be a very big number (since it's |
| - * unsigned). Play it safe and say we didn't transfer anything. |
| - */ |
| - if (urb->actual_length > urb->transfer_buffer_length) { |
| - xhci_warn(xhci, "URB req %u and actual %u transfer length mismatch\n", |
| - urb->transfer_buffer_length, urb->actual_length); |
| - urb->actual_length = 0; |
| - *status = 0; |
| - } |
| - list_del_init(&td->td_list); |
| - /* Was this TD slated to be cancelled but completed anyway? */ |
| - if (!list_empty(&td->cancelled_td_list)) |
| - list_del_init(&td->cancelled_td_list); |
| - |
| - inc_td_cnt(urb); |
| - /* Giveback the urb when all the tds are completed */ |
| - if (last_td_in_urb(td)) { |
| - if ((urb->actual_length != urb->transfer_buffer_length && |
| - (urb->transfer_flags & URB_SHORT_NOT_OK)) || |
| - (*status != 0 && !usb_endpoint_xfer_isoc(&urb->ep->desc))) |
| - xhci_dbg(xhci, "Giveback URB %p, len = %d, expected = %d, status = %d\n", |
| - urb, urb->actual_length, |
| - urb->transfer_buffer_length, *status); |
| - |
| - /* set isoc urb status to 0 just as EHCI, UHCI, and OHCI */ |
| - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) |
| - *status = 0; |
| - xhci_giveback_urb_in_irq(xhci, td, *status); |
| - } |
| - return 0; |
| + return xhci_td_cleanup(xhci, td, ep_ring, status); |
| } |
| |
| /* sum trb lengths from ring dequeue up to stop_trb, _excluding_ stop_trb */ |