Re: [PATCH v4 14/79] media: am437x: fix pm_runtime_get_sync() usage count
From: Mauro Carvalho Chehab
Date: Tue May 04 2021 - 03:19:26 EST
Em Fri, 30 Apr 2021 17:36:46 +0100
Jonathan Cameron <Jonathan.Cameron@xxxxxxxxxx> escreveu:
> On Wed, 28 Apr 2021 16:51:35 +0200
> Mauro Carvalho Chehab <mchehab+huawei@xxxxxxxxxx> wrote:
>
> > The pm_runtime_get_sync() internally increments the
> > dev->power.usage_count without decrementing it, even on errors.
> > Replace it by the new pm_runtime_resume_and_get(), introduced by:
> > commit dd8088d5a896 ("PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter")
> > in order to properly decrement the usage counter and avoid memory
> > leaks.
> >
> > While here, ensure that the driver will check if PM runtime
> > resumed at vpfe_initialize_device().
> >
> > Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@xxxxxxxxxx>
>
> resume and suspend carrying regardless needs a comment I think.
> (see below)
> > ---
> > drivers/media/platform/am437x/am437x-vpfe.c | 22 +++++++++++++++------
> > 1 file changed, 16 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
> > index 6cdc77dda0e4..bced526f30f2 100644
> > --- a/drivers/media/platform/am437x/am437x-vpfe.c
> > +++ b/drivers/media/platform/am437x/am437x-vpfe.c
> > @@ -1021,7 +1021,9 @@ static int vpfe_initialize_device(struct vpfe_device *vpfe)
> > if (ret)
> > return ret;
> >
> > - pm_runtime_get_sync(vpfe->pdev);
> > + ret = pm_runtime_resume_and_get(vpfe->pdev);
> > + if (ret < 0)
> > + return ret;
> >
> > vpfe_config_enable(&vpfe->ccdc, 1);
> >
> > @@ -2443,7 +2445,11 @@ static int vpfe_probe(struct platform_device *pdev)
> > pm_runtime_enable(&pdev->dev);
> >
> > /* for now just enable it here instead of waiting for the open */
> > - pm_runtime_get_sync(&pdev->dev);
> > + ret = pm_runtime_resume_and_get(&pdev->dev);
> > + if (ret < 0) {
> > + vpfe_err(vpfe, "Unable to resume device.\n");
> > + goto probe_out_v4l2_unregister;
> > + }
> >
> > vpfe_ccdc_config_defaults(ccdc);
> >
> > @@ -2527,10 +2533,11 @@ static int vpfe_suspend(struct device *dev)
> > {
> > struct vpfe_device *vpfe = dev_get_drvdata(dev);
> > struct vpfe_ccdc *ccdc = &vpfe->ccdc;
> > + int ret;
> >
> > /* only do full suspend if streaming has started */
> > if (vb2_start_streaming_called(&vpfe->buffer_queue)) {
> > - pm_runtime_get_sync(dev);
> > + ret = pm_runtime_resume_and_get(dev);
>
> Carrying on when you know the resume failed, seems interesting enough to
> deserve a comment in the code. Not sure you can usefully do anything
> but it seems likely a lot of the calls that follow will fail.
This driver indeed has a different behavior. What most drivers do is to
either resume RPM when a V4L2 devnode is opened, or when the device
starts to stream. This one does, instead, at probing time.
It even has a comment there which implies that this is something that may
require changes in the future:
static int vpfe_probe(struct platform_device *pdev)
{
...
/* for now just enable it here instead of waiting for the open */
ret = pm_runtime_resume_and_get(&pdev->dev);
After probe, the driver just assumes that RPM is not suspended during its
entire lifetime (except suspend/resuume).
I can't even see a check at vpfe_open() or at vpfe_start_streaming()
that would cause the functions to fail if, for whatever reason, RPM is
suspended there[1], or if a command sent to the hardware failed.
[1] The only place where there's a check is at v4l2_subdev_call(),
asking sensors to start streaming. If those are on a different
power domain, a valid sensor answer call won't ensure that
am437x VPFE is operational.
Yet, suspend/resume only checks if videobuf2 started its streaming
logic. if streaming was started, suspend/resume logic tries ensure
that the hardware will be ready to be suspended, restoring it to
the previous state before at resume time, but neither one of those
has a check to see if the commands were succeeded, just like the
logic at vpfe_start_streaming().
-
In summary, I'll add a comment there, but fixing it would require
adding error checks on several places (open, start_streaming,
resume and suspend).
Thanks,
Mauro