[PATCH] gpu: anx7808: fix a missing check of return value

Kangjie Lu kjlu at umn.edu
Fri Dec 21 20:51:56 UTC 2018


Thanks for the tip! Will submit patch V2 soon.

On Thu, Dec 20, 2018 at 11:07 PM Laurent Pinchart <
laurent.pinchart at ideasonboard.com> wrote:

> Hi Kangjie,
>
> Thank you for the patch.
>
> On Thursday, 20 December 2018 09:41:16 EET Kangjie Lu wrote:
> > Both anx78xx_set_bits() and anx78xx_clear_bits() in the poweron process
> > may fail. The fix inserts checks for their return values. If the poweron
> > process fails, it calls anx78xx_poweroff().
> >
> > Signed-off-by: Kangjie Lu <kjlu at umn.edu>
> > ---
> >  drivers/gpu/drm/bridge/analogix-anx78xx.c | 26 ++++++++++++++++-------
> >  1 file changed, 18 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c
> > b/drivers/gpu/drm/bridge/analogix-anx78xx.c index
> > f8433c93f463..a57104c71739 100644
> > --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
> > +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> > @@ -610,20 +610,20 @@ static int anx78xx_enable_interrupts(struct anx78xx
> > *anx78xx) return 0;
> >  }
> >
> > -static void anx78xx_poweron(struct anx78xx *anx78xx)
> > +static int anx78xx_poweron(struct anx78xx *anx78xx)
> >  {
> >       struct anx78xx_platform_data *pdata = &anx78xx->pdata;
> > -     int err;
> > +     int err = 0;
> >
> >       if (WARN_ON(anx78xx->powered))
> > -             return;
> > +             return err;
>
> You can return 0 here.
>
> >
> >       if (pdata->dvdd10) {
> >               err = regulator_enable(pdata->dvdd10);
> >               if (err) {
> >                       DRM_ERROR("Failed to enable DVDD10 regulator:
> %d\n",
> >                                 err);
> > -                     return;
> > +                     return err;
> >               }
> >
> >               usleep_range(1000, 2000);
> > @@ -638,12 +638,18 @@ static void anx78xx_poweron(struct anx78xx
> *anx78xx)
> >       gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
> >
> >       /* Power on registers module */
> > -     anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P2],
> SP_POWERDOWN_CTRL_REG,
> > +     err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P2],
> SP_POWERDOWN_CTRL_REG,
> > SP_HDCP_PD | SP_AUDIO_PD | SP_VIDEO_PD | SP_LINK_PD);
> > -     anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P2],
> SP_POWERDOWN_CTRL_REG,
> > +     err |= anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P2],
> > SP_POWERDOWN_CTRL_REG, SP_REGISTER_PD | SP_TOTAL_PD);
>
> If both functions fail with a different error code, this may result in a
> meaningless error being returned. One option is to do
>
>         err = anx78xx_set_bits(...);
>         if (!err)
>                 err = anx78xx_clear_bits(...);
>
> The construct gets quickly ugly though, so I sometimes define register
> accessors as taking an int * for the error code instead of returning it.
>
> void write(..., int *status)
> {
>         if (*status)
>                 return;
>
>         *status = real_write(...);
> }
>
> and then use it as
>
>         int status = 0;
>
>         write(..., &status);
>         write(..., &status);
>         write(..., &status);
>         write(..., &status);
>         write(..., &status);
>
>         return status;
>
> This may be overkill here.
>
> > +     if (err) {
> > +             anx78xx_poweroff(anx78xx);
> > +             return err;
> > +     }
> >
> >       anx78xx->powered = true;
> > +
> > +     return err;
>
> And return 0 here too, removing the need to initialize the err variable to
> 0.
>
> >  }
> >
> >  static void anx78xx_poweroff(struct anx78xx *anx78xx)
> > @@ -1144,7 +1150,9 @@ static irqreturn_t anx78xx_hpd_threaded_handler(int
> > irq, void *data) mutex_lock(&anx78xx->lock);
> >
> >       /* Cable is pulled, power on the chip */
> > -     anx78xx_poweron(anx78xx);
> > +     err = anx78xx_poweron(anx78xx);
> > +     if (err)
> > +             DRM_ERROR("Failed to power on the chip: %d\n", err);
>
> Wouldn't it be better to move the error message to the an78xx_poweron()
> function ? That way it would also be printed in the probe() path.
>
> >       err = anx78xx_enable_interrupts(anx78xx);
> >       if (err)
> > @@ -1379,7 +1387,9 @@ static int anx78xx_i2c_probe(struct i2c_client
> > *client, }
> >
> >       /* Look for supported chip ID */
> > -     anx78xx_poweron(anx78xx);
> > +     err = anx78xx_poweron(anx78xx);
> > +     if (err)
> > +             goto err_poweroff;
>
> If poweron fails, doesn't it clean up after itself ? Do you need to call
> poweroff here ?
>
> >       err = regmap_read(anx78xx->map[I2C_IDX_TX_P2], SP_DEVICE_IDL_REG,
> >                         &idl);
>
> --
> Regards,
>
> Laurent Pinchart
>
>
>
>

-- 
Kangjie Lu
Assistant Professor
Department of Computer Science and Engineering
University of Minnesota
Personal homepage <https://www-users.cs.umn.edu/~kjlu>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20181221/e766e3cd/attachment-0001.html>


More information about the dri-devel mailing list