linux/drivers/acpi/debug.c
<<
>>
Prefs
   1/*
   2 * debug.c - ACPI debug interface to userspace.
   3 */
   4
   5#include <linux/proc_fs.h>
   6#include <linux/seq_file.h>
   7#include <linux/init.h>
   8#include <linux/module.h>
   9#include <linux/kernel.h>
  10#include <linux/moduleparam.h>
  11#include <linux/debugfs.h>
  12#include <asm/uaccess.h>
  13#include <acpi/acpi_drivers.h>
  14
  15#define _COMPONENT              ACPI_SYSTEM_COMPONENT
  16ACPI_MODULE_NAME("debug");
  17
  18struct acpi_dlayer {
  19        const char *name;
  20        unsigned long value;
  21};
  22struct acpi_dlevel {
  23        const char *name;
  24        unsigned long value;
  25};
  26#define ACPI_DEBUG_INIT(v)      { .name = #v, .value = v }
  27
  28static const struct acpi_dlayer acpi_debug_layers[] = {
  29        ACPI_DEBUG_INIT(ACPI_UTILITIES),
  30        ACPI_DEBUG_INIT(ACPI_HARDWARE),
  31        ACPI_DEBUG_INIT(ACPI_EVENTS),
  32        ACPI_DEBUG_INIT(ACPI_TABLES),
  33        ACPI_DEBUG_INIT(ACPI_NAMESPACE),
  34        ACPI_DEBUG_INIT(ACPI_PARSER),
  35        ACPI_DEBUG_INIT(ACPI_DISPATCHER),
  36        ACPI_DEBUG_INIT(ACPI_EXECUTER),
  37        ACPI_DEBUG_INIT(ACPI_RESOURCES),
  38        ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
  39        ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
  40        ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
  41        ACPI_DEBUG_INIT(ACPI_COMPILER),
  42        ACPI_DEBUG_INIT(ACPI_TOOLS),
  43
  44        ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT),
  45        ACPI_DEBUG_INIT(ACPI_AC_COMPONENT),
  46        ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT),
  47        ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT),
  48        ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT),
  49        ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT),
  50        ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT),
  51        ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT),
  52        ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT),
  53        ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT),
  54        ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT),
  55        ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT),
  56        ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT),
  57        ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT),
  58};
  59
  60static const struct acpi_dlevel acpi_debug_levels[] = {
  61        ACPI_DEBUG_INIT(ACPI_LV_INIT),
  62        ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
  63        ACPI_DEBUG_INIT(ACPI_LV_INFO),
  64
  65        ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
  66        ACPI_DEBUG_INIT(ACPI_LV_PARSE),
  67        ACPI_DEBUG_INIT(ACPI_LV_LOAD),
  68        ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
  69        ACPI_DEBUG_INIT(ACPI_LV_EXEC),
  70        ACPI_DEBUG_INIT(ACPI_LV_NAMES),
  71        ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
  72        ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
  73        ACPI_DEBUG_INIT(ACPI_LV_TABLES),
  74        ACPI_DEBUG_INIT(ACPI_LV_VALUES),
  75        ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
  76        ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
  77        ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
  78        ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
  79
  80        ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
  81        ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
  82        ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
  83
  84        ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
  85        ACPI_DEBUG_INIT(ACPI_LV_THREADS),
  86        ACPI_DEBUG_INIT(ACPI_LV_IO),
  87        ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
  88
  89        ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
  90        ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
  91        ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
  92        ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
  93};
  94
  95/* --------------------------------------------------------------------------
  96                              FS Interface (/sys)
  97   -------------------------------------------------------------------------- */
  98static int param_get_debug_layer(char *buffer, struct kernel_param *kp) {
  99        int result = 0;
 100        int i;
 101
 102        result = sprintf(buffer, "%-25s\tHex        SET\n", "Description");
 103
 104        for(i = 0; i <ARRAY_SIZE(acpi_debug_layers); i++) {
 105                result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n",
 106                                        acpi_debug_layers[i].name,
 107                                        acpi_debug_layers[i].value,
 108                                        (acpi_dbg_layer & acpi_debug_layers[i].value) ? '*' : ' ');
 109        }
 110        result += sprintf(buffer+result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
 111                                        ACPI_ALL_DRIVERS,
 112                                        (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
 113                                        ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
 114                                        ACPI_ALL_DRIVERS) == 0 ? ' ' : '-');
 115        result += sprintf(buffer+result, "--\ndebug_layer = 0x%08X ( * = enabled)\n", acpi_dbg_layer);
 116
 117        return result;
 118}
 119
 120static int param_get_debug_level(char *buffer, struct kernel_param *kp) {
 121        int result = 0;
 122        int i;
 123
 124        result = sprintf(buffer, "%-25s\tHex        SET\n", "Description");
 125
 126        for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
 127                result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n",
 128                                     acpi_debug_levels[i].name,
 129                                     acpi_debug_levels[i].value,
 130                                     (acpi_dbg_level & acpi_debug_levels[i].
 131                                      value) ? '*' : ' ');
 132        }
 133        result += sprintf(buffer+result, "--\ndebug_level = 0x%08X (* = enabled)\n",
 134                             acpi_dbg_level);
 135
 136        return result;
 137}
 138
 139module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644);
 140module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644);
 141
 142static char trace_method_name[6];
 143module_param_string(trace_method_name, trace_method_name, 6, 0644);
 144static unsigned int trace_debug_layer;
 145module_param(trace_debug_layer, uint, 0644);
 146static unsigned int trace_debug_level;
 147module_param(trace_debug_level, uint, 0644);
 148
 149static int param_set_trace_state(const char *val, struct kernel_param *kp)
 150{
 151        int result = 0;
 152
 153        if (!strncmp(val, "enable", strlen("enable") - 1)) {
 154                result = acpi_debug_trace(trace_method_name, trace_debug_level,
 155                                          trace_debug_layer, 0);
 156                if (result)
 157                        result = -EBUSY;
 158                goto exit;
 159        }
 160
 161        if (!strncmp(val, "disable", strlen("disable") - 1)) {
 162                int name = 0;
 163                result = acpi_debug_trace((char *)&name, trace_debug_level,
 164                                          trace_debug_layer, 0);
 165                if (result)
 166                        result = -EBUSY;
 167                goto exit;
 168        }
 169
 170        if (!strncmp(val, "1", 1)) {
 171                result = acpi_debug_trace(trace_method_name, trace_debug_level,
 172                                          trace_debug_layer, 1);
 173                if (result)
 174                        result = -EBUSY;
 175                goto exit;
 176        }
 177
 178        result = -EINVAL;
 179exit:
 180        return result;
 181}
 182
 183static int param_get_trace_state(char *buffer, struct kernel_param *kp)
 184{
 185        if (!acpi_gbl_trace_method_name)
 186                return sprintf(buffer, "disable");
 187        else {
 188                if (acpi_gbl_trace_flags & 1)
 189                        return sprintf(buffer, "1");
 190                else
 191                        return sprintf(buffer, "enable");
 192        }
 193        return 0;
 194}
 195
 196module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
 197                  NULL, 0644);
 198
 199/* --------------------------------------------------------------------------
 200                                DebugFS Interface
 201   -------------------------------------------------------------------------- */
 202
 203static ssize_t cm_write(struct file *file, const char __user *user_buf,
 204                        size_t count, loff_t *ppos)
 205{
 206        static char *buf;
 207        static int uncopied_bytes;
 208        struct acpi_table_header table;
 209        acpi_status status;
 210
 211        if (!(*ppos)) {
 212                /* parse the table header to get the table length */
 213                if (count <= sizeof(struct acpi_table_header))
 214                        return -EINVAL;
 215                if (copy_from_user(&table, user_buf,
 216                        sizeof(struct acpi_table_header)))
 217                        return -EFAULT;
 218                uncopied_bytes = table.length;
 219                buf = kzalloc(uncopied_bytes, GFP_KERNEL);
 220                if (!buf)
 221                        return -ENOMEM;
 222        }
 223
 224        if (uncopied_bytes < count) {
 225                kfree(buf);
 226                return -EINVAL;
 227        }
 228
 229        if (copy_from_user(buf + (*ppos), user_buf, count)) {
 230                kfree(buf);
 231                return -EFAULT;
 232        }
 233
 234        uncopied_bytes -= count;
 235        *ppos += count;
 236
 237        if (!uncopied_bytes) {
 238                status = acpi_install_method(buf);
 239                kfree(buf);
 240                if (ACPI_FAILURE(status))
 241                        return -EINVAL;
 242                add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
 243        }
 244
 245        return count;
 246}
 247
 248static const struct file_operations cm_fops = {
 249        .write = cm_write,
 250};
 251
 252static int acpi_debugfs_init(void)
 253{
 254        struct dentry *acpi_dir, *cm_dentry;
 255
 256        acpi_dir = debugfs_create_dir("acpi", NULL);
 257        if (!acpi_dir)
 258                goto err;
 259
 260        cm_dentry = debugfs_create_file("custom_method", S_IWUGO,
 261                                        acpi_dir, NULL, &cm_fops);
 262        if (!cm_dentry)
 263                goto err;
 264
 265        return 0;
 266
 267err:
 268        if (acpi_dir)
 269                debugfs_remove(acpi_dir);
 270        return -EINVAL;
 271}
 272
 273/* --------------------------------------------------------------------------
 274                              FS Interface (/proc)
 275   -------------------------------------------------------------------------- */
 276#ifdef CONFIG_ACPI_PROCFS
 277#define ACPI_SYSTEM_FILE_DEBUG_LAYER    "debug_layer"
 278#define ACPI_SYSTEM_FILE_DEBUG_LEVEL            "debug_level"
 279
 280static int acpi_system_debug_proc_show(struct seq_file *m, void *v)
 281{
 282        unsigned int i;
 283
 284        seq_printf(m, "%-25s\tHex        SET\n", "Description");
 285
 286        switch ((unsigned long)m->private) {
 287        case 0:
 288                for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
 289                        seq_printf(m, "%-25s\t0x%08lX [%c]\n",
 290                                     acpi_debug_layers[i].name,
 291                                     acpi_debug_layers[i].value,
 292                                     (acpi_dbg_layer & acpi_debug_layers[i].
 293                                      value) ? '*' : ' ');
 294                }
 295                seq_printf(m, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
 296                             ACPI_ALL_DRIVERS,
 297                             (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
 298                             ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
 299                                                       ACPI_ALL_DRIVERS) ==
 300                             0 ? ' ' : '-');
 301                seq_printf(m,
 302                             "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
 303                             acpi_dbg_layer);
 304                break;
 305        case 1:
 306                for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
 307                        seq_printf(m, "%-25s\t0x%08lX [%c]\n",
 308                                     acpi_debug_levels[i].name,
 309                                     acpi_debug_levels[i].value,
 310                                     (acpi_dbg_level & acpi_debug_levels[i].
 311                                      value) ? '*' : ' ');
 312                }
 313                seq_printf(m, "--\ndebug_level = 0x%08X (* = enabled)\n",
 314                             acpi_dbg_level);
 315                break;
 316        }
 317        return 0;
 318}
 319
 320static int acpi_system_debug_proc_open(struct inode *inode, struct file *file)
 321{
 322        return single_open(file, acpi_system_debug_proc_show, PDE(inode)->data);
 323}
 324
 325static ssize_t acpi_system_debug_proc_write(struct file *file,
 326                        const char __user * buffer,
 327                        size_t count, loff_t *pos)
 328{
 329        char debug_string[12] = { '\0' };
 330
 331
 332        if (count > sizeof(debug_string) - 1)
 333                return -EINVAL;
 334
 335        if (copy_from_user(debug_string, buffer, count))
 336                return -EFAULT;
 337
 338        debug_string[count] = '\0';
 339
 340        switch ((unsigned long)PDE(file->f_path.dentry->d_inode)->data) {
 341        case 0:
 342                acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
 343                break;
 344        case 1:
 345                acpi_dbg_level = simple_strtoul(debug_string, NULL, 0);
 346                break;
 347        default:
 348                return -EINVAL;
 349        }
 350
 351        return count;
 352}
 353
 354static const struct file_operations acpi_system_debug_proc_fops = {
 355        .owner          = THIS_MODULE,
 356        .open           = acpi_system_debug_proc_open,
 357        .read           = seq_read,
 358        .llseek         = seq_lseek,
 359        .release        = single_release,
 360        .write          = acpi_system_debug_proc_write,
 361};
 362#endif
 363
 364int __init acpi_procfs_init(void)
 365{
 366#ifdef CONFIG_ACPI_PROCFS
 367        struct proc_dir_entry *entry;
 368        int error = 0;
 369        char *name;
 370
 371        /* 'debug_layer' [R/W] */
 372        name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
 373        entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR,
 374                                 acpi_root_dir, &acpi_system_debug_proc_fops,
 375                                 (void *)0);
 376        if (!entry)
 377                goto Error;
 378
 379        /* 'debug_level' [R/W] */
 380        name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
 381        entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR,
 382                                 acpi_root_dir, &acpi_system_debug_proc_fops,
 383                                 (void *)1);
 384        if (!entry)
 385                goto Error;
 386
 387      Done:
 388        return error;
 389
 390      Error:
 391        remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir);
 392        remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir);
 393        error = -ENODEV;
 394        goto Done;
 395#else
 396        return 0;
 397#endif
 398}
 399
 400int __init acpi_debug_init(void)
 401{
 402        acpi_debugfs_init();
 403        acpi_procfs_init();
 404        return 0;
 405}
 406
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.