Commit 74245ae7 authored by Len Brown's avatar Len Brown Committed by Len Brown
parent f2493ff8
......@@ -428,7 +428,9 @@ acpi_cpufreq_cpu_init (
if (result) {
goto err_freqfree;
}
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);
printk(KERN_INFO "cpufreq: CPU%u - ACPI performance management activated.\n",
cpu);
......
......@@ -400,6 +400,9 @@ static int powernow_acpi_init(void)
powernow_table[i].frequency = CPUFREQ_TABLE_END;
powernow_table[i].index = 0;
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);
return 0;
err2:
......
......@@ -768,6 +768,10 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
data->numps = data->acpi_data.state_count;
print_basics(data);
powernow_k8_acpi_pst_values(data, 0);
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);
return 0;
err_out_mem:
......
......@@ -426,6 +426,9 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
centrino_model->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
}
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);
return 0;
err_kfree_all:
......
......@@ -762,7 +762,10 @@ static DECLARE_MUTEX(performance_sem);
* policy is adjusted accordingly.
*/
static int acpi_processor_ppc_is_init = 0;
#define PPC_REGISTERED 1
#define PPC_IN_USE 2
static int acpi_processor_ppc_status = 0;
static int acpi_processor_ppc_notifier(struct notifier_block *nb,
unsigned long event,
......@@ -820,6 +823,10 @@ acpi_processor_get_platform_limit (
* (e.g. 0 = states 0..n; 1 = states 1..n; etc.
*/
status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
if (status != AE_NOT_FOUND)
acpi_processor_ppc_status |= PPC_IN_USE;
if(ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PPC\n"));
return_VALUE(-ENODEV);
......@@ -844,17 +851,17 @@ static int acpi_processor_ppc_has_changed(
static void acpi_processor_ppc_init(void) {
if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
acpi_processor_ppc_is_init = 1;
acpi_processor_ppc_status |= PPC_REGISTERED;
else
printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n");
}
static void acpi_processor_ppc_exit(void) {
if (acpi_processor_ppc_is_init)
if (acpi_processor_ppc_status & PPC_REGISTERED)
cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER);
acpi_processor_ppc_is_init = 0;
acpi_processor_ppc_status &= ~PPC_REGISTERED;
}
/*
......@@ -1074,6 +1081,73 @@ acpi_processor_get_performance_info (
}
int acpi_processor_notify_smm(struct module *calling_module) {
acpi_status status;
static int is_done = 0;
ACPI_FUNCTION_TRACE("acpi_processor_notify_smm");
if (!(acpi_processor_ppc_status & PPC_REGISTERED))
return_VALUE(-EBUSY);
if (!try_module_get(calling_module))
return_VALUE(-EINVAL);
/* is_done is set to negative if an error occured,
* and to postitive if _no_ error occured, but SMM
* was already notified. This avoids double notification
* which might lead to unexpected results...
*/
if (is_done > 0) {
module_put(calling_module);
return_VALUE(0);
}
else if (is_done < 0) {
module_put(calling_module);
return_VALUE(is_done);
}
is_done = -EIO;
/* Can't write pstate_cnt to smi_cmd if either value is zero */
if ((!acpi_fadt.smi_cmd) ||
(!acpi_fadt.pstate_cnt)) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No SMI port or pstate_cnt\n"));
module_put(calling_module);
return_VALUE(0);
}
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
/* FADT v1 doesn't support pstate_cnt, many BIOS vendors use
* it anyway, so we need to support it... */
if (acpi_fadt_is_v1) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Using v1.0 FADT reserved value for pstate_cnt\n"));
}
status = acpi_os_write_port (acpi_fadt.smi_cmd,
(u32) acpi_fadt.pstate_cnt, 8);
if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Failed to write pstate_cnt [0x%x] to "
"smi_cmd [0x%x]\n", acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd));
module_put(calling_module);
return_VALUE(status);
}
/* Success. If there's no _PPC, we need to fear nothing, so
* we can allow the cpufreq driver to be rmmod'ed. */
is_done = 1;
if (!(acpi_processor_ppc_status & PPC_IN_USE))
module_put(calling_module);
return_VALUE(0);
}
EXPORT_SYMBOL(acpi_processor_notify_smm);
#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
/* /proc/acpi/processor/../performance interface (DEPRECATED) */
......@@ -1230,7 +1304,7 @@ acpi_processor_register_performance (
ACPI_FUNCTION_TRACE("acpi_processor_register_performance");
if (!acpi_processor_ppc_is_init)
if (!(acpi_processor_ppc_status & PPC_REGISTERED))
return_VALUE(-EINVAL);
down(&performance_sem);
......@@ -1271,9 +1345,6 @@ acpi_processor_unregister_performance (
ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
if (!acpi_processor_ppc_is_init)
return_VOID;
down(&performance_sem);
pr = processors[cpu];
......
......@@ -50,6 +50,8 @@
ACPI_MODULE_NAME ("tbconvrt")
u8 acpi_fadt_is_v1;
/*******************************************************************************
*
* FUNCTION: acpi_tb_get_table_count
......@@ -212,6 +214,7 @@ acpi_tb_convert_fadt1 (
/* ACPI 1.0 FACS */
/* The BIOS stored FADT should agree with Revision 1.0 */
acpi_fadt_is_v1 = 1;
/*
* Copy the table header and the common part of the tables.
......@@ -240,9 +243,12 @@ acpi_tb_convert_fadt1 (
/*
* Processor Performance State Control. This is the value OSPM writes to
* the SMI_CMD register to assume processor performance state control
* responsibility. There isn't any equivalence in 1.0, leave it zeroed.
* responsibility. There isn't any equivalence in 1.0, but as many 1.x
* ACPI tables contain _PCT and _PSS we also keep this value, unless
* acpi_strict is set.
*/
local_fadt->pstate_cnt = 0;
if (acpi_strict)
local_fadt->pstate_cnt = 0;
/*
* Support for the _CST object and C States change notification.
......
......@@ -330,6 +330,8 @@ struct acpi_table_support
#include "actbl1.h" /* Acpi 1.0 table definitions */
#include "actbl2.h" /* Acpi 2.0 table definitions */
extern u8 acpi_fadt_is_v1; /* is set to 1 if FADT is revision 1,
* needed for certain workarounds */
#pragma pack(1)
/*
......
......@@ -140,4 +140,8 @@ extern void acpi_processor_unregister_performance (
struct acpi_processor_performance * performance,
unsigned int cpu);
/* note: this locks both the calling module and the processor module
if a _PPC object exists, rmmod is disallowed then */
int acpi_processor_notify_smm(struct module *calling_module);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment