1 /* 2 * sysfs.c - ACPI sysfs interface to userspace. 3 */ 4 5 #include <linux/init.h> 6 #include <linux/kernel.h> 7 #include <linux/moduleparam.h> 8 #include <acpi/acpi_drivers.h> 9 10 #include "internal.h" 11 12 #define _COMPONENT ACPI_SYSTEM_COMPONENT 13 ACPI_MODULE_NAME("sysfs"); 14 15 #define PREFIX "ACPI: " 16 17 #ifdef CONFIG_ACPI_DEBUG 18 /* 19 * ACPI debug sysfs I/F, including: 20 * /sys/modules/acpi/parameters/debug_layer 21 * /sys/modules/acpi/parameters/debug_level 22 * /sys/modules/acpi/parameters/trace_method_name 23 * /sys/modules/acpi/parameters/trace_state 24 * /sys/modules/acpi/parameters/trace_debug_layer 25 * /sys/modules/acpi/parameters/trace_debug_level 26 */ 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 ACPI_DEBUG_INIT(ACPI_UTILITIES), 40 ACPI_DEBUG_INIT(ACPI_HARDWARE), 41 ACPI_DEBUG_INIT(ACPI_EVENTS), 42 ACPI_DEBUG_INIT(ACPI_TABLES), 43 ACPI_DEBUG_INIT(ACPI_NAMESPACE), 44 ACPI_DEBUG_INIT(ACPI_PARSER), 45 ACPI_DEBUG_INIT(ACPI_DISPATCHER), 46 ACPI_DEBUG_INIT(ACPI_EXECUTER), 47 ACPI_DEBUG_INIT(ACPI_RESOURCES), 48 ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER), 49 ACPI_DEBUG_INIT(ACPI_OS_SERVICES), 50 ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), 51 ACPI_DEBUG_INIT(ACPI_COMPILER), 52 ACPI_DEBUG_INIT(ACPI_TOOLS), 53 54 ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), 55 ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), 56 ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), 57 ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), 58 ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), 59 ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), 60 ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), 61 ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), 62 ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), 63 ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), 64 ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), 65 ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), 66 ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), 67 ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), 68 }; 69 70 static const struct acpi_dlevel acpi_debug_levels[] = { 71 ACPI_DEBUG_INIT(ACPI_LV_INIT), 72 ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), 73 ACPI_DEBUG_INIT(ACPI_LV_INFO), 74 75 ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES), 76 ACPI_DEBUG_INIT(ACPI_LV_PARSE), 77 ACPI_DEBUG_INIT(ACPI_LV_LOAD), 78 ACPI_DEBUG_INIT(ACPI_LV_DISPATCH), 79 ACPI_DEBUG_INIT(ACPI_LV_EXEC), 80 ACPI_DEBUG_INIT(ACPI_LV_NAMES), 81 ACPI_DEBUG_INIT(ACPI_LV_OPREGION), 82 ACPI_DEBUG_INIT(ACPI_LV_BFIELD), 83 ACPI_DEBUG_INIT(ACPI_LV_TABLES), 84 ACPI_DEBUG_INIT(ACPI_LV_VALUES), 85 ACPI_DEBUG_INIT(ACPI_LV_OBJECTS), 86 ACPI_DEBUG_INIT(ACPI_LV_RESOURCES), 87 ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS), 88 ACPI_DEBUG_INIT(ACPI_LV_PACKAGE), 89 90 ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS), 91 ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS), 92 ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS), 93 94 ACPI_DEBUG_INIT(ACPI_LV_MUTEX), 95 ACPI_DEBUG_INIT(ACPI_LV_THREADS), 96 ACPI_DEBUG_INIT(ACPI_LV_IO), 97 ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS), 98 99 ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE), 100 ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO), 101 ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES), 102 ACPI_DEBUG_INIT(ACPI_LV_EVENTS), 103 }; 104 105 static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) 106 { 107 int result = 0; 108 int i; 109 110 result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); 111 112 for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { 113 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n", 114 acpi_debug_layers[i].name, 115 acpi_debug_layers[i].value, 116 (acpi_dbg_layer & acpi_debug_layers[i].value) 117 ? '*' : ' '); 118 } 119 result += 120 sprintf(buffer + result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", 121 ACPI_ALL_DRIVERS, 122 (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 123 ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) 124 == 0 ? ' ' : '-'); 125 result += 126 sprintf(buffer + result, 127 "--\ndebug_layer = 0x%08X ( * = enabled)\n", 128 acpi_dbg_layer); 129 130 return result; 131 } 132 133 static int param_get_debug_level(char *buffer, const struct kernel_param *kp) 134 { 135 int result = 0; 136 int i; 137 138 result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); 139 140 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { 141 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n", 142 acpi_debug_levels[i].name, 143 acpi_debug_levels[i].value, 144 (acpi_dbg_level & acpi_debug_levels[i].value) 145 ? '*' : ' '); 146 } 147 result += 148 sprintf(buffer + result, "--\ndebug_level = 0x%08X (* = enabled)\n", 149 acpi_dbg_level); 150 151 return result; 152 } 153 154 static const struct kernel_param_ops param_ops_debug_layer = { 155 .set = param_set_uint, 156 .get = param_get_debug_layer, 157 }; 158 159 static const struct kernel_param_ops param_ops_debug_level = { 160 .set = param_set_uint, 161 .get = param_get_debug_level, 162 }; 163 164 module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644); 165 module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644); 166 167 static char trace_method_name[6]; 168 module_param_string(trace_method_name, trace_method_name, 6, 0644); 169 static unsigned int trace_debug_layer; 170 module_param(trace_debug_layer, uint, 0644); 171 static unsigned int trace_debug_level; 172 module_param(trace_debug_level, uint, 0644); 173 174 static int param_set_trace_state(const char *val, struct kernel_param *kp) 175 { 176 int result = 0; 177 178 if (!strncmp(val, "enable", sizeof("enable") - 1)) { 179 result = acpi_debug_trace(trace_method_name, trace_debug_level, 180 trace_debug_layer, 0); 181 if (result) 182 result = -EBUSY; 183 goto exit; 184 } 185 186 if (!strncmp(val, "disable", sizeof("disable") - 1)) { 187 int name = 0; 188 result = acpi_debug_trace((char *)&name, trace_debug_level, 189 trace_debug_layer, 0); 190 if (result) 191 result = -EBUSY; 192 goto exit; 193 } 194 195 if (!strncmp(val, "1", 1)) { 196 result = acpi_debug_trace(trace_method_name, trace_debug_level, 197 trace_debug_layer, 1); 198 if (result) 199 result = -EBUSY; 200 goto exit; 201 } 202 203 result = -EINVAL; 204 exit: 205 return result; 206 } 207 208 static int param_get_trace_state(char *buffer, struct kernel_param *kp) 209 { 210 if (!acpi_gbl_trace_method_name) 211 return sprintf(buffer, "disable"); 212 else { 213 if (acpi_gbl_trace_flags & 1) 214 return sprintf(buffer, "1"); 215 else 216 return sprintf(buffer, "enable"); 217 } 218 return 0; 219 } 220 221 module_param_call(trace_state, param_set_trace_state, param_get_trace_state, 222 NULL, 0644); 223 #endif /* CONFIG_ACPI_DEBUG */ 224 225 226 /* /sys/modules/acpi/parameters/aml_debug_output */ 227 228 module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object, 229 bool, 0644); 230 MODULE_PARM_DESC(aml_debug_output, 231 "To enable/disable the ACPI Debug Object output."); 232 233 /* /sys/module/acpi/parameters/acpica_version */ 234 static int param_get_acpica_version(char *buffer, struct kernel_param *kp) 235 { 236 int result; 237 238 result = sprintf(buffer, "%x", ACPI_CA_VERSION); 239 240 return result; 241 } 242 243 module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); 244 245 /* 246 * ACPI table sysfs I/F: 247 * /sys/firmware/acpi/tables/ 248 * /sys/firmware/acpi/tables/dynamic/ 249 */ 250 251 static LIST_HEAD(acpi_table_attr_list); 252 static struct kobject *tables_kobj; 253 static struct kobject *dynamic_tables_kobj; 254 static struct kobject *hotplug_kobj; 255 256 struct acpi_table_attr { 257 struct bin_attribute attr; 258 char name[8]; 259 int instance; 260 struct list_head node; 261 }; 262 263 static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, 264 struct bin_attribute *bin_attr, char *buf, 265 loff_t offset, size_t count) 266 { 267 struct acpi_table_attr *table_attr = 268 container_of(bin_attr, struct acpi_table_attr, attr); 269 struct acpi_table_header *table_header = NULL; 270 acpi_status status; 271 char name[ACPI_NAME_SIZE]; 272 273 if (strncmp(table_attr->name, "NULL", 4)) 274 memcpy(name, table_attr->name, ACPI_NAME_SIZE); 275 else 276 memcpy(name, "\0\0\0\0", 4); 277 278 status = acpi_get_table(name, table_attr->instance, &table_header); 279 if (ACPI_FAILURE(status)) 280 return -ENODEV; 281 282 return memory_read_from_buffer(buf, count, &offset, 283 table_header, table_header->length); 284 } 285 286 static void acpi_table_attr_init(struct acpi_table_attr *table_attr, 287 struct acpi_table_header *table_header) 288 { 289 struct acpi_table_header *header = NULL; 290 struct acpi_table_attr *attr = NULL; 291 292 sysfs_attr_init(&table_attr->attr.attr); 293 if (table_header->signature[0] != '\0') 294 memcpy(table_attr->name, table_header->signature, 295 ACPI_NAME_SIZE); 296 else 297 memcpy(table_attr->name, "NULL", 4); 298 299 list_for_each_entry(attr, &acpi_table_attr_list, node) { 300 if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) 301 if (table_attr->instance < attr->instance) 302 table_attr->instance = attr->instance; 303 } 304 table_attr->instance++; 305 306 if (table_attr->instance > 1 || (table_attr->instance == 1 && 307 !acpi_get_table 308 (table_header->signature, 2, &header))) 309 sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", 310 table_attr->instance); 311 312 table_attr->attr.size = 0; 313 table_attr->attr.read = acpi_table_show; 314 table_attr->attr.attr.name = table_attr->name; 315 table_attr->attr.attr.mode = 0400; 316 317 return; 318 } 319 320 static acpi_status 321 acpi_sysfs_table_handler(u32 event, void *table, void *context) 322 { 323 struct acpi_table_attr *table_attr; 324 325 switch (event) { 326 case ACPI_TABLE_EVENT_LOAD: 327 table_attr = 328 kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); 329 if (!table_attr) 330 return AE_NO_MEMORY; 331 332 acpi_table_attr_init(table_attr, table); 333 if (sysfs_create_bin_file(dynamic_tables_kobj, 334 &table_attr->attr)) { 335 kfree(table_attr); 336 return AE_ERROR; 337 } else 338 list_add_tail(&table_attr->node, &acpi_table_attr_list); 339 break; 340 case ACPI_TABLE_EVENT_UNLOAD: 341 /* 342 * we do not need to do anything right now 343 * because the table is not deleted from the 344 * global table list when unloading it. 345 */ 346 break; 347 default: 348 return AE_BAD_PARAMETER; 349 } 350 return AE_OK; 351 } 352 353 static int acpi_tables_sysfs_init(void) 354 { 355 struct acpi_table_attr *table_attr; 356 struct acpi_table_header *table_header = NULL; 357 int table_index = 0; 358 int result; 359 360 tables_kobj = kobject_create_and_add("tables", acpi_kobj); 361 if (!tables_kobj) 362 goto err; 363 364 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj); 365 if (!dynamic_tables_kobj) 366 goto err_dynamic_tables; 367 368 do { 369 result = acpi_get_table_by_index(table_index, &table_header); 370 if (!result) { 371 table_index++; 372 table_attr = NULL; 373 table_attr = 374 kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); 375 if (!table_attr) 376 return -ENOMEM; 377 378 acpi_table_attr_init(table_attr, table_header); 379 result = 380 sysfs_create_bin_file(tables_kobj, 381 &table_attr->attr); 382 if (result) { 383 kfree(table_attr); 384 return result; 385 } else 386 list_add_tail(&table_attr->node, 387 &acpi_table_attr_list); 388 } 389 } while (!result); 390 kobject_uevent(tables_kobj, KOBJ_ADD); 391 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); 392 result = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); 393 394 return result == AE_OK ? 0 : -EINVAL; 395 err_dynamic_tables: 396 kobject_put(tables_kobj); 397 err: 398 return -ENOMEM; 399 } 400 401 /* 402 * Detailed ACPI IRQ counters: 403 * /sys/firmware/acpi/interrupts/ 404 */ 405 406 u32 acpi_irq_handled; 407 u32 acpi_irq_not_handled; 408 409 #define COUNT_GPE 0 410 #define COUNT_SCI 1 /* acpi_irq_handled */ 411 #define COUNT_SCI_NOT 2 /* acpi_irq_not_handled */ 412 #define COUNT_ERROR 3 /* other */ 413 #define NUM_COUNTERS_EXTRA 4 414 415 struct event_counter { 416 u32 count; 417 u32 flags; 418 }; 419 420 static struct event_counter *all_counters; 421 static u32 num_gpes; 422 static u32 num_counters; 423 static struct attribute **all_attrs; 424 static u32 acpi_gpe_count; 425 426 static struct attribute_group interrupt_stats_attr_group = { 427 .name = "interrupts", 428 }; 429 430 static struct kobj_attribute *counter_attrs; 431 432 static void delete_gpe_attr_array(void) 433 { 434 struct event_counter *tmp = all_counters; 435 436 all_counters = NULL; 437 kfree(tmp); 438 439 if (counter_attrs) { 440 int i; 441 442 for (i = 0; i < num_gpes; i++) 443 kfree(counter_attrs[i].attr.name); 444 445 kfree(counter_attrs); 446 } 447 kfree(all_attrs); 448 449 return; 450 } 451 452 static void gpe_count(u32 gpe_number) 453 { 454 acpi_gpe_count++; 455 456 if (!all_counters) 457 return; 458 459 if (gpe_number < num_gpes) 460 all_counters[gpe_number].count++; 461 else 462 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + 463 COUNT_ERROR].count++; 464 465 return; 466 } 467 468 static void fixed_event_count(u32 event_number) 469 { 470 if (!all_counters) 471 return; 472 473 if (event_number < ACPI_NUM_FIXED_EVENTS) 474 all_counters[num_gpes + event_number].count++; 475 else 476 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + 477 COUNT_ERROR].count++; 478 479 return; 480 } 481 482 static void acpi_global_event_handler(u32 event_type, acpi_handle device, 483 u32 event_number, void *context) 484 { 485 if (event_type == ACPI_EVENT_TYPE_GPE) 486 gpe_count(event_number); 487 488 if (event_type == ACPI_EVENT_TYPE_FIXED) 489 fixed_event_count(event_number); 490 } 491 492 static int get_status(u32 index, acpi_event_status *status, 493 acpi_handle *handle) 494 { 495 int result = 0; 496 497 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) 498 goto end; 499 500 if (index < num_gpes) { 501 result = acpi_get_gpe_device(index, handle); 502 if (result) { 503 ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, 504 "Invalid GPE 0x%x", index)); 505 goto end; 506 } 507 result = acpi_get_gpe_status(*handle, index, status); 508 } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) 509 result = acpi_get_event_status(index - num_gpes, status); 510 511 end: 512 return result; 513 } 514 515 static ssize_t counter_show(struct kobject *kobj, 516 struct kobj_attribute *attr, char *buf) 517 { 518 int index = attr - counter_attrs; 519 int size; 520 acpi_handle handle; 521 acpi_event_status status; 522 int result = 0; 523 524 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count = 525 acpi_irq_handled; 526 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count = 527 acpi_irq_not_handled; 528 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = 529 acpi_gpe_count; 530 size = sprintf(buf, "%8d", all_counters[index].count); 531 532 /* "gpe_all" or "sci" */ 533 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) 534 goto end; 535 536 result = get_status(index, &status, &handle); 537 if (result) 538 goto end; 539 540 if (!(status & ACPI_EVENT_FLAG_HANDLE)) 541 size += sprintf(buf + size, " invalid"); 542 else if (status & ACPI_EVENT_FLAG_ENABLED) 543 size += sprintf(buf + size, " enabled"); 544 else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) 545 size += sprintf(buf + size, " wake_enabled"); 546 else 547 size += sprintf(buf + size, " disabled"); 548 549 end: 550 size += sprintf(buf + size, "\n"); 551 return result ? result : size; 552 } 553 554 /* 555 * counter_set() sets the specified counter. 556 * setting the total "sci" file to any value clears all counters. 557 * enable/disable/clear a gpe/fixed event in user space. 558 */ 559 static ssize_t counter_set(struct kobject *kobj, 560 struct kobj_attribute *attr, const char *buf, 561 size_t size) 562 { 563 int index = attr - counter_attrs; 564 acpi_event_status status; 565 acpi_handle handle; 566 int result = 0; 567 568 if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { 569 int i; 570 for (i = 0; i < num_counters; ++i) 571 all_counters[i].count = 0; 572 acpi_gpe_count = 0; 573 acpi_irq_handled = 0; 574 acpi_irq_not_handled = 0; 575 goto end; 576 } 577 578 /* show the event status for both GPEs and Fixed Events */ 579 result = get_status(index, &status, &handle); 580 if (result) 581 goto end; 582 583 if (!(status & ACPI_EVENT_FLAG_HANDLE)) { 584 printk(KERN_WARNING PREFIX 585 "Can not change Invalid GPE/Fixed Event status\n"); 586 return -EINVAL; 587 } 588 589 if (index < num_gpes) { 590 if (!strcmp(buf, "disable\n") && 591 (status & ACPI_EVENT_FLAG_ENABLED)) 592 result = acpi_disable_gpe(handle, index); 593 else if (!strcmp(buf, "enable\n") && 594 !(status & ACPI_EVENT_FLAG_ENABLED)) 595 result = acpi_enable_gpe(handle, index); 596 else if (!strcmp(buf, "clear\n") && 597 (status & ACPI_EVENT_FLAG_SET)) 598 result = acpi_clear_gpe(handle, index); 599 else 600 all_counters[index].count = strtoul(buf, NULL, 0); 601 } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { 602 int event = index - num_gpes; 603 if (!strcmp(buf, "disable\n") && 604 (status & ACPI_EVENT_FLAG_ENABLED)) 605 result = acpi_disable_event(event, ACPI_NOT_ISR); 606 else if (!strcmp(buf, "enable\n") && 607 !(status & ACPI_EVENT_FLAG_ENABLED)) 608 result = acpi_enable_event(event, ACPI_NOT_ISR); 609 else if (!strcmp(buf, "clear\n") && 610 (status & ACPI_EVENT_FLAG_SET)) 611 result = acpi_clear_event(event); 612 else 613 all_counters[index].count = strtoul(buf, NULL, 0); 614 } else 615 all_counters[index].count = strtoul(buf, NULL, 0); 616 617 if (ACPI_FAILURE(result)) 618 result = -EINVAL; 619 end: 620 return result ? result : size; 621 } 622 623 void acpi_irq_stats_init(void) 624 { 625 acpi_status status; 626 int i; 627 628 if (all_counters) 629 return; 630 631 num_gpes = acpi_current_gpe_count; 632 num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; 633 634 all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), 635 GFP_KERNEL); 636 if (all_attrs == NULL) 637 return; 638 639 all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), 640 GFP_KERNEL); 641 if (all_counters == NULL) 642 goto fail; 643 644 status = acpi_install_global_event_handler(acpi_global_event_handler, NULL); 645 if (ACPI_FAILURE(status)) 646 goto fail; 647 648 counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), 649 GFP_KERNEL); 650 if (counter_attrs == NULL) 651 goto fail; 652 653 for (i = 0; i < num_counters; ++i) { 654 char buffer[12]; 655 char *name; 656 657 if (i < num_gpes) 658 sprintf(buffer, "gpe%02X", i); 659 else if (i == num_gpes + ACPI_EVENT_PMTIMER) 660 sprintf(buffer, "ff_pmtimer"); 661 else if (i == num_gpes + ACPI_EVENT_GLOBAL) 662 sprintf(buffer, "ff_gbl_lock"); 663 else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON) 664 sprintf(buffer, "ff_pwr_btn"); 665 else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON) 666 sprintf(buffer, "ff_slp_btn"); 667 else if (i == num_gpes + ACPI_EVENT_RTC) 668 sprintf(buffer, "ff_rt_clk"); 669 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE) 670 sprintf(buffer, "gpe_all"); 671 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) 672 sprintf(buffer, "sci"); 673 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT) 674 sprintf(buffer, "sci_not"); 675 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR) 676 sprintf(buffer, "error"); 677 else 678 sprintf(buffer, "bug%02X", i); 679 680 name = kstrdup(buffer, GFP_KERNEL); 681 if (name == NULL) 682 goto fail; 683 684 sysfs_attr_init(&counter_attrs[i].attr); 685 counter_attrs[i].attr.name = name; 686 counter_attrs[i].attr.mode = 0644; 687 counter_attrs[i].show = counter_show; 688 counter_attrs[i].store = counter_set; 689 690 all_attrs[i] = &counter_attrs[i].attr; 691 } 692 693 interrupt_stats_attr_group.attrs = all_attrs; 694 if (!sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group)) 695 return; 696 697 fail: 698 delete_gpe_attr_array(); 699 return; 700 } 701 702 static void __exit interrupt_stats_exit(void) 703 { 704 sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group); 705 706 delete_gpe_attr_array(); 707 708 return; 709 } 710 711 static ssize_t 712 acpi_show_profile(struct device *dev, struct device_attribute *attr, 713 char *buf) 714 { 715 return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile); 716 } 717 718 static const struct device_attribute pm_profile_attr = 719 __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL); 720 721 static ssize_t hotplug_enabled_show(struct kobject *kobj, 722 struct kobj_attribute *attr, char *buf) 723 { 724 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj); 725 726 return sprintf(buf, "%d\n", hotplug->enabled); 727 } 728 729 static ssize_t hotplug_enabled_store(struct kobject *kobj, 730 struct kobj_attribute *attr, 731 const char *buf, size_t size) 732 { 733 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj); 734 unsigned int val; 735 736 if (kstrtouint(buf, 10, &val) || val > 1) 737 return -EINVAL; 738 739 acpi_scan_hotplug_enabled(hotplug, val); 740 return size; 741 } 742 743 static struct kobj_attribute hotplug_enabled_attr = 744 __ATTR(enabled, S_IRUGO | S_IWUSR, hotplug_enabled_show, 745 hotplug_enabled_store); 746 747 static struct attribute *hotplug_profile_attrs[] = { 748 &hotplug_enabled_attr.attr, 749 NULL 750 }; 751 752 static struct kobj_type acpi_hotplug_profile_ktype = { 753 .sysfs_ops = &kobj_sysfs_ops, 754 .default_attrs = hotplug_profile_attrs, 755 }; 756 757 void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, 758 const char *name) 759 { 760 int error; 761 762 if (!hotplug_kobj) 763 goto err_out; 764 765 kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype); 766 error = kobject_set_name(&hotplug->kobj, "%s", name); 767 if (error) 768 goto err_out; 769 770 hotplug->kobj.parent = hotplug_kobj; 771 error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL); 772 if (error) 773 goto err_out; 774 775 kobject_uevent(&hotplug->kobj, KOBJ_ADD); 776 return; 777 778 err_out: 779 pr_err(PREFIX "Unable to add hotplug profile '%s'\n", name); 780 } 781 782 static ssize_t force_remove_show(struct kobject *kobj, 783 struct kobj_attribute *attr, char *buf) 784 { 785 return sprintf(buf, "%d\n", !!acpi_force_hot_remove); 786 } 787 788 static ssize_t force_remove_store(struct kobject *kobj, 789 struct kobj_attribute *attr, 790 const char *buf, size_t size) 791 { 792 bool val; 793 int ret; 794 795 ret = strtobool(buf, &val); 796 if (ret < 0) 797 return ret; 798 799 lock_device_hotplug(); 800 acpi_force_hot_remove = val; 801 unlock_device_hotplug(); 802 return size; 803 } 804 805 static const struct kobj_attribute force_remove_attr = 806 __ATTR(force_remove, S_IRUGO | S_IWUSR, force_remove_show, 807 force_remove_store); 808 809 int __init acpi_sysfs_init(void) 810 { 811 int result; 812 813 result = acpi_tables_sysfs_init(); 814 if (result) 815 return result; 816 817 hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj); 818 result = sysfs_create_file(hotplug_kobj, &force_remove_attr.attr); 819 if (result) 820 return result; 821 822 result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr); 823 return result; 824 } 825