#include <asm/uaccess.h>
#endif
+#ifdef CONFIG_X86
+#include <asm/cpufeature.h>
+#endif
+
#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
-#define ACPI_PROCESSOR_COMPONENT 0x01000000
#define ACPI_PROCESSOR_CLASS "processor"
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
* policy is adjusted accordingly.
*/
-static unsigned int ignore_ppc = 0;
-module_param(ignore_ppc, uint, 0644);
+/* ignore_ppc:
+ * -1 -> cpufreq low level drivers not initialized -> _PSS, etc. not called yet
+ * ignore _PPC
+ * 0 -> cpufreq low level drivers initialized -> consider _PPC values
+ * 1 -> ignore _PPC totally -> forced by user through boot param
+ */
+static int ignore_ppc = -1;
+module_param(ignore_ppc, int, 0644);
MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
"limited by BIOS, this should help");
#define PPC_REGISTERED 1
#define PPC_IN_USE 2
-static int acpi_processor_ppc_status = 0;
+static int acpi_processor_ppc_status;
static int acpi_processor_ppc_notifier(struct notifier_block *nb,
unsigned long event, void *data)
struct acpi_processor *pr;
unsigned int ppc = 0;
- if (ignore_ppc)
+ if (event == CPUFREQ_START && ignore_ppc <= 0) {
+ ignore_ppc = 0;
return 0;
+ }
- mutex_lock(&performance_mutex);
+ if (ignore_ppc)
+ return 0;
if (event != CPUFREQ_INCOMPATIBLE)
- goto out;
+ return 0;
- pr = processors[policy->cpu];
+ mutex_lock(&performance_mutex);
+
+ pr = per_cpu(processors, policy->cpu);
if (!pr || !pr->performance)
goto out;
static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
{
acpi_status status = 0;
- unsigned long ppc = 0;
+ unsigned long long ppc = 0;
if (!pr)
acpi_status status = AE_OK;
acpi_handle handle = NULL;
-
if (!pr || !pr->performance || !pr->handle)
return -EINVAL;
result = acpi_processor_get_performance_control(pr);
if (result)
- return result;
+ goto update_bios;
result = acpi_processor_get_performance_states(pr);
if (result)
- return result;
+ goto update_bios;
return 0;
+
+ /*
+ * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
+ * the BIOS is older than the CPU and does not know its frequencies
+ */
+ update_bios:
+#ifdef CONFIG_X86
+ if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){
+ if(boot_cpu_has(X86_FEATURE_EST))
+ printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
+ "frequency support\n");
+ }
+#endif
+ return result;
}
int acpi_processor_notify_smm(struct module *calling_module)
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
static struct file_operations acpi_processor_perf_fops = {
+ .owner = THIS_MODULE,
.open = acpi_processor_perf_open_fs,
.read = seq_read,
.llseek = seq_lseek,
static void acpi_cpufreq_add_file(struct acpi_processor *pr)
{
- struct proc_dir_entry *entry = NULL;
struct acpi_device *device = NULL;
return;
/* add file 'performance' [R/W] */
- entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
- S_IFREG | S_IRUGO,
- acpi_device_dir(device));
- if (entry){
- entry->proc_fops = &acpi_processor_perf_fops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
+ proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO,
+ acpi_device_dir(device),
+ &acpi_processor_perf_fops, acpi_driver_data(device));
return;
}
psd = buffer.pointer;
if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _PSD data\n");
result = -EFAULT;
goto end;
}
if (psd->package.count != 1) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _PSD data\n");
result = -EFAULT;
goto end;
}
status = acpi_extract_package(&(psd->package.elements[0]),
&format, &state);
if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+ printk(KERN_ERR PREFIX "Invalid _PSD data\n");
result = -EFAULT;
goto end;
}
if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n"));
+ printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n");
result = -EFAULT;
goto end;
}
if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
- ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n"));
+ printk(KERN_ERR PREFIX "Unknown _PSD:revision\n");
result = -EFAULT;
goto end;
}
/* Call _PSD for all CPUs */
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr) {
/* Look only at processors in ACPI namespace */
continue;
* domain info.
*/
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr)
continue;
cpus_clear(covered_cpus);
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr)
continue;
if (i == j)
continue;
- match_pr = processors[j];
+ match_pr = per_cpu(processors, j);
if (!match_pr)
continue;
if (i == j)
continue;
- match_pr = processors[j];
+ match_pr = per_cpu(processors, j);
if (!match_pr)
continue;
err_ret:
for_each_possible_cpu(i) {
- pr = processors[i];
+ pr = per_cpu(processors, i);
if (!pr || !pr->performance)
continue;
mutex_lock(&performance_mutex);
- pr = processors[cpu];
+ pr = per_cpu(processors, cpu);
if (!pr) {
mutex_unlock(&performance_mutex);
return -ENODEV;
mutex_lock(&performance_mutex);
- pr = processors[cpu];
+ pr = per_cpu(processors, cpu);
if (!pr) {
mutex_unlock(&performance_mutex);
return;