]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.4.180/alsa-line6-use-dynamic-buffers.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.4.180 / alsa-line6-use-dynamic-buffers.patch
CommitLineData
5132e7f8
GKH
1From e5c812e84f0dece3400d5caf42522287e6ef139f Mon Sep 17 00:00:00 2001
2From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
3Date: Sun, 28 Apr 2019 18:04:11 +0200
4Subject: ALSA: line6: use dynamic buffers
5
6From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
7
8commit e5c812e84f0dece3400d5caf42522287e6ef139f upstream.
9
10The line6 driver uses a lot of USB buffers off of the stack, which is
11not allowed on many systems, causing the driver to crash on some of
12them. Fix this up by dynamically allocating the buffers with kmalloc()
13which allows for proper DMA-able memory.
14
15Reported-by: Christo Gouws <gouws.christo@gmail.com>
16Reported-by: Alan Stern <stern@rowland.harvard.edu>
17Tested-by: Christo Gouws <gouws.christo@gmail.com>
18Cc: stable <stable@vger.kernel.org>
19Signed-off-by: Takashi Iwai <tiwai@suse.de>
20Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
21
22---
23 sound/usb/line6/driver.c | 60 ++++++++++++++++++++++++++-------------------
24 sound/usb/line6/toneport.c | 24 +++++++++++++-----
25 2 files changed, 53 insertions(+), 31 deletions(-)
26
27--- a/sound/usb/line6/driver.c
28+++ b/sound/usb/line6/driver.c
29@@ -307,12 +307,16 @@ int line6_read_data(struct usb_line6 *li
30 {
31 struct usb_device *usbdev = line6->usbdev;
32 int ret;
33- unsigned char len;
34+ unsigned char *len;
35 unsigned count;
36
37 if (address > 0xffff || datalen > 0xff)
38 return -EINVAL;
39
40+ len = kmalloc(sizeof(*len), GFP_KERNEL);
41+ if (!len)
42+ return -ENOMEM;
43+
44 /* query the serial number: */
45 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
46 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
47@@ -321,7 +325,7 @@ int line6_read_data(struct usb_line6 *li
48
49 if (ret < 0) {
50 dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
51- return ret;
52+ goto exit;
53 }
54
55 /* Wait for data length. We'll get 0xff until length arrives. */
56@@ -331,28 +335,29 @@ int line6_read_data(struct usb_line6 *li
57 ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
58 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
59 USB_DIR_IN,
60- 0x0012, 0x0000, &len, 1,
61+ 0x0012, 0x0000, len, 1,
62 LINE6_TIMEOUT * HZ);
63 if (ret < 0) {
64 dev_err(line6->ifcdev,
65 "receive length failed (error %d)\n", ret);
66- return ret;
67+ goto exit;
68 }
69
70- if (len != 0xff)
71+ if (*len != 0xff)
72 break;
73 }
74
75- if (len == 0xff) {
76+ ret = -EIO;
77+ if (*len == 0xff) {
78 dev_err(line6->ifcdev, "read failed after %d retries\n",
79 count);
80- return -EIO;
81- } else if (len != datalen) {
82+ goto exit;
83+ } else if (*len != datalen) {
84 /* should be equal or something went wrong */
85 dev_err(line6->ifcdev,
86 "length mismatch (expected %d, got %d)\n",
87- (int)datalen, (int)len);
88- return -EIO;
89+ (int)datalen, (int)*len);
90+ goto exit;
91 }
92
93 /* receive the result: */
94@@ -361,12 +366,12 @@ int line6_read_data(struct usb_line6 *li
95 0x0013, 0x0000, data, datalen,
96 LINE6_TIMEOUT * HZ);
97
98- if (ret < 0) {
99+ if (ret < 0)
100 dev_err(line6->ifcdev, "read failed (error %d)\n", ret);
101- return ret;
102- }
103
104- return 0;
105+exit:
106+ kfree(len);
107+ return ret;
108 }
109 EXPORT_SYMBOL_GPL(line6_read_data);
110
111@@ -378,12 +383,16 @@ int line6_write_data(struct usb_line6 *l
112 {
113 struct usb_device *usbdev = line6->usbdev;
114 int ret;
115- unsigned char status;
116+ unsigned char *status;
117 int count;
118
119 if (address > 0xffff || datalen > 0xffff)
120 return -EINVAL;
121
122+ status = kmalloc(sizeof(*status), GFP_KERNEL);
123+ if (!status)
124+ return -ENOMEM;
125+
126 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
127 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
128 0x0022, address, data, datalen,
129@@ -392,7 +401,7 @@ int line6_write_data(struct usb_line6 *l
130 if (ret < 0) {
131 dev_err(line6->ifcdev,
132 "write request failed (error %d)\n", ret);
133- return ret;
134+ goto exit;
135 }
136
137 for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) {
138@@ -403,28 +412,29 @@ int line6_write_data(struct usb_line6 *l
139 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
140 USB_DIR_IN,
141 0x0012, 0x0000,
142- &status, 1, LINE6_TIMEOUT * HZ);
143+ status, 1, LINE6_TIMEOUT * HZ);
144
145 if (ret < 0) {
146 dev_err(line6->ifcdev,
147 "receiving status failed (error %d)\n", ret);
148- return ret;
149+ goto exit;
150 }
151
152- if (status != 0xff)
153+ if (*status != 0xff)
154 break;
155 }
156
157- if (status == 0xff) {
158+ if (*status == 0xff) {
159 dev_err(line6->ifcdev, "write failed after %d retries\n",
160 count);
161- return -EIO;
162- } else if (status != 0) {
163+ ret = -EIO;
164+ } else if (*status != 0) {
165 dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
166- return -EIO;
167+ ret = -EIO;
168 }
169-
170- return 0;
171+exit:
172+ kfree(status);
173+ return ret;
174 }
175 EXPORT_SYMBOL_GPL(line6_write_data);
176
177--- a/sound/usb/line6/toneport.c
178+++ b/sound/usb/line6/toneport.c
179@@ -365,15 +365,20 @@ static bool toneport_has_source_select(s
180 /*
181 Setup Toneport device.
182 */
183-static void toneport_setup(struct usb_line6_toneport *toneport)
184+static int toneport_setup(struct usb_line6_toneport *toneport)
185 {
186- int ticks;
187+ int *ticks;
188 struct usb_line6 *line6 = &toneport->line6;
189 struct usb_device *usbdev = line6->usbdev;
190
191+ ticks = kmalloc(sizeof(*ticks), GFP_KERNEL);
192+ if (!ticks)
193+ return -ENOMEM;
194+
195 /* sync time on device with host: */
196- ticks = (int)get_seconds();
197- line6_write_data(line6, 0x80c6, &ticks, 4);
198+ *ticks = (int)get_seconds();
199+ line6_write_data(line6, 0x80c6, ticks, 4);
200+ kfree(ticks);
201
202 /* enable device: */
203 toneport_send_cmd(usbdev, 0x0301, 0x0000);
204@@ -388,6 +393,7 @@ static void toneport_setup(struct usb_li
205 toneport_update_led(toneport);
206
207 mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ);
208+ return 0;
209 }
210
211 /*
212@@ -451,7 +457,9 @@ static int toneport_init(struct usb_line
213 return err;
214 }
215
216- toneport_setup(toneport);
217+ err = toneport_setup(toneport);
218+ if (err)
219+ return err;
220
221 /* register audio system: */
222 return snd_card_register(line6->card);
223@@ -463,7 +471,11 @@ static int toneport_init(struct usb_line
224 */
225 static int toneport_reset_resume(struct usb_interface *interface)
226 {
227- toneport_setup(usb_get_intfdata(interface));
228+ int err;
229+
230+ err = toneport_setup(usb_get_intfdata(interface));
231+ if (err)
232+ return err;
233 return line6_resume(interface);
234 }
235 #endif