Control: tag -1 patch moreinfo Please test whether the attached patches fix this. You can find instructions for rebuilding the kernel package at: https://kernel-handbook.alioth.debian.org/ch-common-tasks.html#s-common-official Ben. -- Ben Hutchings Design a system any fool can use, and only a fool will want to use it.
From: Ben Hutchings <ben@decadent.org.uk>
Date: Fri, 27 Jan 2017 00:28:33 +0000
Subject: [1/2] ALSA: line6: toneport: Add error checks to toneport_setup()
etc.
Origin: https://git.kernel.org/linus/fc5e7a3683e1a0ce039c7ed8440ae49d60e6dfd6
Bug-Debian: https://bugs.debian.org/852749
toneport_setup() currently ignores all errors and returns void. Make
it and toneport_update_led() report errors, and make toneport_init()
check for this.
Fixes: 705ececd1c60 ("Staging: add line6 usb driver")
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
sound/usb/line6/toneport.c | 43 +++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index 8e22f430d700..646c27a79f68 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -294,11 +294,11 @@ static bool toneport_has_led(struct usb_line6_toneport *toneport)
static const char * const led_colors[2] = { "red", "green" };
static const int led_init_vals[2] = { 0x00, 0x26 };
-static void toneport_update_led(struct usb_line6_toneport *toneport)
+static int toneport_update_led(struct usb_line6_toneport *toneport)
{
- toneport_send_cmd(toneport->line6.usbdev,
- (toneport->leds[0].dev.brightness << 8) | 0x0002,
- toneport->leds[1].dev.brightness);
+ return toneport_send_cmd(toneport->line6.usbdev,
+ (toneport->leds[0].dev.brightness << 8) | 0x0002,
+ toneport->leds[1].dev.brightness);
}
static void toneport_led_brightness_set(struct led_classdev *led_cdev,
@@ -365,29 +365,42 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport)
/*
Setup Toneport device.
*/
-static void toneport_setup(struct usb_line6_toneport *toneport)
+static int toneport_setup(struct usb_line6_toneport *toneport)
{
int ticks;
struct usb_line6 *line6 = &toneport->line6;
struct usb_device *usbdev = line6->usbdev;
+ int err;
/* sync time on device with host: */
ticks = (int)get_seconds();
- line6_write_data(line6, 0x80c6, &ticks, 4);
+ err = line6_write_data(line6, 0x80c6, &ticks, 4);
+ if (err < 0)
+ return err;
/* enable device: */
- toneport_send_cmd(usbdev, 0x0301, 0x0000);
+ err = toneport_send_cmd(usbdev, 0x0301, 0x0000);
+ if (err < 0)
+ return err;
/* initialize source select: */
- if (toneport_has_source_select(toneport))
- toneport_send_cmd(usbdev,
- toneport_source_info[toneport->source].code,
- 0x0000);
+ if (toneport_has_source_select(toneport)) {
+ err = toneport_send_cmd(usbdev,
+ toneport_source_info[toneport->source].code,
+ 0x0000);
+ if (err < 0)
+ return err;
+ }
- if (toneport_has_led(toneport))
- toneport_update_led(toneport);
+ if (toneport_has_led(toneport)) {
+ err = toneport_update_led(toneport);
+ if (err < 0)
+ return err;
+ }
mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ);
+
+ return 0;
}
/*
@@ -451,7 +464,9 @@ static int toneport_init(struct usb_line6 *line6,
return err;
}
- toneport_setup(toneport);
+ err = toneport_setup(toneport);
+ if (err < 0)
+ return err;
/* register audio system: */
return snd_card_register(line6->card);
From: Ben Hutchings <ben@decadent.org.uk>
Date: Fri, 27 Jan 2017 00:40:49 +0000
Subject: [2/2] ALSA: line6: Move USB message buffers off-stack
Origin: https://git.kernel.org/linus/13d338f1016e8898c98faa9c790d7056ef934307
Bug-Debian: https://bugs.debian.org/852749
Allocating USB buffers on the stack is not portable, and no longer
works on x86_64 (with VMAP_STACK enabled as per default).
Fixes: 705ececd1c60 ("Staging: add line6 usb driver")
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
sound/usb/line6/driver.c | 64 +++++++++++++++++++++++++++++-----------------
sound/usb/line6/podhd.c | 22 ++++++++++------
sound/usb/line6/toneport.c | 10 +++++---
3 files changed, 61 insertions(+), 35 deletions(-)
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
index 90009c0b3a92..b3a7f0c809da 100644
--- a/sound/usb/line6/driver.c
+++ b/sound/usb/line6/driver.c
@@ -337,12 +337,16 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
{
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(1, GFP_ATOMIC);
+ 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,
@@ -351,7 +355,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
if (ret < 0) {
dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
- return ret;
+ goto out;
}
/* Wait for data length. We'll get 0xff until length arrives. */
@@ -361,28 +365,30 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
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 out;
}
- if (len != 0xff)
+ if (*len != 0xff)
break;
}
- if (len == 0xff) {
+ if (*len == 0xff) {
dev_err(line6->ifcdev, "read failed after %d retries\n",
count);
- return -EIO;
- } else if (len != datalen) {
+ ret = -EIO;
+ goto out;
+ } 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);
+ ret = -EIO;
+ goto out;
}
/* receive the result: */
@@ -391,12 +397,14 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data,
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;
- }
+ else
+ ret = 0;
- return 0;
+out:
+ kfree(len);
+ return ret;
}
EXPORT_SYMBOL_GPL(line6_read_data);
@@ -408,12 +416,16 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
{
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(1, GFP_ATOMIC);
+ 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,
@@ -422,7 +434,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
if (ret < 0) {
dev_err(line6->ifcdev,
"write request failed (error %d)\n", ret);
- return ret;
+ goto out;
}
for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
@@ -433,28 +445,32 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data,
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 out;
}
- 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;
+ } else {
+ ret = 0;
}
- return 0;
+out:
+ kfree(status);
+ return ret;
}
EXPORT_SYMBOL_GPL(line6_write_data);
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
index 6ab23e5aee71..b59939fa4d27 100644
--- a/sound/usb/line6/podhd.c
+++ b/sound/usb/line6/podhd.c
@@ -222,28 +222,32 @@ static void podhd_startup_start_workqueue(unsigned long data)
static int podhd_dev_start(struct usb_line6_podhd *pod)
{
int ret;
- u8 init_bytes[8];
+ u8 *init_bytes;
int i;
struct usb_device *usbdev = pod->line6.usbdev;
+ init_bytes = kmalloc(8, GFP_ATOMIC);
+ if (!init_bytes)
+ return -ENOMEM;
+
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x11, 0,
NULL, 0, LINE6_TIMEOUT * HZ);
if (ret < 0) {
dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret);
- return ret;
+ goto out;
}
/* NOTE: looks like some kind of ping message */
ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
0x11, 0x0,
- &init_bytes, 3, LINE6_TIMEOUT * HZ);
+ init_bytes, 3, LINE6_TIMEOUT * HZ);
if (ret < 0) {
dev_err(pod->line6.ifcdev,
"receive length failed (error %d)\n", ret);
- return ret;
+ goto out;
}
pod->firmware_version =
@@ -252,7 +256,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod)
for (i = 0; i <= 16; i++) {
ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8);
if (ret < 0)
- return ret;
+ goto out;
}
ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
@@ -260,10 +264,12 @@ static int podhd_dev_start(struct usb_line6_podhd *pod)
USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT,
1, 0,
NULL, 0, LINE6_TIMEOUT * HZ);
- if (ret < 0)
- return ret;
+ if (ret > 0)
+ ret = 0;
- return 0;
+out:
+ kfree(init_bytes);
+ return ret;
}
static void podhd_startup_workqueue(struct work_struct *work)
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index 646c27a79f68..62998af0db0b 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -367,14 +367,18 @@ static bool toneport_has_source_select(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;
int err;
/* sync time on device with host: */
- ticks = (int)get_seconds();
- err = line6_write_data(line6, 0x80c6, &ticks, 4);
+ ticks = kmalloc(sizeof(*ticks), GFP_ATOMIC);
+ if (!ticks)
+ return -ENOMEM;
+ *ticks = (int)get_seconds();
+ err = line6_write_data(line6, 0x80c6, ticks, 4);
+ kfree(ticks);
if (err < 0)
return err;
Attachment:
signature.asc
Description: This is a digitally signed message part