From c8cdf70890d89c07c9e890b103106d58999f0ce4 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Fri, 2 Sep 2016 23:36:15 -0700 Subject: iio: trigger: allow immutable triggers to be assigned There are times when an assigned trigger to a device shouldn't ever change after intialization. Examples of this being used is when an provider device has a trigger that is assigned to an ADC, which uses it populate data into a callback buffer. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- include/linux/iio/iio.h | 2 ++ include/linux/iio/trigger.h | 9 +++++++++ 2 files changed, 11 insertions(+) (limited to 'include/linux/iio') diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 854e2dad1e0d..786952cd509f 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -483,6 +483,7 @@ struct iio_buffer_setup_ops { * @scan_timestamp: [INTERN] set if any buffers have requested timestamp * @scan_index_timestamp:[INTERN] cache of the index to the timestamp * @trig: [INTERN] current device trigger (buffer modes) + * @trig_readonly [INTERN] mark the current trigger immutable * @pollfunc: [DRIVER] function run on trigger being received * @pollfunc_event: [DRIVER] function run on events trigger being received * @channels: [DRIVER] channel specification structure table @@ -523,6 +524,7 @@ struct iio_dev { bool scan_timestamp; unsigned scan_index_timestamp; struct iio_trigger *trig; + bool trig_readonly; struct iio_poll_func *pollfunc; struct iio_poll_func *pollfunc_event; diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index 1c9e028e0d4a..a122bdd4076c 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -131,6 +131,15 @@ int iio_trigger_register(struct iio_trigger *trig_info); **/ void iio_trigger_unregister(struct iio_trigger *trig_info); +/** + * iio_trigger_set_immutable() - set an immutable trigger on destination + * + * @indio_dev - IIO device structure containing the device + * @trig - trigger to assign to device + * + **/ +int iio_trigger_set_immutable(struct iio_dev *indio_dev, struct iio_trigger *trig); + /** * iio_trigger_poll() - called on a trigger occurring * @trig: trigger which occurred -- cgit v1.2.3 From 9083325f1197a6956db17809d74dbe3578dc1005 Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Fri, 2 Sep 2016 20:47:54 +0200 Subject: iio:trigger: add resource managed (un)register Add resource managed devm_iio_trigger_register() and devm_iio_triger_unregister() to automatically clean up registered triggers allocated by IIO drivers, thus leading to simplified IIO drivers code. Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- Documentation/driver-model/devres.txt | 2 ++ drivers/iio/industrialio-trigger.c | 59 +++++++++++++++++++++++++++++++++++ include/linux/iio/trigger.h | 6 ++++ 3 files changed, 67 insertions(+) (limited to 'include/linux/iio') diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index b0d775d28e97..6a2138a7c3ff 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -268,6 +268,8 @@ IIO devm_iio_kfifo_free() devm_iio_trigger_alloc() devm_iio_trigger_free() + devm_iio_trigger_register() + devm_iio_trigger_unregister() devm_iio_channel_get() devm_iio_channel_release() devm_iio_channel_get_all() diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index 3dde81e57e97..ba584b5e71f4 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -642,6 +642,65 @@ void devm_iio_trigger_free(struct device *dev, struct iio_trigger *iio_trig) } EXPORT_SYMBOL_GPL(devm_iio_trigger_free); +static void devm_iio_trigger_unreg(struct device *dev, void *res) +{ + iio_trigger_unregister(*(struct iio_trigger **)res); +} + +/** + * devm_iio_trigger_register - Resource-managed iio_trigger_register() + * @dev: device this trigger was allocated for + * @trig_info: trigger to register + * + * Managed iio_trigger_register(). The IIO trigger registered with this + * function is automatically unregistered on driver detach. This function + * calls iio_trigger_register() internally. Refer to that function for more + * information. + * + * If an iio_trigger registered with this function needs to be unregistered + * separately, devm_iio_trigger_unregister() must be used. + * + * RETURNS: + * 0 on success, negative error number on failure. + */ +int devm_iio_trigger_register(struct device *dev, struct iio_trigger *trig_info) +{ + struct iio_trigger **ptr; + int ret; + + ptr = devres_alloc(devm_iio_trigger_unreg, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + *ptr = trig_info; + ret = iio_trigger_register(trig_info); + if (!ret) + devres_add(dev, ptr); + else + devres_free(ptr); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_iio_trigger_register); + +/** + * devm_iio_trigger_unregister - Resource-managed iio_trigger_unregister() + * @dev: device this iio_trigger belongs to + * @trig_info: the trigger associated with the device + * + * Unregister trigger registered with devm_iio_trigger_register(). + */ +void devm_iio_trigger_unregister(struct device *dev, + struct iio_trigger *trig_info) +{ + int rc; + + rc = devres_release(dev, devm_iio_trigger_unreg, devm_iio_trigger_match, + trig_info); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister); + void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { indio_dev->groups[indio_dev->groupcounter++] = diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index a122bdd4076c..f0890a5abf13 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -125,12 +125,18 @@ static inline void *iio_trigger_get_drvdata(struct iio_trigger *trig) **/ int iio_trigger_register(struct iio_trigger *trig_info); +int devm_iio_trigger_register(struct device *dev, + struct iio_trigger *trig_info); + /** * iio_trigger_unregister() - unregister a trigger from the core * @trig_info: trigger to be unregistered **/ void iio_trigger_unregister(struct iio_trigger *trig_info); +void devm_iio_trigger_unregister(struct device *dev, + struct iio_trigger *trig_info); + /** * iio_trigger_set_immutable() - set an immutable trigger on destination * -- cgit v1.2.3 From 70e483487db787b152da756d4be0fef917378142 Mon Sep 17 00:00:00 2001 From: Gregor Boirie Date: Fri, 2 Sep 2016 20:47:55 +0200 Subject: iio: add resource managed triggered buffer init helpers Add resource managed devm_iio_triggered_buffer_setup() and devm_iio_triggered_buffer_cleanup() to automatically clean up triggered buffers setup by IIO drivers, thus leading to simplified IIO drivers code. Signed-off-by: Gregor Boirie Signed-off-by: Jonathan Cameron --- Documentation/driver-model/devres.txt | 2 ++ drivers/iio/buffer/industrialio-triggered-buffer.c | 42 ++++++++++++++++++++++ drivers/iio/industrialio-core.c | 3 +- include/linux/iio/iio.h | 1 + include/linux/iio/triggered_buffer.h | 8 +++++ 5 files changed, 55 insertions(+), 1 deletion(-) (limited to 'include/linux/iio') diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt index 6a2138a7c3ff..75bc5b8add2f 100644 --- a/Documentation/driver-model/devres.txt +++ b/Documentation/driver-model/devres.txt @@ -266,6 +266,8 @@ IIO devm_iio_device_unregister() devm_iio_kfifo_allocate() devm_iio_kfifo_free() + devm_iio_triggered_buffer_setup() + devm_iio_triggered_buffer_cleanup() devm_iio_trigger_alloc() devm_iio_trigger_free() devm_iio_trigger_register() diff --git a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c index 4b2858ba1fd6..d3db1fce54d2 100644 --- a/drivers/iio/buffer/industrialio-triggered-buffer.c +++ b/drivers/iio/buffer/industrialio-triggered-buffer.c @@ -98,6 +98,48 @@ void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev) } EXPORT_SYMBOL(iio_triggered_buffer_cleanup); +static void devm_iio_triggered_buffer_clean(struct device *dev, void *res) +{ + iio_triggered_buffer_cleanup(*(struct iio_dev **)res); +} + +int devm_iio_triggered_buffer_setup(struct device *dev, + struct iio_dev *indio_dev, + irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + const struct iio_buffer_setup_ops *ops) +{ + struct iio_dev **ptr; + int ret; + + ptr = devres_alloc(devm_iio_triggered_buffer_clean, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + *ptr = indio_dev; + + ret = iio_triggered_buffer_setup(indio_dev, h, thread, ops); + if (!ret) + devres_add(dev, ptr); + else + devres_free(ptr); + + return ret; +} +EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_setup); + +void devm_iio_triggered_buffer_cleanup(struct device *dev, + struct iio_dev *indio_dev) +{ + int rc; + + rc = devres_release(dev, devm_iio_triggered_buffer_clean, + devm_iio_device_match, indio_dev); + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_iio_triggered_buffer_cleanup); + MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_DESCRIPTION("IIO helper functions for setting up triggered buffers"); MODULE_LICENSE("GPL"); diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index f914d5d140e4..0528a0c1b964 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -1309,7 +1309,7 @@ static void devm_iio_device_release(struct device *dev, void *res) iio_device_free(*(struct iio_dev **)res); } -static int devm_iio_device_match(struct device *dev, void *res, void *data) +int devm_iio_device_match(struct device *dev, void *res, void *data) { struct iio_dev **r = res; if (!r || !*r) { @@ -1318,6 +1318,7 @@ static int devm_iio_device_match(struct device *dev, void *res, void *data) } return *r == data; } +EXPORT_SYMBOL_GPL(devm_iio_device_match); /** * devm_iio_device_alloc - Resource-managed iio_device_alloc() diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 786952cd509f..b4a0679e4a49 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -644,6 +644,7 @@ static inline struct iio_dev *iio_priv_to_dev(void *priv) } void iio_device_free(struct iio_dev *indio_dev); +int devm_iio_device_match(struct device *dev, void *res, void *data); struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv); void devm_iio_device_free(struct device *dev, struct iio_dev *indio_dev); struct iio_trigger *devm_iio_trigger_alloc(struct device *dev, diff --git a/include/linux/iio/triggered_buffer.h b/include/linux/iio/triggered_buffer.h index f72f70d5a97b..30145616773d 100644 --- a/include/linux/iio/triggered_buffer.h +++ b/include/linux/iio/triggered_buffer.h @@ -12,4 +12,12 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev, const struct iio_buffer_setup_ops *setup_ops); void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev); +int devm_iio_triggered_buffer_setup(struct device *dev, + struct iio_dev *indio_dev, + irqreturn_t (*h)(int irq, void *p), + irqreturn_t (*thread)(int irq, void *p), + const struct iio_buffer_setup_ops *ops); +void devm_iio_triggered_buffer_cleanup(struct device *dev, + struct iio_dev *indio_dev); + #endif -- cgit v1.2.3 From 702a7b8e064a93df0b63e9d718b666a9851088fc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 1 Sep 2016 10:27:17 +0200 Subject: iio: trigger: helpers to determine own trigger This adds a helper function to the IIO trigger framework: iio_trigger_using_own(): for an IIO device, this tells whether the device is using itself as a trigger. This is true if the indio device: (A) supplies a trigger and (B) has assigned its own buffer poll function to use this trigger. This helper function is good when constructing triggered, buffered drivers that can either use its own hardware *OR* an external trigger such as a HRTimer or even the trigger from a totally different sensor. Under such circumstances it is important to know for example if the timestamp from the same trigger hardware should be used when populating the buffer: if iio_trigger_using_own() is true, we can use this timestamp, else we need to pick a unique timestamp directly in the trigger handler. For this to work of course IIO devices registering hardware triggers must follow the convention to set the parent device properly, as as well as setting the parent of the IIO device itself. When a new poll function is attached, we check if the parent device of the IIO of the poll function is the same as the parent device of the trigger and in that case we conclude that the hardware is using itself as trigger. Cc: Giuseppe Barba Cc: Denis Ciocca Cc: Crestez Dan Leonard Cc: Gregor Boirie Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 16 ++++++++++++++++ include/linux/iio/trigger.h | 11 +++++++++++ 2 files changed, 27 insertions(+) (limited to 'include/linux/iio') diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index ba584b5e71f4..e1e104845e38 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -271,6 +271,14 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig, goto out_free_irq; } + /* + * Check if we just registered to our own trigger: we determine that + * this is the case if the IIO device and the trigger device share the + * same parent device. + */ + if (pf->indio_dev->dev.parent == trig->dev.parent) + trig->attached_own_device = true; + return ret; out_free_irq: @@ -295,6 +303,8 @@ static int iio_trigger_detach_poll_func(struct iio_trigger *trig, if (ret) return ret; } + if (pf->indio_dev->dev.parent == trig->dev.parent) + trig->attached_own_device = false; iio_trigger_put_irq(trig, pf->irq); free_irq(pf->irq, pf); module_put(pf->indio_dev->info->driver_module); @@ -701,6 +711,12 @@ void devm_iio_trigger_unregister(struct device *dev, } EXPORT_SYMBOL_GPL(devm_iio_trigger_unregister); +bool iio_trigger_using_own(struct iio_dev *indio_dev) +{ + return indio_dev->trig->attached_own_device; +} +EXPORT_SYMBOL(iio_trigger_using_own); + void iio_device_register_trigger_consumer(struct iio_dev *indio_dev) { indio_dev->groups[indio_dev->groupcounter++] = diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index f0890a5abf13..4f1154f7a33c 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -56,6 +56,9 @@ struct iio_trigger_ops { * @subirqs: [INTERN] information about the 'child' irqs. * @pool: [INTERN] bitmap of irqs currently in use. * @pool_lock: [INTERN] protection of the irq pool. + * @attached_own_device:[INTERN] if we are using our own device as trigger, + * i.e. if we registered a poll function to the same + * device as the one providing the trigger. **/ struct iio_trigger { const struct iio_trigger_ops *ops; @@ -73,6 +76,7 @@ struct iio_trigger { struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER]; unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; struct mutex pool_lock; + bool attached_own_device; }; @@ -160,6 +164,13 @@ irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); __printf(1, 2) struct iio_trigger *iio_trigger_alloc(const char *fmt, ...); void iio_trigger_free(struct iio_trigger *trig); +/** + * iio_trigger_using_own() - tells us if we use our own HW trigger ourselves + * @indio_dev: device to check + */ +bool iio_trigger_using_own(struct iio_dev *indio_dev); + + #else struct iio_trigger; struct iio_trigger_ops; -- cgit v1.2.3