diff options
| author | Len Brown <len.brown@intel.com> | 2004-10-22 18:16:04 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2004-10-22 18:16:04 -0400 |
| commit | b0c31e87da79bffd0bdfe40736e9bd708c5ae6df (patch) | |
| tree | 4c9f75e505ed16014417b94be171dc397fdd5fe8 /drivers/acpi/processor.c | |
| parent | 289a395eaaacf6584975e3b89915dad270c7235e (diff) | |
| parent | a2eb4b43e048c44b72ab09016ba71b9c3b02488c (diff) | |
Merge intel.com:/home/lenb/src/26-latest-dominik
into intel.com:/home/lenb/src/26-latest-dev
Diffstat (limited to 'drivers/acpi/processor.c')
| -rw-r--r-- | drivers/acpi/processor.c | 87 |
1 files changed, 79 insertions, 8 deletions
diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c index 0dd1b57f933e..97164d83a7ab 100644 --- a/drivers/acpi/processor.c +++ b/drivers/acpi/processor.c @@ -781,7 +781,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, @@ -839,6 +842,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); @@ -863,17 +870,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; } /* @@ -1093,6 +1100,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) */ @@ -1249,7 +1323,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); @@ -1290,9 +1364,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]; |
