]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 May 2019 09:22:14 +0000 (11:22 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 4 May 2019 09:22:14 +0000 (11:22 +0200)
added patches:
alsa-line6-use-dynamic-buffers.patch

queue-4.4/alsa-line6-use-dynamic-buffers.patch [new file with mode: 0644]
queue-4.4/series

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 (file)
index 0000000..be7a63d
--- /dev/null
@@ -0,0 +1,235 @@
+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
index 306469dbe6a9a7f68c7895621e15b3f266f0d2ea..206adbf360a34b101ce53f5daee5c9709c9abed3 100644 (file)
@@ -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