Skip to content
  • Rafael J. Wysocki's avatar
    cpufreq: Fix cpufreq driver module refcount balance after suspend/resume · e9ef4410
    Rafael J. Wysocki authored
    
    
    commit 2a99859932281ed6c2ecdd988855f8f6838f6743 upstream.
    
    Since cpufreq_cpu_put() called by __cpufreq_remove_dev() drops the
    driver module refcount, __cpufreq_remove_dev() causes that refcount
    to become negative for the cpufreq driver after a suspend/resume
    cycle.
    
    This is not the only bad thing that happens there, however, because
    kobject_put() should only be called for the policy kobject at this
    point if the CPU is not the last one for that policy.
    
    Namely, if the given CPU is the last one for that policy, the
    policy kobject's refcount should be 1 at this point, as set by
    cpufreq_add_dev_interface(), and only needs to be dropped once for
    the kobject to go away.  This actually happens under the cpu == 1
    check, so it need not be done before by cpufreq_cpu_put().
    
    On the other hand, if the given CPU is not the last one for that
    policy, this means that cpufreq_add_policy_cpu() has been called
    at least once for that policy and cpufreq_cpu_get() has been
    called for it too.  To balance that cpufreq_cpu_get(), we need to
    call cpufreq_cpu_put() in that case.
    
    Thus, to fix the described problem and keep the reference
    counters balanced in both cases, move the cpufreq_cpu_get() call
    in __cpufreq_remove_dev() to the code path executed only for
    CPUs that share the policy with other CPUs.
    
    Reported-and-tested-by: default avatarToralf Förster <toralf.foerster@gmx.de>
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    Reviewed-by: default avatarSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    e9ef4410