aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Mester <ttmesterr@gmail.com>2014-01-06 23:29:24 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-01-13 08:05:57 -0500
commit4609981f84a23e8d481502f4728e0fed910abe03 (patch)
treee6550efdec073e3a5b7c4d4aeb0ccfed5333a37e
parentbbd8f3fef9d289fcfddaefccc2e5a2355da5d2f4 (diff)
[media] au8028: Fix cleanup on kzalloc fail
Free what was allocated if there is a failure allocating transfer buffers. Stop the feed on a start feed error. The stop feed is not always called if start feed fails. If the feed is not stopped on error, then the driver will be stuck so that it can never start feeding again. [m.chehab@samsung.com: CodingStyle cleanup] Signed-off-by: Tim Mester <tmester@ieee.org> Acked-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/media/usb/au0828/au0828-dvb.c71
-rw-r--r--drivers/media/usb/au0828/au0828.h2
2 files changed, 54 insertions, 19 deletions
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c
index 9a6f15613a38..3c718dbeae71 100644
--- a/drivers/media/usb/au0828/au0828-dvb.c
+++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -153,9 +153,11 @@ static int stop_urb_transfer(struct au0828_dev *dev)
153 153
154 dev->urb_streaming = 0; 154 dev->urb_streaming = 0;
155 for (i = 0; i < URB_COUNT; i++) { 155 for (i = 0; i < URB_COUNT; i++) {
156 usb_kill_urb(dev->urbs[i]); 156 if (dev->urbs[i]) {
157 kfree(dev->urbs[i]->transfer_buffer); 157 usb_kill_urb(dev->urbs[i]);
158 usb_free_urb(dev->urbs[i]); 158 kfree(dev->urbs[i]->transfer_buffer);
159 usb_free_urb(dev->urbs[i]);
160 }
159 } 161 }
160 162
161 return 0; 163 return 0;
@@ -185,6 +187,9 @@ static int start_urb_transfer(struct au0828_dev *dev)
185 if (!purb->transfer_buffer) { 187 if (!purb->transfer_buffer) {
186 usb_free_urb(purb); 188 usb_free_urb(purb);
187 dev->urbs[i] = NULL; 189 dev->urbs[i] = NULL;
190 printk(KERN_ERR
191 "%s: failed big buffer allocation, err = %d\n",
192 __func__, ret);
188 goto err; 193 goto err;
189 } 194 }
190 195
@@ -217,6 +222,27 @@ err:
217 return ret; 222 return ret;
218} 223}
219 224
225static void au0828_start_transport(struct au0828_dev *dev)
226{
227 au0828_write(dev, 0x608, 0x90);
228 au0828_write(dev, 0x609, 0x72);
229 au0828_write(dev, 0x60a, 0x71);
230 au0828_write(dev, 0x60b, 0x01);
231
232}
233
234static void au0828_stop_transport(struct au0828_dev *dev, int full_stop)
235{
236 if (full_stop) {
237 au0828_write(dev, 0x608, 0x00);
238 au0828_write(dev, 0x609, 0x00);
239 au0828_write(dev, 0x60a, 0x00);
240 }
241 au0828_write(dev, 0x60b, 0x00);
242}
243
244
245
220static int au0828_dvb_start_feed(struct dvb_demux_feed *feed) 246static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
221{ 247{
222 struct dvb_demux *demux = feed->demux; 248 struct dvb_demux *demux = feed->demux;
@@ -231,13 +257,17 @@ static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
231 257
232 if (dvb) { 258 if (dvb) {
233 mutex_lock(&dvb->lock); 259 mutex_lock(&dvb->lock);
260 dvb->start_count++;
261 dprintk(1, "%s(), start_count: %d, stop_count: %d\n", __func__,
262 dvb->start_count, dvb->stop_count);
234 if (dvb->feeding++ == 0) { 263 if (dvb->feeding++ == 0) {
235 /* Start transport */ 264 /* Start transport */
236 au0828_write(dev, 0x608, 0x90); 265 au0828_start_transport(dev);
237 au0828_write(dev, 0x609, 0x72);
238 au0828_write(dev, 0x60a, 0x71);
239 au0828_write(dev, 0x60b, 0x01);
240 ret = start_urb_transfer(dev); 266 ret = start_urb_transfer(dev);
267 if (ret < 0) {
268 au0828_stop_transport(dev, 0);
269 dvb->feeding--; /* We ran out of memory... */
270 }
241 } 271 }
242 mutex_unlock(&dvb->lock); 272 mutex_unlock(&dvb->lock);
243 } 273 }
@@ -256,10 +286,16 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
256 286
257 if (dvb) { 287 if (dvb) {
258 mutex_lock(&dvb->lock); 288 mutex_lock(&dvb->lock);
259 if (--dvb->feeding == 0) { 289 dvb->stop_count++;
260 /* Stop transport */ 290 dprintk(1, "%s(), start_count: %d, stop_count: %d\n", __func__,
261 ret = stop_urb_transfer(dev); 291 dvb->start_count, dvb->stop_count);
262 au0828_write(dev, 0x60b, 0x00); 292 if (dvb->feeding > 0) {
293 dvb->feeding--;
294 if (dvb->feeding == 0) {
295 /* Stop transport */
296 ret = stop_urb_transfer(dev);
297 au0828_stop_transport(dev, 0);
298 }
263 } 299 }
264 mutex_unlock(&dvb->lock); 300 mutex_unlock(&dvb->lock);
265 } 301 }
@@ -282,16 +318,10 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
282 318
283 /* Stop transport */ 319 /* Stop transport */
284 stop_urb_transfer(dev); 320 stop_urb_transfer(dev);
285 au0828_write(dev, 0x608, 0x00); 321 au0828_stop_transport(dev, 1);
286 au0828_write(dev, 0x609, 0x00);
287 au0828_write(dev, 0x60a, 0x00);
288 au0828_write(dev, 0x60b, 0x00);
289 322
290 /* Start transport */ 323 /* Start transport */
291 au0828_write(dev, 0x608, 0x90); 324 au0828_start_transport(dev);
292 au0828_write(dev, 0x609, 0x72);
293 au0828_write(dev, 0x60a, 0x71);
294 au0828_write(dev, 0x60b, 0x01);
295 start_urb_transfer(dev); 325 start_urb_transfer(dev);
296 326
297 mutex_unlock(&dvb->lock); 327 mutex_unlock(&dvb->lock);
@@ -375,6 +405,9 @@ static int dvb_register(struct au0828_dev *dev)
375 405
376 /* register network adapter */ 406 /* register network adapter */
377 dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); 407 dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
408
409 dvb->start_count = 0;
410 dvb->stop_count = 0;
378 return 0; 411 return 0;
379 412
380fail_fe_conn: 413fail_fe_conn:
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
index ef1f57f22be7..a00b400f8703 100644
--- a/drivers/media/usb/au0828/au0828.h
+++ b/drivers/media/usb/au0828/au0828.h
@@ -102,6 +102,8 @@ struct au0828_dvb {
102 struct dmx_frontend fe_mem; 102 struct dmx_frontend fe_mem;
103 struct dvb_net net; 103 struct dvb_net net;
104 int feeding; 104 int feeding;
105 int start_count;
106 int stop_count;
105}; 107};
106 108
107enum au0828_stream_state { 109enum au0828_stream_state {