| 1 | |
| 2 | * debug.c - ACPI debug interface to userspace.
|
| 3 |
|
| 4 |
|
| 5 | #include <linux/proc_fs.h>
|
| 6 | #include <linux/init.h>
|
| 7 | #include <linux/module.h>
|
| 8 | #include <linux/kernel.h>
|
| 9 | #include <linux/moduleparam.h>
|
| 10 | #include <asm/uaccess.h>
|
| 11 | #include <acpi/acpi_drivers.h>
|
| 12 | #include <acpi/acglobal.h>
|
| 13 |
|
| 14 | #define _COMPONENT ACPI_SYSTEM_COMPONENT
|
| 15 | ACPI_MODULE_NAME ("debug")
|
| 16 |
|
| 17 | #define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
|
| 18 | #define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
|
| 19 |
|
| 20 | #ifdef MODULE_PARAM_PREFIX
|
| 21 | #undef MODULE_PARAM_PREFIX
|
| 22 | #endif
|
| 23 |
|
| 24 | #define MODULE_PARAM_PREFIX
|
| 25 | module_param(acpi_dbg_layer, uint, 0400);
|
| 26 | module_param(acpi_dbg_level, uint, 0400);
|
| 27 |
|
| 28 | struct acpi_dlayer {
|
| 29 | const char *name;
|
| 30 | unsigned long value;
|
| 31 | };
|
| 32 | struct acpi_dlevel {
|
| 33 | const char *name;
|
| 34 | unsigned long value;
|
| 35 | };
|
| 36 | #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
|
| 37 |
|
| 38 | static const struct acpi_dlayer acpi_debug_layers[] =
|
| 39 | {
|
| 40 | ACPI_DEBUG_INIT(ACPI_UTILITIES),
|
| 41 | ACPI_DEBUG_INIT(ACPI_HARDWARE),
|
| 42 | ACPI_DEBUG_INIT(ACPI_EVENTS),
|
| 43 | ACPI_DEBUG_INIT(ACPI_TABLES),
|
| 44 | ACPI_DEBUG_INIT(ACPI_NAMESPACE),
|
| 45 | ACPI_DEBUG_INIT(ACPI_PARSER),
|
| 46 | ACPI_DEBUG_INIT(ACPI_DISPATCHER),
|
| 47 | ACPI_DEBUG_INIT(ACPI_EXECUTER),
|
| 48 | ACPI_DEBUG_INIT(ACPI_RESOURCES),
|
| 49 | ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
|
| 50 | ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
|
| 51 | ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
|
| 52 | ACPI_DEBUG_INIT(ACPI_COMPILER),
|
| 53 | ACPI_DEBUG_INIT(ACPI_TOOLS),
|
| 54 | };
|
| 55 |
|
| 56 | static const struct acpi_dlevel acpi_debug_levels[] =
|
| 57 | {
|
| 58 | ACPI_DEBUG_INIT(ACPI_LV_ERROR),
|
| 59 | ACPI_DEBUG_INIT(ACPI_LV_WARN),
|
| 60 | ACPI_DEBUG_INIT(ACPI_LV_INIT),
|
| 61 | ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
|
| 62 | ACPI_DEBUG_INIT(ACPI_LV_INFO),
|
| 63 |
|
| 64 | ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
|
| 65 | ACPI_DEBUG_INIT(ACPI_LV_PARSE),
|
| 66 | ACPI_DEBUG_INIT(ACPI_LV_LOAD),
|
| 67 | ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
|
| 68 | ACPI_DEBUG_INIT(ACPI_LV_EXEC),
|
| 69 | ACPI_DEBUG_INIT(ACPI_LV_NAMES),
|
| 70 | ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
|
| 71 | ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
|
| 72 | ACPI_DEBUG_INIT(ACPI_LV_TABLES),
|
| 73 | ACPI_DEBUG_INIT(ACPI_LV_VALUES),
|
| 74 | ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
|
| 75 | ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
|
| 76 | ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
|
| 77 | ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
|
| 78 |
|
| 79 | ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
|
| 80 | ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
|
| 81 | ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
|
| 82 |
|
| 83 | ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
|
| 84 | ACPI_DEBUG_INIT(ACPI_LV_THREADS),
|
| 85 | ACPI_DEBUG_INIT(ACPI_LV_IO),
|
| 86 | ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
|
| 87 |
|
| 88 | ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
|
| 89 | ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
|
| 90 | ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
|
| 91 | ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
|
| 92 | };
|
| 93 |
|
| 94 | static int
|
| 95 | acpi_system_read_debug (
|
| 96 | char *page,
|
| 97 | char **start,
|
| 98 | off_t off,
|
| 99 | int count,
|
| 100 | int *eof,
|
| 101 | void *data)
|
| 102 | {
|
| 103 | char *p = page;
|
| 104 | int size = 0;
|
| 105 | unsigned int i;
|
| 106 |
|
| 107 | if (off != 0)
|
| 108 | goto end;
|
| 109 |
|
| 110 | p += sprintf(p, "%-25s\tHex SET\n", "Description");
|
| 111 |
|
| 112 | switch ((unsigned long) data) {
|
| 113 | case 0:
|
| 114 | for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
|
| 115 | p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
|
| 116 | acpi_debug_layers[i].name,
|
| 117 | acpi_debug_layers[i].value,
|
| 118 | (acpi_dbg_layer & acpi_debug_layers[i].value) ?
|
| 119 | '*' : ' ');
|
| 120 | }
|
| 121 | p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
|
| 122 | ACPI_ALL_DRIVERS,
|
| 123 | (acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS?
|
| 124 | '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0 ?
|
| 125 | ' ' : '-');
|
| 126 | p += sprintf(p,
|
| 127 | "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
|
| 128 | acpi_dbg_layer);
|
| 129 | break;
|
| 130 | case 1:
|
| 131 | for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
|
| 132 | p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
|
| 133 | acpi_debug_levels[i].name,
|
| 134 | acpi_debug_levels[i].value,
|
| 135 | (acpi_dbg_level & acpi_debug_levels[i].value) ?
|
| 136 | '*' : ' ');
|
| 137 | }
|
| 138 | p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
|
| 139 | acpi_dbg_level);
|
| 140 | break;
|
| 141 | default:
|
| 142 | p += sprintf(p, "Invalid debug option\n");
|
| 143 | break;
|
| 144 | }
|
| 145 |
|
| 146 | end:
|
| 147 | size = (p - page);
|
| 148 | if (size <= off+count) *eof = 1;
|
| 149 | *start = page + off;
|
| 150 | size -= off;
|
| 151 | if (size>count) size = count;
|
| 152 | if (size<0) size = 0;
|
| 153 |
|
| 154 | return size;
|
| 155 | }
|
| 156 |
|
| 157 |
|
| 158 | static int
|
| 159 | acpi_system_write_debug (
|
| 160 | struct file *file,
|
| 161 | const char __user *buffer,
|
| 162 | unsigned long count,
|
| 163 | void *data)
|
| 164 | {
|
| 165 | char debug_string[12] = {'\0'};
|
| 166 |
|
| 167 | ACPI_FUNCTION_TRACE("acpi_system_write_debug");
|
| 168 |
|
| 169 | if (count > sizeof(debug_string) - 1)
|
| 170 | return_VALUE(-EINVAL);
|
| 171 |
|
| 172 | if (copy_from_user(debug_string, buffer, count))
|
| 173 | return_VALUE(-EFAULT);
|
| 174 |
|
| 175 | debug_string[count] = '\0';
|
| 176 |
|
| 177 | switch ((unsigned long) data) {
|
| 178 | case 0:
|
| 179 | acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
|
| 180 | break;
|
| 181 | case 1:
|
| 182 | acpi_dbg_level = simple_strtoul(debug_string, NULL, 0);
|
| 183 | break;
|
| 184 | default:
|
| 185 | return_VALUE(-EINVAL);
|
| 186 | }
|
| 187 |
|
| 188 | return_VALUE(count);
|
| 189 | }
|
| 190 |
|
| 191 | static int __init acpi_debug_init(void)
|
| 192 | {
|
| 193 | struct proc_dir_entry *entry;
|
| 194 | int error = 0;
|
| 195 | char * name;
|
| 196 |
|
| 197 | ACPI_FUNCTION_TRACE("acpi_debug_init");
|
| 198 |
|
| 199 | if (acpi_disabled)
|
| 200 | return_VALUE(0);
|
| 201 |
|
| 202 |
|
| 203 | name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
|
| 204 | entry = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir,
|
| 205 | acpi_system_read_debug,(void *)0);
|
| 206 | if (entry)
|
| 207 | entry->write_proc = acpi_system_write_debug;
|
| 208 | else
|
| 209 | goto Error;
|
| 210 |
|
| 211 |
|
| 212 | name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
|
| 213 | entry = create_proc_read_entry(name, S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir,
|
| 214 | acpi_system_read_debug, (void *)1);
|
| 215 | if (entry)
|
| 216 | entry->write_proc = acpi_system_write_debug;
|
| 217 | else
|
| 218 | goto Error;
|
| 219 |
|
| 220 | Done:
|
| 221 | return_VALUE(error);
|
| 222 |
|
| 223 | Error:
|
| 224 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
| 225 | "Unable to create '%s' proc fs entry\n", name));
|
| 226 |
|
| 227 | remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir);
|
| 228 | remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir);
|
| 229 | error = -EFAULT;
|
| 230 | goto Done;
|
| 231 | }
|
| 232 |
|
| 233 | subsys_initcall(acpi_debug_init);
|