summaryrefslogtreecommitdiff
path: root/drivers/acpi/processor.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2004-10-22 18:16:04 -0400
committerLen Brown <len.brown@intel.com>2004-10-22 18:16:04 -0400
commitb0c31e87da79bffd0bdfe40736e9bd708c5ae6df (patch)
tree4c9f75e505ed16014417b94be171dc397fdd5fe8 /drivers/acpi/processor.c
parent289a395eaaacf6584975e3b89915dad270c7235e (diff)
parenta2eb4b43e048c44b72ab09016ba71b9c3b02488c (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.c87
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];