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

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)