#include <linux/cpufreq.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/dmi.h>
-#include <linux/moduleparam.h>
#include <asm/io.h>
#include <asm/system.h>
* each IDE controller's DMA status to make sure we catch all
* DMA activity.
*/
- dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+ dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB,
PCI_ANY_ID, PCI_ANY_ID, NULL);
- if (dev) {
+ if (dev)
errata.piix4.bmisx = pci_resource_start(dev, 4);
- pci_dev_put(dev);
- }
/*
* Type-F DMA
* disable C3 support if this is enabled, as some legacy
* devices won't operate well if fast DMA is disabled.
*/
- dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+ dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_0,
PCI_ANY_ID, PCI_ANY_ID, NULL);
if (dev) {
pci_read_config_byte(dev, 0x77, &value2);
if ((value1 & 0x80) || (value2 & 0x80))
errata.piix4.fdma = 1;
- pci_dev_put(dev);
}
break;
/*
* PIIX4
*/
- dev = pci_get_subsys(PCI_VENDOR_ID_INTEL,
+ dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_3, PCI_ANY_ID, PCI_ANY_ID, NULL);
- if (dev) {
+ if (dev)
result = acpi_processor_errata_piix4(dev);
- pci_dev_put(dev);
- }
return_VALUE(result);
}
{
struct acpi_processor *pr = NULL;
struct acpi_processor_cx *cx = NULL;
- unsigned int next_state = 0;
- unsigned int sleep_ticks = 0;
+ int next_state = 0;
+ int sleep_ticks = 0;
u32 t1, t2 = 0;
pr = processors[smp_processor_id()];
*/
local_irq_disable();
- /*
- * Check whether we truly need to go idle, or should
- * reschedule:
- */
- if (unlikely(need_resched())) {
- local_irq_enable();
- return;
- }
-
cx = &(pr->power.states[pr->power.state]);
/*
switch (pr->power.state) {
case ACPI_STATE_C1:
- /*
- * Invoke C1.
- * Use the appropriate idle routine, the one that would
- * be used without acpi C-states.
- */
- if (pm_idle_save)
- pm_idle_save();
- else
- safe_halt();
+ /* Invoke C1. */
+ safe_halt();
/*
* TBD: Can't get time duration while in C1, as resumes
* go to an ISR rather than here. Need to instrument
* Track the number of longs (time asleep is greater than threshold)
* and promote when the count threshold is reached. Note that bus
* mastering activity may prevent promotions.
- * Do not promote above max_cstate.
*/
- if (cx->promotion.state && (cx->promotion.state <= max_cstate)) {
+ if (cx->promotion.state) {
if (sleep_ticks > cx->promotion.threshold.ticks) {
cx->promotion.count++;
cx->demotion.count = 0;
}
end:
- /*
- * Demote if current state exceeds max_cstate
- */
- if (pr->power.state > max_cstate) {
- next_state = max_cstate;
- }
-
/*
* New Cx State?
* -------------
* policy is adjusted accordingly.
*/
-#define PPC_REGISTERED 1
-#define PPC_IN_USE 2
-
-static int acpi_processor_ppc_status = 0;
+static int acpi_processor_ppc_is_init = 0;
static int acpi_processor_ppc_notifier(struct notifier_block *nb,
unsigned long event,
* (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);
static void acpi_processor_ppc_init(void) {
if (!cpufreq_register_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER))
- acpi_processor_ppc_status |= PPC_REGISTERED;
+ acpi_processor_ppc_is_init = 1;
else
printk(KERN_DEBUG "Warning: Processor Platform Limit not supported.\n");
}
static void acpi_processor_ppc_exit(void) {
- if (acpi_processor_ppc_status & PPC_REGISTERED)
+ if (acpi_processor_ppc_is_init)
cpufreq_unregister_notifier(&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER);
- acpi_processor_ppc_status &= ~PPC_REGISTERED;
+ acpi_processor_ppc_is_init = 0;
}
/*
struct acpi_buffer format = {sizeof("NNNNNN"), "NNNNNN"};
struct acpi_buffer state = {0, NULL};
union acpi_object *pss = NULL;
- unsigned int i;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_processor_get_performance_states");
}
-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) */
static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_processor *pr = (struct acpi_processor *)seq->private;
- unsigned int i;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_processor_perf_seq_show");
(u32) pr->performance->states[i].transition_latency);
end:
- return_VALUE(0);
+ return 0;
}
static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
ACPI_FUNCTION_TRACE("acpi_processor_register_performance");
- if (!(acpi_processor_ppc_status & PPC_REGISTERED))
+ if (!acpi_processor_ppc_is_init)
return_VALUE(-EINVAL);
down(&performance_sem);
ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
+ if (!acpi_processor_ppc_is_init)
+ return_VOID;
+
down(&performance_sem);
pr = processors[cpu];
pr->flags.limit ? "yes" : "no");
end:
- return_VALUE(0);
+ return 0;
}
static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_processor *pr = (struct acpi_processor *)seq->private;
- unsigned int i;
+ int i = 0;
ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show");
seq_printf(seq, "active state: C%d\n"
"default state: C%d\n"
- "max_cstate: C%d\n"
"bus master activity: %08x\n",
pr->power.state,
pr->power.default_state,
- max_cstate,
pr->power.bm_activity);
seq_puts(seq, "states:\n");
}
end:
- return_VALUE(0);
+ return 0;
}
static int acpi_processor_power_open_fs(struct inode *inode, struct file *file)
(pr->throttling.states[i].performance?pr->throttling.states[i].performance/10:0));
end:
- return_VALUE(0);
+ return 0;
}
static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
pr->limit.thermal.px, pr->limit.thermal.tx);
end:
- return_VALUE(0);
+ return 0;
}
static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
/*
* Install the idle handler if processor power management is supported.
- * Note that we use previously set idle handler will be used on
+ * Note that the default idle handler (default_idle) will be used on
* platforms that only support C1.
*/
- if ((pr->flags.power) && (!boot_option_idle_override)) {
- printk(KERN_INFO PREFIX "%s [%s] (supports",
- acpi_device_name(device), acpi_device_bid(device));
- for (i = 1; i < ACPI_C_STATE_COUNT; i++)
- if (pr->power.states[i].valid)
- printk(" C%d", i);
- printk(")\n");
- if (pr->id == 0) {
- pm_idle_save = pm_idle;
- pm_idle = acpi_processor_idle;
- }
+ if ((pr->id == 0) && (pr->flags.power)) {
+ pm_idle_save = pm_idle;
+ pm_idle = acpi_processor_idle;
}
- if (pr->flags.throttling) {
- printk(KERN_INFO PREFIX "%s [%s] (supports",
- acpi_device_name(device), acpi_device_bid(device));
- printk(" %d throttling states", pr->throttling.state_count);
- printk(")\n");
- }
+ printk(KERN_INFO PREFIX "%s [%s] (supports",
+ acpi_device_name(device), acpi_device_bid(device));
+ for (i=1; i<ACPI_C_STATE_COUNT; i++)
+ if (pr->power.states[i].valid)
+ printk(" C%d", i);
+ if (pr->flags.throttling)
+ printk(", %d throttling states", pr->throttling.state_count);
+ printk(")\n");
end:
if (result) {
return_VALUE(0);
}
-/*
- * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
- * For now disable this. Probably a bug somewhere else.
- *
- * To skip this limit, boot/load with a large max_cstate limit.
- */
-static int no_c2c3(struct dmi_system_id *id)
-{
- if (max_cstate > ACPI_C_STATES_MAX)
- return 0;
-
- printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled."
- " Override with \"processor.max_cstate=9\"\n", id->ident);
-
- max_cstate = 1;
-
- return 0;
-}
-
-static struct dmi_system_id __initdata processor_dmi_table[] = {
- { no_c2c3, "IBM ThinkPad R40e", {
- DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
- DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }},
- { no_c2c3, "Medion 41700", {
- DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
- DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }},
- {},
-};
-
-/* We keep the driver loaded even when ACPI is not running.
- This is needed for the powernow-k8 driver, that works even without
- ACPI, but needs symbols from this driver */
static int __init
acpi_processor_init (void)
acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
if (!acpi_processor_dir)
- return_VALUE(0);
+ return_VALUE(-ENODEV);
acpi_processor_dir->owner = THIS_MODULE;
result = acpi_bus_register_driver(&acpi_processor_driver);
if (result < 0) {
remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
- return_VALUE(0);
+ return_VALUE(-ENODEV);
}
acpi_thermal_cpufreq_init();
acpi_processor_ppc_init();
- dmi_check_system(processor_dmi_table);
-
- if (max_cstate < ACPI_C_STATES_MAX)
- printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", max_cstate);
-
return_VALUE(0);
}
module_init(acpi_processor_init);
module_exit(acpi_processor_exit);
-module_param_named(max_cstate, max_cstate, uint, 0);
EXPORT_SYMBOL(acpi_processor_set_thermal_limit);