/* If a passive cooling situation is detected, primarily CPUfreq is used, as it * offers (in most cases) voltage scaling in addition to frequency scaling, and * thus a cubic (instead of linear) reduction of energy. Also, we allow for * _any_ cpufreq driver and not only the acpi-cpufreq driver.
*/
/* * Minimum throttle percentage for processor_thermal cooling device. * The processor_thermal driver uses it to calculate the percentage amount by * which cpu frequency must be reduced for each cooling state. This is also used * to calculate the maximum number of throttling steps or cooling states.
*/ staticint cpufreq_thermal_reduction_pctg __read_mostly = 20;
/* * Emulate "per package data" using per cpu data (which should really be * provided elsewhere) * * Note we can lose a CPU on cpu hotunplug, in this case we forget the state * temporarily. Fortunately that's not a big issue here (I hope)
*/ staticint phys_package_first_cpu(int cpu)
{ int i; int id = topology_physical_package_id(cpu);
for_each_online_cpu(i) if (topology_physical_package_id(i) == id) return i; return 0;
}
staticint cpufreq_get_max_state(unsignedint cpu)
{ if (!cpu_has_cpufreq(cpu)) return 0;
return cpufreq_thermal_max_step;
}
staticint cpufreq_get_cur_state(unsignedint cpu)
{ if (!cpu_has_cpufreq(cpu)) return 0;
return reduction_step(cpu);
}
staticint cpufreq_set_cur_state(unsignedint cpu, int state)
{ struct cpufreq_policy *policy; struct acpi_processor *pr; unsignedlong max_freq; int i, ret;
if (!cpu_has_cpufreq(cpu)) return 0;
reduction_step(cpu) = state;
/* * Update all the CPUs in the same package because they all * contribute to the temperature and often share the same * frequency.
*/
for_each_online_cpu(i) { if (topology_physical_package_id(i) !=
topology_physical_package_id(cpu)) continue;
pr = per_cpu(processors, i);
if (unlikely(!freq_qos_request_active(&pr->thermal_req))) continue;
policy = cpufreq_cpu_get(i); if (!policy) return -EINVAL;
ret = freq_qos_update_request(&pr->thermal_req, max_freq); if (ret < 0) {
pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n",
pr->id, ret);
}
} return 0;
}
staticvoid acpi_thermal_cpufreq_config(void)
{ int cpufreq_pctg = acpi_arch_thermal_cpufreq_pctg();
if (!cpufreq_pctg) return;
cpufreq_thermal_reduction_pctg = cpufreq_pctg;
/* * Derive the MAX_STEP from minimum throttle percentage so that the reduction * percentage doesn't end up becoming negative. Also, cap the MAX_STEP so that * the CPU performance doesn't become 0.
*/
cpufreq_thermal_max_step = (100 / cpufreq_pctg) - 2;
}
/* * There exists four states according to * cpufreq_thermal_reduction_step. 0, 1, 2, 3
*/
max_state += cpufreq_get_max_state(pr->id); if (pr->flags.throttling)
max_state += (pr->throttling.state_count -1);
int acpi_processor_thermal_init(struct acpi_processor *pr, struct acpi_device *device)
{ int result = 0;
pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops); if (IS_ERR(pr->cdev)) {
result = PTR_ERR(pr->cdev); return result;
}
dev_dbg(&device->dev, "registered as cooling_device%d\n",
pr->cdev->id);
result = sysfs_create_link(&device->dev.kobj,
&pr->cdev->device.kobj, "thermal_cooling"); if (result) {
dev_err(&device->dev, "Failed to create sysfs link 'thermal_cooling'\n"); goto err_thermal_unregister;
}
result = sysfs_create_link(&pr->cdev->device.kobj,
&device->dev.kobj, "device"); if (result) {
dev_err(&pr->cdev->device, "Failed to create sysfs link 'device'\n"); goto err_remove_sysfs_thermal;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.1Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.