[ 047/102] Bluetooth: ath3k: dont use stack memory for DMA
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date: 2013-08-09 01:59:05
Also in:
lkml
3.10-stable review patch. If anyone has any objections, please let me know. ------------------ From: Stanislaw Gruszka <redacted> commit 517828a87994f41af6ae5a0f96f0f069f05baa81 upstream. Memory allocated by vmalloc (including stack) can not be used for DMA, i.e. data pointer on usb_control_msg() should not point to stack memory. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=977558 Reported-and-tested-by: Andy Lawrence <redacted> Signed-off-by: Stanislaw Gruszka <redacted> Signed-off-by: Gustavo Padovan <redacted> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> --- drivers/bluetooth/ath3k.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-)
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c@@ -195,24 +195,44 @@ error: static int ath3k_get_state(struct usb_device *udev, unsigned char *state) { - int pipe = 0; + int ret, pipe = 0; + char *buf; + + buf = kmalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; pipe = usb_rcvctrlpipe(udev, 0); - return usb_control_msg(udev, pipe, ATH3K_GETSTATE, - USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, - state, 0x01, USB_CTRL_SET_TIMEOUT); + ret = usb_control_msg(udev, pipe, ATH3K_GETSTATE, + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, + buf, sizeof(*buf), USB_CTRL_SET_TIMEOUT); + + *state = *buf; + kfree(buf); + + return ret; } static int ath3k_get_version(struct usb_device *udev, struct ath3k_version *version) { - int pipe = 0; + int ret, pipe = 0; + struct ath3k_version *buf; + const int size = sizeof(*buf); + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) + return -ENOMEM; pipe = usb_rcvctrlpipe(udev, 0); - return usb_control_msg(udev, pipe, ATH3K_GETVERSION, - USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version, - sizeof(struct ath3k_version), - USB_CTRL_SET_TIMEOUT); + ret = usb_control_msg(udev, pipe, ATH3K_GETVERSION, + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, + buf, size, USB_CTRL_SET_TIMEOUT); + + memcpy(version, buf, size); + kfree(buf); + + return ret; } static int ath3k_load_fwfile(struct usb_device *udev,