PM / devfreq: bw_hwmon: Fix a race condition in hwmon stop
Currently, the bw_hwmon governor handles DEVFREQ_GOV_STOP and
DEVFREQ_GOV_SUSPEND events by calling devfreq_monitor_stop
and devfreq_monitor_suspend respectively, prior to disabling
the bw_hwmon irq. Doing so allows for the following race condition:
T0: bw_hwmon irq thread:
/* df->governor == bw_hwmon
* changing to
* powersave governor
*/
governor_store()
/* Calls bw_hwmon governor event
* handler with DEVFREQ_GOV_STOP
* event
*/
df->governor->event_handler()
gov_stop()
stop_monitor()
update_bw_hwmon()
devfreq_monitor_stop()
/* Cancels timer for future calls
* to devfreq_monitor
*/
devfreq_monitor_stop()
/* Calls free_irq(), which waits
* for the bw_hwmon IRQ thread
* to finish.
*/
hw->stop_hwmon()
--finishes update_devfreq()--
/* Incorrectly starts
* devfreq_monitoring
*/
devfreq_monitor_start()
--thread finishes execution--
--finishes DEVFREQ_GOV_STOP
handling--
--switches governor to powersave--
/* devfreq monitor for this
* instance. This will call
* queue_delayed_work()
* which internally queues
* the timer for this devfreq
* structure.
*/
devfreq_monitor()
/* df->governor == powersave
* changing to bw_hwmon
*/
governor_store()
/* powersave: DEVFREQ_GOV_STOP
*/
df->governor->event_handler()
/* bw_hwmon: DEVFREQ_GOV_START
*/
df->governor->event_handler()
gov_start()
/* Will incorrectly adjust
* the fields within the
* timer and corrupt the
* timer data structure
*/
devfreq_monitor_start()
Since this corrupts the timer data structures, when the timer
gets expired, it will be expired twice. Fix this race condition
by introducing new lock to synchronize the access to the
mon_started variable, so that the irq thread does not restart
the devfreq monitor after it has been stopped.
Change-Id: I2dced21d5343afd6ec2e13876e26aeb5c83a4d12
Signed-off-by:
Rama Aparna Mallavarapu <aparnam@codeaurora.org>
Loading
Please register or sign in to comment