summaryrefslogtreecommitdiffstats
path: root/net/rfkill/core.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2016-01-20 10:39:23 +0100
committerJohannes Berg <johannes.berg@intel.com>2016-02-24 09:04:22 +0100
commitdd21dfc645d5dce0657af78761b3fa11a3a95398 (patch)
tree22047c62a10871568f5fa9c17ee14342ebf670da /net/rfkill/core.c
parentf06b7ab875037c3d99cd30a07c51caf34fbecb2c (diff)
downloadlinux-dd21dfc645d5dce0657af78761b3fa11a3a95398.tar.bz2
rfkill: disentangle polling pause and suspend
When suspended while polling is paused, polling will erroneously resume at resume time. Fix this by tracking pause and suspend in separate state variable and adding the necessary checks. Clarify the documentation on this as well. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/rfkill/core.c')
-rw-r--r--net/rfkill/core.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index f53bf3b6558b..166439995f34 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -57,6 +57,8 @@ struct rfkill {
bool registered;
bool persistent;
+ bool polling_paused;
+ bool suspended;
const struct rfkill_ops *ops;
void *data;
@@ -786,6 +788,7 @@ void rfkill_pause_polling(struct rfkill *rfkill)
if (!rfkill->ops->poll)
return;
+ rfkill->polling_paused = true;
cancel_delayed_work_sync(&rfkill->poll_work);
}
EXPORT_SYMBOL(rfkill_pause_polling);
@@ -797,6 +800,11 @@ void rfkill_resume_polling(struct rfkill *rfkill)
if (!rfkill->ops->poll)
return;
+ rfkill->polling_paused = false;
+
+ if (rfkill->suspended)
+ return;
+
queue_delayed_work(system_power_efficient_wq,
&rfkill->poll_work, 0);
}
@@ -807,7 +815,8 @@ static int rfkill_suspend(struct device *dev)
{
struct rfkill *rfkill = to_rfkill(dev);
- rfkill_pause_polling(rfkill);
+ rfkill->suspended = true;
+ cancel_delayed_work_sync(&rfkill->poll_work);
return 0;
}
@@ -817,12 +826,16 @@ static int rfkill_resume(struct device *dev)
struct rfkill *rfkill = to_rfkill(dev);
bool cur;
+ rfkill->suspended = false;
+
if (!rfkill->persistent) {
cur = !!(rfkill->state & RFKILL_BLOCK_SW);
rfkill_set_block(rfkill, cur);
}
- rfkill_resume_polling(rfkill);
+ if (rfkill->ops->poll && !rfkill->polling_paused)
+ queue_delayed_work(system_power_efficient_wq,
+ &rfkill->poll_work, 0);
return 0;
}