diff options
author | Alexey Polyudov <apolyudov@google.com> | 2016-04-19 13:03:00 -0700 |
---|---|---|
committer | Ben Fennema <fennema@google.com> | 2016-04-26 12:24:41 -0700 |
commit | 4d20b89163c5118a2fccb4ff780e8268c1d68b55 (patch) | |
tree | e3cd17f02666d55b969ef9e6b78e7d3b3e9b3433 | |
parent | acf177ecb4ea0457fec1678c6978b58b7d4edad0 (diff) | |
download | mediatek-4d20b89163c5118a2fccb4ff780e8268c1d68b55.tar.gz |
ANDROID: nanohub: fix suspend interaction with IRQ2
platforms with IRQ2 available are not able to suspend,
if non-wakeup events are flowing quite often.
To fix it, we acquire lock on wakeup signal, before
attempting to check for IO activity.
We no longer need to check the activity of worker thread,
because if we have the lock, thread has nothing to do but wait
for us, however it may not yet reach the IDLE state, and
we don't want to lose time waiting for this to happen.
Signed-off-by: Alexey Polyudov <apolyudov@google.com>
Change-Id: Id9c661ec022b8a6b1b53ebdcd7392006d74e40d5
Bug: 28271752
-rw-r--r-- | drivers/staging/nanohub/main.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/drivers/staging/nanohub/main.c b/drivers/staging/nanohub/main.c index 1521d2bdfa6e..d6669ab6d2ab 100644 --- a/drivers/staging/nanohub/main.c +++ b/drivers/staging/nanohub/main.c @@ -1488,30 +1488,40 @@ int nanohub_remove(struct iio_dev *iio_dev) int nanohub_suspend(struct iio_dev *iio_dev) { struct nanohub_data *data = iio_priv(iio_dev); + int ret; if (data->irq2) disable_irq(data->irq2); else nanohub_mask_interrupt(data, 2); - if (nanohub_irq1_fired(data) || - nanohub_get_state(data) != ST_IDLE || - request_wakeup_system(data) < 0) { - if (data->irq2) - enable_irq(data->irq2); - else - nanohub_unmask_interrupt(data, 2); - - if (nanohub_irq2_fired(data)) - nanohub_notify_thread(data); + ret = request_wakeup_system(data); + if (!ret) { + if (!nanohub_irq1_fired(data)) { + enable_irq_wake(data->irq1); + return 0; + } - dev_err(&iio_dev->dev, "%s: failed to suspend\n", __func__); - return -EBUSY; + ret = -EBUSY; + dev_info(&iio_dev->dev, + "%s: failed to suspend: IRQ1=%d, state=%d\n", + __func__, nanohub_irq1_fired(data), + nanohub_get_state(data)); + release_wakeup_system(data); + } else { + dev_info(&iio_dev->dev, "%s: could not take wakeup lock\n", + __func__); } - enable_irq_wake(data->irq1); + if (data->irq2) + enable_irq(data->irq2); + else + nanohub_unmask_interrupt(data, 2); - return 0; + if (nanohub_irq2_fired(data)) + nanohub_notify_thread(data); + + return ret; } int nanohub_resume(struct iio_dev *iio_dev) |