--- /dev/null
+From e5c812e84f0dece3400d5caf42522287e6ef139f Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Sun, 28 Apr 2019 18:04:11 +0200
+Subject: ALSA: line6: use dynamic buffers
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+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 <gouws.christo@gmail.com>
+Reported-by: Alan Stern <stern@rowland.harvard.edu>
+Tested-by: Christo Gouws <gouws.christo@gmail.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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