summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Polyudov <apolyudov@google.com>2016-04-19 13:03:00 -0700
committerBen Fennema <fennema@google.com>2016-04-26 12:24:41 -0700
commit4d20b89163c5118a2fccb4ff780e8268c1d68b55 (patch)
treee3cd17f02666d55b969ef9e6b78e7d3b3e9b3433
parentacf177ecb4ea0457fec1678c6978b58b7d4edad0 (diff)
downloadmediatek-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.c38
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)