• Viresh Kumar's avatar
    intel_pstate: Update frequencies of policy->cpus only from ->set_policy() · 41cfd64c
    Viresh Kumar authored
    The intel-pstate driver is using intel_pstate_hwp_set() from two
    separate paths, i.e. ->set_policy() callback and sysfs update path for
    the files present in /sys/devices/system/cpu/intel_pstate/ directory.
    
    While an update to the sysfs path applies to all the CPUs being managed
    by the driver (which essentially means all the online CPUs), the update
    via the ->set_policy() callback applies to a smaller group of CPUs
    managed by the policy for which ->set_policy() is called.
    
    And so, intel_pstate_hwp_set() should update frequencies of only the
    CPUs that are part of policy->cpus mask, while it is called from
    ->set_policy() callback.
    
    In order to do that, add a parameter (cpumask) to intel_pstate_hwp_set()
    and apply the frequency changes only to the concerned CPUs.
    
    For ->set_policy() path, we are only concerned about policy->cpus, and
    so policy->rwsem lock taken by the core prior to calling ->set_policy()
    is enough to take care of any races. The larger lock acquired by
    get_online_cpus() is required only for the updates to sysfs files.
    
    Add another routine, intel_pstate_hwp_set_online_cpus(), and call it
    from the sysfs update paths.
    
    This also fixes a lockdep reported recently, where policy->rwsem and
    get_online_cpus() could have been acquired in any order causing an ABBA
    deadlock. The sequence of events leading to that was:
    
    intel_pstate_init(...)
    	...cpufreq_online(...)
    		down_write(&policy->rwsem); // Locks policy->rwsem
    		...
    		cpufreq_init_policy(policy);
    			...intel_pstate_hwp_set();
    				get_online_cpus(); // Temporarily locks cpu_hotplug.lock
    		...
    		up_write(&policy->rwsem);
    
    pm_suspend(...)
    	...disable_nonboot_cpus()
    		_cpu_down()
    			cpu_hotplug_begin(); // Locks cpu_hotplug.lock
    			__cpu_notify(CPU_DOWN_PREPARE, ...);
    				...cpufreq_offline_prepare();
    					down_write(&policy->rwsem); // Locks policy->rwsem
    Reported-and-tested-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
    Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
    Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
    Acked-by: default avatarSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    41cfd64c
intel_pstate.c 34.7 KB