From: Greg Kroah-Hartman Date: Thu, 19 Dec 2019 08:55:22 +0000 (+0100) Subject: 5.4-stable patches X-Git-Tag: v4.4.207~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e6334eb0fd65af78d349183910a8f6e7852b07de;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: usb-fix-incorrect-dma-allocations-for-local-memory-pool-drivers.patch --- diff --git a/queue-5.4/series b/queue-5.4/series new file mode 100644 index 00000000000..77d118288d9 --- /dev/null +++ b/queue-5.4/series @@ -0,0 +1 @@ +usb-fix-incorrect-dma-allocations-for-local-memory-pool-drivers.patch diff --git a/queue-5.4/usb-fix-incorrect-dma-allocations-for-local-memory-pool-drivers.patch b/queue-5.4/usb-fix-incorrect-dma-allocations-for-local-memory-pool-drivers.patch new file mode 100644 index 00000000000..800a1b570a2 --- /dev/null +++ b/queue-5.4/usb-fix-incorrect-dma-allocations-for-local-memory-pool-drivers.patch @@ -0,0 +1,126 @@ +From f8c63edfd78905320e86b6b2be2b7a5ac768fa4e Mon Sep 17 00:00:00 2001 +From: Fredrik Noring +Date: Tue, 10 Dec 2019 18:29:05 +0100 +Subject: USB: Fix incorrect DMA allocations for local memory pool drivers + +From: Fredrik Noring + +commit f8c63edfd78905320e86b6b2be2b7a5ac768fa4e upstream. + +Fix commit 7b81cb6bddd2 ("usb: add a HCD_DMA flag instead of +guestimating DMA capabilities") where local memory USB drivers +erroneously allocate DMA memory instead of pool memory, causing + + OHCI Unrecoverable Error, disabled + HC died; cleaning up + +The order between hcd_uses_dma() and hcd->localmem_pool is now +arranged as in hcd_buffer_alloc() and hcd_buffer_free(), with the +test for hcd->localmem_pool placed first. + +As an alternative, one might consider adjusting hcd_uses_dma() with + + static inline bool hcd_uses_dma(struct usb_hcd *hcd) + { +- return IS_ENABLED(CONFIG_HAS_DMA) && (hcd->driver->flags & HCD_DMA); ++ return IS_ENABLED(CONFIG_HAS_DMA) && ++ (hcd->driver->flags & HCD_DMA) && ++ (hcd->localmem_pool == NULL); + } + +One can also consider unsetting HCD_DMA for local memory pool drivers. + +Fixes: 7b81cb6bddd2 ("usb: add a HCD_DMA flag instead of guestimating DMA capabilities") +Cc: stable +Signed-off-by: Fredrik Noring +Link: https://lore.kernel.org/r/20191210172905.GA52526@sx9 +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hcd.c | 42 ++++++++++++++++++++--------------------- + drivers/usb/storage/scsiglue.c | 3 +- + 2 files changed, 23 insertions(+), 22 deletions(-) + +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -1409,7 +1409,17 @@ int usb_hcd_map_urb_for_dma(struct usb_h + if (usb_endpoint_xfer_control(&urb->ep->desc)) { + if (hcd->self.uses_pio_for_control) + return ret; +- if (hcd_uses_dma(hcd)) { ++ if (hcd->localmem_pool) { ++ ret = hcd_alloc_coherent( ++ urb->dev->bus, mem_flags, ++ &urb->setup_dma, ++ (void **)&urb->setup_packet, ++ sizeof(struct usb_ctrlrequest), ++ DMA_TO_DEVICE); ++ if (ret) ++ return ret; ++ urb->transfer_flags |= URB_SETUP_MAP_LOCAL; ++ } else if (hcd_uses_dma(hcd)) { + if (is_vmalloc_addr(urb->setup_packet)) { + WARN_ONCE(1, "setup packet is not dma capable\n"); + return -EAGAIN; +@@ -1427,23 +1437,22 @@ int usb_hcd_map_urb_for_dma(struct usb_h + urb->setup_dma)) + return -EAGAIN; + urb->transfer_flags |= URB_SETUP_MAP_SINGLE; +- } else if (hcd->localmem_pool) { +- ret = hcd_alloc_coherent( +- urb->dev->bus, mem_flags, +- &urb->setup_dma, +- (void **)&urb->setup_packet, +- sizeof(struct usb_ctrlrequest), +- DMA_TO_DEVICE); +- if (ret) +- return ret; +- urb->transfer_flags |= URB_SETUP_MAP_LOCAL; + } + } + + dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + if (urb->transfer_buffer_length != 0 + && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { +- if (hcd_uses_dma(hcd)) { ++ if (hcd->localmem_pool) { ++ ret = hcd_alloc_coherent( ++ urb->dev->bus, mem_flags, ++ &urb->transfer_dma, ++ &urb->transfer_buffer, ++ urb->transfer_buffer_length, ++ dir); ++ if (ret == 0) ++ urb->transfer_flags |= URB_MAP_LOCAL; ++ } else if (hcd_uses_dma(hcd)) { + if (urb->num_sgs) { + int n; + +@@ -1497,15 +1506,6 @@ int usb_hcd_map_urb_for_dma(struct usb_h + else + urb->transfer_flags |= URB_DMA_MAP_SINGLE; + } +- } else if (hcd->localmem_pool) { +- ret = hcd_alloc_coherent( +- urb->dev->bus, mem_flags, +- &urb->transfer_dma, +- &urb->transfer_buffer, +- urb->transfer_buffer_length, +- dir); +- if (ret == 0) +- urb->transfer_flags |= URB_MAP_LOCAL; + } + if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE | + URB_SETUP_MAP_LOCAL))) +--- a/drivers/usb/storage/scsiglue.c ++++ b/drivers/usb/storage/scsiglue.c +@@ -135,7 +135,8 @@ static int slave_configure(struct scsi_d + * For such controllers we need to make sure the block layer sets + * up bounce buffers in addressable memory. + */ +- if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus))) ++ if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)) || ++ (bus_to_hcd(us->pusb_dev->bus)->localmem_pool != NULL)) + blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH); + + /*