Skip to content
  • Sebastian Andrzej Siewior's avatar
    cpufreq: Remove cpufreq_rwsem · 454d3a25
    Sebastian Andrzej Siewior authored
    cpufreq_rwsem was introduced in commit 6eed9404
    
     ("cpufreq: Use
    rwsem for protecting critical sections) in order to replace
    try_module_get() on the cpu-freq driver. That try_module_get() worked
    well until the refcount was so heavily used that module removal became
    more or less impossible.
    
    Though when looking at the various (undocumented) protection
    mechanisms in that code, the randomly sprinkeled around cpufreq_rwsem
    locking sites are superfluous.
    
    The policy, which is acquired in cpufreq_cpu_get() and released in
    cpufreq_cpu_put() is sufficiently protected already.
    
      cpufreq_cpu_get(cpu)
        /* Protects against concurrent driver removal */
        read_lock_irqsave(&cpufreq_driver_lock, flags);
        policy = per_cpu(cpufreq_cpu_data, cpu);
        kobject_get(&policy->kobj);
        read_unlock_irqrestore(&cpufreq_driver_lock, flags);
    
    The reference on the policy serializes versus module unload already:
    
      cpufreq_unregister_driver()
        subsys_interface_unregister()
          __cpufreq_remove_dev_finish()
            per_cpu(cpufreq_cpu_data) = NULL;
    	cpufreq_policy_put_kobj()
    
    If there is a reference held on the policy, i.e. obtained prior to the
    unregister call, then cpufreq_policy_put_kobj() will wait until that
    reference is dropped. So once subsys_interface_unregister() returns
    there is no policy pointer in flight and no new reference can be
    obtained. So that rwsem protection is useless.
    
    The other usage of cpufreq_rwsem in show()/store() of the sysfs
    interface is redundant as well because sysfs already does the proper
    kobject_get()/put() pairs.
    
    That leaves CPU hotplug versus module removal. The current
    down_write() around the write_lock() in cpufreq_unregister_driver() is
    silly at best as it protects actually nothing.
    
    The trivial solution to this is to prevent hotplug across
    cpufreq_unregister_driver completely.
    
    Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    454d3a25