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 = table_header->length; 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; 358 acpi_status status; 359 int ret; 360 361 tables_kobj = kobject_create_and_add("tables", acpi_kobj); 362 if (!tables_kobj) 363 goto err; 364 365 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj); 366 if (!dynamic_tables_kobj) 367 goto err_dynamic_tables; 368 369 for (table_index = 0;; table_index++) { 370 status = acpi_get_table_by_index(table_index, &table_header); 371 372 if (status == AE_BAD_PARAMETER) 373 break; 374 375 if (ACPI_FAILURE(status)) 376 continue; 377 378 table_attr = NULL; 379 table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL); 380 if (!table_attr) 381 return -ENOMEM; 382 383 acpi_table_attr_init(table_attr, table_header); 384 ret = sysfs_create_bin_file(tables_kobj, &table_attr->attr); 385 if (ret) { 386 kfree(table_attr); 387 return ret; 388 } 389 list_add_tail(&table_attr->node, &acpi_table_attr_list); 390 } 391 392 kobject_uevent(tables_kobj, KOBJ_ADD); 393 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); 394 status = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); 395 396 return ACPI_FAILURE(status) ? -EINVAL : 0; 397 err_dynamic_tables: 398 kobject_put(tables_kobj); 399 err: 400 return -ENOMEM; 401 } 402 403 /* 404 * Detailed ACPI IRQ counters: 405 * /sys/firmware/acpi/interrupts/ 406 */ 407 408 u32 acpi_irq_handled; 409 u32 acpi_irq_not_handled; 410 411 #define COUNT_GPE 0 412 #define COUNT_SCI 1 /* acpi_irq_handled */ 413 #define COUNT_SCI_NOT 2 /* acpi_irq_not_handled */ 414 #define COUNT_ERROR 3 /* other */ 415 #define NUM_COUNTERS_EXTRA 4 416 417 struct event_counter { 418 u32 count; 419 u32 flags; 420 }; 421 422 static struct event_counter *all_counters; 423 static u32 num_gpes; 424 static u32 num_counters; 425 static struct attribute **all_attrs; 426 static u32 acpi_gpe_count; 427 428 static struct attribute_group interrupt_stats_attr_group = { 429 .name = "interrupts", 430 }; 431 432 static struct kobj_attribute *counter_attrs; 433 434 static void delete_gpe_attr_array(void) 435 { 436 struct event_counter *tmp = all_counters; 437 438 all_counters = NULL; 439 kfree(tmp); 440 441 if (counter_attrs) { 442 int i; 443 444 for (i = 0; i < num_gpes; i++) 445 kfree(counter_attrs[i].attr.name); 446 447 kfree(counter_attrs); 448 } 449 kfree(all_attrs); 450 451 return; 452 } 453 454 static void gpe_count(u32 gpe_number) 455 { 456 acpi_gpe_count++; 457 458 if (!all_counters) 459 return; 460 461 if (gpe_number < num_gpes) 462 all_counters[gpe_number].count++; 463 else 464 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + 465 COUNT_ERROR].count++; 466 467 return; 468 } 469 470 static void fixed_event_count(u32 event_number) 471 { 472 if (!all_counters) 473 return; 474 475 if (event_number < ACPI_NUM_FIXED_EVENTS) 476 all_counters[num_gpes + event_number].count++; 477 else 478 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + 479 COUNT_ERROR].count++; 480 481 return; 482 } 483 484 static void acpi_global_event_handler(u32 event_type, acpi_handle device, 485 u32 event_number, void *context) 486 { 487 if (event_type == ACPI_EVENT_TYPE_GPE) 488 gpe_count(event_number); 489 490 if (event_type == ACPI_EVENT_TYPE_FIXED) 491 fixed_event_count(event_number); 492 } 493 494 static int get_status(u32 index, acpi_event_status *status, 495 acpi_handle *handle) 496 { 497 int result = 0; 498 499 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) 500 goto end; 501 502 if (index < num_gpes) { 503 result = acpi_get_gpe_device(index, handle); 504 if (result) { 505 ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND, 506 "Invalid GPE 0x%x", index)); 507 goto end; 508 } 509 result = acpi_get_gpe_status(*handle, index, status); 510 } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) 511 result = acpi_get_event_status(index - num_gpes, status); 512 513 end: 514 return result; 515 } 516 517 static ssize_t counter_show(struct kobject *kobj, 518 struct kobj_attribute *attr, char *buf) 519 { 520 int index = attr - counter_attrs; 521 int size; 522 acpi_handle handle; 523 acpi_event_status status; 524 int result = 0; 525 526 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count = 527 acpi_irq_handled; 528 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count = 529 acpi_irq_not_handled; 530 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count = 531 acpi_gpe_count; 532 size = sprintf(buf, "%8d", all_counters[index].count); 533 534 /* "gpe_all" or "sci" */ 535 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS) 536 goto end; 537 538 result = get_status(index, &status, &handle); 539 if (result) 540 goto end; 541 542 if (!(status & ACPI_EVENT_FLAG_HANDLE)) 543 size += sprintf(buf + size, " invalid"); 544 else if (status & ACPI_EVENT_FLAG_ENABLED) 545 size += sprintf(buf + size, " enabled"); 546 else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) 547 size += sprintf(buf + size, " wake_enabled"); 548 else 549 size += sprintf(buf + size, " disabled"); 550 551 end: 552 size += sprintf(buf + size, "\n"); 553 return result ? result : size; 554 } 555 556 /* 557 * counter_set() sets the specified counter. 558 * setting the total "sci" file to any value clears all counters. 559 * enable/disable/clear a gpe/fixed event in user space. 560 */ 561 static ssize_t counter_set(struct kobject *kobj, 562 struct kobj_attribute *attr, const char *buf, 563 size_t size) 564 { 565 int index = attr - counter_attrs; 566 acpi_event_status status; 567 acpi_handle handle; 568 int result = 0; 569 unsigned long tmp; 570 571 if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { 572 int i; 573 for (i = 0; i < num_counters; ++i) 574 all_counters[i].count = 0; 575 acpi_gpe_count = 0; 576 acpi_irq_handled = 0; 577 acpi_irq_not_handled = 0; 578 goto end; 579 } 580 581 /* show the event status for both GPEs and Fixed Events */ 582 result = get_status(index, &status, &handle); 583 if (result) 584 goto end; 585 586 if (!(status & ACPI_EVENT_FLAG_HANDLE)) { 587 printk(KERN_WARNING PREFIX 588 "Can not change Invalid GPE/Fixed Event status\n"); 589 return -EINVAL; 590 } 591 592 if (index < num_gpes) { 593 if (!strcmp(buf, "disable\n") && 594 (status & ACPI_EVENT_FLAG_ENABLED)) 595 result = acpi_disable_gpe(handle, index); 596 else if (!strcmp(buf, "enable\n") && 597 !(status & ACPI_EVENT_FLAG_ENABLED)) 598 result = acpi_enable_gpe(handle, index); 599 else if (!strcmp(buf, "clear\n") && 600 (status & ACPI_EVENT_FLAG_SET)) 601 result = acpi_clear_gpe(handle, index); 602 else if (!kstrtoul(buf, 0, &tmp)) 603 all_counters[index].count = tmp; 604 else 605 result = -EINVAL; 606 } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) { 607 int event = index - num_gpes; 608 if (!strcmp(buf, "disable\n") && 609 (status & ACPI_EVENT_FLAG_ENABLED)) 610 result = acpi_disable_event(event, ACPI_NOT_ISR); 611 else if (!strcmp(buf, "enable\n") && 612 !(status & ACPI_EVENT_FLAG_ENABLED)) 613 result = acpi_enable_event(event, ACPI_NOT_ISR); 614 else if (!strcmp(buf, "clear\n") && 615 (status & ACPI_EVENT_FLAG_SET)) 616 result = acpi_clear_event(event); 617 else if (!kstrtoul(buf, 0, &tmp)) 618 all_counters[index].count = tmp; 619 else 620 result = -EINVAL; 621 } else 622 all_counters[index].count = strtoul(buf, NULL, 0); 623 624 if (ACPI_FAILURE(result)) 625 result = -EINVAL; 626 end: 627 return result ? result : size; 628 } 629 630 void acpi_irq_stats_init(void) 631 { 632 acpi_status status; 633 int i; 634 635 if (all_counters) 636 return; 637 638 num_gpes = acpi_current_gpe_count; 639 num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; 640 641 all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), 642 GFP_KERNEL); 643 if (all_attrs == NULL) 644 return; 645 646 all_counters = kzalloc(sizeof(struct event_counter) * (num_counters), 647 GFP_KERNEL); 648 if (all_counters == NULL) 649 goto fail; 650 651 status = acpi_install_global_event_handler(acpi_global_event_handler, NULL); 652 if (ACPI_FAILURE(status)) 653 goto fail; 654 655 counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), 656 GFP_KERNEL); 657 if (counter_attrs == NULL) 658 goto fail; 659 660 for (i = 0; i < num_counters; ++i) { 661 char buffer[12]; 662 char *name; 663 664 if (i < num_gpes) 665 sprintf(buffer, "gpe%02X", i); 666 else if (i == num_gpes + ACPI_EVENT_PMTIMER) 667 sprintf(buffer, "ff_pmtimer"); 668 else if (i == num_gpes + ACPI_EVENT_GLOBAL) 669 sprintf(buffer, "ff_gbl_lock"); 670 else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON) 671 sprintf(buffer, "ff_pwr_btn"); 672 else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON) 673 sprintf(buffer, "ff_slp_btn"); 674 else if (i == num_gpes + ACPI_EVENT_RTC) 675 sprintf(buffer, "ff_rt_clk"); 676 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE) 677 sprintf(buffer, "gpe_all"); 678 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) 679 sprintf(buffer, "sci"); 680 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT) 681 sprintf(buffer, "sci_not"); 682 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR) 683 sprintf(buffer, "error"); 684 else 685 sprintf(buffer, "bug%02X", i); 686 687 name = kstrdup(buffer, GFP_KERNEL); 688 if (name == NULL) 689 goto fail; 690 691 sysfs_attr_init(&counter_attrs[i].attr); 692 counter_attrs[i].attr.name = name; 693 counter_attrs[i].attr.mode = 0644; 694 counter_attrs[i].show = counter_show; 695 counter_attrs[i].store = counter_set; 696 697 all_attrs[i] = &counter_attrs[i].attr; 698 } 699 700 interrupt_stats_attr_group.attrs = all_attrs; 701 if (!sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group)) 702 return; 703 704 fail: 705 delete_gpe_attr_array(); 706 return; 707 } 708 709 static void __exit interrupt_stats_exit(void) 710 { 711 sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group); 712 713 delete_gpe_attr_array(); 714 715 return; 716 } 717 718 static ssize_t 719 acpi_show_profile(struct device *dev, struct device_attribute *attr, 720 char *buf) 721 { 722 return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile); 723 } 724 725 static const struct device_attribute pm_profile_attr = 726 __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL); 727 728 static ssize_t hotplug_enabled_show(struct kobject *kobj, 729 struct kobj_attribute *attr, char *buf) 730 { 731 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj); 732 733 return sprintf(buf, "%d\n", hotplug->enabled); 734 } 735 736 static ssize_t hotplug_enabled_store(struct kobject *kobj, 737 struct kobj_attribute *attr, 738 const char *buf, size_t size) 739 { 740 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj); 741 unsigned int val; 742 743 if (kstrtouint(buf, 10, &val) || val > 1) 744 return -EINVAL; 745 746 acpi_scan_hotplug_enabled(hotplug, val); 747 return size; 748 } 749 750 static struct kobj_attribute hotplug_enabled_attr = 751 __ATTR(enabled, S_IRUGO | S_IWUSR, hotplug_enabled_show, 752 hotplug_enabled_store); 753 754 static struct attribute *hotplug_profile_attrs[] = { 755 &hotplug_enabled_attr.attr, 756 NULL 757 }; 758 759 static struct kobj_type acpi_hotplug_profile_ktype = { 760 .sysfs_ops = &kobj_sysfs_ops, 761 .default_attrs = hotplug_profile_attrs, 762 }; 763 764 void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug, 765 const char *name) 766 { 767 int error; 768 769 if (!hotplug_kobj) 770 goto err_out; 771 772 error = kobject_init_and_add(&hotplug->kobj, 773 &acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name); 774 if (error) 775 goto err_out; 776 777 kobject_uevent(&hotplug->kobj, KOBJ_ADD); 778 return; 779 780 err_out: 781 pr_err(PREFIX "Unable to add hotplug profile '%s'\n", name); 782 } 783 784 static ssize_t force_remove_show(struct kobject *kobj, 785 struct kobj_attribute *attr, char *buf) 786 { 787 return sprintf(buf, "%d\n", !!acpi_force_hot_remove); 788 } 789 790 static ssize_t force_remove_store(struct kobject *kobj, 791 struct kobj_attribute *attr, 792 const char *buf, size_t size) 793 { 794 bool val; 795 int ret; 796 797 ret = strtobool(buf, &val); 798 if (ret < 0) 799 return ret; 800 801 lock_device_hotplug(); 802 acpi_force_hot_remove = val; 803 unlock_device_hotplug(); 804 return size; 805 } 806 807 static const struct kobj_attribute force_remove_attr = 808 __ATTR(force_remove, S_IRUGO | S_IWUSR, force_remove_show, 809 force_remove_store); 810 811 int __init acpi_sysfs_init(void) 812 { 813 int result; 814 815 result = acpi_tables_sysfs_init(); 816 if (result) 817 return result; 818 819 hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj); 820 result = sysfs_create_file(hotplug_kobj, &force_remove_attr.attr); 821 if (result) 822 return result; 823 824 result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr); 825 return result; 826 } 827