• Bo Yan's avatar
    cpufreq: Skip cpufreq resume if it's not suspended · 703cbaa6
    Bo Yan authored
    cpufreq_resume can be called even without preceding cpufreq_suspend.
    This can happen in following scenario:
    
        suspend_devices_and_enter
           --> dpm_suspend_start
              --> dpm_prepare
                  --> device_prepare : this function errors out
              --> dpm_suspend: this is skipped due to dpm_prepare failure
                               this means cpufreq_suspend is skipped over
           --> goto Recover_platform, due to previous error
           --> goto Resume_devices
           --> dpm_resume_end
               --> dpm_resume
                   --> cpufreq_resume
    
    In case schedutil is used as frequency governor, cpufreq_resume will
    eventually call sugov_start, which does following:
    
        memset(sg_cpu, 0, sizeof(*sg_cpu));
        ....
    
    This effectively erases function pointer for frequency update, causing
    crash later on. The function pointer would have been set correctly if
    subsequent cpufreq_add_update_util_hook runs successfully, but that
    function returns earlier because cpufreq_suspend was not called:
    
        if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu)))
    		return;
    
    The fix is to check cpufreq_suspended first, if it's false, that means
    cpufreq_suspend was not called in the first place, so do not resume
    cpufreq.
    Signed-off-by: default avatarBo Yan <byan@nvidia.com>
    Acked-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
    [ rjw: Dropped printing a message ]
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    703cbaa6
cpufreq.c 66.8 KB