Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pm-4.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
"These fix a cpufreq core issue with the initialization of the cpufreq
sysfs interface and a cpuidle powernv driver initialization issue.

Specifics:

- symbolic links from CPU directories to the corresponding cpufreq
policy directories in sysfs are not created during initialization
in some cases which confuses user space, so prevent that from
happening (Rafael Wysocki).

- the powernv cpuidle driver fails to pass a correct cpumaks to the
cpuidle core in some cases which causes subsequent failures to
occur, so fix it (Vaidyanathan Srinivasan)"

* tag 'pm-4.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
cpuidle: powernv: Pass correct drv->cpumask for registration
cpufreq: Fix creation of symbolic links to policy directories

+39 -17
+21 -17
drivers/cpufreq/cpufreq.c
··· 918 918 .release = cpufreq_sysfs_release, 919 919 }; 920 920 921 - static int add_cpu_dev_symlink(struct cpufreq_policy *policy, 922 - struct device *dev) 921 + static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu) 923 922 { 923 + struct device *dev = get_cpu_device(cpu); 924 + 925 + if (!dev) 926 + return; 927 + 928 + if (cpumask_test_and_set_cpu(cpu, policy->real_cpus)) 929 + return; 930 + 924 931 dev_dbg(dev, "%s: Adding symlink\n", __func__); 925 - return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); 932 + if (sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq")) 933 + dev_err(dev, "cpufreq symlink creation failed\n"); 926 934 } 927 935 928 936 static void remove_cpu_dev_symlink(struct cpufreq_policy *policy, ··· 1188 1180 policy->user_policy.min = policy->min; 1189 1181 policy->user_policy.max = policy->max; 1190 1182 1191 - write_lock_irqsave(&cpufreq_driver_lock, flags); 1192 - for_each_cpu(j, policy->related_cpus) 1183 + for_each_cpu(j, policy->related_cpus) { 1193 1184 per_cpu(cpufreq_cpu_data, j) = policy; 1194 - write_unlock_irqrestore(&cpufreq_driver_lock, flags); 1185 + add_cpu_dev_symlink(policy, j); 1186 + } 1195 1187 } else { 1196 1188 policy->min = policy->user_policy.min; 1197 1189 policy->max = policy->user_policy.max; ··· 1283 1275 1284 1276 if (cpufreq_driver->exit) 1285 1277 cpufreq_driver->exit(policy); 1278 + 1279 + for_each_cpu(j, policy->real_cpus) 1280 + remove_cpu_dev_symlink(policy, get_cpu_device(j)); 1281 + 1286 1282 out_free_policy: 1287 1283 cpufreq_policy_free(policy); 1288 1284 return ret; 1289 1285 } 1290 - 1291 - static int cpufreq_offline(unsigned int cpu); 1292 1286 1293 1287 /** 1294 1288 * cpufreq_add_dev - the cpufreq interface for a CPU device. ··· 1313 1303 1314 1304 /* Create sysfs link on CPU registration */ 1315 1305 policy = per_cpu(cpufreq_cpu_data, cpu); 1316 - if (!policy || cpumask_test_and_set_cpu(cpu, policy->real_cpus)) 1317 - return 0; 1306 + if (policy) 1307 + add_cpu_dev_symlink(policy, cpu); 1318 1308 1319 - ret = add_cpu_dev_symlink(policy, dev); 1320 - if (ret) { 1321 - cpumask_clear_cpu(cpu, policy->real_cpus); 1322 - cpufreq_offline(cpu); 1323 - } 1324 - 1325 - return ret; 1309 + return 0; 1326 1310 } 1327 1311 1328 1312 static int cpufreq_offline(unsigned int cpu)
+18
drivers/cpuidle/cpuidle-powernv.c
··· 175 175 drv->state_count += 1; 176 176 } 177 177 178 + /* 179 + * On the PowerNV platform cpu_present may be less than cpu_possible in 180 + * cases when firmware detects the CPU, but it is not available to the 181 + * OS. If CONFIG_HOTPLUG_CPU=n, then such CPUs are not hotplugable at 182 + * run time and hence cpu_devices are not created for those CPUs by the 183 + * generic topology_init(). 184 + * 185 + * drv->cpumask defaults to cpu_possible_mask in 186 + * __cpuidle_driver_init(). This breaks cpuidle on PowerNV where 187 + * cpu_devices are not created for CPUs in cpu_possible_mask that 188 + * cannot be hot-added later at run time. 189 + * 190 + * Trying cpuidle_register_device() on a CPU without a cpu_device is 191 + * incorrect, so pass a correct CPU mask to the generic cpuidle driver. 192 + */ 193 + 194 + drv->cpumask = (struct cpumask *)cpu_present_mask; 195 + 178 196 return 0; 179 197 } 180 198