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>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
3d843c92da
commit
dda06a8e46
@@ -364,15 +364,16 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
enum dmx_success success)
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = filter->priv;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (dmxdevfilter->buffer.error) {
|
||||
wake_up(&dmxdevfilter->buffer.queue);
|
||||
return 0;
|
||||
}
|
||||
spin_lock(&dmxdevfilter->dev->lock);
|
||||
spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
|
||||
if (dmxdevfilter->state != DMXDEV_STATE_GO) {
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
del_timer(&dmxdevfilter->timer);
|
||||
@@ -391,7 +392,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
}
|
||||
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
|
||||
dmxdevfilter->state = DMXDEV_STATE_DONE;
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
wake_up(&dmxdevfilter->buffer.queue);
|
||||
return 0;
|
||||
}
|
||||
@@ -403,11 +404,12 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = feed->priv;
|
||||
struct dvb_ringbuffer *buffer;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock(&dmxdevfilter->dev->lock);
|
||||
spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
|
||||
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -417,7 +419,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
else
|
||||
buffer = &dmxdevfilter->dev->dvr_buffer;
|
||||
if (buffer->error) {
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
wake_up(&buffer->queue);
|
||||
return 0;
|
||||
}
|
||||
@@ -428,7 +430,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
dvb_ringbuffer_flush(buffer);
|
||||
buffer->error = ret;
|
||||
}
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
wake_up(&buffer->queue);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user