Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a6af9d8 authored by Shuah Khan's avatar Shuah Khan Committed by Greg Kroah-Hartman
Browse files

misc: rtsx_usb: fix use of dma mapped buffer for usb bulk transfer



[ Upstream commit eb7f8e28420372787933eec079735c35034bda7d ]

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: default avatarShuah Khan <skhan@linuxfoundation.org>
Cc: stable <stable@kernel.org>
Link: https://lore.kernel.org/r/667d627d502e1ba9ff4f9b94966df3299d2d3c0d.1656642167.git.skhan@linuxfoundation.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 45ce2e46
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -642,8 +642,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;

@@ -679,8 +678,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;
}

@@ -693,8 +693,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
+0 −1
Original line number Diff line number Diff line
@@ -66,7 +66,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;