ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes
[safe/jmp/linux-2.6] / drivers / acpi / debug.c
index d48f65a..cc421b7 100644 (file)
@@ -3,21 +3,17 @@
  */
 
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/moduleparam.h>
+#include <linux/debugfs.h>
 #include <asm/uaccess.h>
 #include <acpi/acpi_drivers.h>
-#include <acpi/acglobal.h>
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
-ACPI_MODULE_NAME("debug")
-
-#ifdef MODULE_PARAM_PREFIX
-#undef MODULE_PARAM_PREFIX
-#endif
-#define MODULE_PARAM_PREFIX "acpi."
+ACPI_MODULE_NAME("debug");
 
 struct acpi_dlayer {
        const char *name;
@@ -44,11 +40,24 @@ static const struct acpi_dlayer acpi_debug_layers[] = {
        ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
        ACPI_DEBUG_INIT(ACPI_COMPILER),
        ACPI_DEBUG_INIT(ACPI_TOOLS),
+
+       ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_AC_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT),
+       ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT),
 };
 
 static const struct acpi_dlevel acpi_debug_levels[] = {
-       ACPI_DEBUG_INIT(ACPI_LV_ERROR),
-       ACPI_DEBUG_INIT(ACPI_LV_WARN),
        ACPI_DEBUG_INIT(ACPI_LV_INIT),
        ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
        ACPI_DEBUG_INIT(ACPI_LV_INFO),
@@ -130,6 +139,137 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) {
 module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644);
 module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644);
 
+static char trace_method_name[6];
+module_param_string(trace_method_name, trace_method_name, 6, 0644);
+static unsigned int trace_debug_layer;
+module_param(trace_debug_layer, uint, 0644);
+static unsigned int trace_debug_level;
+module_param(trace_debug_level, uint, 0644);
+
+static int param_set_trace_state(const char *val, struct kernel_param *kp)
+{
+       int result = 0;
+
+       if (!strncmp(val, "enable", strlen("enable") - 1)) {
+               result = acpi_debug_trace(trace_method_name, trace_debug_level,
+                                         trace_debug_layer, 0);
+               if (result)
+                       result = -EBUSY;
+               goto exit;
+       }
+
+       if (!strncmp(val, "disable", strlen("disable") - 1)) {
+               int name = 0;
+               result = acpi_debug_trace((char *)&name, trace_debug_level,
+                                         trace_debug_layer, 0);
+               if (result)
+                       result = -EBUSY;
+               goto exit;
+       }
+
+       if (!strncmp(val, "1", 1)) {
+               result = acpi_debug_trace(trace_method_name, trace_debug_level,
+                                         trace_debug_layer, 1);
+               if (result)
+                       result = -EBUSY;
+               goto exit;
+       }
+
+       result = -EINVAL;
+exit:
+       return result;
+}
+
+static int param_get_trace_state(char *buffer, struct kernel_param *kp)
+{
+       if (!acpi_gbl_trace_method_name)
+               return sprintf(buffer, "disable");
+       else {
+               if (acpi_gbl_trace_flags & 1)
+                       return sprintf(buffer, "1");
+               else
+                       return sprintf(buffer, "enable");
+       }
+       return 0;
+}
+
+module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
+                 NULL, 0644);
+
+/* --------------------------------------------------------------------------
+                               DebugFS Interface
+   -------------------------------------------------------------------------- */
+
+static ssize_t cm_write(struct file *file, const char __user *user_buf,
+                       size_t count, loff_t *ppos)
+{
+       static char *buf;
+       static int uncopied_bytes;
+       struct acpi_table_header table;
+       acpi_status status;
+
+       if (!(*ppos)) {
+               /* parse the table header to get the table length */
+               if (count <= sizeof(struct acpi_table_header))
+                       return -EINVAL;
+               if (copy_from_user(&table, user_buf,
+                       sizeof(struct acpi_table_header)))
+                       return -EFAULT;
+               uncopied_bytes = table.length;
+               buf = kzalloc(uncopied_bytes, GFP_KERNEL);
+               if (!buf)
+                       return -ENOMEM;
+       }
+
+       if (uncopied_bytes < count) {
+               kfree(buf);
+               return -EINVAL;
+       }
+
+       if (copy_from_user(buf + (*ppos), user_buf, count)) {
+               kfree(buf);
+               return -EFAULT;
+       }
+
+       uncopied_bytes -= count;
+       *ppos += count;
+
+       if (!uncopied_bytes) {
+               status = acpi_install_method(buf);
+               kfree(buf);
+               if (ACPI_FAILURE(status))
+                       return -EINVAL;
+               add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
+       }
+
+       return count;
+}
+
+static const struct file_operations cm_fops = {
+       .write = cm_write,
+};
+
+static int acpi_debugfs_init(void)
+{
+       struct dentry *acpi_dir, *cm_dentry;
+
+       acpi_dir = debugfs_create_dir("acpi", NULL);
+       if (!acpi_dir)
+               goto err;
+
+       cm_dentry = debugfs_create_file("custom_method", S_IWUGO,
+                                       acpi_dir, NULL, &cm_fops);
+       if (!cm_dentry)
+               goto err;
+
+       return 0;
+
+err:
+       if (acpi_dir)
+               debugfs_remove(acpi_dir);
+       return -EINVAL;
+}
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -137,72 +277,54 @@ module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_
 #define ACPI_SYSTEM_FILE_DEBUG_LAYER   "debug_layer"
 #define ACPI_SYSTEM_FILE_DEBUG_LEVEL           "debug_level"
 
-static int
-acpi_system_read_debug(char *page,
-                      char **start, off_t off, int count, int *eof, void *data)
+static int acpi_system_debug_proc_show(struct seq_file *m, void *v)
 {
-       char *p = page;
-       int size = 0;
        unsigned int i;
 
-       if (off != 0)
-               goto end;
+       seq_printf(m, "%-25s\tHex        SET\n", "Description");
 
-       p += sprintf(p, "%-25s\tHex        SET\n", "Description");
-
-       switch ((unsigned long)data) {
+       switch ((unsigned long)m->private) {
        case 0:
                for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
-                       p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
+                       seq_printf(m, "%-25s\t0x%08lX [%c]\n",
                                     acpi_debug_layers[i].name,
                                     acpi_debug_layers[i].value,
                                     (acpi_dbg_layer & acpi_debug_layers[i].
                                      value) ? '*' : ' ');
                }
-               p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
+               seq_printf(m, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
                             ACPI_ALL_DRIVERS,
                             (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
                             ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
                                                       ACPI_ALL_DRIVERS) ==
                             0 ? ' ' : '-');
-               p += sprintf(p,
+               seq_printf(m,
                             "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
                             acpi_dbg_layer);
                break;
        case 1:
                for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
-                       p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
+                       seq_printf(m, "%-25s\t0x%08lX [%c]\n",
                                     acpi_debug_levels[i].name,
                                     acpi_debug_levels[i].value,
                                     (acpi_dbg_level & acpi_debug_levels[i].
                                      value) ? '*' : ' ');
                }
-               p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
+               seq_printf(m, "--\ndebug_level = 0x%08X (* = enabled)\n",
                             acpi_dbg_level);
                break;
-       default:
-               p += sprintf(p, "Invalid debug option\n");
-               break;
        }
+       return 0;
+}
 
-      end:
-       size = (p - page);
-       if (size <= off + count)
-               *eof = 1;
-       *start = page + off;
-       size -= off;
-       if (size > count)
-               size = count;
-       if (size < 0)
-               size = 0;
-
-       return size;
+static int acpi_system_debug_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, acpi_system_debug_proc_show, PDE(inode)->data);
 }
 
-static int
-acpi_system_write_debug(struct file *file,
+static ssize_t acpi_system_debug_proc_write(struct file *file,
                        const char __user * buffer,
-                       unsigned long count, void *data)
+                       size_t count, loff_t *pos)
 {
        char debug_string[12] = { '\0' };
 
@@ -215,7 +337,7 @@ acpi_system_write_debug(struct file *file,
 
        debug_string[count] = '\0';
 
-       switch ((unsigned long)data) {
+       switch ((unsigned long)PDE(file->f_path.dentry->d_inode)->data) {
        case 0:
                acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
                break;
@@ -229,36 +351,37 @@ acpi_system_write_debug(struct file *file,
        return count;
 }
 
-static int __init acpi_debug_init(void)
+static const struct file_operations acpi_system_debug_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = acpi_system_debug_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = acpi_system_debug_proc_write,
+};
+#endif
+
+int __init acpi_procfs_init(void)
 {
+#ifdef CONFIG_ACPI_PROCFS
        struct proc_dir_entry *entry;
        int error = 0;
        char *name;
 
-
-       if (acpi_disabled)
-               return 0;
-
        /* 'debug_layer' [R/W] */
        name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
-       entry =
-           create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
-                                  acpi_root_dir, acpi_system_read_debug,
-                                  (void *)0);
-       if (entry)
-               entry->write_proc = acpi_system_write_debug;
-       else
+       entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_root_dir, &acpi_system_debug_proc_fops,
+                                (void *)0);
+       if (!entry)
                goto Error;
 
        /* 'debug_level' [R/W] */
        name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
-       entry =
-           create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
-                                  acpi_root_dir, acpi_system_read_debug,
-                                  (void *)1);
-       if (entry)
-               entry->write_proc = acpi_system_write_debug;
-       else
+       entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_root_dir, &acpi_system_debug_proc_fops,
+                                (void *)1);
+       if (!entry)
                goto Error;
 
       Done:
@@ -269,7 +392,14 @@ static int __init acpi_debug_init(void)
        remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir);
        error = -ENODEV;
        goto Done;
+#else
+       return 0;
+#endif
 }
 
-subsys_initcall(acpi_debug_init);
-#endif
+int __init acpi_debug_init(void)
+{
+       acpi_debugfs_init();
+       acpi_procfs_init();
+       return 0;
+}