From: Greg Kroah-Hartman Date: Sat, 4 May 2019 09:22:14 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.19.40~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5132e7f82a51d99ff05bd38e677324cd689af754;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: alsa-line6-use-dynamic-buffers.patch --- diff --git a/queue-4.4/alsa-line6-use-dynamic-buffers.patch b/queue-4.4/alsa-line6-use-dynamic-buffers.patch new file mode 100644 index 00000000000..be7a63d5251 --- /dev/null +++ b/queue-4.4/alsa-line6-use-dynamic-buffers.patch @@ -0,0 +1,235 @@ +From e5c812e84f0dece3400d5caf42522287e6ef139f Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Sun, 28 Apr 2019 18:04:11 +0200 +Subject: ALSA: line6: use dynamic buffers + +From: Greg Kroah-Hartman + +commit e5c812e84f0dece3400d5caf42522287e6ef139f upstream. + +The line6 driver uses a lot of USB buffers off of the stack, which is +not allowed on many systems, causing the driver to crash on some of +them. Fix this up by dynamically allocating the buffers with kmalloc() +which allows for proper DMA-able memory. + +Reported-by: Christo Gouws +Reported-by: Alan Stern +Tested-by: Christo Gouws +Cc: stable +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/line6/driver.c | 60 ++++++++++++++++++++++++++------------------- + sound/usb/line6/toneport.c | 24 +++++++++++++----- + 2 files changed, 53 insertions(+), 31 deletions(-) + +--- a/sound/usb/line6/driver.c ++++ b/sound/usb/line6/driver.c +@@ -307,12 +307,16 @@ int line6_read_data(struct usb_line6 *li + { + struct usb_device *usbdev = line6->usbdev; + int ret; +- unsigned char len; ++ unsigned char *len; + unsigned count; + + if (address > 0xffff || datalen > 0xff) + return -EINVAL; + ++ len = kmalloc(sizeof(*len), GFP_KERNEL); ++ if (!len) ++ return -ENOMEM; ++ + /* query the serial number: */ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +@@ -321,7 +325,7 @@ int line6_read_data(struct usb_line6 *li + + if (ret < 0) { + dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + /* Wait for data length. We'll get 0xff until length arrives. */ +@@ -331,28 +335,29 @@ int line6_read_data(struct usb_line6 *li + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, +- 0x0012, 0x0000, &len, 1, ++ 0x0012, 0x0000, len, 1, + LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(line6->ifcdev, + "receive length failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + +- if (len != 0xff) ++ if (*len != 0xff) + break; + } + +- if (len == 0xff) { ++ ret = -EIO; ++ if (*len == 0xff) { + dev_err(line6->ifcdev, "read failed after %d retries\n", + count); +- return -EIO; +- } else if (len != datalen) { ++ goto exit; ++ } else if (*len != datalen) { + /* should be equal or something went wrong */ + dev_err(line6->ifcdev, + "length mismatch (expected %d, got %d)\n", +- (int)datalen, (int)len); +- return -EIO; ++ (int)datalen, (int)*len); ++ goto exit; + } + + /* receive the result: */ +@@ -361,12 +366,12 @@ int line6_read_data(struct usb_line6 *li + 0x0013, 0x0000, data, datalen, + LINE6_TIMEOUT * HZ); + +- if (ret < 0) { ++ if (ret < 0) + dev_err(line6->ifcdev, "read failed (error %d)\n", ret); +- return ret; +- } + +- return 0; ++exit: ++ kfree(len); ++ return ret; + } + EXPORT_SYMBOL_GPL(line6_read_data); + +@@ -378,12 +383,16 @@ int line6_write_data(struct usb_line6 *l + { + struct usb_device *usbdev = line6->usbdev; + int ret; +- unsigned char status; ++ unsigned char *status; + int count; + + if (address > 0xffff || datalen > 0xffff) + return -EINVAL; + ++ status = kmalloc(sizeof(*status), GFP_KERNEL); ++ if (!status) ++ return -ENOMEM; ++ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x0022, address, data, datalen, +@@ -392,7 +401,7 @@ int line6_write_data(struct usb_line6 *l + if (ret < 0) { + dev_err(line6->ifcdev, + "write request failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) { +@@ -403,28 +412,29 @@ int line6_write_data(struct usb_line6 *l + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, + 0x0012, 0x0000, +- &status, 1, LINE6_TIMEOUT * HZ); ++ status, 1, LINE6_TIMEOUT * HZ); + + if (ret < 0) { + dev_err(line6->ifcdev, + "receiving status failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + +- if (status != 0xff) ++ if (*status != 0xff) + break; + } + +- if (status == 0xff) { ++ if (*status == 0xff) { + dev_err(line6->ifcdev, "write failed after %d retries\n", + count); +- return -EIO; +- } else if (status != 0) { ++ ret = -EIO; ++ } else if (*status != 0) { + dev_err(line6->ifcdev, "write failed (error %d)\n", ret); +- return -EIO; ++ ret = -EIO; + } +- +- return 0; ++exit: ++ kfree(status); ++ return ret; + } + EXPORT_SYMBOL_GPL(line6_write_data); + +--- a/sound/usb/line6/toneport.c ++++ b/sound/usb/line6/toneport.c +@@ -365,15 +365,20 @@ static bool toneport_has_source_select(s + /* + Setup Toneport device. + */ +-static void toneport_setup(struct usb_line6_toneport *toneport) ++static int toneport_setup(struct usb_line6_toneport *toneport) + { +- int ticks; ++ int *ticks; + struct usb_line6 *line6 = &toneport->line6; + struct usb_device *usbdev = line6->usbdev; + ++ ticks = kmalloc(sizeof(*ticks), GFP_KERNEL); ++ if (!ticks) ++ return -ENOMEM; ++ + /* sync time on device with host: */ +- ticks = (int)get_seconds(); +- line6_write_data(line6, 0x80c6, &ticks, 4); ++ *ticks = (int)get_seconds(); ++ line6_write_data(line6, 0x80c6, ticks, 4); ++ kfree(ticks); + + /* enable device: */ + toneport_send_cmd(usbdev, 0x0301, 0x0000); +@@ -388,6 +393,7 @@ static void toneport_setup(struct usb_li + toneport_update_led(toneport); + + mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); ++ return 0; + } + + /* +@@ -451,7 +457,9 @@ static int toneport_init(struct usb_line + return err; + } + +- toneport_setup(toneport); ++ err = toneport_setup(toneport); ++ if (err) ++ return err; + + /* register audio system: */ + return snd_card_register(line6->card); +@@ -463,7 +471,11 @@ static int toneport_init(struct usb_line + */ + static int toneport_reset_resume(struct usb_interface *interface) + { +- toneport_setup(usb_get_intfdata(interface)); ++ int err; ++ ++ err = toneport_setup(usb_get_intfdata(interface)); ++ if (err) ++ return err; + return line6_resume(interface); + } + #endif diff --git a/queue-4.4/series b/queue-4.4/series index 306469dbe6a..206adbf360a 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -107,3 +107,4 @@ scsi-zfcp-reduce-flood-of-fcrscn1-trace-records-on-m.patch libata-fix-using-dma-buffers-on-stack.patch kconfig-mn-conf-handle-backspace-h-key.patch vfio-type1-limit-dma-mappings-per-container.patch +alsa-line6-use-dynamic-buffers.patch