| From foo@baz Tue Aug 8 16:51:58 PDT 2017 |
| From: Thomas Jarosch <thomas.jarosch@intra2net.com> |
| Date: Sat, 22 Jul 2017 17:14:34 +0200 |
| Subject: mcs7780: Fix initialization when CONFIG_VMAP_STACK is enabled |
| |
| From: Thomas Jarosch <thomas.jarosch@intra2net.com> |
| |
| |
| [ Upstream commit 9476d393667968b4a02afbe9d35a3558482b943e ] |
| |
| DMA transfers are not allowed to buffers that are on the stack. |
| Therefore allocate a buffer to store the result of usb_control_message(). |
| |
| Fixes these bugreports: |
| https://bugzilla.kernel.org/show_bug.cgi?id=195217 |
| |
| https://bugzilla.redhat.com/show_bug.cgi?id=1421387 |
| https://bugzilla.redhat.com/show_bug.cgi?id=1427398 |
| |
| Shortened kernel backtrace from 4.11.9-200.fc25.x86_64: |
| kernel: ------------[ cut here ]------------ |
| kernel: WARNING: CPU: 3 PID: 2957 at drivers/usb/core/hcd.c:1587 |
| kernel: transfer buffer not dma capable |
| kernel: Call Trace: |
| kernel: dump_stack+0x63/0x86 |
| kernel: __warn+0xcb/0xf0 |
| kernel: warn_slowpath_fmt+0x5a/0x80 |
| kernel: usb_hcd_map_urb_for_dma+0x37f/0x570 |
| kernel: ? try_to_del_timer_sync+0x53/0x80 |
| kernel: usb_hcd_submit_urb+0x34e/0xb90 |
| kernel: ? schedule_timeout+0x17e/0x300 |
| kernel: ? del_timer_sync+0x50/0x50 |
| kernel: ? __slab_free+0xa9/0x300 |
| kernel: usb_submit_urb+0x2f4/0x560 |
| kernel: ? urb_destroy+0x24/0x30 |
| kernel: usb_start_wait_urb+0x6e/0x170 |
| kernel: usb_control_msg+0xdc/0x120 |
| kernel: mcs_get_reg+0x36/0x40 [mcs7780] |
| kernel: mcs_net_open+0xb5/0x5c0 [mcs7780] |
| ... |
| |
| Regression goes back to 4.9, so it's a good candidate for -stable. |
| Though it's the decision of the maintainer. |
| |
| Thanks to Dan Williams for adding the "transfer buffer not dma capable" |
| warning in the first place. It instantly pointed me in the right direction. |
| |
| Patch has been tested with transferring data from a Polar watch. |
| |
| Signed-off-by: Thomas Jarosch <thomas.jarosch@intra2net.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/irda/mcs7780.c | 16 +++++++++++++--- |
| 1 file changed, 13 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/net/irda/mcs7780.c |
| +++ b/drivers/net/irda/mcs7780.c |
| @@ -141,9 +141,19 @@ static int mcs_set_reg(struct mcs_cb *mc |
| static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val) |
| { |
| struct usb_device *dev = mcs->usbdev; |
| - int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, |
| - MCS_RD_RTYPE, 0, reg, val, 2, |
| - msecs_to_jiffies(MCS_CTRL_TIMEOUT)); |
| + void *dmabuf; |
| + int ret; |
| + |
| + dmabuf = kmalloc(sizeof(__u16), GFP_KERNEL); |
| + if (!dmabuf) |
| + return -ENOMEM; |
| + |
| + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, |
| + MCS_RD_RTYPE, 0, reg, dmabuf, 2, |
| + msecs_to_jiffies(MCS_CTRL_TIMEOUT)); |
| + |
| + memcpy(val, dmabuf, sizeof(__u16)); |
| + kfree(dmabuf); |
| |
| return ret; |
| } |