diff options
author | Andreas Oberritter <obi@linuxtv.org> | 2008-09-24 04:00:37 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-04 21:59:55 -0400 |
commit | dda06a8e4610757def753ee3a541a0b1a1feb36b (patch) | |
tree | 54e2b56b4c46b90100b9b00493497ee389887eae /drivers/media/dvb/dvb-core/dmxdev.c | |
parent | 3d843c92da5a1f1ab2cbc2b2e04f84d5ecedf5aa (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>
Diffstat (limited to 'drivers/media/dvb/dvb-core/dmxdev.c')
-rw-r--r-- | drivers/media/dvb/dvb-core/dmxdev.c | 16 |
1 files changed, 9 insertions, 7 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 | } |