Commit dd21dfc6 authored by Johannes Berg's avatar Johannes Berg

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: default avatarJohannes Berg <johannes.berg@intel.com>
parent f06b7ab8
...@@ -104,7 +104,8 @@ int __must_check rfkill_register(struct rfkill *rfkill); ...@@ -104,7 +104,8 @@ int __must_check rfkill_register(struct rfkill *rfkill);
* *
* Pause polling -- say transmitter is off for other reasons. * Pause polling -- say transmitter is off for other reasons.
* NOTE: not necessary for suspend/resume -- in that case the * NOTE: not necessary for suspend/resume -- in that case the
* core stops polling anyway * core stops polling anyway (but will also correctly handle
* the case of polling having been paused before suspend.)
*/ */
void rfkill_pause_polling(struct rfkill *rfkill); void rfkill_pause_polling(struct rfkill *rfkill);
......
...@@ -57,6 +57,8 @@ struct rfkill { ...@@ -57,6 +57,8 @@ struct rfkill {
bool registered; bool registered;
bool persistent; bool persistent;
bool polling_paused;
bool suspended;
const struct rfkill_ops *ops; const struct rfkill_ops *ops;
void *data; void *data;
...@@ -786,6 +788,7 @@ void rfkill_pause_polling(struct rfkill *rfkill) ...@@ -786,6 +788,7 @@ void rfkill_pause_polling(struct rfkill *rfkill)
if (!rfkill->ops->poll) if (!rfkill->ops->poll)
return; return;
rfkill->polling_paused = true;
cancel_delayed_work_sync(&rfkill->poll_work); cancel_delayed_work_sync(&rfkill->poll_work);
} }
EXPORT_SYMBOL(rfkill_pause_polling); EXPORT_SYMBOL(rfkill_pause_polling);
...@@ -797,6 +800,11 @@ void rfkill_resume_polling(struct rfkill *rfkill) ...@@ -797,6 +800,11 @@ void rfkill_resume_polling(struct rfkill *rfkill)
if (!rfkill->ops->poll) if (!rfkill->ops->poll)
return; return;
rfkill->polling_paused = false;
if (rfkill->suspended)
return;
queue_delayed_work(system_power_efficient_wq, queue_delayed_work(system_power_efficient_wq,
&rfkill->poll_work, 0); &rfkill->poll_work, 0);
} }
...@@ -807,7 +815,8 @@ static int rfkill_suspend(struct device *dev) ...@@ -807,7 +815,8 @@ static int rfkill_suspend(struct device *dev)
{ {
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
rfkill_pause_polling(rfkill); rfkill->suspended = true;
cancel_delayed_work_sync(&rfkill->poll_work);
return 0; return 0;
} }
...@@ -817,12 +826,16 @@ static int rfkill_resume(struct device *dev) ...@@ -817,12 +826,16 @@ static int rfkill_resume(struct device *dev)
struct rfkill *rfkill = to_rfkill(dev); struct rfkill *rfkill = to_rfkill(dev);
bool cur; bool cur;
rfkill->suspended = false;
if (!rfkill->persistent) { if (!rfkill->persistent) {
cur = !!(rfkill->state & RFKILL_BLOCK_SW); cur = !!(rfkill->state & RFKILL_BLOCK_SW);
rfkill_set_block(rfkill, cur); 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment