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> Signed-off-by:
Santosh Mardi <gsantosh@codeaurora.org>
Loading
Please register or sign in to comment