All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joel Stanley <joel@jms.id.au>
To: Eddie James <eajames@linux.ibm.com>
Cc: linux-iio@vger.kernel.org,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Lars-Peter Clausen <lars@metafoo.de>,
	Jonathan Cameron <jic23@kernel.org>
Subject: Re: [PATCH v2 2/2] iio: pressure: dps310: Reset chip if MEAS_CFG is corrupt
Date: Tue, 24 May 2022 02:12:45 +0000	[thread overview]
Message-ID: <CACPK8XeOT6NvEe=oBZ9dUJynHougj-mTMAC2FCwDkvpzBaTKDQ@mail.gmail.com> (raw)
In-Reply-To: <20220518144818.12957-3-eajames@linux.ibm.com>

On Wed, 18 May 2022 at 14:48, Eddie James <eajames@linux.ibm.com> wrote:
>
> Corruption of the MEAS_CFG register has been observed soon after
> system boot. In order to recover this scenario, check MEAS_CFG if
> measurement isn't ready, and if it's incorrect, reset the DPS310
> and execute the startup procedure.

I have some suggestions below on how to rework to make the code easier
to understand. But before we got to that, I had some high level
questions:


You don't seem to be setting the en bits in the CFG register after
doing the reset. Is that required?

Are we ok to sleep for 2.5ms in the iio_info->read_raw callback?


>
> Fixes: ba6ec48e76bc ("iio: Add driver for Infineon DPS310")
> Signed-off-by: Eddie James <eajames@linux.ibm.com>
> ---
>  drivers/iio/pressure/dps310.c | 89 ++++++++++++++++++++++++++++-------
>  1 file changed, 71 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/iio/pressure/dps310.c b/drivers/iio/pressure/dps310.c
> index f79b274bb38d..c6d02679ef33 100644
> --- a/drivers/iio/pressure/dps310.c
> +++ b/drivers/iio/pressure/dps310.c
> @@ -397,6 +397,39 @@ static int dps310_get_temp_k(struct dps310_data *data)
>         return scale_factors[ilog2(rc)];
>  }
>
> +/* Called with lock held */

Perhaps add this to your comment: Returns a negative value on error, a
positive value when the device is not ready (and may have been reset
due to corruption), and zero when the device is ready.

> +static int dps310_check_reset_meas_cfg(struct dps310_data *data, int ready_bit)
> +{
> +       int en = DPS310_PRS_EN | DPS310_TEMP_EN | DPS310_BACKGROUND;
> +       int meas_cfg;
> +       int rc = regmap_read(data->regmap, DPS310_MEAS_CFG, &meas_cfg);
> +
> +       if (rc < 0)
> +               return rc;
> +
> +       if (meas_cfg & ready_bit)
> +               return 0;
> +
> +       if ((meas_cfg & en) != en) {
> +               /* DPS310 register state corrupt, better start from scratch */
> +               rc = regmap_write(data->regmap, DPS310_RESET,
> +                                 DPS310_RESET_MAGIC);
> +               if (rc < 0)
> +                       return rc;
> +
> +               /* Wait for device chip access: 2.5ms in specification */
> +               usleep_range(2500, 12000);
> +               rc = dps310_startup(data);
> +               if (rc)
> +                       return rc;
> +
> +               dev_info(&data->client->dev,
> +                        "recovered from corrupted MEAS_CFG=%02x\n", meas_cfg);
> +       }
> +
> +       return 1;

I'm confused about this case. We get there when the device doesn't
have ready_bit set in meas_cfg and we've done a reset, but we also get
here when the bit isn't set and we haven't done anything to resolve it
(after re-reading the code I understand now, but perhaps reworking it
as follows will make it clear):

Could we write it like this:

if (meas_cfg & ready_bit) {
  /* Device ready, must be okay */
  return 0;
}

 if (meas_cfg & en) {
   /* Device okay (but not ready), no action required */
   return 1;
}

  /* DPS310 register state corrupt, better start from scratch */
...
 return 1;


> +}
> +
>  static int dps310_read_pres_raw(struct dps310_data *data)
>  {
>         int rc;
> @@ -409,15 +442,25 @@ static int dps310_read_pres_raw(struct dps310_data *data)
>         if (mutex_lock_interruptible(&data->lock))
>                 return -EINTR;
>
> -       rate = dps310_get_pres_samp_freq(data);
> -       timeout = DPS310_POLL_TIMEOUT_US(rate);
> -
> -       /* Poll for sensor readiness; base the timeout upon the sample rate. */
> -       rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
> -                                     ready & DPS310_PRS_RDY,
> -                                     DPS310_POLL_SLEEP_US(timeout), timeout);
> -       if (rc)
> -               goto done;
> +       rc = dps310_check_reset_meas_cfg(data, DPS310_PRS_RDY);

can we do this:

 if (rc < 0)
   goto done;

if (rc > 0) {

}

The rework I suggest makes it clearer that we've considered the '0'
case, when the device is ready before this code runs.

> +       if (rc) {
> +               if (rc < 0)
> +                       goto done;
> +
> +               rate = dps310_get_pres_samp_freq(data);
> +               timeout = DPS310_POLL_TIMEOUT_US(rate);
> +
> +               /*
> +                * Poll for sensor readiness; base the timeout upon the sample
> +                * rate.
> +                */
> +               rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG,
> +                                             ready, ready & DPS310_PRS_RDY,
> +                                             DPS310_POLL_SLEEP_US(timeout),
> +                                             timeout);
> +               if (rc)
> +                       goto done;
> +       }
>
>         rc = regmap_bulk_read(data->regmap, DPS310_PRS_BASE, val, sizeof(val));
>         if (rc < 0)
> @@ -458,15 +501,25 @@ static int dps310_read_temp_raw(struct dps310_data *data)
>         if (mutex_lock_interruptible(&data->lock))
>                 return -EINTR;
>
> -       rate = dps310_get_temp_samp_freq(data);
> -       timeout = DPS310_POLL_TIMEOUT_US(rate);
> -
> -       /* Poll for sensor readiness; base the timeout upon the sample rate. */
> -       rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
> -                                     ready & DPS310_TMP_RDY,
> -                                     DPS310_POLL_SLEEP_US(timeout), timeout);
> -       if (rc < 0)
> -               goto done;
> +       rc = dps310_check_reset_meas_cfg(data, DPS310_TMP_RDY);
> +       if (rc) {
> +               if (rc < 0)
> +                       goto done;
> +
> +               rate = dps310_get_temp_samp_freq(data);
> +               timeout = DPS310_POLL_TIMEOUT_US(rate);
> +
> +               /*
> +                * Poll for sensor readiness; base the timeout upon the sample
> +                * rate.
> +                */
> +               rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG,
> +                                             ready, ready & DPS310_TMP_RDY,
> +                                             DPS310_POLL_SLEEP_US(timeout),
> +                                             timeout);
> +               if (rc < 0)
> +                       goto done;
> +       }
>
>         rc = dps310_read_temp_ready(data);
>
> --
> 2.27.0
>

  reply	other threads:[~2022-05-24  2:13 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-18 14:48 [PATCH v2 0/2] iio: pressure: dps310: Reset chip if MEAS_CFG is corrupt Eddie James
2022-05-18 14:48 ` [PATCH v2 1/2] iio: pressure: dps310: Refactor startup procedure Eddie James
2022-05-18 14:48 ` [PATCH v2 2/2] iio: pressure: dps310: Reset chip if MEAS_CFG is corrupt Eddie James
2022-05-24  2:12   ` Joel Stanley [this message]
2022-05-24 14:18     ` Eddie James
2022-05-22 11:41 ` [PATCH v2 0/2] " Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CACPK8XeOT6NvEe=oBZ9dUJynHougj-mTMAC2FCwDkvpzBaTKDQ@mail.gmail.com' \
    --to=joel@jms.id.au \
    --cc=eajames@linux.ibm.com \
    --cc=jic23@kernel.org \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.