On Tue, 31 Mar 2020 13:48:06 +0200 Nuno Sá <nuno.sa@xxxxxxxxxx> wrote: > This patch adds support for a managed device version of > adis_setup_buffer_and_trigger. It works exactly as the original > one but it calls all the devm_iio_* functions to setup an iio > buffer and trigger. Hence we do not need to care about cleaning those > and we do not need to support a remove() callback for every driver using > the adis library. > > Signed-off-by: Nuno Sá <nuno.sa@xxxxxxxxxx> Random thought inline. Something we could use more in IIO :) > --- > Changes in v2: > * Added blank lines for readability. > > Changes in V3: > * Removed unnecessary inline; > * Free buffer resources. > > drivers/iio/imu/adis_buffer.c | 45 ++++++++++++++++++++++++++++++++++ > drivers/iio/imu/adis_trigger.c | 41 ++++++++++++++++++++++++++++--- > include/linux/iio/imu/adis.h | 17 +++++++++++++ > 3 files changed, 100 insertions(+), 3 deletions(-) > > diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c > index 04e5e2a0fd6b..c2211ab80d8c 100644 > --- a/drivers/iio/imu/adis_buffer.c > +++ b/drivers/iio/imu/adis_buffer.c > @@ -156,6 +156,14 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) > return IRQ_HANDLED; > } > > +static void adis_buffer_cleanup(void *arg) > +{ > + struct adis *adis = arg; > + > + kfree(adis->buffer); > + kfree(adis->xfer); > +} > + > /** > * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device > * @adis: The adis device. > @@ -198,6 +206,43 @@ int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, > } > EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger); > > +/** > + * devm_adis_setup_buffer_and_trigger() - Sets up buffer and trigger for > + * the managed adis device > + * @adis: The adis device > + * @indio_dev: The IIO device > + * @trigger_handler: Optional trigger handler, may be NULL. > + * > + * Returns 0 on success, a negative error code otherwise. > + * > + * This function perfoms exactly the same as adis_setup_buffer_and_trigger() > + */ > +int > +devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, > + irqreturn_t (*trigger_handler)(int, void *)) It occurred to me that there must be a lot of irq handling function pointers in the kernel and it would be odd if there wasn't a type for this... There is :) irq_handler_t https://elixir.bootlin.com/linux/latest/source/include/linux/interrupt.h#L92 Not sure why I never noticed that before. Hohum. Jonathan > +{ > + int ret; > + > + if (!trigger_handler) > + trigger_handler = adis_trigger_handler; > + > + ret = devm_iio_triggered_buffer_setup(&adis->spi->dev, indio_dev, > + &iio_pollfunc_store_time, > + trigger_handler, NULL); > + if (ret) > + return ret; > + > + if (adis->spi->irq) { > + ret = devm_adis_probe_trigger(adis, indio_dev); > + if (ret) > + return ret; > + } > + > + return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup, > + adis); > +} > +EXPORT_SYMBOL_GPL(devm_adis_setup_buffer_and_trigger); > + > /** > * adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources > * @adis: The adis device. > diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c > index 8b9cd02c0f9f..a36810e0b1ab 100644 > --- a/drivers/iio/imu/adis_trigger.c > +++ b/drivers/iio/imu/adis_trigger.c > @@ -27,6 +27,13 @@ static const struct iio_trigger_ops adis_trigger_ops = { > .set_trigger_state = &adis_data_rdy_trigger_set_state, > }; > > +static void adis_trigger_setup(struct adis *adis) > +{ > + adis->trig->dev.parent = &adis->spi->dev; > + adis->trig->ops = &adis_trigger_ops; > + iio_trigger_set_drvdata(adis->trig, adis); > +} > + > /** > * adis_probe_trigger() - Sets up trigger for a adis device > * @adis: The adis device > @@ -45,9 +52,7 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) > if (adis->trig == NULL) > return -ENOMEM; > > - adis->trig->dev.parent = &adis->spi->dev; > - adis->trig->ops = &adis_trigger_ops; > - iio_trigger_set_drvdata(adis->trig, adis); > + adis_trigger_setup(adis); > > ret = request_irq(adis->spi->irq, > &iio_trigger_generic_data_rdy_poll, > @@ -73,6 +78,36 @@ int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) > } > EXPORT_SYMBOL_GPL(adis_probe_trigger); > > +/** > + * devm_adis_probe_trigger() - Sets up trigger for a managed adis device > + * @adis: The adis device > + * @indio_dev: The IIO device > + * > + * Returns 0 on success or a negative error code > + */ > +int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) > +{ > + int ret; > + > + adis->trig = devm_iio_trigger_alloc(&adis->spi->dev, "%s-dev%d", > + indio_dev->name, indio_dev->id); > + if (!adis->trig) > + return -ENOMEM; > + > + adis_trigger_setup(adis); > + > + ret = devm_request_irq(&adis->spi->dev, adis->spi->irq, > + &iio_trigger_generic_data_rdy_poll, > + IRQF_TRIGGER_RISING, > + indio_dev->name, > + adis->trig); > + if (ret) > + return ret; > + > + return devm_iio_trigger_register(&adis->spi->dev, adis->trig); > +} > +EXPORT_SYMBOL_GPL(devm_adis_probe_trigger); > + > /** > * adis_remove_trigger() - Remove trigger for a adis devices > * @adis: The adis device > diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h > index dd8219138c2e..ac94c483bf2b 100644 > --- a/include/linux/iio/imu/adis.h > +++ b/include/linux/iio/imu/adis.h > @@ -448,11 +448,15 @@ struct adis_burst { > unsigned int extra_len; > }; > > +int > +devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, > + irqreturn_t (*trigger_handler)(int, void *)); > int adis_setup_buffer_and_trigger(struct adis *adis, > struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *)); > void adis_cleanup_buffer_and_trigger(struct adis *adis, > struct iio_dev *indio_dev); > > +int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev); > int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev); > void adis_remove_trigger(struct adis *adis); > > @@ -461,6 +465,13 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, > > #else /* CONFIG_IIO_BUFFER */ > > +static inline int > +devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, > + irqreturn_t (*trigger_handler)(int, void *)) > +{ > + return 0; > +} > + > static inline int adis_setup_buffer_and_trigger(struct adis *adis, > struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *)) > { > @@ -472,6 +483,12 @@ static inline void adis_cleanup_buffer_and_trigger(struct adis *adis, > { > } > > +static inline int devm_adis_probe_trigger(struct adis *adis, > + struct iio_dev *indio_dev) > +{ > + return 0; > +} > + > static inline int adis_probe_trigger(struct adis *adis, > struct iio_dev *indio_dev) > {