| 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 | #ifdef MODULE_PARAM_PREFIX
|
| 18 | #undef MODULE_PARAM_PREFIX
|
| 19 | #endif
|
| 20 | #define MODULE_PARAM_PREFIX "acpi."
|
| 21 |
|
| 22 | struct acpi_dlayer {
|
| 23 | const char *name;
|
| 24 | unsigned long value;
|
| 25 | };
|
| 26 | struct acpi_dlevel {
|
| 27 | const char *name;
|
| 28 | unsigned long value;
|
| 29 | };
|
| 30 | #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
|
| 31 |
|
| 32 | static const struct acpi_dlayer acpi_debug_layers[] = {
|
| 33 | ACPI_DEBUG_INIT(ACPI_UTILITIES),
|
| 34 | ACPI_DEBUG_INIT(ACPI_HARDWARE),
|
| 35 | ACPI_DEBUG_INIT(ACPI_EVENTS),
|
| 36 | ACPI_DEBUG_INIT(ACPI_TABLES),
|
| 37 | ACPI_DEBUG_INIT(ACPI_NAMESPACE),
|
| 38 | ACPI_DEBUG_INIT(ACPI_PARSER),
|
| 39 | ACPI_DEBUG_INIT(ACPI_DISPATCHER),
|
| 40 | ACPI_DEBUG_INIT(ACPI_EXECUTER),
|
| 41 | ACPI_DEBUG_INIT(ACPI_RESOURCES),
|
| 42 | ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
|
| 43 | ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
|
| 44 | ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
|
| 45 | ACPI_DEBUG_INIT(ACPI_COMPILER),
|
| 46 | ACPI_DEBUG_INIT(ACPI_TOOLS),
|
| 47 | };
|
| 48 |
|
| 49 | static const struct acpi_dlevel acpi_debug_levels[] = {
|
| 50 | ACPI_DEBUG_INIT(ACPI_LV_ERROR),
|
| 51 | ACPI_DEBUG_INIT(ACPI_LV_WARN),
|
| 52 | ACPI_DEBUG_INIT(ACPI_LV_INIT),
|
| 53 | ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
|
| 54 | ACPI_DEBUG_INIT(ACPI_LV_INFO),
|
| 55 |
|
| 56 | ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
|
| 57 | ACPI_DEBUG_INIT(ACPI_LV_PARSE),
|
| 58 | ACPI_DEBUG_INIT(ACPI_LV_LOAD),
|
| 59 | ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
|
| 60 | ACPI_DEBUG_INIT(ACPI_LV_EXEC),
|
| 61 | ACPI_DEBUG_INIT(ACPI_LV_NAMES),
|
| 62 | ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
|
| 63 | ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
|
| 64 | ACPI_DEBUG_INIT(ACPI_LV_TABLES),
|
| 65 | ACPI_DEBUG_INIT(ACPI_LV_VALUES),
|
| 66 | ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
|
| 67 | ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
|
| 68 | ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
|
| 69 | ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
|
| 70 |
|
| 71 | ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
|
| 72 | ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
|
| 73 | ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
|
| 74 |
|
| 75 | ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
|
| 76 | ACPI_DEBUG_INIT(ACPI_LV_THREADS),
|
| 77 | ACPI_DEBUG_INIT(ACPI_LV_IO),
|
| 78 | ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
|
| 79 |
|
| 80 | ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
|
| 81 | ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
|
| 82 | ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
|
| 83 | ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
|
| 84 | };
|
| 85 |
|
| 86 | |
| 87 | FS Interface (/sys)
|
| 88 | --------------------------------------------------------------------------
|
| 89 | static int param_get_debug_layer(char *buffer, struct kernel_param *kp) {
|
| 90 | int result = 0;
|
| 91 | int i;
|
| 92 |
|
| 93 | result = sprintf(buffer, "%-25s\tHex SET\n", "Description");
|
| 94 |
|
| 95 | for(i = 0; i <ARRAY_SIZE(acpi_debug_layers); i++) {
|
| 96 | result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n",
|
| 97 | acpi_debug_layers[i].name,
|
| 98 | acpi_debug_layers[i].value,
|
| 99 | (acpi_dbg_layer & acpi_debug_layers[i].value) ? '*' : ' ');
|
| 100 | }
|
| 101 | result += sprintf(buffer+result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
|
| 102 | ACPI_ALL_DRIVERS,
|
| 103 | (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
|
| 104 | ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
|
| 105 | ACPI_ALL_DRIVERS) == 0 ? ' ' : '-');
|
| 106 | result += sprintf(buffer+result, "--\ndebug_layer = 0x%08X ( * = enabled)\n", acpi_dbg_layer);
|
| 107 |
|
| 108 | return result;
|
| 109 | }
|
| 110 |
|
| 111 | static int param_get_debug_level(char *buffer, struct kernel_param *kp) {
|
| 112 | int result = 0;
|
| 113 | int i;
|
| 114 |
|
| 115 | result = sprintf(buffer, "%-25s\tHex SET\n", "Description");
|
| 116 |
|
| 117 | for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
|
| 118 | result += sprintf(buffer+result, "%-25s\t0x%08lX [%c]\n",
|
| 119 | acpi_debug_levels[i].name,
|
| 120 | acpi_debug_levels[i].value,
|
| 121 | (acpi_dbg_level & acpi_debug_levels[i].
|
| 122 | value) ? '*' : ' ');
|
| 123 | }
|
| 124 | result += sprintf(buffer+result, "--\ndebug_level = 0x%08X (* = enabled)\n",
|
| 125 | acpi_dbg_level);
|
| 126 |
|
| 127 | return result;
|
| 128 | }
|
| 129 |
|
| 130 | module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644);
|
| 131 | module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644);
|
| 132 |
|
| 133 | |
| 134 | FS Interface (/proc)
|
| 135 | --------------------------------------------------------------------------
|
| 136 | #ifdef CONFIG_ACPI_PROCFS
|
| 137 | #define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer"
|
| 138 | #define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level"
|
| 139 |
|
| 140 | static int
|
| 141 | acpi_system_read_debug(char *page,
|
| 142 | char **start, off_t off, int count, int *eof, void *data)
|
| 143 | {
|
| 144 | char *p = page;
|
| 145 | int size = 0;
|
| 146 | unsigned int i;
|
| 147 |
|
| 148 | if (off != 0)
|
| 149 | goto end;
|
| 150 |
|
| 151 | p += sprintf(p, "%-25s\tHex SET\n", "Description");
|
| 152 |
|
| 153 | switch ((unsigned long)data) {
|
| 154 | case 0:
|
| 155 | for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
|
| 156 | p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
|
| 157 | acpi_debug_layers[i].name,
|
| 158 | acpi_debug_layers[i].value,
|
| 159 | (acpi_dbg_layer & acpi_debug_layers[i].
|
| 160 | value) ? '*' : ' ');
|
| 161 | }
|
| 162 | p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
|
| 163 | ACPI_ALL_DRIVERS,
|
| 164 | (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
|
| 165 | ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer &
|
| 166 | ACPI_ALL_DRIVERS) ==
|
| 167 | 0 ? ' ' : '-');
|
| 168 | p += sprintf(p,
|
| 169 | "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
|
| 170 | acpi_dbg_layer);
|
| 171 | break;
|
| 172 | case 1:
|
| 173 | for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
|
| 174 | p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
|
| 175 | acpi_debug_levels[i].name,
|
| 176 | acpi_debug_levels[i].value,
|
| 177 | (acpi_dbg_level & acpi_debug_levels[i].
|
| 178 | value) ? '*' : ' ');
|
| 179 | }
|
| 180 | p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
|
| 181 | acpi_dbg_level);
|
| 182 | break;
|
| 183 | default:
|
| 184 | p += sprintf(p, "Invalid debug option\n");
|
| 185 | break;
|
| 186 | }
|
| 187 |
|
| 188 | end:
|
| 189 | size = (p - page);
|
| 190 | if (size <= off + count)
|
| 191 | *eof = 1;
|
| 192 | *start = page + off;
|
| 193 | size -= off;
|
| 194 | if (size > count)
|
| 195 | size = count;
|
| 196 | if (size < 0)
|
| 197 | size = 0;
|
| 198 |
|
| 199 | return size;
|
| 200 | }
|
| 201 |
|
| 202 | static int
|
| 203 | acpi_system_write_debug(struct file *file,
|
| 204 | const char __user * buffer,
|
| 205 | unsigned long count, void *data)
|
| 206 | {
|
| 207 | char debug_string[12] = { '\0' };
|
| 208 |
|
| 209 |
|
| 210 | if (count > sizeof(debug_string) - 1)
|
| 211 | return -EINVAL;
|
| 212 |
|
| 213 | if (copy_from_user(debug_string, buffer, count))
|
| 214 | return -EFAULT;
|
| 215 |
|
| 216 | debug_string[count] = '\0';
|
| 217 |
|
| 218 | switch ((unsigned long)data) {
|
| 219 | case 0:
|
| 220 | acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0);
|
| 221 | break;
|
| 222 | case 1:
|
| 223 | acpi_dbg_level = simple_strtoul(debug_string, NULL, 0);
|
| 224 | break;
|
| 225 | default:
|
| 226 | return -EINVAL;
|
| 227 | }
|
| 228 |
|
| 229 | return count;
|
| 230 | }
|
| 231 |
|
| 232 | static int __init acpi_debug_init(void)
|
| 233 | {
|
| 234 | struct proc_dir_entry *entry;
|
| 235 | int error = 0;
|
| 236 | char *name;
|
| 237 |
|
| 238 |
|
| 239 | if (acpi_disabled)
|
| 240 | return 0;
|
| 241 |
|
| 242 |
|
| 243 | name = ACPI_SYSTEM_FILE_DEBUG_LAYER;
|
| 244 | entry =
|
| 245 | create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
|
| 246 | acpi_root_dir, acpi_system_read_debug,
|
| 247 | (void *)0);
|
| 248 | if (entry)
|
| 249 | entry->write_proc = acpi_system_write_debug;
|
| 250 | else
|
| 251 | goto Error;
|
| 252 |
|
| 253 |
|
| 254 | name = ACPI_SYSTEM_FILE_DEBUG_LEVEL;
|
| 255 | entry =
|
| 256 | create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
|
| 257 | acpi_root_dir, acpi_system_read_debug,
|
| 258 | (void *)1);
|
| 259 | if (entry)
|
| 260 | entry->write_proc = acpi_system_write_debug;
|
| 261 | else
|
| 262 | goto Error;
|
| 263 |
|
| 264 | Done:
|
| 265 | return error;
|
| 266 |
|
| 267 | Error:
|
| 268 | remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LEVEL, acpi_root_dir);
|
| 269 | remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir);
|
| 270 | error = -ENODEV;
|
| 271 | goto Done;
|
| 272 | }
|
| 273 |
|
| 274 | subsys_initcall(acpi_debug_init);
|
| 275 | #endif
|