xhci: move xhci_td_cleanup so it can be called by more functions
[ Upstream commit 69eaf9e79fa7c7ff4b1eb626493ce5a81e467520 ] No funtional changes Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20210129130044.206855-17-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Stable-dep-of: a1575120972e ("xhci: Prevent infinite loop in transaction errors recovery for streams") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
44c635c60f
commit
9b63a80c45
@@ -773,6 +773,52 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
|
|||||||
seg->bounce_offs = 0;
|
seg->bounce_offs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
|
||||||
|
struct xhci_ring *ep_ring, int *status)
|
||||||
|
{
|
||||||
|
struct urb *urb = NULL;
|
||||||
|
|
||||||
|
/* Clean up the endpoint's TD list */
|
||||||
|
urb = td->urb;
|
||||||
|
|
||||||
|
/* if a bounce buffer was used to align this td then unmap it */
|
||||||
|
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 xhci_reset_halted_ep(struct xhci_hcd *xhci, unsigned int slot_id,
|
static int xhci_reset_halted_ep(struct xhci_hcd *xhci, unsigned int slot_id,
|
||||||
unsigned int ep_index, enum xhci_ep_reset_type reset_type)
|
unsigned int ep_index, enum xhci_ep_reset_type reset_type)
|
||||||
{
|
{
|
||||||
@@ -2013,52 +2059,6 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
|
|
||||||
struct xhci_ring *ep_ring, int *status)
|
|
||||||
{
|
|
||||||
struct urb *urb = NULL;
|
|
||||||
|
|
||||||
/* Clean up the endpoint's TD list */
|
|
||||||
urb = td->urb;
|
|
||||||
|
|
||||||
/* if a bounce buffer was used to align this td then unmap it */
|
|
||||||
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,
|
static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
|
||||||
struct xhci_transfer_event *event,
|
struct xhci_transfer_event *event,
|
||||||
struct xhci_virt_ep *ep, int *status)
|
struct xhci_virt_ep *ep, int *status)
|
||||||
|
Reference in New Issue
Block a user