Dear Mita-san,
On Mon, May 21, 2018 at 12:40:38AM +0900, Akinobu Mita wrote:
> The open() operation for the pxa_camera driver always calls s_power()
> operation to put its subdevice sensor in normal operation mode, and the
> release() operation always call s_power() operation to put the subdevice
> in power saving mode.
>
> This requires the subdevice sensor driver to keep track of its power
> state in order to avoid putting the subdevice in power saving mode while
> the device is still opened by some users.
>
> Many subdevice drivers handle it by the boilerplate code that increments
> and decrements an internal counter in s_power() like below:
>
> /*
> * If the power count is modified from 0 to != 0 or from != 0 to 0,
> * update the power state.
> */
> if (sensor->power_count == !on) {
> ret = ov5640_set_power(sensor, !!on);
> if (ret)
> goto out;
> }
>
> /* Update the power count. */
> sensor->power_count += on ? 1 : -1;
>
> However, some subdevice drivers don't handle it and may cause a problem
> with the pxa_camera driver if the video device is opened by more than
> two users at the same time.
>
> Instead of propagating the boilerplate code for each subdevice driver
> that implement s_power, this introduces an trick that many V4L2 drivers
> are using with v4l2_fh_is_singular_file().
I'd rather like that the sub-device drivers would move to use runtime PM
instead of depending on the s_power() callback. It's much cleaner that way.
It's not a near-term solution though. The approach seems fine, please see
comments below though.
>
> Cc: Sakari Ailus <[email protected]>
> Cc: Mauro Carvalho Chehab <[email protected]>
> Signed-off-by: Akinobu Mita <[email protected]>
> ---
> drivers/media/platform/pxa_camera.c | 17 ++++++++++++-----
> 1 file changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/media/platform/pxa_camera.c
> b/drivers/media/platform/pxa_camera.c
> index c71a007..c792cb1 100644
> --- a/drivers/media/platform/pxa_camera.c
> +++ b/drivers/media/platform/pxa_camera.c
> @@ -2040,6 +2040,9 @@ static int pxac_fops_camera_open(struct file *filp)
> if (ret < 0)
> goto out;
>
> + if (!v4l2_fh_is_singular_file(filp))
> + goto out;
> +
> ret = sensor_call(pcdev, core, s_power, 1);
> if (ret)
> v4l2_fh_release(filp);
> @@ -2052,13 +2055,17 @@ static int pxac_fops_camera_release(struct file *filp)
> {
> struct pxa_camera_dev *pcdev = video_drvdata(filp);
> int ret;
> -
> - ret = vb2_fop_release(filp);
> - if (ret < 0)
> - return ret;
> + bool fh_singular;
>
> mutex_lock(&pcdev->mlock);
> - ret = sensor_call(pcdev, core, s_power, 0);
> +
> + fh_singular = v4l2_fh_is_singular_file(filp);
> +
> + ret = _vb2_fop_release(filp, NULL);
I'm not sure whether using the return value to return an error from release
is really useful. If you want to use it, I'd shout loud instead.
> +
> + if (fh_singular)
ret assigned previously is overwritten here without checking.
> + ret = sensor_call(pcdev, core, s_power, 0);
> +
> mutex_unlock(&pcdev->mlock);
>
> return ret;
--
Sakari Ailus
[email protected]