On Wed, 2019-07-24 at 17:43 +0200, gregkh@xxxxxxxxxxxxxxxxxxx wrote: > The patch below does not apply to the 5.2-stable tree. > If someone wants it applied there, or to any other stable or longterm > tree, then please email the backport, including the original git commit > id to <stable@xxxxxxxxxxxxxxx>. > > thanks, > > greg k-h > For the record, just so it doesn't get lost, it is indeed needed. I'll take care of it as long as Matthias doesn't prefer to do it himself. > ------------------ original commit in Linus's tree ------------------ > > From 13b82b746310b51b064bc855993a1c84bf862726 Mon Sep 17 00:00:00 2001 > From: Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx> > Date: Wed, 22 May 2019 14:34:00 +0300 > Subject: [PATCH] xhci: Fix immediate data transfer if buffer is already DMA > mapped > > xhci immediate data transfer (IDT) support in 5.2-rc1 caused regression > on various Samsung Exynos boards with ASIX USB 2.0 ethernet dongle. > > If the transfer buffer in the URB is already DMA mapped then IDT should > not be used. urb->transfer_dma will already contain a valid dma address, > and there is no guarantee the data in urb->transfer_buffer is valid. > > The IDT support patch used urb->transfer_dma as a temporary storage, > copying data from urb->transfer_buffer into it. > > Issue was solved by preventing IDT if transfer buffer is already dma > mapped, and by not using urb->transfer_dma as temporary storage. > > Fixes: 33e39350ebd2 ("usb: xhci: add Immediate Data Transfer support") > Reported-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> > Tested-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> > CC: Nicolas Saenz Julienne <nsaenzjulienne@xxxxxxx> > Signed-off-by: Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx> > Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> > > diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c > index ef7c8698772e..88392aa65722 100644 > --- a/drivers/usb/host/xhci-ring.c > +++ b/drivers/usb/host/xhci-ring.c > @@ -3432,11 +3432,14 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t > mem_flags, > > if (urb->transfer_buffer_length > 0) { > u32 length_field, remainder; > + u64 addr; > > if (xhci_urb_suitable_for_idt(urb)) { > - memcpy(&urb->transfer_dma, urb->transfer_buffer, > + memcpy(&addr, urb->transfer_buffer, > urb->transfer_buffer_length); > field |= TRB_IDT; > + } else { > + addr = (u64) urb->transfer_dma; > } > > remainder = xhci_td_remainder(xhci, 0, > @@ -3449,8 +3452,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t > mem_flags, > if (setup->bRequestType & USB_DIR_IN) > field |= TRB_DIR_IN; > queue_trb(xhci, ep_ring, true, > - lower_32_bits(urb->transfer_dma), > - upper_32_bits(urb->transfer_dma), > + lower_32_bits(addr), > + upper_32_bits(addr), > length_field, > field | ep_ring->cycle_state); > } > diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h > index a450a99e90eb..7f8b950d1a73 100644 > --- a/drivers/usb/host/xhci.h > +++ b/drivers/usb/host/xhci.h > @@ -2160,7 +2160,8 @@ static inline bool xhci_urb_suitable_for_idt(struct urb > *urb) > { > if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) && > usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE && > - urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE) > + urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE && > + !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) > return true; > > return false; >
Attachment:
signature.asc
Description: This is a digitally signed message part