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 <linux/acpi.h> 9 10 #include "internal.h" 11 12 #define _COMPONENT ACPI_SYSTEM_COMPONENT 13 ACPI_MODULE_NAME("sysfs"); 14 15 #ifdef CONFIG_ACPI_DEBUG 16 /* 17 * ACPI debug sysfs I/F, including: 18 * /sys/modules/acpi/parameters/debug_layer 19 * /sys/modules/acpi/parameters/debug_level 20 * /sys/modules/acpi/parameters/trace_method_name 21 * /sys/modules/acpi/parameters/trace_state 22 * /sys/modules/acpi/parameters/trace_debug_layer 23 * /sys/modules/acpi/parameters/trace_debug_level 24 */ 25 26 struct acpi_dlayer { 27 const char *name; 28 unsigned long value; 29 }; 30 struct acpi_dlevel { 31 const char *name; 32 unsigned long value; 33 }; 34 #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v } 35 36 static const struct acpi_dlayer acpi_debug_layers[] = { 37 ACPI_DEBUG_INIT(ACPI_UTILITIES), 38 ACPI_DEBUG_INIT(ACPI_HARDWARE), 39 ACPI_DEBUG_INIT(ACPI_EVENTS), 40 ACPI_DEBUG_INIT(ACPI_TABLES), 41 ACPI_DEBUG_INIT(ACPI_NAMESPACE), 42 ACPI_DEBUG_INIT(ACPI_PARSER), 43 ACPI_DEBUG_INIT(ACPI_DISPATCHER), 44 ACPI_DEBUG_INIT(ACPI_EXECUTER), 45 ACPI_DEBUG_INIT(ACPI_RESOURCES), 46 ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER), 47 ACPI_DEBUG_INIT(ACPI_OS_SERVICES), 48 ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), 49 ACPI_DEBUG_INIT(ACPI_COMPILER), 50 ACPI_DEBUG_INIT(ACPI_TOOLS), 51 52 ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), 53 ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), 54 ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), 55 ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), 56 ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), 57 ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), 58 ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), 59 ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), 60 ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), 61 ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), 62 ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), 63 ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), 64 ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), 65 ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), 66 }; 67 68 static const struct acpi_dlevel acpi_debug_levels[] = { 69 ACPI_DEBUG_INIT(ACPI_LV_INIT), 70 ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), 71 ACPI_DEBUG_INIT(ACPI_LV_INFO), 72 73 ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES), 74 ACPI_DEBUG_INIT(ACPI_LV_PARSE), 75 ACPI_DEBUG_INIT(ACPI_LV_LOAD), 76 ACPI_DEBUG_INIT(ACPI_LV_DISPATCH), 77 ACPI_DEBUG_INIT(ACPI_LV_EXEC), 78 ACPI_DEBUG_INIT(ACPI_LV_NAMES), 79 ACPI_DEBUG_INIT(ACPI_LV_OPREGION), 80 ACPI_DEBUG_INIT(ACPI_LV_BFIELD), 81 ACPI_DEBUG_INIT(ACPI_LV_TABLES), 82 ACPI_DEBUG_INIT(ACPI_LV_VALUES), 83 ACPI_DEBUG_INIT(ACPI_LV_OBJECTS), 84 ACPI_DEBUG_INIT(ACPI_LV_RESOURCES), 85 ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS), 86 ACPI_DEBUG_INIT(ACPI_LV_PACKAGE), 87 88 ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS), 89 ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS), 90 ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS), 91 92 ACPI_DEBUG_INIT(ACPI_LV_MUTEX), 93 ACPI_DEBUG_INIT(ACPI_LV_THREADS), 94 ACPI_DEBUG_INIT(ACPI_LV_IO), 95 ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS), 96 97 ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE), 98 ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO), 99 ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES), 100 ACPI_DEBUG_INIT(ACPI_LV_EVENTS), 101 }; 102 103 static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) 104 { 105 int result = 0; 106 int i; 107 108 result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); 109 110 for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { 111 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n", 112 acpi_debug_layers[i].name, 113 acpi_debug_layers[i].value, 114 (acpi_dbg_layer & acpi_debug_layers[i].value) 115 ? '*' : ' '); 116 } 117 result += 118 sprintf(buffer + result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", 119 ACPI_ALL_DRIVERS, 120 (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 121 ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) 122 == 0 ? ' ' : '-'); 123 result += 124 sprintf(buffer + result, 125 "--\ndebug_layer = 0x%08X ( * = enabled)\n", 126 acpi_dbg_layer); 127 128 return result; 129 } 130 131 static int param_get_debug_level(char *buffer, const struct kernel_param *kp) 132 { 133 int result = 0; 134 int i; 135 136 result = sprintf(buffer, "%-25s\tHex SET\n", "Description"); 137 138 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { 139 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n", 140 acpi_debug_levels[i].name, 141 acpi_debug_levels[i].value, 142 (acpi_dbg_level & acpi_debug_levels[i].value) 143 ? '*' : ' '); 144 } 145 result += 146 sprintf(buffer + result, "--\ndebug_level = 0x%08X (* = enabled)\n", 147 acpi_dbg_level); 148 149 return result; 150 } 151 152 static const struct kernel_param_ops param_ops_debug_layer = { 153 .set = param_set_uint, 154 .get = param_get_debug_layer, 155 }; 156 157 static const struct kernel_param_ops param_ops_debug_level = { 158 .set = param_set_uint, 159 .get = param_get_debug_level, 160 }; 161 162 module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644); 163 module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644); 164 165 static char trace_method_name[6]; 166 module_param_string(trace_method_name, trace_method_name, 6, 0644); 167 static unsigned int trace_debug_layer; 168 module_param(trace_debug_layer, uint, 0644); 169 static unsigned int trace_debug_level; 170 module_param(trace_debug_level, uint, 0644); 171 172 static int param_set_trace_state(const char *val, struct kernel_param *kp) 173 { 174 int result = 0; 175 176 if (!strncmp(val, "enable", sizeof("enable") - 1)) { 177 result = acpi_debug_trace(trace_method_name, trace_debug_level, 178 trace_debug_layer, 0); 179 if (result) 180 result = -EBUSY; 181 goto exit; 182 } 183 184 if (!strncmp(val, "disable", sizeof("disable") - 1)) { 185 int name = 0; 186 result = acpi_debug_trace((char *)&name, trace_debug_level, 187 trace_debug_layer, 0); 188 if (result) 189 result = -EBUSY; 190 goto exit; 191 } 192 193 if (!strncmp(val, "1", 1)) { 194 result = acpi_debug_trace(trace_method_name, trace_debug_level, 195 trace_debug_layer, 1); 196 if (result) 197 result = -EBUSY; 198 goto exit; 199 } 200 201 result = -EINVAL; 202 exit: 203 return result; 204 } 205 206 static int param_get_trace_state(char *buffer, struct kernel_param *kp) 207 { 208 if (!acpi_gbl_trace_method_name) 209 return sprintf(buffer, "disable"); 210 else { 211 if (acpi_gbl_trace_flags & 1) 212 return sprintf(buffer, "1"); 213 else 214 return sprintf(buffer, "enable"); 215 } 216 return 0; 217 } 218 219 module_param_call(trace_state, param_set_trace_state, param_get_trace_state, 220 NULL, 0644); 221 #endif /* CONFIG_ACPI_DEBUG */ 222 223 224 /* /sys/modules/acpi/parameters/aml_debug_output */ 225 226 module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object, 227 byte, 0644); 228 MODULE_PARM_DESC(aml_debug_output, 229 "To enable/disable the ACPI Debug Object output."); 230 231 /* /sys/module/acpi/parameters/acpica_version */ 232 static int param_get_acpica_version(char *buffer, struct kernel_param *kp) 233 { 234 int result; 235 236 result = sprintf(buffer, "%x", ACPI_CA_VERSION); 237 238 return result; 239 } 240 241 module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); 242 243 /* 244 * ACPI table sysfs I/F: 245 * /sys/firmware/acpi/tables/ 246 * /sys/firmware/acpi/tables/dynamic/ 247 */ 248 249 static LIST_HEAD(acpi_table_attr_list); 250 static struct kobject *tables_kobj; 251 static struct kobject *dynamic_tables_kobj; 252 static struct kobject *hotplug_kobj; 253 254 struct acpi_table_attr { 255 struct bin_attribute attr; 256 char name[8]; 257 int instance; 258 struct list_head node; 259 }; 260 261 static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, 262 struct bin_attribute *bin_attr, char *buf, 263 loff_t offset, size_t count) 264 { 265 struct acpi_table_attr *table_attr = 266 container_of(bin_attr, struct acpi_table_attr, attr); 267 struct acpi_table_header *table_header = NULL; 268 acpi_status status; 269 char name[ACPI_NAME_SIZE]; 270 271 if (strncmp(table_attr->name, "NULL", 4)) 272 memcpy(name, table_attr->name, ACPI_NAME_SIZE); 273 else 274 memcpy(name, "\0\0\0\0", 4); 275 276 status = acpi_get_table(name, table_attr->instance, &table_header); 277 if (ACPI_FAILURE(status)) 278 return -ENODEV; 279 280 return memory_read_from_buffer(buf, count, &offset, 281 table_header, table_header->length); 282 } 283 284 static void acpi_table_attr_init(struct acpi_table_attr *table_attr, 285 struct acpi_table_header *table_header) 286 { 287 struct acpi_table_header *header = NULL; 288 struct acpi_table_attr *attr = NULL; 289 290 sysfs_attr_init(&table_attr->attr.attr); 291 if (table_header->signature[0] != '\0') 292 memcpy(table_attr->name, table_header->signature, 293 ACPI_NAME_SIZE); 294 else 295 memcpy(table_attr->name, "NULL", 4); 296 297 list_for_each_entry(attr, &acpi_table_attr_list, node) { 298 if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) 299 if (table_attr->instance < attr->instance) 300 table_attr->instance = attr->instance; 301 } 302 table_attr->instance++; 303 304 if (table_attr->instance > 1 || (table_attr->instance == 1 && 305 !acpi_get_table 306 (table_header->signature, 2, &header))) 307 sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", 308 table_attr->instance); 309 310 table_attr->attr.size = table_header->length; 311 table_attr->attr.read = acpi_table_show; 312 table_attr->attr.attr.name = table_attr->name; 313 table_attr->attr.attr.mode = 0400; 314 315 return; 316 } 317 318 static acpi_status 319 acpi_sysfs_table_handler(u32 event, void *table, void *context) 320 { 321 struct acpi_table_attr *table_attr; 322 323 switch (event) { 324 case ACPI_TABLE_EVENT_LOAD: 325 table_attr = 326 kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); 327 if (!table_attr) 328 return AE_NO_MEMORY; 329 330 acpi_table_attr_init(table_attr, table); 331 if (sysfs_create_bin_file(dynamic_tables_kobj, 332 &table_attr->attr)) { 333 kfree(table_attr); 334 return AE_ERROR; 335 } else 336 list_add_tail(&table_attr->node, &acpi_table_attr_list); 337 break; 338 case ACPI_TABLE_EVENT_UNLOAD: 339 /* 340 * we do not need to do anything right now 341 * because the table is not deleted from the 342 * global table list when unloading it. 343 */ 344 break; 345 default: 346 return AE_BAD_PARAMETER; 347 } 348 return AE_OK; 349 } 350 351 static int acpi_tables_sysfs_init(void) 352 { 353 struct acpi_table_attr *table_attr; 354 struct acpi_table_header *table_header = NULL; 355 int table_index; 356 acpi_status status; 357 int ret; 358 359 tables_kobj = kobject_create_and_add("tables", acpi_kobj); 360 if (!tables_kobj) 361 goto err; 362 363 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj); 364 if (!dynamic_tables_kobj) 365 goto err_dynamic_tables; 366 367 for (table_index = 0;; table_index++) { 368 status = acpi_get_table_by_index(table_index, &table_header); 369 370 if (status == AE_BAD_PARAMETER) 371 break; 372 373 if (ACPI_FAILURE(status)) 374 continue; 375 376 table_attr = NULL; 377 table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL); 378 if (!table_attr) 379 return -ENOMEM; 380 381 acpi_table_attr_init(table_attr, table_header); 382 ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr); 383 if (ret) { 384 kfree(table_attr); 385 return ret; 386 } 387 list_add_tail(&table_attr->node, &acpi_table_attr_list); 388 } 389 390 kobject_uevent(tables_kobj, KOBJ_ADD); 391 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); 392 status = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); 393 394 return ACPI_FAILURE(status) ? -EINVAL : 0; 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 unsigned long tmp; 568 569 if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { 570 int i; 571 for (i = 0; i < num_counters; ++i) 572 all_counters[i].count = 0; 573 acpi_gpe_count = 0; 574 acpi_irq_handled = 0; 575 acpi_irq_not_handled = 0; 576 goto end; 577 } 578 579 /* show the event status for both GPEs and Fixed Events */ 580 result = get_status(index, &status, &handle); 581 if (result) 582 goto end; 583 584 if (!(status & ACPI_EVENT_FLAG_HANDLE)) { 585 printk(KERN_WARNING PREFIX 586 "Can not change Invalid GPE/Fixed Event status\n"); 587 return -EINVAL; 588 } 589 590 if (index < num_gpes) { 591 if (!strcmp(buf, "disable\n") && 592 (status & ACPI_EVENT_FLAG_ENABLED)) 593 result = acpi_disable_gpe(handle, index); 594 else if (!strcmp(buf, "enable\n") && 595 !(status & ACPI_EVENT_FLAG_ENABLED)) 596 result = acpi_enable_gpe(handle, index); 597 else if (!strcmp(buf, "clear\n") && 598 (status & ACPI_EVENT_FLAG_SET)) 599 result = acpi_clear_gpe(handle, index); 600 else if (!kstrtoul(buf, 0, &tmp)) 601 all_counters[index].count = tmp; 602 else 603 result = -EINVAL; 604 } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { 605 int event = index - num_gpes; 606 if (!strcmp(buf, "disable\n") && 607 (status & ACPI_EVENT_FLAG_ENABLED)) 608 result = acpi_disable_event(event, ACPI_NOT_ISR); 609 else if (!strcmp(buf, "enable\n") && 610 !(status & ACPI_EVENT_FLAG_ENABLED)) 611 result = acpi_enable_event(event, ACPI_NOT_ISR); 612 else if (!strcmp(buf, "clear\n") && 613 (status & ACPI_EVENT_FLAG_SET)) 614 result = acpi_clear_event(event); 615 else if (!kstrtoul(buf, 0, &tmp)) 616 all_counters[index].count = tmp; 617 else 618 result = -EINVAL; 619 } else 620 all_counters[index].count = strtoul(buf, NULL, 0); 621 622 if (ACPI_FAILURE(result)) 623 result = -EINVAL; 624 end: 625 return result ? result : size; 626 } 627 628 void acpi_irq_stats_init(void) 629 { 630 acpi_status status; 631 int i; 632 633 if (all_counters) 634 return; 635 636 num_gpes = acpi_current_gpe_count; 637 num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; 638 639 all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), 640 GFP_KERNEL); 641 if (all_attrs == NULL) 642 return; 643 644 all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), 645 GFP_KERNEL); 646 if (all_counters == NULL) 647 goto fail; 648 649 status = acpi_install_global_event_handler(acpi_global_event_handler, NULL); 650 if (ACPI_FAILURE(status)) 651 goto fail; 652 653 counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), 654 GFP_KERNEL); 655 if (counter_attrs == NULL) 656 goto fail; 657 658 for (i = 0; i < num_counters; ++i) { 659 char buffer[12]; 660 char *name; 661 662 if (i < num_gpes) 663 sprintf(buffer, "gpe%02X", i); 664 else if (i == num_gpes + ACPI_EVENT_PMTIMER) 665 sprintf(buffer, "ff_pmtimer"); 666 else if (i == num_gpes + ACPI_EVENT_GLOBAL) 667 sprintf(buffer, "ff_gbl_lock"); 668 else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON) 669 sprintf(buffer, "ff_pwr_btn"); 670 else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON) 671 sprintf(buffer, "ff_slp_btn"); 672 else if (i == num_gpes + ACPI_EVENT_RTC) 673 sprintf(buffer, "ff_rt_clk"); 674 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE) 675 sprintf(buffer, "gpe_all"); 676 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) 677 sprintf(buffer, "sci"); 678 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT) 679 sprintf(buffer, "sci_not"); 680 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR) 681 sprintf(buffer, "error"); 682 else 683 sprintf(buffer, "bug%02X", i); 684 685 name = kstrdup(buffer, GFP_KERNEL); 686 if (name == NULL) 687 goto fail; 688 689 sysfs_attr_init(&counter_attrs[i].attr); 690 counter_attrs[i].attr.name = name; 691 counter_attrs[i].attr.mode = 0644; 692 counter_attrs[i].show = counter_show; 693 counter_attrs[i].store = counter_set; 694 695 all_attrs[i] = &counter_attrs[i].attr; 696 } 697 698 interrupt_stats_attr_group.attrs = all_attrs; 699 if (!sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group)) 700 return; 701 702 fail: 703 delete_gpe_attr_array(); 704 return; 705 } 706 707 static void __exit interrupt_stats_exit(void) 708 { 709 sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group); 710 711 delete_gpe_attr_array(); 712 713 return; 714 } 715 716 static ssize_t 717 acpi_show_profile(struct device *dev, struct device_attribute *attr, 718 char *buf) 719 { 720 return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile); 721 } 722 723 static const struct device_attribute pm_profile_attr = 724 __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL); 725 726 static ssize_t hotplug_enabled_show(struct kobject *kobj, 727 struct kobj_attribute *attr, char *buf) 728 { 729 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj); 730 731 return sprintf(buf, "%d\n", hotplug->enabled); 732 } 733 734 static ssize_t hotplug_enabled_store(struct kobject *kobj, 735 struct kobj_attribute *attr, 736 const char *buf, size_t size) 737 { 738 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj); 739 unsigned int val; 740 741 if (kstrtouint(buf, 10, &val) || val > 1) 742 return -EINVAL; 743 744 acpi_scan_hotplug_enabled(hotplug, val); 745 return size; 746 } 747 748 static struct kobj_attribute hotplug_enabled_attr = 749 __ATTR(enabled, S_IRUGO | S_IWUSR, hotplug_enabled_show, 750 hotplug_enabled_store); 751 752 static struct attribute *hotplug_profile_attrs[] = { 753 &hotplug_enabled_attr.attr, 754 NULL 755 }; 756 757 static struct kobj_type acpi_hotplug_profile_ktype = { 758 .sysfs_ops = &kobj_sysfs_ops, 759 .default_attrs = hotplug_profile_attrs, 760 }; 761 762 void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, 763 const char *name) 764 { 765 int error; 766 767 if (!hotplug_kobj) 768 goto err_out; 769 770 error = kobject_init_and_add(&hotplug->kobj, 771 &acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name); 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