aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Oberritter <obi@linuxtv.org>2008-09-24 04:00:37 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-04 21:59:55 -0400
commitdda06a8e4610757def753ee3a541a0b1a1feb36b (patch)
tree54e2b56b4c46b90100b9b00493497ee389887eae
parent3d843c92da5a1f1ab2cbc2b2e04f84d5ecedf5aa (diff)
V4L/DVB (9029): Fix deadlock in demux code
The functions dvb_dmxdev_section_callback, dvb_dmxdev_ts_callback, dvb_dmx_swfilter_packet, dvb_dmx_swfilter_packets, dvb_dmx_swfilter and dvb_dmx_swfilter_204 may be called from both interrupt and process context. Therefore they need to be protected by spin_lock_irqsave() instead of spin_lock(). This fixes a deadlock discovered by lockdep. Signed-off-by: Andreas Oberritter <obi@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c16
2 files changed, 19 insertions, 13 deletions
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 069d847ba887..0c733c66a441 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -364,15 +364,16 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
364 enum dmx_success success) 364 enum dmx_success success)
365{ 365{
366 struct dmxdev_filter *dmxdevfilter = filter->priv; 366 struct dmxdev_filter *dmxdevfilter = filter->priv;
367 unsigned long flags;
367 int ret; 368 int ret;
368 369
369 if (dmxdevfilter->buffer.error) { 370 if (dmxdevfilter->buffer.error) {
370 wake_up(&dmxdevfilter->buffer.queue); 371 wake_up(&dmxdevfilter->buffer.queue);
371 return 0; 372 return 0;
372 } 373 }
373 spin_lock(&dmxdevfilter->dev->lock); 374 spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
374 if (dmxdevfilter->state != DMXDEV_STATE_GO) { 375 if (dmxdevfilter->state != DMXDEV_STATE_GO) {
375 spin_unlock(&dmxdevfilter->dev->lock); 376 spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
376 return 0; 377 return 0;
377 } 378 }
378 del_timer(&dmxdevfilter->timer); 379 del_timer(&dmxdevfilter->timer);
@@ -391,7 +392,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
391 } 392 }
392 if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) 393 if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
393 dmxdevfilter->state = DMXDEV_STATE_DONE; 394 dmxdevfilter->state = DMXDEV_STATE_DONE;
394 spin_unlock(&dmxdevfilter->dev->lock); 395 spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
395 wake_up(&dmxdevfilter->buffer.queue); 396 wake_up(&dmxdevfilter->buffer.queue);
396 return 0; 397 return 0;
397} 398}
@@ -403,11 +404,12 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
403{ 404{
404 struct dmxdev_filter *dmxdevfilter = feed->priv; 405 struct dmxdev_filter *dmxdevfilter = feed->priv;
405 struct dvb_ringbuffer *buffer; 406 struct dvb_ringbuffer *buffer;
407 unsigned long flags;
406 int ret; 408 int ret;
407 409
408 spin_lock(&dmxdevfilter->dev->lock); 410 spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
409 if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { 411 if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
410 spin_unlock(&dmxdevfilter->dev->lock); 412 spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
411 return 0; 413 return 0;
412 } 414 }
413 415
@@ -417,7 +419,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
417 else 419 else
418 buffer = &dmxdevfilter->dev->dvr_buffer; 420 buffer = &dmxdevfilter->dev->dvr_buffer;
419 if (buffer->error) { 421 if (buffer->error) {
420 spin_unlock(&dmxdevfilter->dev->lock); 422 spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
421 wake_up(&buffer->queue); 423 wake_up(&buffer->queue);
422 return 0; 424 return 0;
423 } 425 }
@@ -428,7 +430,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
428 dvb_ringbuffer_flush(buffer); 430 dvb_ringbuffer_flush(buffer);
429 buffer->error = ret; 431 buffer->error = ret;
430 } 432 }
431 spin_unlock(&dmxdevfilter->dev->lock); 433 spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
432 wake_up(&buffer->queue); 434 wake_up(&buffer->queue);
433 return 0; 435 return 0;
434} 436}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index e2eca0b1fe7c..a2c1fd5d2f67 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -399,7 +399,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
399void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, 399void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
400 size_t count) 400 size_t count)
401{ 401{
402 spin_lock(&demux->lock); 402 unsigned long flags;
403
404 spin_lock_irqsave(&demux->lock, flags);
403 405
404 while (count--) { 406 while (count--) {
405 if (buf[0] == 0x47) 407 if (buf[0] == 0x47)
@@ -407,16 +409,17 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
407 buf += 188; 409 buf += 188;
408 } 410 }
409 411
410 spin_unlock(&demux->lock); 412 spin_unlock_irqrestore(&demux->lock, flags);
411} 413}
412 414
413EXPORT_SYMBOL(dvb_dmx_swfilter_packets); 415EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
414 416
415void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) 417void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
416{ 418{
419 unsigned long flags;
417 int p = 0, i, j; 420 int p = 0, i, j;
418 421
419 spin_lock(&demux->lock); 422 spin_lock_irqsave(&demux->lock, flags);
420 423
421 if (demux->tsbufp) { 424 if (demux->tsbufp) {
422 i = demux->tsbufp; 425 i = demux->tsbufp;
@@ -449,17 +452,18 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
449 } 452 }
450 453
451bailout: 454bailout:
452 spin_unlock(&demux->lock); 455 spin_unlock_irqrestore(&demux->lock, flags);
453} 456}
454 457
455EXPORT_SYMBOL(dvb_dmx_swfilter); 458EXPORT_SYMBOL(dvb_dmx_swfilter);
456 459
457void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) 460void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
458{ 461{
462 unsigned long flags;
459 int p = 0, i, j; 463 int p = 0, i, j;
460 u8 tmppack[188]; 464 u8 tmppack[188];
461 465
462 spin_lock(&demux->lock); 466 spin_lock_irqsave(&demux->lock, flags);
463 467
464 if (demux->tsbufp) { 468 if (demux->tsbufp) {
465 i = demux->tsbufp; 469 i = demux->tsbufp;
@@ -500,7 +504,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
500 } 504 }
501 505
502bailout: 506bailout:
503 spin_unlock(&demux->lock); 507 spin_unlock_irqrestore(&demux->lock, flags);
504} 508}
505 509
506EXPORT_SYMBOL(dvb_dmx_swfilter_204); 510EXPORT_SYMBOL(dvb_dmx_swfilter_204);