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>

authored by Andreas Oberritter and committed by Mauro Carvalho Chehab dda06a8e 3d843c92

+19 -13
+9 -7
drivers/media/dvb/dvb-core/dmxdev.c
··· 364 enum dmx_success success) 365 { 366 struct dmxdev_filter *dmxdevfilter = filter->priv; 367 int ret; 368 369 if (dmxdevfilter->buffer.error) { 370 wake_up(&dmxdevfilter->buffer.queue); 371 return 0; 372 } 373 - spin_lock(&dmxdevfilter->dev->lock); 374 if (dmxdevfilter->state != DMXDEV_STATE_GO) { 375 - spin_unlock(&dmxdevfilter->dev->lock); 376 return 0; 377 } 378 del_timer(&dmxdevfilter->timer); ··· 392 } 393 if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) 394 dmxdevfilter->state = DMXDEV_STATE_DONE; 395 - spin_unlock(&dmxdevfilter->dev->lock); 396 wake_up(&dmxdevfilter->buffer.queue); 397 return 0; 398 } ··· 404 { 405 struct dmxdev_filter *dmxdevfilter = feed->priv; 406 struct dvb_ringbuffer *buffer; 407 int ret; 408 409 - spin_lock(&dmxdevfilter->dev->lock); 410 if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { 411 - spin_unlock(&dmxdevfilter->dev->lock); 412 return 0; 413 } 414 ··· 419 else 420 buffer = &dmxdevfilter->dev->dvr_buffer; 421 if (buffer->error) { 422 - spin_unlock(&dmxdevfilter->dev->lock); 423 wake_up(&buffer->queue); 424 return 0; 425 } ··· 430 dvb_ringbuffer_flush(buffer); 431 buffer->error = ret; 432 } 433 - spin_unlock(&dmxdevfilter->dev->lock); 434 wake_up(&buffer->queue); 435 return 0; 436 }
··· 364 enum dmx_success success) 365 { 366 struct dmxdev_filter *dmxdevfilter = filter->priv; 367 + unsigned long flags; 368 int ret; 369 370 if (dmxdevfilter->buffer.error) { 371 wake_up(&dmxdevfilter->buffer.queue); 372 return 0; 373 } 374 + spin_lock_irqsave(&dmxdevfilter->dev->lock, flags); 375 if (dmxdevfilter->state != DMXDEV_STATE_GO) { 376 + spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); 377 return 0; 378 } 379 del_timer(&dmxdevfilter->timer); ··· 391 } 392 if (dmxdevfilter->params.sec.flags & DMX_ONESHOT) 393 dmxdevfilter->state = DMXDEV_STATE_DONE; 394 + spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); 395 wake_up(&dmxdevfilter->buffer.queue); 396 return 0; 397 } ··· 403 { 404 struct dmxdev_filter *dmxdevfilter = feed->priv; 405 struct dvb_ringbuffer *buffer; 406 + unsigned long flags; 407 int ret; 408 409 + spin_lock_irqsave(&dmxdevfilter->dev->lock, flags); 410 if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) { 411 + spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); 412 return 0; 413 } 414 ··· 417 else 418 buffer = &dmxdevfilter->dev->dvr_buffer; 419 if (buffer->error) { 420 + spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); 421 wake_up(&buffer->queue); 422 return 0; 423 } ··· 428 dvb_ringbuffer_flush(buffer); 429 buffer->error = ret; 430 } 431 + spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags); 432 wake_up(&buffer->queue); 433 return 0; 434 }
+10 -6
drivers/media/dvb/dvb-core/dvb_demux.c
··· 399 void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, 400 size_t count) 401 { 402 - spin_lock(&demux->lock); 403 404 while (count--) { 405 if (buf[0] == 0x47) ··· 409 buf += 188; 410 } 411 412 - spin_unlock(&demux->lock); 413 } 414 415 EXPORT_SYMBOL(dvb_dmx_swfilter_packets); 416 417 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) 418 { 419 int p = 0, i, j; 420 421 - spin_lock(&demux->lock); 422 423 if (demux->tsbufp) { 424 i = demux->tsbufp; ··· 452 } 453 454 bailout: 455 - spin_unlock(&demux->lock); 456 } 457 458 EXPORT_SYMBOL(dvb_dmx_swfilter); 459 460 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) 461 { 462 int p = 0, i, j; 463 u8 tmppack[188]; 464 465 - spin_lock(&demux->lock); 466 467 if (demux->tsbufp) { 468 i = demux->tsbufp; ··· 504 } 505 506 bailout: 507 - spin_unlock(&demux->lock); 508 } 509 510 EXPORT_SYMBOL(dvb_dmx_swfilter_204);
··· 399 void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, 400 size_t count) 401 { 402 + unsigned long flags; 403 + 404 + spin_lock_irqsave(&demux->lock, flags); 405 406 while (count--) { 407 if (buf[0] == 0x47) ··· 407 buf += 188; 408 } 409 410 + spin_unlock_irqrestore(&demux->lock, flags); 411 } 412 413 EXPORT_SYMBOL(dvb_dmx_swfilter_packets); 414 415 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) 416 { 417 + unsigned long flags; 418 int p = 0, i, j; 419 420 + spin_lock_irqsave(&demux->lock, flags); 421 422 if (demux->tsbufp) { 423 i = demux->tsbufp; ··· 449 } 450 451 bailout: 452 + spin_unlock_irqrestore(&demux->lock, flags); 453 } 454 455 EXPORT_SYMBOL(dvb_dmx_swfilter); 456 457 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) 458 { 459 + unsigned long flags; 460 int p = 0, i, j; 461 u8 tmppack[188]; 462 463 + spin_lock_irqsave(&demux->lock, flags); 464 465 if (demux->tsbufp) { 466 i = demux->tsbufp; ··· 500 } 501 502 bailout: 503 + spin_unlock_irqrestore(&demux->lock, flags); 504 } 505 506 EXPORT_SYMBOL(dvb_dmx_swfilter_204);