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