misc: rtsx_usb: fix use of dma mapped buffer for usb bulk transfer
authorShuah Khan <skhan@linuxfoundation.org>
Fri, 1 Jul 2022 02:32:55 +0000 (20:32 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Jul 2022 06:53:23 +0000 (08:53 +0200)
rtsx_usb driver allocates coherent dma buffer for urb transfers.
This buffer is passed to usb_bulk_msg() and usb core tries to
map already mapped buffer running into a dma mapping error.

xhci_hcd 0000:01:00.0: rejecting DMA map of vmalloc memory
WARNING: CPU: 1 PID: 279 at include/linux/dma-mapping.h:326 usb_ hcd_map_urb_for_dma+0x7d6/0x820

...

xhci_map_urb_for_dma+0x291/0x4e0
usb_hcd_submit_urb+0x199/0x12b0
...
usb_submit_urb+0x3b8/0x9e0
usb_start_wait_urb+0xe3/0x2d0
usb_bulk_msg+0x115/0x240
rtsx_usb_transfer_data+0x185/0x1a8 [rtsx_usb]
rtsx_usb_send_cmd+0xbb/0x123 [rtsx_usb]
rtsx_usb_write_register+0x12c/0x143 [rtsx_usb]
rtsx_usb_probe+0x226/0x4b2 [rtsx_usb]

Fix it to use kmalloc() to get DMA-able memory region instead.

Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
Cc: stable <stable@kernel.org>
Link: https://lore.kernel.org/r/667d627d502e1ba9ff4f9b94966df3299d2d3c0d.1656642167.git.skhan@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/cardreader/rtsx_usb.c
include/linux/rtsx_usb.h

index 1ef9b61..e147cc8 100644 (file)
@@ -631,8 +631,7 @@ static int rtsx_usb_probe(struct usb_interface *intf,
 
        ucr->pusb_dev = usb_dev;
 
-       ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
-                       GFP_KERNEL, &ucr->iobuf_dma);
+       ucr->iobuf = kmalloc(IOBUF_SIZE, GFP_KERNEL);
        if (!ucr->iobuf)
                return -ENOMEM;
 
@@ -668,8 +667,9 @@ static int rtsx_usb_probe(struct usb_interface *intf,
 
 out_init_fail:
        usb_set_intfdata(ucr->pusb_intf, NULL);
-       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
-                       ucr->iobuf_dma);
+       kfree(ucr->iobuf);
+       ucr->iobuf = NULL;
+       ucr->cmd_buf = ucr->rsp_buf = NULL;
        return ret;
 }
 
@@ -682,8 +682,9 @@ static void rtsx_usb_disconnect(struct usb_interface *intf)
        mfd_remove_devices(&intf->dev);
 
        usb_set_intfdata(ucr->pusb_intf, NULL);
-       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
-                       ucr->iobuf_dma);
+       kfree(ucr->iobuf);
+       ucr->iobuf = NULL;
+       ucr->cmd_buf = ucr->rsp_buf = NULL;
 }
 
 #ifdef CONFIG_PM
index 159729c..a07f734 100644 (file)
@@ -55,7 +55,6 @@ struct rtsx_ucr {
        struct usb_interface    *pusb_intf;
        struct usb_sg_request   current_sg;
        unsigned char           *iobuf;
-       dma_addr_t              iobuf_dma;
 
        struct timer_list       sg_timer;
        struct mutex            dev_mutex;