• X
    cpufreq: Fix governor start/stop race condition · 95731ebb
    Xiaoguang Chen 提交于
    Cpufreq governors' stop and start operations should be carried out
    in sequence.  Otherwise, there will be unexpected behavior, like in
    the example below.
    
    Suppose there are 4 CPUs and policy->cpu=CPU0, CPU1/2/3 are linked
    to CPU0.  The normal sequence is:
    
     1) Current governor is userspace.  An application tries to set the
        governor to ondemand.  It will call __cpufreq_set_policy() in
        which it will stop the userspace governor and then start the
        ondemand governor.
    
     2) Current governor is userspace.  The online of CPU3 runs on CPU0.
        It will call cpufreq_add_policy_cpu() in which it will first
        stop the userspace governor, and then start it again.
    
    If the sequence of the above two cases interleaves, it becomes:
    
     1) Application stops userspace governor
     2)                                  Hotplug stops userspace governor
    
    which is a problem, because the governor shouldn't be stopped twice
    in a row.  What happens next is:
    
     3) Application starts ondemand governor
     4)                                  Hotplug starts a governor
    
    In step 4, the hotplug is supposed to start the userspace governor,
    but now the governor has been changed by the application to ondemand,
    so the ondemand governor is started once again, which is incorrect.
    
    The solution is to prevent policy governors from being stopped
    multiple times in a row.  A governor should only be stopped once for
    one policy.  After it has been stopped, no more governor stop
    operations should be executed.
    
    Also add a mutex to serialize governor operations.
    
    [rjw: Changelog.  And you owe me a beverage of my choice.]
    Signed-off-by: NXiaoguang Chen <chenxg@marvell.com>
    Acked-by: NViresh Kumar <viresh.kumar@linaro.org>
    Signed-off-by: NRafael J. Wysocki <rafael.j.wysocki@intel.com>
    95731ebb
cpufreq.h 13.9 KB