patch-2.4.6 linux/drivers/acpi/driver.c
Next file: linux/drivers/acpi/driver.h
Previous file: linux/drivers/acpi/dispatcher/dswstate.c
Back to the patch index
Back to the overall index
- Lines: 621
- Date:
Wed Jun 20 17:47:39 2001
- Orig file:
v2.4.5/linux/drivers/acpi/driver.c
- Orig date:
Tue May 22 09:38:51 2001
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/driver.c linux/drivers/acpi/driver.c
@@ -2,6 +2,7 @@
* driver.c - ACPI driver
*
* Copyright (C) 2000 Andrew Henroid
+ * Copyright (C) 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,6 +22,10 @@
* Changes
* David Woodhouse <dwmw2@redhat.com> 2000-12-6
* - Fix interruptible_sleep_on() races
+ * Andrew Grover <andrew.grover@intel.com> 2001-2-28
+ * - Major revamping
+ * Peter Breuer <ptb@it.uc3m.es> 2001-5-20
+ * - parse boot time params.
*/
#include <linux/config.h>
@@ -39,416 +44,44 @@
#ifdef CONFIG_ACPI_KERNEL_CONFIG
#include <asm/efi.h>
-#define ACPI_CAN_USE_EFI_STRUCT
+#define ACPI_USE_EFI
#endif
#define _COMPONENT OS_DEPENDENT
MODULE_NAME ("driver")
-struct acpi_run_entry
-{
- void (*callback)(void*);
- void *context;
- struct tq_struct task;
-};
-
-static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
-static volatile u32 acpi_event_status = 0;
-static volatile acpi_sstate_t acpi_event_state = ACPI_STATE_S0;
-static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
-
-static volatile int acpi_thread_pid = -1;
-
-static int acpi_start = 1;
-
-/************************************************/
-/* DECLARE_TASK_QUEUE is defined in */
-/* /usr/src/linux/include/linux/tqueue.h */
-/* So, acpi_thread_run is a pointer to a */
-/* tq_struct structure,defined in the same file.*/
-/************************************************/
-static DECLARE_TASK_QUEUE(acpi_thread_run);
-
-static DECLARE_WAIT_QUEUE_HEAD(acpi_thread_wait);
-
-static struct ctl_table_header *acpi_sysctl = NULL;
-
-/*
- * Examine/modify value
- */
-static int
-acpi_do_ulong(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len)
-{
- char str[2 * sizeof(unsigned long) + 4], *strend;
- unsigned long val;
- int size;
-
- if (!write) {
- if (file->f_pos) {
- *len = 0;
- return 0;
- }
-
- val = *(unsigned long *) ctl->data;
- size = sprintf(str, "0x%08lx\n", val);
- if (*len >= size) {
- copy_to_user(buffer, str, size);
- *len = size;
- }
- else
- *len = 0;
- }
- else {
- size = sizeof(str) - 1;
- if (size > *len)
- size = *len;
- copy_from_user(str, buffer, size);
- str[size] = '\0';
- val = simple_strtoul(str, &strend, 0);
- if (strend == str)
- return -EINVAL;
- *(unsigned long *) ctl->data = val;
- }
-
- file->f_pos += *len;
- return 0;
-}
-
-static int
-acpi_do_pm_timer(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len)
-{
- int size;
- u32 val = 0;
-
- char str[12];
-
- if (file->f_pos) {
- *len = 0;
- return 0;
- }
-
- val = acpi_read_pm_timer();
-
- size = sprintf(str, "0x%08x\n", val);
- if (*len >= size) {
- copy_to_user(buffer, str, size);
- *len = size;
- }
- else
- *len = 0;
-
- file->f_pos += *len;
-
- return 0;
-}
-
-/*
- * Handle ACPI event
- */
-static u32
-acpi_event(void *context)
-{
- unsigned long flags;
- int event = (int)(long)context;
- int mask = 0;
-
- switch (event) {
- case ACPI_EVENT_POWER_BUTTON:
- mask = ACPI_PWRBTN;
- break;
- case ACPI_EVENT_SLEEP_BUTTON:
- mask = ACPI_SLPBTN;
- break;
- default:
- return AE_ERROR;
- }
-
- if (mask) {
- // notify process waiting on /dev/acpi
- spin_lock_irqsave(&acpi_event_lock, flags);
- acpi_event_status |= mask;
- spin_unlock_irqrestore(&acpi_event_lock, flags);
- acpi_event_state = acpi_sleep_state;
- wake_up_interruptible(&acpi_event_wait);
- }
-
- return AE_OK;
-}
-
-/*
- * Wait for next event
- */
-static int
-acpi_do_event(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len)
-{
- u32 event_status = 0;
- acpi_sstate_t event_state = 0;
- char str[27];
- int size;
-
- if (write)
- return -EPERM;
- if (*len < sizeof(str)) {
- *len = 0;
- return 0;
- }
-
- while (!event_status) {
- unsigned long flags;
- DECLARE_WAITQUEUE(wait, current);
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&acpi_event_wait, &wait);
-
- // we need an atomic exchange here
- spin_lock_irqsave(&acpi_event_lock, flags);
- event_status = acpi_event_status;
- acpi_event_status = 0;
- spin_unlock_irqrestore(&acpi_event_lock, flags);
- event_state = acpi_event_state;
-
- if (!event_status)
- schedule();
-
- remove_wait_queue(&acpi_event_wait, &wait);
- set_current_state(TASK_RUNNING);
-
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
-
- size = sprintf(str,
- "0x%08x 0x%08x 0x%01x\n",
- event_status,
- 0,
- event_state);
- copy_to_user(buffer, str, size);
- *len = size;
- file->f_pos += size;
-
- return 0;
-}
-
-/*
- * Enter system sleep state
- */
-/*static int
-acpi_do_sleep(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len)
-{
- if (!write) {
- if (file->f_pos) {
- *len = 0;
- return 0;
- }
- }
- else {
- int status = acpi_enter_sx(ACPI_STATE_S1);
- if (status)
- return status;
- }
- file->f_pos += *len;
- return 0;
-}*/
-
-
-/*
- * Output important ACPI tables to proc
- */
-static int
-acpi_do_table(ctl_table * ctl,
- int write,
- struct file *file,
- void *buffer,
- size_t * len)
-{
- u32 table_type;
- size_t size;
- ACPI_BUFFER buf;
- u8* data;
-
- table_type = (u32) ctl->data;
- size = 0;
- buf.length = 0;
- buf.pointer = NULL;
-
- /* determine what buffer size we will need */
- if (acpi_get_table(table_type, 1, &buf) != AE_BUFFER_OVERFLOW) {
- *len = 0;
- return 0;
- }
-
- buf.pointer = kmalloc(buf.length, GFP_KERNEL);
- if (!buf.pointer) {
- return -ENOMEM;
- }
-
- /* get the table for real */
- if (!ACPI_SUCCESS(acpi_get_table(table_type, 1, &buf))) {
- kfree(buf.pointer);
- *len = 0;
- return 0;
- }
-
- if (file->f_pos < buf.length) {
- data = buf.pointer + file->f_pos;
- size = buf.length - file->f_pos;
- if (size > *len)
- size = *len;
- if (copy_to_user(buffer, data, size)) {
- kfree(buf.pointer);
- return -EFAULT;
- }
- }
+FADT_DESCRIPTOR acpi_fadt;
- kfree(buf.pointer);
-
- *len = size;
- file->f_pos += size;
- return 0;
-}
-
-/********************************************************************/
-/* R U N Q U E U E D C A L L B A C K */
-/* */
-/* The "callback" function address that was tramped through via */
-/* "acpi_run" below is finally called and executed. If we trace all */
-/* this down, the function is acpi_ev_asynch_execute_gpe_method, in */
-/* evevent.c The only other function that is ever queued is */
-/* acpi_ev_global_lock_thread in evmisc.c. */
-/********************************************************************/
-static void
-acpi_run_exec(void *context)
-{
- struct acpi_run_entry *entry
- = (struct acpi_run_entry*) context;
- (*entry->callback)(entry->context);
- kfree(entry);
-}
+static int acpi_disabled = 0;
/*
- * Queue for execution by the ACPI thread
+ * Start the interpreter
*/
int
-acpi_run(void (*callback)(void*), void *context)
-{
- struct acpi_run_entry *entry;
-
- entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
- if (!entry)
- return -1;
-
- memset(entry, 0, sizeof(entry));
- entry->callback = callback;
- entry->context = context;
- entry->task.routine = acpi_run_exec;
- entry->task.data = entry;
-
- queue_task(&entry->task, &acpi_thread_run);
-
- if (waitqueue_active(&acpi_thread_wait))
- wake_up(&acpi_thread_wait);
-
- return 0;
-}
-
-static struct ctl_table acpi_table[] =
-{
- {ACPI_P_LVL2_LAT, "c2_exit_latency",
- &acpi_c2_exit_latency, sizeof(acpi_c2_exit_latency),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_ENTER_LVL2_LAT, "c2_enter_latency",
- &acpi_c2_enter_latency, sizeof(acpi_c2_enter_latency),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_P_LVL3_LAT, "c3_exit_latency",
- &acpi_c3_exit_latency, sizeof(acpi_c3_exit_latency),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_ENTER_LVL3_LAT, "c3_enter_latency",
- &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_C1_COUNT, "c1_count",
- &acpi_c1_count, sizeof(acpi_c1_count),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_C2_COUNT, "c2_count",
- &acpi_c2_count, sizeof(acpi_c2_count),
- 0644, NULL, &acpi_do_ulong},
-
- {ACPI_C3_COUNT, "c3_count",
- &acpi_c3_count, sizeof(acpi_c3_count),
- 0644, NULL, &acpi_do_ulong},
-
-
-/* until it actually works */
-/* {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},*/
-
- {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
-
- {ACPI_FADT, "fadt", (void *) ACPI_TABLE_FADT, sizeof(int),
- 0444, NULL, &acpi_do_table},
-
- {ACPI_DSDT, "dsdt", (void *) ACPI_TABLE_DSDT, sizeof(int),
- 0444, NULL, &acpi_do_table},
-
- {ACPI_FACS, "facs", (void *) ACPI_TABLE_FACS, sizeof(int),
- 0444, NULL, &acpi_do_table},
-
- {ACPI_XSDT, "xsdt", (void *) ACPI_TABLE_XSDT, sizeof(int),
- 0444, NULL, &acpi_do_table},
-
- {ACPI_PMTIMER, "pm_timer", NULL, 0, 0444, NULL, &acpi_do_pm_timer},
-
- {0}
-};
-
-static struct ctl_table acpi_dir_table[] =
-{
- {CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table},
- {0}
-};
-
-/*
- * Initialize and run interpreter within a kernel thread
- */
-static int
-acpi_thread(void *context)
+acpi_init(void)
{
ACPI_PHYSICAL_ADDRESS rsdp_phys;
ACPI_BUFFER buffer;
ACPI_SYSTEM_INFO sys_info;
- /*
- * initialize
- */
- daemonize();
- strcpy(current->comm, "kacpid");
+ if (PM_IS_ACTIVE()) {
+ printk(KERN_NOTICE "ACPI: APM is already active, exiting\n");
+ return -ENODEV;
+ }
+
+
+ if (acpi_disabled) {
+ printk(KERN_NOTICE "ACPI: disabled by cmdline, exiting\n");
+ return -ENODEV;
+ }
if (!ACPI_SUCCESS(acpi_initialize_subsystem())) {
printk(KERN_ERR "ACPI: Driver initialization failed\n");
return -ENODEV;
}
-#ifndef ACPI_CAN_USE_EFI_STRUCT
+#ifndef ACPI_USE_EFI
if (!ACPI_SUCCESS(acpi_find_root_pointer(&rsdp_phys))) {
printk(KERN_ERR "ACPI: System description tables not found\n");
return -ENODEV;
@@ -456,12 +89,22 @@
#else
rsdp_phys = efi.acpi;
#endif
-
- if (!ACPI_SUCCESS(acpi_find_and_load_tables(rsdp_phys)))
+
+ /* from this point on, on error we must call acpi_terminate() */
+
+ if (!ACPI_SUCCESS(acpi_load_tables(rsdp_phys))) {
+ printk(KERN_ERR "ACPI: System description table load failed\n");
+ acpi_terminate();
return -ENODEV;
+ }
- if (PM_IS_ACTIVE()) {
- printk(KERN_NOTICE "ACPI: APM is already active, exiting\n");
+ /* get a separate copy of the FADT for use by other drivers */
+ memset(&acpi_fadt, 0, sizeof(acpi_fadt));
+ buffer.pointer = &acpi_fadt;
+ buffer.length = sizeof(acpi_fadt);
+
+ if (!ACPI_SUCCESS(acpi_get_table(ACPI_TABLE_FADT, 1, &buffer))) {
+ printk(KERN_ERR "ACPI: Could not get FADT\n");
acpi_terminate();
return -ENODEV;
}
@@ -483,129 +126,37 @@
return -ENODEV;
}
- printk(KERN_ERR "ACPI: Subsystem enabled\n");
+ printk(KERN_INFO "ACPI: Subsystem enabled\n");
pm_active = 1;
- acpi_cpu_init();
- acpi_sys_init();
- acpi_ec_init();
- acpi_power_init();
-
- /*
- * Non-intuitive: 0 means pwr and sleep are implemented using the fixed
- * feature model, so we install handlers. 1 means a control method
- * implementation, or none at all, so do nothing. See ACPI spec.
- */
- if (acpi_fadt.pwr_button == 0) {
- if (!ACPI_SUCCESS(acpi_install_fixed_event_handler(
- ACPI_EVENT_POWER_BUTTON,
- acpi_event,
- (void *) ACPI_EVENT_POWER_BUTTON))) {
- printk(KERN_ERR "ACPI: power button enable failed\n");
- }
- }
-
- if (acpi_fadt.sleep_button == 0) {
- if (!ACPI_SUCCESS(acpi_install_fixed_event_handler(
- ACPI_EVENT_SLEEP_BUTTON,
- acpi_event,
- (void *) ACPI_EVENT_SLEEP_BUTTON))) {
- printk(KERN_ERR "ACPI: sleep button enable failed\n");
- }
- }
-
- acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
-
- /*
- * run
- */
- for (;;) {
- DECLARE_WAITQUEUE(wait, current);
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&acpi_thread_wait, &wait);
-
- if (list_empty(&acpi_thread_run))
- schedule();
-
- remove_wait_queue(&acpi_thread_wait, &wait);
- set_current_state(TASK_RUNNING);
-
- if (signal_pending(current))
- break;
-
- run_task_queue(&acpi_thread_run);
- }
-
- /*
- * terminate
- */
- unregister_sysctl_table(acpi_sysctl);
-
- /* do not terminate, because we need acpi in order to shut down */
- /*acpi_terminate();*/
-
- acpi_thread_pid = -1;
-
return 0;
}
/*
- * Start the interpreter
- */
-int __init
-acpi_init(void)
-{
- if (acpi_start) {
- acpi_thread_pid = kernel_thread(acpi_thread,
- NULL,
- (CLONE_FS | CLONE_FILES
- | CLONE_SIGHAND | SIGCHLD));
- }
- else {
- printk(KERN_INFO "ACPI: Disabled\n");
- }
-
- return ((acpi_thread_pid >= 0) ? 0:-ENODEV);
-}
-
-/*
* Terminate the interpreter
*/
-void __exit
+void
acpi_exit(void)
{
- int count;
+ acpi_terminate();
- if (!kill_proc(acpi_thread_pid, SIGTERM, 1)) {
- // wait until thread terminates (at most 5 seconds)
- count = 5 * HZ;
- while (acpi_thread_pid >= 0 && --count) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- }
- }
-
- pm_idle = NULL;
- pm_power_off = NULL;
pm_active = 0;
+
+ printk(KERN_ERR "ACPI: Subsystem disabled\n");
}
module_init(acpi_init);
module_exit(acpi_exit);
#ifndef MODULE
-static int __init acpi_setup(char *str)
-{
- while ((str != NULL) && (*str != '\0')) {
- if (strncmp(str, "no-idle", 7) == 0)
- acpi_use_idle = 0;
- if (strncmp(str, "off", 3) == 0)
- acpi_start = 0;
- str = strchr(str, ',');
- if (str != NULL)
- str += strspn(str, ", \t");
+static int __init acpi_setup(char *str) {
+ while (str && *str) {
+ if (strncmp(str, "off", 3) == 0)
+ acpi_disabled = 1;
+ str = strchr(str, ',');
+ if (str)
+ str += strspn(str, ", \t");
}
return 1;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)