All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eddie James <eajames@linux.ibm.com>
To: Joel Stanley <joel@jms.id.au>
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 09:18:32 -0500	[thread overview]
Message-ID: <a817037e-0c8f-a890-549a-6df42e2bb26d@linux.ibm.com> (raw)
In-Reply-To: <CACPK8XeOT6NvEe=oBZ9dUJynHougj-mTMAC2FCwDkvpzBaTKDQ@mail.gmail.com>


On 5/23/22 21:12, Joel Stanley wrote:
> 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?


It does set the enable bits in the startup procedure, called after the 
reset.


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


I believe it's safe... the code already has a mutex, so its not called 
in atomic context.


>
>
>> 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.


Good idea.


>
>> +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;


Yea it could be clearer, I can update that.


>
>
>> +}
>> +
>>   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.


Sure. Thanks for the review, I'll get a v3 up.


Thanks,

Eddie


>
>> +       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 14:18 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
2022-05-24 14:18     ` Eddie James [this message]
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=a817037e-0c8f-a890-549a-6df42e2bb26d@linux.ibm.com \
    --to=eajames@linux.ibm.com \
    --cc=jic23@kernel.org \
    --cc=joel@jms.id.au \
    --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.