Message ID | 20231005-ad2s1210-mainline-v4-17-ec00746840fc@baylibre.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | iio: resolver: move ad2s1210 out of staging | expand |
On Thu, 5 Oct 2023 19:50:34 -0500 David Lechner <dlechner@baylibre.com> wrote: > We can simplify the code and get rid of most of the gotos by using > guard(mutex) from cleanup.h. You could consider scoped_guard() for a few cases in here, but perhaps it's better to be consistent and always use the guard() version. There is a small timing question wrt to the gpio manipulation inline. > > Signed-off-by: David Lechner <dlechner@baylibre.com> > --- > > v4 changes: New patch in v4. > > drivers/staging/iio/resolver/ad2s1210.c | 157 ++++++++++---------------------- > 1 file changed, 50 insertions(+), 107 deletions(-) > > diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c > index c4e1bc22e8b0..c4e0ffa92dc2 100644 > --- a/drivers/staging/iio/resolver/ad2s1210.c > +++ b/drivers/staging/iio/resolver/ad2s1210.c > @@ -47,6 +47,7 @@ > > #include <linux/bitfield.h> > #include <linux/bits.h> > +#include <linux/cleanup.h> > #include <linux/clk.h> > #include <linux/delay.h> > #include <linux/device.h> > @@ -404,11 +405,13 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > s64 timestamp; > int ret; > > - mutex_lock(&st->lock); > + guard(mutex)(&st->lock); > + > gpiod_set_value(st->sample_gpio, 1); > timestamp = iio_get_time_ns(indio_dev); > /* delay (6 * tck + 20) nano seconds */ > udelay(1); > + gpiod_set_value(st->sample_gpio, 0); > > switch (chan->type) { > case IIO_ANGL: > @@ -418,14 +421,13 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > ret = ad2s1210_set_mode(st, MOD_VEL); > break; > default: > - ret = -EINVAL; > - break; > + return -EINVAL; > } > if (ret < 0) > - goto error_ret; > + return ret; > ret = spi_read(st->sdev, &st->sample, 3); > if (ret < 0) > - goto error_ret; > + return ret; > > switch (chan->type) { > case IIO_ANGL: > @@ -437,17 +439,11 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > ret = IIO_VAL_INT; > break; > default: > - ret = -EINVAL; > - break; > + return -EINVAL; > } > > ad2s1210_push_events(indio_dev, st->sample.fault, timestamp); > > -error_ret: > - gpiod_set_value(st->sample_gpio, 0); > - /* delay (2 * tck + 20) nano seconds */ > - udelay(1); Dropping this delay isn't obviously safe (though it probably is given stuff done before we exit). I assume there are no rules on holding the gpio down for the register read. If nothing else I think the patch description needs to made an argument for why it is fine. > - mutex_unlock(&st->lock); > return ret; > } >
On Tue, Oct 10, 2023 at 11:17 AM Jonathan Cameron <jic23@kernel.org> wrote: > > On Thu, 5 Oct 2023 19:50:34 -0500 > David Lechner <dlechner@baylibre.com> wrote: > > > We can simplify the code and get rid of most of the gotos by using > > guard(mutex) from cleanup.h. > You could consider scoped_guard() for a few cases in here, but perhaps > it's better to be consistent and always use the guard() version. Yes, there it doesn't look like there are any cases where there is any long-running operation that could be done after unlocking the mutex, so I went with the simpler approach everywhere. > > There is a small timing question wrt to the gpio manipulation inline. > > > > > Signed-off-by: David Lechner <dlechner@baylibre.com> > > --- > > > > v4 changes: New patch in v4. > > > > drivers/staging/iio/resolver/ad2s1210.c | 157 ++++++++++---------------------- > > 1 file changed, 50 insertions(+), 107 deletions(-) > > > > diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c > > index c4e1bc22e8b0..c4e0ffa92dc2 100644 > > --- a/drivers/staging/iio/resolver/ad2s1210.c > > +++ b/drivers/staging/iio/resolver/ad2s1210.c > > @@ -47,6 +47,7 @@ > > > > #include <linux/bitfield.h> > > #include <linux/bits.h> > > +#include <linux/cleanup.h> > > #include <linux/clk.h> > > #include <linux/delay.h> > > #include <linux/device.h> > > @@ -404,11 +405,13 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > > s64 timestamp; > > int ret; > > > > - mutex_lock(&st->lock); > > + guard(mutex)(&st->lock); > > + > > gpiod_set_value(st->sample_gpio, 1); > > timestamp = iio_get_time_ns(indio_dev); > > /* delay (6 * tck + 20) nano seconds */ > > udelay(1); > > + gpiod_set_value(st->sample_gpio, 0); > > > > switch (chan->type) { > > case IIO_ANGL: > > @@ -418,14 +421,13 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > > ret = ad2s1210_set_mode(st, MOD_VEL); > > break; > > default: > > - ret = -EINVAL; > > - break; > > + return -EINVAL; > > } > > if (ret < 0) > > - goto error_ret; > > + return ret; > > ret = spi_read(st->sdev, &st->sample, 3); > > if (ret < 0) > > - goto error_ret; > > + return ret; > > > > switch (chan->type) { > > case IIO_ANGL: > > @@ -437,17 +439,11 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > > ret = IIO_VAL_INT; > > break; > > default: > > - ret = -EINVAL; > > - break; > > + return -EINVAL; > > } > > > > ad2s1210_push_events(indio_dev, st->sample.fault, timestamp); > > > > -error_ret: > > - gpiod_set_value(st->sample_gpio, 0); > > - /* delay (2 * tck + 20) nano seconds */ > > - udelay(1); > > Dropping this delay isn't obviously safe (though it probably is given stuff done before we exit). > I assume there are no rules on holding the gpio down for the register read. Correct. The SAMPLE gpio only needs to be held for a short time (~350 nanoseconds) to latch in the current values, then it doesn't matter when it is released. (Figure 35 in datasheet) > > If nothing else I think the patch description needs to made an argument for why it is fine. The longest possible delay needed after releasing the SAMPLE line before reasserting is ~350 nanoseconds. Is there a rule of thumb for deciding when there are enough instructions that no processor could execute them faster than this vs. when we should add an explicit delay? I think I will consider adding a patch in the next round to refactor the SAMPLE toggle to a separate function so we can be sure it is handled the same in all cases. > > > - mutex_unlock(&st->lock); > > return ret; > > } > >
On Tue, 10 Oct 2023 12:40:03 -0500 David Lechner <dlechner@baylibre.com> wrote: > On Tue, Oct 10, 2023 at 11:17 AM Jonathan Cameron <jic23@kernel.org> wrote: > > > > On Thu, 5 Oct 2023 19:50:34 -0500 > > David Lechner <dlechner@baylibre.com> wrote: > > > > > We can simplify the code and get rid of most of the gotos by using > > > guard(mutex) from cleanup.h. > > You could consider scoped_guard() for a few cases in here, but perhaps > > it's better to be consistent and always use the guard() version. > > Yes, there it doesn't look like there are any cases where there is any > long-running operation that could be done after unlocking the mutex, > so I went with the simpler approach everywhere. > > > > > There is a small timing question wrt to the gpio manipulation inline. > > > > > > > > Signed-off-by: David Lechner <dlechner@baylibre.com> > > > --- > > > > > > v4 changes: New patch in v4. > > > > > > drivers/staging/iio/resolver/ad2s1210.c | 157 ++++++++++---------------------- > > > 1 file changed, 50 insertions(+), 107 deletions(-) > > > > > > diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c > > > index c4e1bc22e8b0..c4e0ffa92dc2 100644 > > > --- a/drivers/staging/iio/resolver/ad2s1210.c > > > +++ b/drivers/staging/iio/resolver/ad2s1210.c > > > @@ -47,6 +47,7 @@ > > > > > > #include <linux/bitfield.h> > > > #include <linux/bits.h> > > > +#include <linux/cleanup.h> > > > #include <linux/clk.h> > > > #include <linux/delay.h> > > > #include <linux/device.h> > > > @@ -404,11 +405,13 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > > > s64 timestamp; > > > int ret; > > > > > > - mutex_lock(&st->lock); > > > + guard(mutex)(&st->lock); > > > + > > > gpiod_set_value(st->sample_gpio, 1); > > > timestamp = iio_get_time_ns(indio_dev); > > > /* delay (6 * tck + 20) nano seconds */ > > > udelay(1); > > > + gpiod_set_value(st->sample_gpio, 0); > > > > > > switch (chan->type) { > > > case IIO_ANGL: > > > @@ -418,14 +421,13 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > > > ret = ad2s1210_set_mode(st, MOD_VEL); > > > break; > > > default: > > > - ret = -EINVAL; > > > - break; > > > + return -EINVAL; > > > } > > > if (ret < 0) > > > - goto error_ret; > > > + return ret; > > > ret = spi_read(st->sdev, &st->sample, 3); > > > if (ret < 0) > > > - goto error_ret; > > > + return ret; > > > > > > switch (chan->type) { > > > case IIO_ANGL: > > > @@ -437,17 +439,11 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, > > > ret = IIO_VAL_INT; > > > break; > > > default: > > > - ret = -EINVAL; > > > - break; > > > + return -EINVAL; > > > } > > > > > > ad2s1210_push_events(indio_dev, st->sample.fault, timestamp); > > > > > > -error_ret: > > > - gpiod_set_value(st->sample_gpio, 0); > > > - /* delay (2 * tck + 20) nano seconds */ > > > - udelay(1); > > > > Dropping this delay isn't obviously safe (though it probably is given stuff done before we exit). > > I assume there are no rules on holding the gpio down for the register read. > > Correct. The SAMPLE gpio only needs to be held for a short time (~350 > nanoseconds) to latch in the current values, then it doesn't matter > when it is released. (Figure 35 in datasheet) > > > > > If nothing else I think the patch description needs to made an argument for why it is fine. > > The longest possible delay needed after releasing the SAMPLE line > before reasserting is ~350 nanoseconds. Is there a rule of thumb for > deciding when there are enough instructions that no processor could > execute them faster than this vs. when we should add an explicit > delay? Almost always use an explicit delay as then we don't have to think about it. > > I think I will consider adding a patch in the next round to refactor > the SAMPLE toggle to a separate function so we can be sure it is > handled the same in all cases. Sounds good. Jonathan > > > > > > - mutex_unlock(&st->lock); > > > return ret; > > > } > > >
diff --git a/drivers/staging/iio/resolver/ad2s1210.c b/drivers/staging/iio/resolver/ad2s1210.c index c4e1bc22e8b0..c4e0ffa92dc2 100644 --- a/drivers/staging/iio/resolver/ad2s1210.c +++ b/drivers/staging/iio/resolver/ad2s1210.c @@ -47,6 +47,7 @@ #include <linux/bitfield.h> #include <linux/bits.h> +#include <linux/cleanup.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/device.h> @@ -404,11 +405,13 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, s64 timestamp; int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + gpiod_set_value(st->sample_gpio, 1); timestamp = iio_get_time_ns(indio_dev); /* delay (6 * tck + 20) nano seconds */ udelay(1); + gpiod_set_value(st->sample_gpio, 0); switch (chan->type) { case IIO_ANGL: @@ -418,14 +421,13 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, ret = ad2s1210_set_mode(st, MOD_VEL); break; default: - ret = -EINVAL; - break; + return -EINVAL; } if (ret < 0) - goto error_ret; + return ret; ret = spi_read(st->sdev, &st->sample, 3); if (ret < 0) - goto error_ret; + return ret; switch (chan->type) { case IIO_ANGL: @@ -437,17 +439,11 @@ static int ad2s1210_single_conversion(struct iio_dev *indio_dev, ret = IIO_VAL_INT; break; default: - ret = -EINVAL; - break; + return -EINVAL; } ad2s1210_push_events(indio_dev, st->sample.fault, timestamp); -error_ret: - gpiod_set_value(st->sample_gpio, 0); - /* delay (2 * tck + 20) nano seconds */ - udelay(1); - mutex_unlock(&st->lock); return ret; } @@ -455,11 +451,9 @@ static int ad2s1210_get_hysteresis(struct ad2s1210_state *st, int *val) { int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); ret = regmap_test_bits(st->regmap, AD2S1210_REG_CONTROL, AD2S1210_ENABLE_HYSTERESIS); - mutex_unlock(&st->lock); - if (ret < 0) return ret; @@ -469,15 +463,10 @@ static int ad2s1210_get_hysteresis(struct ad2s1210_state *st, int *val) static int ad2s1210_set_hysteresis(struct ad2s1210_state *st, int val) { - int ret; - - mutex_lock(&st->lock); - ret = regmap_update_bits(st->regmap, AD2S1210_REG_CONTROL, - AD2S1210_ENABLE_HYSTERESIS, - val ? AD2S1210_ENABLE_HYSTERESIS : 0); - mutex_unlock(&st->lock); - - return ret; + guard(mutex)(&st->lock); + return regmap_update_bits(st->regmap, AD2S1210_REG_CONTROL, + AD2S1210_ENABLE_HYSTERESIS, + val ? AD2S1210_ENABLE_HYSTERESIS : 0); } static int ad2s1210_get_phase_lock_range(struct ad2s1210_state *st, @@ -485,11 +474,9 @@ static int ad2s1210_get_phase_lock_range(struct ad2s1210_state *st, { int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); ret = regmap_test_bits(st->regmap, AD2S1210_REG_CONTROL, AD2S1210_PHASE_LOCK_RANGE_44); - mutex_unlock(&st->lock); - if (ret < 0) return ret; @@ -509,7 +496,7 @@ static int ad2s1210_get_phase_lock_range(struct ad2s1210_state *st, static int ad2s1210_set_phase_lock_range(struct ad2s1210_state *st, int val, int val2) { - int deg, ret; + int deg; /* convert radians to degrees - only two allowable values */ if (val == PHASE_44_DEG_TO_RAD_INT && val2 == PHASE_44_DEG_TO_RAD_MICRO) @@ -520,12 +507,10 @@ static int ad2s1210_set_phase_lock_range(struct ad2s1210_state *st, else return -EINVAL; - mutex_lock(&st->lock); - ret = regmap_update_bits(st->regmap, AD2S1210_REG_CONTROL, - AD2S1210_PHASE_LOCK_RANGE_44, - deg == 44 ? AD2S1210_PHASE_LOCK_RANGE_44 : 0); - mutex_unlock(&st->lock); - return ret; + guard(mutex)(&st->lock); + return regmap_update_bits(st->regmap, AD2S1210_REG_CONTROL, + AD2S1210_PHASE_LOCK_RANGE_44, + deg == 44 ? AD2S1210_PHASE_LOCK_RANGE_44 : 0); } /* map resolution to microradians/LSB for LOT registers */ @@ -542,10 +527,8 @@ static int ad2s1210_get_voltage_threshold(struct ad2s1210_state *st, unsigned int reg_val; int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); ret = regmap_read(st->regmap, reg, ®_val); - mutex_unlock(&st->lock); - if (ret < 0) return ret; @@ -557,15 +540,11 @@ static int ad2s1210_set_voltage_threshold(struct ad2s1210_state *st, unsigned int reg, int val) { unsigned int reg_val; - int ret; reg_val = val / THRESHOLD_MILLIVOLT_PER_LSB; - mutex_lock(&st->lock); - ret = regmap_write(st->regmap, reg, reg_val); - mutex_unlock(&st->lock); - - return ret; + guard(mutex)(&st->lock); + return regmap_write(st->regmap, reg, reg_val); } static int ad2s1210_get_lot_high_threshold(struct ad2s1210_state *st, @@ -574,10 +553,8 @@ static int ad2s1210_get_lot_high_threshold(struct ad2s1210_state *st, unsigned int reg_val; int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); ret = regmap_read(st->regmap, AD2S1210_REG_LOT_HIGH_THRD, ®_val); - mutex_unlock(&st->lock); - if (ret < 0) return ret; @@ -596,18 +573,18 @@ static int ad2s1210_set_lot_high_threshold(struct ad2s1210_state *st, if (val != 0) return -EINVAL; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); /* * We need to read both high and low registers first so we can preserve * the hysteresis. */ ret = regmap_read(st->regmap, AD2S1210_REG_LOT_HIGH_THRD, &high_reg_val); if (ret < 0) - goto error_ret; + return ret; ret = regmap_read(st->regmap, AD2S1210_REG_LOT_LOW_THRD, &low_reg_val); if (ret < 0) - goto error_ret; + return ret; hysteresis = high_reg_val - low_reg_val; high_reg_val = val2 / ad2s1210_lot_threshold_urad_per_lsb[st->resolution]; @@ -615,14 +592,9 @@ static int ad2s1210_set_lot_high_threshold(struct ad2s1210_state *st, ret = regmap_write(st->regmap, AD2S1210_REG_LOT_HIGH_THRD, high_reg_val); if (ret < 0) - goto error_ret; - - ret = regmap_write(st->regmap, AD2S1210_REG_LOT_LOW_THRD, low_reg_val); - -error_ret: - mutex_unlock(&st->lock); + return ret; - return ret; + return regmap_write(st->regmap, AD2S1210_REG_LOT_LOW_THRD, low_reg_val); } static int ad2s1210_get_lot_low_threshold(struct ad2s1210_state *st, @@ -631,16 +603,13 @@ static int ad2s1210_get_lot_low_threshold(struct ad2s1210_state *st, unsigned int high_reg_val, low_reg_val; int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + ret = regmap_read(st->regmap, AD2S1210_REG_LOT_HIGH_THRD, &high_reg_val); if (ret < 0) - goto error_ret; + return ret; ret = regmap_read(st->regmap, AD2S1210_REG_LOT_LOW_THRD, &low_reg_val); - -error_ret: - mutex_unlock(&st->lock); - if (ret < 0) return ret; @@ -663,18 +632,14 @@ static int ad2s1210_set_lot_low_threshold(struct ad2s1210_state *st, hysteresis = val2 / ad2s1210_lot_threshold_urad_per_lsb[st->resolution]; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + ret = regmap_read(st->regmap, AD2S1210_REG_LOT_HIGH_THRD, ®_val); if (ret < 0) - goto error_ret; + return ret; - ret = regmap_write(st->regmap, AD2S1210_REG_LOT_LOW_THRD, + return regmap_write(st->regmap, AD2S1210_REG_LOT_LOW_THRD, reg_val - hysteresis); - -error_ret: - mutex_unlock(&st->lock); - - return ret; } static int ad2s1210_get_excitation_frequency(struct ad2s1210_state *st, int *val) @@ -682,31 +647,23 @@ static int ad2s1210_get_excitation_frequency(struct ad2s1210_state *st, int *val unsigned int reg_val; int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); + ret = regmap_read(st->regmap, AD2S1210_REG_EXCIT_FREQ, ®_val); if (ret < 0) - goto error_ret; + return ret; *val = reg_val * st->clkin_hz / (1 << 15); - ret = IIO_VAL_INT; - -error_ret: - mutex_unlock(&st->lock); - return ret; + return IIO_VAL_INT; } static int ad2s1210_set_excitation_frequency(struct ad2s1210_state *st, int val) { - int ret; - if (val < AD2S1210_MIN_EXCIT || val > AD2S1210_MAX_EXCIT) return -EINVAL; - mutex_lock(&st->lock); - ret = ad2s1210_reinit_excitation_frequency(st, val); - mutex_unlock(&st->lock); - - return ret; + guard(mutex)(&st->lock); + return ad2s1210_reinit_excitation_frequency(st, val); } static const int ad2s1210_velocity_scale[] = { @@ -982,10 +939,8 @@ static ssize_t event_attr_voltage_reg_show(struct device *dev, unsigned int value; int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); ret = regmap_read(st->regmap, iattr->address, &value); - mutex_unlock(&st->lock); - if (ret < 0) return ret; @@ -1005,11 +960,9 @@ static ssize_t event_attr_voltage_reg_store(struct device *dev, if (ret) return -EINVAL; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); ret = regmap_write(st->regmap, iattr->address, data / THRESHOLD_MILLIVOLT_PER_LSB); - mutex_unlock(&st->lock); - if (ret < 0) return ret; @@ -1083,7 +1036,7 @@ static int ad2s1210_initial(struct ad2s1210_state *st) unsigned int data; int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); /* Use default config register value plus resolution from devicetree. */ data = FIELD_PREP(AD2S1210_PHASE_LOCK_RANGE_44, 1); @@ -1093,13 +1046,9 @@ static int ad2s1210_initial(struct ad2s1210_state *st) ret = regmap_write(st->regmap, AD2S1210_REG_CONTROL, data); if (ret < 0) - goto error_ret; - - ret = ad2s1210_reinit_excitation_frequency(st, AD2S1210_DEF_EXCIT); + return ret; -error_ret: - mutex_unlock(&st->lock); - return ret; + return ad2s1210_reinit_excitation_frequency(st, AD2S1210_DEF_EXCIT); } static int ad2s1210_read_label(struct iio_dev *indio_dev, @@ -1243,18 +1192,13 @@ static int ad2s1210_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int *readval) { struct ad2s1210_state *st = iio_priv(indio_dev); - int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); if (readval) - ret = regmap_read(st->regmap, reg, readval); - else - ret = regmap_write(st->regmap, reg, writeval); - - mutex_unlock(&st->lock); + return regmap_read(st->regmap, reg, readval); - return ret; + return regmap_write(st->regmap, reg, writeval); } static irqreturn_t ad2s1210_trigger_handler(int irq, void *p) @@ -1265,7 +1209,7 @@ static irqreturn_t ad2s1210_trigger_handler(int irq, void *p) size_t chan = 0; int ret; - mutex_lock(&st->lock); + guard(mutex)(&st->lock); memset(&st->scan, 0, sizeof(st->scan)); gpiod_set_value(st->sample_gpio, 1); @@ -1299,7 +1243,6 @@ static irqreturn_t ad2s1210_trigger_handler(int irq, void *p) error_ret: gpiod_set_value(st->sample_gpio, 0); - mutex_unlock(&st->lock); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED;
We can simplify the code and get rid of most of the gotos by using guard(mutex) from cleanup.h. Signed-off-by: David Lechner <dlechner@baylibre.com> --- v4 changes: New patch in v4. drivers/staging/iio/resolver/ad2s1210.c | 157 ++++++++++---------------------- 1 file changed, 50 insertions(+), 107 deletions(-)