| From 99543823357966ac938d9a310947e731b67338e6 Mon Sep 17 00:00:00 2001 |
| From: Crestez Dan Leonard <leonard.crestez@intel.com> |
| Date: Tue, 3 May 2016 15:27:09 +0300 |
| Subject: iio: Fix error handling in iio_trigger_attach_poll_func |
| |
| From: Crestez Dan Leonard <leonard.crestez@intel.com> |
| |
| commit 99543823357966ac938d9a310947e731b67338e6 upstream. |
| |
| When attaching a pollfunc iio_trigger_attach_poll_func will allocate a |
| virtual irq and call the driver's set_trigger_state function. Fix error |
| handling to undo previous steps if any fails. |
| |
| In particular this fixes handling errors from a driver's |
| set_trigger_state function. When using triggered buffers a failure to |
| enable the trigger used to make the buffer unusable. |
| |
| Signed-off-by: Crestez Dan Leonard <leonard.crestez@intel.com> |
| Signed-off-by: Jonathan Cameron <jic23@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/iio/industrialio-trigger.c | 23 ++++++++++++++++++----- |
| 1 file changed, 18 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/iio/industrialio-trigger.c |
| +++ b/drivers/iio/industrialio-trigger.c |
| @@ -210,22 +210,35 @@ static int iio_trigger_attach_poll_func( |
| |
| /* Prevent the module from being removed whilst attached to a trigger */ |
| __module_get(pf->indio_dev->info->driver_module); |
| + |
| + /* Get irq number */ |
| pf->irq = iio_trigger_get_irq(trig); |
| + if (pf->irq < 0) |
| + goto out_put_module; |
| + |
| + /* Request irq */ |
| ret = request_threaded_irq(pf->irq, pf->h, pf->thread, |
| pf->type, pf->name, |
| pf); |
| - if (ret < 0) { |
| - module_put(pf->indio_dev->info->driver_module); |
| - return ret; |
| - } |
| + if (ret < 0) |
| + goto out_put_irq; |
| |
| + /* Enable trigger in driver */ |
| if (trig->ops && trig->ops->set_trigger_state && notinuse) { |
| ret = trig->ops->set_trigger_state(trig, true); |
| if (ret < 0) |
| - module_put(pf->indio_dev->info->driver_module); |
| + goto out_free_irq; |
| } |
| |
| return ret; |
| + |
| +out_free_irq: |
| + free_irq(pf->irq, pf); |
| +out_put_irq: |
| + iio_trigger_put_irq(trig, pf->irq); |
| +out_put_module: |
| + module_put(pf->indio_dev->info->driver_module); |
| + return ret; |
| } |
| |
| static int iio_trigger_detach_poll_func(struct iio_trigger *trig, |