Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] s5p-fimc: Add missing FIMC-LITE file operations locking

commit 5126f2590bee412e3053de851cb07f531e4be36a
"v4l2-dev: add flag to have the core lock all file operations"
introduced an additional bit flag (V4L2_FL_LOCK_ALL_FOPS) that
should be set by drivers that use the v4l2 core lock for all file
operations. Since this driver has been merged at the same time as
the core changes it doesn't set this flags and thus its all file
operations except IOCTL are not properly serialized. Fix this by
adding file ops locking in the driver.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Sylwester Nawrocki and committed by
Mauro Carvalho Chehab
4e39da01 5aedc109

+44 -17
+44 -17
drivers/media/video/s5p-fimc/fimc-lite.c
··· 453 453 struct fimc_lite *fimc = video_drvdata(file); 454 454 int ret; 455 455 456 + if (mutex_lock_interruptible(&fimc->lock)) 457 + return -ERESTARTSYS; 458 + 456 459 set_bit(ST_FLITE_IN_USE, &fimc->state); 457 460 ret = pm_runtime_get_sync(&fimc->pdev->dev); 458 461 if (ret < 0) 459 - return ret; 460 - 461 - if (++fimc->ref_count != 1 || fimc->out_path != FIMC_IO_DMA) 462 - return 0; 462 + goto done; 463 463 464 464 ret = v4l2_fh_open(file); 465 465 if (ret < 0) 466 - return ret; 466 + goto done; 467 467 468 - ret = fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd->entity, 469 - true); 470 - if (ret < 0) { 471 - pm_runtime_put_sync(&fimc->pdev->dev); 472 - fimc->ref_count--; 473 - v4l2_fh_release(file); 474 - clear_bit(ST_FLITE_IN_USE, &fimc->state); 468 + if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) { 469 + ret = fimc_pipeline_initialize(&fimc->pipeline, 470 + &fimc->vfd->entity, true); 471 + if (ret < 0) { 472 + pm_runtime_put_sync(&fimc->pdev->dev); 473 + fimc->ref_count--; 474 + v4l2_fh_release(file); 475 + clear_bit(ST_FLITE_IN_USE, &fimc->state); 476 + } 477 + 478 + fimc_lite_clear_event_counters(fimc); 475 479 } 476 - 477 - fimc_lite_clear_event_counters(fimc); 480 + done: 481 + mutex_unlock(&fimc->lock); 478 482 return ret; 479 483 } 480 484 481 485 static int fimc_lite_close(struct file *file) 482 486 { 483 487 struct fimc_lite *fimc = video_drvdata(file); 488 + int ret; 489 + 490 + if (mutex_lock_interruptible(&fimc->lock)) 491 + return -ERESTARTSYS; 484 492 485 493 if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) { 486 494 clear_bit(ST_FLITE_IN_USE, &fimc->state); ··· 502 494 if (fimc->ref_count == 0) 503 495 vb2_queue_release(&fimc->vb_queue); 504 496 505 - return v4l2_fh_release(file); 497 + ret = v4l2_fh_release(file); 498 + 499 + mutex_unlock(&fimc->lock); 500 + return ret; 506 501 } 507 502 508 503 static unsigned int fimc_lite_poll(struct file *file, 509 504 struct poll_table_struct *wait) 510 505 { 511 506 struct fimc_lite *fimc = video_drvdata(file); 512 - return vb2_poll(&fimc->vb_queue, file, wait); 507 + int ret; 508 + 509 + if (mutex_lock_interruptible(&fimc->lock)) 510 + return POLL_ERR; 511 + 512 + ret = vb2_poll(&fimc->vb_queue, file, wait); 513 + mutex_unlock(&fimc->lock); 514 + 515 + return ret; 513 516 } 514 517 515 518 static int fimc_lite_mmap(struct file *file, struct vm_area_struct *vma) 516 519 { 517 520 struct fimc_lite *fimc = video_drvdata(file); 518 - return vb2_mmap(&fimc->vb_queue, vma); 521 + int ret; 522 + 523 + if (mutex_lock_interruptible(&fimc->lock)) 524 + return -ERESTARTSYS; 525 + 526 + ret = vb2_mmap(&fimc->vb_queue, vma); 527 + mutex_unlock(&fimc->lock); 528 + 529 + return ret; 519 530 } 520 531 521 532 static const struct v4l2_file_operations fimc_lite_fops = {