diff options
| author | Len Brown <len.brown@intel.com> | 2004-10-08 08:55:44 -0400 |
|---|---|---|
| committer | Len Brown <lenb@dhcppc3.> | 2004-10-08 08:55:44 -0400 |
| commit | 74245ae77995707df10ebc4aba2e8074dd99626f (patch) | |
| tree | 895d5006ebbe606cad5830c0ad0435f17b5cd1b0 | |
| parent | f2493ff8e27a501063d270a2c6089295c77c73fc (diff) | |
[ACPI] Notify SMM of cpufreq
http://marc.theaimsgroup.com/?l=acpi4linux&m=109428989121089&w=2
Signed-off-by: Dominik Brodowski <linux@brodo.de>
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/acpi.c | 4 | ||||
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 3 | ||||
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 4 | ||||
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 3 | ||||
| -rw-r--r-- | drivers/acpi/processor.c | 87 | ||||
| -rw-r--r-- | drivers/acpi/tables/tbconvrt.c | 10 | ||||
| -rw-r--r-- | include/acpi/actbl.h | 2 | ||||
| -rw-r--r-- | include/acpi/processor.h | 4 |
8 files changed, 106 insertions, 11 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c index 4ba912733cbd..16a05faf007c 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi.c @@ -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); diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index c7e3aa60dba5..1f4d6e392183 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -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: diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index e52390d12c8d..dbdbc121fdb0 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -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: diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 56aafbde6377..d8acdade9be8 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -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: diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c index 83fb743aa3e7..f55b23e0ecfa 100644 --- a/drivers/acpi/processor.c +++ b/drivers/acpi/processor.c @@ -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]; diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c index ee6818832665..8534b26ba7bf 100644 --- a/drivers/acpi/tables/tbconvrt.c +++ b/drivers/acpi/tables/tbconvrt.c @@ -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. diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index b380c23584fe..364791188f7f 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -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) /* diff --git a/include/acpi/processor.h b/include/acpi/processor.h index dab7521d8ac6..055e97ca13e9 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -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 |
