diff options
Diffstat (limited to 'drivers/staging/iio/industrialio-trigger.c')
-rw-r--r-- | drivers/staging/iio/industrialio-trigger.c | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c index 90ca2df23eab..f1ece8619e8d 100644 --- a/drivers/staging/iio/industrialio-trigger.c +++ b/drivers/staging/iio/industrialio-trigger.c @@ -8,7 +8,6 @@ */ #include <linux/kernel.h> -#include <linux/module.h> #include <linux/idr.h> #include <linux/err.h> #include <linux/device.h> @@ -18,6 +17,8 @@ #include "iio.h" #include "trigger.h" +#include "iio_core.h" +#include "iio_core_trigger.h" #include "trigger_consumer.h" /* RFC - Question of approach @@ -173,13 +174,12 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name, void iio_trigger_poll(struct iio_trigger *trig, s64 time) { int i; - if (!trig->use_count) { + if (!trig->use_count) for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) if (trig->subirqs[i].enabled) { trig->use_count++; generic_handle_irq(trig->subirq_base + i); } - } } EXPORT_SYMBOL(iio_trigger_poll); @@ -206,8 +206,8 @@ EXPORT_SYMBOL(iio_trigger_poll_chained); void iio_trigger_notify_done(struct iio_trigger *trig) { trig->use_count--; - if (trig->use_count == 0 && trig->try_reenable) - if (trig->try_reenable(trig)) { + if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) + if (trig->ops->try_reenable(trig)) { /* Missed and interrupt so launch new poll now */ iio_trigger_poll(trig, 0); } @@ -215,6 +215,26 @@ void iio_trigger_notify_done(struct iio_trigger *trig) EXPORT_SYMBOL(iio_trigger_notify_done); /* Trigger Consumer related functions */ +static int iio_trigger_get_irq(struct iio_trigger *trig) +{ + int ret; + mutex_lock(&trig->pool_lock); + ret = bitmap_find_free_region(trig->pool, + CONFIG_IIO_CONSUMERS_PER_TRIGGER, + ilog2(1)); + mutex_unlock(&trig->pool_lock); + if (ret >= 0) + ret += trig->subirq_base; + + return ret; +} + +static void iio_trigger_put_irq(struct iio_trigger *trig, int irq) +{ + mutex_lock(&trig->pool_lock); + clear_bit(irq - trig->subirq_base, trig->pool); + mutex_unlock(&trig->pool_lock); +} /* Complexity in here. With certain triggers (datardy) an acknowledgement * may be needed if the pollfuncs do not include the data read for the @@ -223,44 +243,45 @@ EXPORT_SYMBOL(iio_trigger_notify_done); * the relevant function is in there may be the best option. */ /* Worth protecting against double additions?*/ -int iio_trigger_attach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) +static int iio_trigger_attach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) { int ret = 0; bool notinuse = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); + /* Prevent the module being removed whilst attached to a trigger */ + __module_get(pf->indio_dev->info->driver_module); pf->irq = iio_trigger_get_irq(trig); ret = request_threaded_irq(pf->irq, pf->h, pf->thread, pf->type, pf->name, pf); - if (trig->set_trigger_state && notinuse) - ret = trig->set_trigger_state(trig, true); + if (trig->ops && trig->ops->set_trigger_state && notinuse) + ret = trig->ops->set_trigger_state(trig, true); return ret; } -EXPORT_SYMBOL(iio_trigger_attach_poll_func); -int iio_trigger_dettach_poll_func(struct iio_trigger *trig, - struct iio_poll_func *pf) +static int iio_trigger_dettach_poll_func(struct iio_trigger *trig, + struct iio_poll_func *pf) { int ret = 0; bool no_other_users = (bitmap_weight(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER) == 1); - if (trig->set_trigger_state && no_other_users) { - ret = trig->set_trigger_state(trig, false); + if (trig->ops && trig->ops->set_trigger_state && no_other_users) { + ret = trig->ops->set_trigger_state(trig, false); if (ret) goto error_ret; } iio_trigger_put_irq(trig, pf->irq); free_irq(pf->irq, pf); + module_put(pf->indio_dev->info->driver_module); error_ret: return ret; } -EXPORT_SYMBOL(iio_trigger_dettach_poll_func); irqreturn_t iio_pollfunc_store_time(int irq, void *p) { @@ -274,7 +295,7 @@ struct iio_poll_func *iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), irqreturn_t (*thread)(int irq, void *p), int type, - void *private, + struct iio_dev *indio_dev, const char *fmt, ...) { @@ -294,7 +315,7 @@ struct iio_poll_func pf->h = h; pf->thread = thread; pf->type = type; - pf->private_data = private; + pf->indio_dev = indio_dev; return pf; } @@ -318,12 +339,10 @@ static ssize_t iio_trigger_read_current(struct device *dev, char *buf) { struct iio_dev *dev_info = dev_get_drvdata(dev); - int len = 0; + if (dev_info->trig) - len = sprintf(buf, - "%s\n", - dev_info->trig->name); - return len; + return sprintf(buf, "%s\n", dev_info->trig->name); + return 0; } /** @@ -358,8 +377,8 @@ static ssize_t iio_trigger_write_current(struct device *dev, return ret; } - if (trig && trig->validate_device) { - ret = trig->validate_device(trig, dev_info); + if (trig && trig->ops && trig->ops->validate_device) { + ret = trig->ops->validate_device(trig, dev_info); if (ret) return ret; } @@ -477,6 +496,7 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) IRQ_NOPROBE); } iio_get(); + get_device(&trig->dev); } return trig; } @@ -491,20 +511,18 @@ EXPORT_SYMBOL(iio_free_trigger); int iio_device_register_trigger_consumer(struct iio_dev *dev_info) { - int ret; - ret = sysfs_create_group(&dev_info->dev.kobj, - &iio_trigger_consumer_attr_group); - return ret; + return sysfs_create_group(&dev_info->dev.kobj, + &iio_trigger_consumer_attr_group); } -EXPORT_SYMBOL(iio_device_register_trigger_consumer); -int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) +void iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) { + /* Clean up and associated but not attached triggers references */ + if (dev_info->trig) + iio_put_trigger(dev_info->trig); sysfs_remove_group(&dev_info->dev.kobj, &iio_trigger_consumer_attr_group); - return 0; } -EXPORT_SYMBOL(iio_device_unregister_trigger_consumer); int iio_triggered_ring_postenable(struct iio_dev *indio_dev) { |