0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) "ACPI: " fmt
0007
0008 #include <linux/acpi.h>
0009 #include <linux/bitmap.h>
0010 #include <linux/init.h>
0011 #include <linux/kernel.h>
0012 #include <linux/moduleparam.h>
0013
0014 #include "internal.h"
0015
0016 #ifdef CONFIG_ACPI_DEBUG
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 struct acpi_dlayer {
0028 const char *name;
0029 unsigned long value;
0030 };
0031 struct acpi_dlevel {
0032 const char *name;
0033 unsigned long value;
0034 };
0035 #define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
0036
0037 static const struct acpi_dlayer acpi_debug_layers[] = {
0038 ACPI_DEBUG_INIT(ACPI_UTILITIES),
0039 ACPI_DEBUG_INIT(ACPI_HARDWARE),
0040 ACPI_DEBUG_INIT(ACPI_EVENTS),
0041 ACPI_DEBUG_INIT(ACPI_TABLES),
0042 ACPI_DEBUG_INIT(ACPI_NAMESPACE),
0043 ACPI_DEBUG_INIT(ACPI_PARSER),
0044 ACPI_DEBUG_INIT(ACPI_DISPATCHER),
0045 ACPI_DEBUG_INIT(ACPI_EXECUTER),
0046 ACPI_DEBUG_INIT(ACPI_RESOURCES),
0047 ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
0048 ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
0049 ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
0050 ACPI_DEBUG_INIT(ACPI_COMPILER),
0051 ACPI_DEBUG_INIT(ACPI_TOOLS),
0052 };
0053
0054 static const struct acpi_dlevel acpi_debug_levels[] = {
0055 ACPI_DEBUG_INIT(ACPI_LV_INIT),
0056 ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
0057 ACPI_DEBUG_INIT(ACPI_LV_INFO),
0058 ACPI_DEBUG_INIT(ACPI_LV_REPAIR),
0059 ACPI_DEBUG_INIT(ACPI_LV_TRACE_POINT),
0060
0061 ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
0062 ACPI_DEBUG_INIT(ACPI_LV_PARSE),
0063 ACPI_DEBUG_INIT(ACPI_LV_LOAD),
0064 ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
0065 ACPI_DEBUG_INIT(ACPI_LV_EXEC),
0066 ACPI_DEBUG_INIT(ACPI_LV_NAMES),
0067 ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
0068 ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
0069 ACPI_DEBUG_INIT(ACPI_LV_TABLES),
0070 ACPI_DEBUG_INIT(ACPI_LV_VALUES),
0071 ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
0072 ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
0073 ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
0074 ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
0075
0076 ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
0077 ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
0078 ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
0079
0080 ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
0081 ACPI_DEBUG_INIT(ACPI_LV_THREADS),
0082 ACPI_DEBUG_INIT(ACPI_LV_IO),
0083 ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
0084
0085 ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
0086 ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
0087 ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
0088 ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
0089 };
0090
0091 static int param_get_debug_layer(char *buffer, const struct kernel_param *kp)
0092 {
0093 int result = 0;
0094 int i;
0095
0096 result = sprintf(buffer, "%-25s\tHex SET\n", "Description");
0097
0098 for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
0099 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n",
0100 acpi_debug_layers[i].name,
0101 acpi_debug_layers[i].value,
0102 (acpi_dbg_layer & acpi_debug_layers[i].value)
0103 ? '*' : ' ');
0104 }
0105 result +=
0106 sprintf(buffer + result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
0107 ACPI_ALL_DRIVERS,
0108 (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
0109 ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS)
0110 == 0 ? ' ' : '-');
0111 result +=
0112 sprintf(buffer + result,
0113 "--\ndebug_layer = 0x%08X ( * = enabled)\n",
0114 acpi_dbg_layer);
0115
0116 return result;
0117 }
0118
0119 static int param_get_debug_level(char *buffer, const struct kernel_param *kp)
0120 {
0121 int result = 0;
0122 int i;
0123
0124 result = sprintf(buffer, "%-25s\tHex SET\n", "Description");
0125
0126 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
0127 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n",
0128 acpi_debug_levels[i].name,
0129 acpi_debug_levels[i].value,
0130 (acpi_dbg_level & acpi_debug_levels[i].value)
0131 ? '*' : ' ');
0132 }
0133 result +=
0134 sprintf(buffer + result, "--\ndebug_level = 0x%08X (* = enabled)\n",
0135 acpi_dbg_level);
0136
0137 return result;
0138 }
0139
0140 static const struct kernel_param_ops param_ops_debug_layer = {
0141 .set = param_set_uint,
0142 .get = param_get_debug_layer,
0143 };
0144
0145 static const struct kernel_param_ops param_ops_debug_level = {
0146 .set = param_set_uint,
0147 .get = param_get_debug_level,
0148 };
0149
0150 module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644);
0151 module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644);
0152
0153 static char trace_method_name[1024];
0154
0155 static int param_set_trace_method_name(const char *val,
0156 const struct kernel_param *kp)
0157 {
0158 u32 saved_flags = 0;
0159 bool is_abs_path = true;
0160
0161 if (*val != '\\')
0162 is_abs_path = false;
0163
0164 if ((is_abs_path && strlen(val) > 1023) ||
0165 (!is_abs_path && strlen(val) > 1022)) {
0166 pr_err("%s: string parameter too long\n", kp->name);
0167 return -ENOSPC;
0168 }
0169
0170
0171
0172
0173
0174
0175 saved_flags = acpi_gbl_trace_flags;
0176 (void)acpi_debug_trace(NULL,
0177 acpi_gbl_trace_dbg_level,
0178 acpi_gbl_trace_dbg_layer,
0179 0);
0180
0181
0182 if (is_abs_path)
0183 strcpy(trace_method_name, val);
0184 else {
0185 trace_method_name[0] = '\\';
0186 strcpy(trace_method_name+1, val);
0187 }
0188
0189
0190 (void)acpi_debug_trace(trace_method_name,
0191 acpi_gbl_trace_dbg_level,
0192 acpi_gbl_trace_dbg_layer,
0193 saved_flags);
0194
0195 return 0;
0196 }
0197
0198 static int param_get_trace_method_name(char *buffer, const struct kernel_param *kp)
0199 {
0200 return scnprintf(buffer, PAGE_SIZE, "%s\n", acpi_gbl_trace_method_name);
0201 }
0202
0203 static const struct kernel_param_ops param_ops_trace_method = {
0204 .set = param_set_trace_method_name,
0205 .get = param_get_trace_method_name,
0206 };
0207
0208 static const struct kernel_param_ops param_ops_trace_attrib = {
0209 .set = param_set_uint,
0210 .get = param_get_uint,
0211 };
0212
0213 module_param_cb(trace_method_name, ¶m_ops_trace_method, &trace_method_name, 0644);
0214 module_param_cb(trace_debug_layer, ¶m_ops_trace_attrib, &acpi_gbl_trace_dbg_layer, 0644);
0215 module_param_cb(trace_debug_level, ¶m_ops_trace_attrib, &acpi_gbl_trace_dbg_level, 0644);
0216
0217 static int param_set_trace_state(const char *val,
0218 const struct kernel_param *kp)
0219 {
0220 acpi_status status;
0221 const char *method = trace_method_name;
0222 u32 flags = 0;
0223
0224
0225 #define acpi_compare_param(val, key) \
0226 strncmp((val), (key), sizeof(key) - 1)
0227
0228 if (!acpi_compare_param(val, "enable")) {
0229 method = NULL;
0230 flags = ACPI_TRACE_ENABLED;
0231 } else if (!acpi_compare_param(val, "disable"))
0232 method = NULL;
0233 else if (!acpi_compare_param(val, "method-once"))
0234 flags = ACPI_TRACE_ENABLED | ACPI_TRACE_ONESHOT;
0235 else if (!acpi_compare_param(val, "method"))
0236 flags = ACPI_TRACE_ENABLED;
0237 else if (!acpi_compare_param(val, "opcode-once"))
0238 flags = ACPI_TRACE_ENABLED | ACPI_TRACE_ONESHOT | ACPI_TRACE_OPCODE;
0239 else if (!acpi_compare_param(val, "opcode"))
0240 flags = ACPI_TRACE_ENABLED | ACPI_TRACE_OPCODE;
0241 else
0242 return -EINVAL;
0243
0244 status = acpi_debug_trace(method,
0245 acpi_gbl_trace_dbg_level,
0246 acpi_gbl_trace_dbg_layer,
0247 flags);
0248 if (ACPI_FAILURE(status))
0249 return -EBUSY;
0250
0251 return 0;
0252 }
0253
0254 static int param_get_trace_state(char *buffer, const struct kernel_param *kp)
0255 {
0256 if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED))
0257 return sprintf(buffer, "disable\n");
0258 if (!acpi_gbl_trace_method_name)
0259 return sprintf(buffer, "enable\n");
0260 if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT)
0261 return sprintf(buffer, "method-once\n");
0262 else
0263 return sprintf(buffer, "method\n");
0264 }
0265
0266 module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
0267 NULL, 0644);
0268 #endif
0269
0270
0271
0272
0273 module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object,
0274 byte, 0644);
0275 MODULE_PARM_DESC(aml_debug_output,
0276 "To enable/disable the ACPI Debug Object output.");
0277
0278
0279 static int param_get_acpica_version(char *buffer,
0280 const struct kernel_param *kp)
0281 {
0282 int result;
0283
0284 result = sprintf(buffer, "%x\n", ACPI_CA_VERSION);
0285
0286 return result;
0287 }
0288
0289 module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
0290
0291
0292
0293
0294
0295
0296
0297
0298 static LIST_HEAD(acpi_table_attr_list);
0299 static struct kobject *tables_kobj;
0300 static struct kobject *tables_data_kobj;
0301 static struct kobject *dynamic_tables_kobj;
0302 static struct kobject *hotplug_kobj;
0303
0304 #define ACPI_MAX_TABLE_INSTANCES 999
0305 #define ACPI_INST_SIZE 4
0306
0307 struct acpi_table_attr {
0308 struct bin_attribute attr;
0309 char name[ACPI_NAMESEG_SIZE];
0310 int instance;
0311 char filename[ACPI_NAMESEG_SIZE+ACPI_INST_SIZE];
0312 struct list_head node;
0313 };
0314
0315 struct acpi_data_attr {
0316 struct bin_attribute attr;
0317 u64 addr;
0318 };
0319
0320 static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
0321 struct bin_attribute *bin_attr, char *buf,
0322 loff_t offset, size_t count)
0323 {
0324 struct acpi_table_attr *table_attr =
0325 container_of(bin_attr, struct acpi_table_attr, attr);
0326 struct acpi_table_header *table_header = NULL;
0327 acpi_status status;
0328 ssize_t rc;
0329
0330 status = acpi_get_table(table_attr->name, table_attr->instance,
0331 &table_header);
0332 if (ACPI_FAILURE(status))
0333 return -ENODEV;
0334
0335 rc = memory_read_from_buffer(buf, count, &offset, table_header,
0336 table_header->length);
0337 acpi_put_table(table_header);
0338 return rc;
0339 }
0340
0341 static int acpi_table_attr_init(struct kobject *tables_obj,
0342 struct acpi_table_attr *table_attr,
0343 struct acpi_table_header *table_header)
0344 {
0345 struct acpi_table_header *header = NULL;
0346 struct acpi_table_attr *attr = NULL;
0347 char instance_str[ACPI_INST_SIZE];
0348
0349 sysfs_attr_init(&table_attr->attr.attr);
0350 ACPI_COPY_NAMESEG(table_attr->name, table_header->signature);
0351
0352 list_for_each_entry(attr, &acpi_table_attr_list, node) {
0353 if (ACPI_COMPARE_NAMESEG(table_attr->name, attr->name))
0354 if (table_attr->instance < attr->instance)
0355 table_attr->instance = attr->instance;
0356 }
0357 table_attr->instance++;
0358 if (table_attr->instance > ACPI_MAX_TABLE_INSTANCES) {
0359 pr_warn("%4.4s: too many table instances\n", table_attr->name);
0360 return -ERANGE;
0361 }
0362
0363 ACPI_COPY_NAMESEG(table_attr->filename, table_header->signature);
0364 table_attr->filename[ACPI_NAMESEG_SIZE] = '\0';
0365 if (table_attr->instance > 1 || (table_attr->instance == 1 &&
0366 !acpi_get_table
0367 (table_header->signature, 2, &header))) {
0368 snprintf(instance_str, sizeof(instance_str), "%u",
0369 table_attr->instance);
0370 strcat(table_attr->filename, instance_str);
0371 }
0372
0373 table_attr->attr.size = table_header->length;
0374 table_attr->attr.read = acpi_table_show;
0375 table_attr->attr.attr.name = table_attr->filename;
0376 table_attr->attr.attr.mode = 0400;
0377
0378 return sysfs_create_bin_file(tables_obj, &table_attr->attr);
0379 }
0380
0381 acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context)
0382 {
0383 struct acpi_table_attr *table_attr;
0384
0385 switch (event) {
0386 case ACPI_TABLE_EVENT_INSTALL:
0387 table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL);
0388 if (!table_attr)
0389 return AE_NO_MEMORY;
0390
0391 if (acpi_table_attr_init(dynamic_tables_kobj,
0392 table_attr, table)) {
0393 kfree(table_attr);
0394 return AE_ERROR;
0395 }
0396 list_add_tail(&table_attr->node, &acpi_table_attr_list);
0397 break;
0398 case ACPI_TABLE_EVENT_LOAD:
0399 case ACPI_TABLE_EVENT_UNLOAD:
0400 case ACPI_TABLE_EVENT_UNINSTALL:
0401
0402
0403
0404
0405
0406 break;
0407 default:
0408 return AE_BAD_PARAMETER;
0409 }
0410 return AE_OK;
0411 }
0412
0413 static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
0414 struct bin_attribute *bin_attr, char *buf,
0415 loff_t offset, size_t count)
0416 {
0417 struct acpi_data_attr *data_attr;
0418 void __iomem *base;
0419 ssize_t size;
0420
0421 data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
0422 size = data_attr->attr.size;
0423
0424 if (offset < 0)
0425 return -EINVAL;
0426
0427 if (offset >= size)
0428 return 0;
0429
0430 if (count > size - offset)
0431 count = size - offset;
0432
0433 base = acpi_os_map_iomem(data_attr->addr, size);
0434 if (!base)
0435 return -ENOMEM;
0436
0437 memcpy_fromio(buf, base + offset, count);
0438
0439 acpi_os_unmap_iomem(base, size);
0440
0441 return count;
0442 }
0443
0444 static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)
0445 {
0446 struct acpi_table_bert *bert = th;
0447
0448 if (bert->header.length < sizeof(struct acpi_table_bert) ||
0449 bert->region_length < sizeof(struct acpi_hest_generic_status)) {
0450 kfree(data_attr);
0451 return -EINVAL;
0452 }
0453 data_attr->addr = bert->address;
0454 data_attr->attr.size = bert->region_length;
0455 data_attr->attr.attr.name = "BERT";
0456
0457 return sysfs_create_bin_file(tables_data_kobj, &data_attr->attr);
0458 }
0459
0460 static struct acpi_data_obj {
0461 char *name;
0462 int (*fn)(void *, struct acpi_data_attr *);
0463 } acpi_data_objs[] = {
0464 { ACPI_SIG_BERT, acpi_bert_data_init },
0465 };
0466
0467 #define NUM_ACPI_DATA_OBJS ARRAY_SIZE(acpi_data_objs)
0468
0469 static int acpi_table_data_init(struct acpi_table_header *th)
0470 {
0471 struct acpi_data_attr *data_attr;
0472 int i;
0473
0474 for (i = 0; i < NUM_ACPI_DATA_OBJS; i++) {
0475 if (ACPI_COMPARE_NAMESEG(th->signature, acpi_data_objs[i].name)) {
0476 data_attr = kzalloc(sizeof(*data_attr), GFP_KERNEL);
0477 if (!data_attr)
0478 return -ENOMEM;
0479 sysfs_attr_init(&data_attr->attr.attr);
0480 data_attr->attr.read = acpi_data_show;
0481 data_attr->attr.attr.mode = 0400;
0482 return acpi_data_objs[i].fn(th, data_attr);
0483 }
0484 }
0485 return 0;
0486 }
0487
0488 static int acpi_tables_sysfs_init(void)
0489 {
0490 struct acpi_table_attr *table_attr;
0491 struct acpi_table_header *table_header = NULL;
0492 int table_index;
0493 acpi_status status;
0494 int ret;
0495
0496 tables_kobj = kobject_create_and_add("tables", acpi_kobj);
0497 if (!tables_kobj)
0498 goto err;
0499
0500 tables_data_kobj = kobject_create_and_add("data", tables_kobj);
0501 if (!tables_data_kobj)
0502 goto err_tables_data;
0503
0504 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj);
0505 if (!dynamic_tables_kobj)
0506 goto err_dynamic_tables;
0507
0508 for (table_index = 0;; table_index++) {
0509 status = acpi_get_table_by_index(table_index, &table_header);
0510
0511 if (status == AE_BAD_PARAMETER)
0512 break;
0513
0514 if (ACPI_FAILURE(status))
0515 continue;
0516
0517 table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL);
0518 if (!table_attr)
0519 return -ENOMEM;
0520
0521 ret = acpi_table_attr_init(tables_kobj,
0522 table_attr, table_header);
0523 if (ret) {
0524 kfree(table_attr);
0525 return ret;
0526 }
0527 list_add_tail(&table_attr->node, &acpi_table_attr_list);
0528 acpi_table_data_init(table_header);
0529 }
0530
0531 kobject_uevent(tables_kobj, KOBJ_ADD);
0532 kobject_uevent(tables_data_kobj, KOBJ_ADD);
0533 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD);
0534
0535 return 0;
0536 err_dynamic_tables:
0537 kobject_put(tables_data_kobj);
0538 err_tables_data:
0539 kobject_put(tables_kobj);
0540 err:
0541 return -ENOMEM;
0542 }
0543
0544
0545
0546
0547
0548
0549 u32 acpi_irq_handled;
0550 u32 acpi_irq_not_handled;
0551
0552 #define COUNT_GPE 0
0553 #define COUNT_SCI 1
0554 #define COUNT_SCI_NOT 2
0555 #define COUNT_ERROR 3
0556 #define NUM_COUNTERS_EXTRA 4
0557
0558 struct event_counter {
0559 u32 count;
0560 u32 flags;
0561 };
0562
0563 static struct event_counter *all_counters;
0564 static u32 num_gpes;
0565 static u32 num_counters;
0566 static struct attribute **all_attrs;
0567 static u32 acpi_gpe_count;
0568
0569 static struct attribute_group interrupt_stats_attr_group = {
0570 .name = "interrupts",
0571 };
0572
0573 static struct kobj_attribute *counter_attrs;
0574
0575 static void delete_gpe_attr_array(void)
0576 {
0577 struct event_counter *tmp = all_counters;
0578
0579 all_counters = NULL;
0580 kfree(tmp);
0581
0582 if (counter_attrs) {
0583 int i;
0584
0585 for (i = 0; i < num_gpes; i++)
0586 kfree(counter_attrs[i].attr.name);
0587
0588 kfree(counter_attrs);
0589 }
0590 kfree(all_attrs);
0591 }
0592
0593 static void gpe_count(u32 gpe_number)
0594 {
0595 acpi_gpe_count++;
0596
0597 if (!all_counters)
0598 return;
0599
0600 if (gpe_number < num_gpes)
0601 all_counters[gpe_number].count++;
0602 else
0603 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS +
0604 COUNT_ERROR].count++;
0605 }
0606
0607 static void fixed_event_count(u32 event_number)
0608 {
0609 if (!all_counters)
0610 return;
0611
0612 if (event_number < ACPI_NUM_FIXED_EVENTS)
0613 all_counters[num_gpes + event_number].count++;
0614 else
0615 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS +
0616 COUNT_ERROR].count++;
0617 }
0618
0619 static void acpi_global_event_handler(u32 event_type, acpi_handle device,
0620 u32 event_number, void *context)
0621 {
0622 if (event_type == ACPI_EVENT_TYPE_GPE) {
0623 gpe_count(event_number);
0624 pr_debug("GPE event 0x%02x\n", event_number);
0625 } else if (event_type == ACPI_EVENT_TYPE_FIXED) {
0626 fixed_event_count(event_number);
0627 pr_debug("Fixed event 0x%02x\n", event_number);
0628 } else {
0629 pr_debug("Other event 0x%02x\n", event_number);
0630 }
0631 }
0632
0633 static int get_status(u32 index, acpi_event_status *ret,
0634 acpi_handle *handle)
0635 {
0636 acpi_status status;
0637
0638 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
0639 return -EINVAL;
0640
0641 if (index < num_gpes) {
0642 status = acpi_get_gpe_device(index, handle);
0643 if (ACPI_FAILURE(status)) {
0644 pr_warn("Invalid GPE 0x%x", index);
0645 return -ENXIO;
0646 }
0647 status = acpi_get_gpe_status(*handle, index, ret);
0648 } else {
0649 status = acpi_get_event_status(index - num_gpes, ret);
0650 }
0651 if (ACPI_FAILURE(status))
0652 return -EIO;
0653
0654 return 0;
0655 }
0656
0657 static ssize_t counter_show(struct kobject *kobj,
0658 struct kobj_attribute *attr, char *buf)
0659 {
0660 int index = attr - counter_attrs;
0661 int size;
0662 acpi_handle handle;
0663 acpi_event_status status;
0664 int result = 0;
0665
0666 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count =
0667 acpi_irq_handled;
0668 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count =
0669 acpi_irq_not_handled;
0670 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count =
0671 acpi_gpe_count;
0672 size = sprintf(buf, "%8u", all_counters[index].count);
0673
0674
0675 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
0676 goto end;
0677
0678 result = get_status(index, &status, &handle);
0679 if (result)
0680 goto end;
0681
0682 if (status & ACPI_EVENT_FLAG_ENABLE_SET)
0683 size += sprintf(buf + size, " EN");
0684 else
0685 size += sprintf(buf + size, " ");
0686 if (status & ACPI_EVENT_FLAG_STATUS_SET)
0687 size += sprintf(buf + size, " STS");
0688 else
0689 size += sprintf(buf + size, " ");
0690
0691 if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER))
0692 size += sprintf(buf + size, " invalid ");
0693 else if (status & ACPI_EVENT_FLAG_ENABLED)
0694 size += sprintf(buf + size, " enabled ");
0695 else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED)
0696 size += sprintf(buf + size, " wake_enabled");
0697 else
0698 size += sprintf(buf + size, " disabled ");
0699 if (status & ACPI_EVENT_FLAG_MASKED)
0700 size += sprintf(buf + size, " masked ");
0701 else
0702 size += sprintf(buf + size, " unmasked");
0703
0704 end:
0705 size += sprintf(buf + size, "\n");
0706 return result ? result : size;
0707 }
0708
0709
0710
0711
0712
0713
0714 static ssize_t counter_set(struct kobject *kobj,
0715 struct kobj_attribute *attr, const char *buf,
0716 size_t size)
0717 {
0718 int index = attr - counter_attrs;
0719 acpi_event_status status;
0720 acpi_handle handle;
0721 int result = 0;
0722 unsigned long tmp;
0723
0724 if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
0725 int i;
0726 for (i = 0; i < num_counters; ++i)
0727 all_counters[i].count = 0;
0728 acpi_gpe_count = 0;
0729 acpi_irq_handled = 0;
0730 acpi_irq_not_handled = 0;
0731 goto end;
0732 }
0733
0734
0735 result = get_status(index, &status, &handle);
0736 if (result)
0737 goto end;
0738
0739 if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER)) {
0740 pr_warn("Can not change Invalid GPE/Fixed Event status\n");
0741 return -EINVAL;
0742 }
0743
0744 if (index < num_gpes) {
0745 if (!strcmp(buf, "disable\n") &&
0746 (status & ACPI_EVENT_FLAG_ENABLED))
0747 result = acpi_disable_gpe(handle, index);
0748 else if (!strcmp(buf, "enable\n") &&
0749 !(status & ACPI_EVENT_FLAG_ENABLED))
0750 result = acpi_enable_gpe(handle, index);
0751 else if (!strcmp(buf, "clear\n") &&
0752 (status & ACPI_EVENT_FLAG_STATUS_SET))
0753 result = acpi_clear_gpe(handle, index);
0754 else if (!strcmp(buf, "mask\n"))
0755 result = acpi_mask_gpe(handle, index, TRUE);
0756 else if (!strcmp(buf, "unmask\n"))
0757 result = acpi_mask_gpe(handle, index, FALSE);
0758 else if (!kstrtoul(buf, 0, &tmp))
0759 all_counters[index].count = tmp;
0760 else
0761 result = -EINVAL;
0762 } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
0763 int event = index - num_gpes;
0764 if (!strcmp(buf, "disable\n") &&
0765 (status & ACPI_EVENT_FLAG_ENABLE_SET))
0766 result = acpi_disable_event(event, ACPI_NOT_ISR);
0767 else if (!strcmp(buf, "enable\n") &&
0768 !(status & ACPI_EVENT_FLAG_ENABLE_SET))
0769 result = acpi_enable_event(event, ACPI_NOT_ISR);
0770 else if (!strcmp(buf, "clear\n") &&
0771 (status & ACPI_EVENT_FLAG_STATUS_SET))
0772 result = acpi_clear_event(event);
0773 else if (!kstrtoul(buf, 0, &tmp))
0774 all_counters[index].count = tmp;
0775 else
0776 result = -EINVAL;
0777 } else
0778 all_counters[index].count = strtoul(buf, NULL, 0);
0779
0780 if (ACPI_FAILURE(result))
0781 result = -EINVAL;
0782 end:
0783 return result ? result : size;
0784 }
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803 #define ACPI_MASKABLE_GPE_MAX 0x100
0804 static DECLARE_BITMAP(acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX) __initdata;
0805
0806 static int __init acpi_gpe_set_masked_gpes(char *val)
0807 {
0808 int ret;
0809 u8 gpe;
0810
0811 ret = kstrtou8(val, 0, &gpe);
0812 if (ret) {
0813 ret = bitmap_parselist(val, acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX);
0814 if (ret)
0815 return ret;
0816 } else
0817 set_bit(gpe, acpi_masked_gpes_map);
0818
0819 return 1;
0820 }
0821 __setup("acpi_mask_gpe=", acpi_gpe_set_masked_gpes);
0822
0823 void __init acpi_gpe_apply_masked_gpes(void)
0824 {
0825 acpi_handle handle;
0826 acpi_status status;
0827 u16 gpe;
0828
0829 for_each_set_bit(gpe, acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX) {
0830 status = acpi_get_gpe_device(gpe, &handle);
0831 if (ACPI_SUCCESS(status)) {
0832 pr_info("Masking GPE 0x%x.\n", gpe);
0833 (void)acpi_mask_gpe(handle, gpe, TRUE);
0834 }
0835 }
0836 }
0837
0838 void acpi_irq_stats_init(void)
0839 {
0840 acpi_status status;
0841 int i;
0842
0843 if (all_counters)
0844 return;
0845
0846 num_gpes = acpi_current_gpe_count;
0847 num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA;
0848
0849 all_attrs = kcalloc(num_counters + 1, sizeof(*all_attrs), GFP_KERNEL);
0850 if (all_attrs == NULL)
0851 return;
0852
0853 all_counters = kcalloc(num_counters, sizeof(*all_counters), GFP_KERNEL);
0854 if (all_counters == NULL)
0855 goto fail;
0856
0857 status = acpi_install_global_event_handler(acpi_global_event_handler, NULL);
0858 if (ACPI_FAILURE(status))
0859 goto fail;
0860
0861 counter_attrs = kcalloc(num_counters, sizeof(*counter_attrs), GFP_KERNEL);
0862 if (counter_attrs == NULL)
0863 goto fail;
0864
0865 for (i = 0; i < num_counters; ++i) {
0866 char buffer[12];
0867 char *name;
0868
0869 if (i < num_gpes)
0870 sprintf(buffer, "gpe%02X", i);
0871 else if (i == num_gpes + ACPI_EVENT_PMTIMER)
0872 sprintf(buffer, "ff_pmtimer");
0873 else if (i == num_gpes + ACPI_EVENT_GLOBAL)
0874 sprintf(buffer, "ff_gbl_lock");
0875 else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON)
0876 sprintf(buffer, "ff_pwr_btn");
0877 else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON)
0878 sprintf(buffer, "ff_slp_btn");
0879 else if (i == num_gpes + ACPI_EVENT_RTC)
0880 sprintf(buffer, "ff_rt_clk");
0881 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE)
0882 sprintf(buffer, "gpe_all");
0883 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI)
0884 sprintf(buffer, "sci");
0885 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT)
0886 sprintf(buffer, "sci_not");
0887 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR)
0888 sprintf(buffer, "error");
0889 else
0890 sprintf(buffer, "bug%02X", i);
0891
0892 name = kstrdup(buffer, GFP_KERNEL);
0893 if (name == NULL)
0894 goto fail;
0895
0896 sysfs_attr_init(&counter_attrs[i].attr);
0897 counter_attrs[i].attr.name = name;
0898 counter_attrs[i].attr.mode = 0644;
0899 counter_attrs[i].show = counter_show;
0900 counter_attrs[i].store = counter_set;
0901
0902 all_attrs[i] = &counter_attrs[i].attr;
0903 }
0904
0905 interrupt_stats_attr_group.attrs = all_attrs;
0906 if (!sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group))
0907 return;
0908
0909 fail:
0910 delete_gpe_attr_array();
0911 }
0912
0913 static void __exit interrupt_stats_exit(void)
0914 {
0915 sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group);
0916
0917 delete_gpe_attr_array();
0918 }
0919
0920 static ssize_t pm_profile_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
0921 {
0922 return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
0923 }
0924
0925 static const struct kobj_attribute pm_profile_attr = __ATTR_RO(pm_profile);
0926
0927 static ssize_t enabled_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
0928 {
0929 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
0930
0931 return sprintf(buf, "%d\n", hotplug->enabled);
0932 }
0933
0934 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
0935 const char *buf, size_t size)
0936 {
0937 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
0938 unsigned int val;
0939
0940 if (kstrtouint(buf, 10, &val) || val > 1)
0941 return -EINVAL;
0942
0943 acpi_scan_hotplug_enabled(hotplug, val);
0944 return size;
0945 }
0946
0947 static struct kobj_attribute hotplug_enabled_attr = __ATTR_RW(enabled);
0948
0949 static struct attribute *hotplug_profile_attrs[] = {
0950 &hotplug_enabled_attr.attr,
0951 NULL
0952 };
0953 ATTRIBUTE_GROUPS(hotplug_profile);
0954
0955 static struct kobj_type acpi_hotplug_profile_ktype = {
0956 .sysfs_ops = &kobj_sysfs_ops,
0957 .default_groups = hotplug_profile_groups,
0958 };
0959
0960 void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
0961 const char *name)
0962 {
0963 int error;
0964
0965 if (!hotplug_kobj)
0966 goto err_out;
0967
0968 error = kobject_init_and_add(&hotplug->kobj,
0969 &acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name);
0970 if (error) {
0971 kobject_put(&hotplug->kobj);
0972 goto err_out;
0973 }
0974
0975 kobject_uevent(&hotplug->kobj, KOBJ_ADD);
0976 return;
0977
0978 err_out:
0979 pr_err("Unable to add hotplug profile '%s'\n", name);
0980 }
0981
0982 static ssize_t force_remove_show(struct kobject *kobj,
0983 struct kobj_attribute *attr, char *buf)
0984 {
0985 return sprintf(buf, "%d\n", 0);
0986 }
0987
0988 static ssize_t force_remove_store(struct kobject *kobj,
0989 struct kobj_attribute *attr,
0990 const char *buf, size_t size)
0991 {
0992 bool val;
0993 int ret;
0994
0995 ret = strtobool(buf, &val);
0996 if (ret < 0)
0997 return ret;
0998
0999 if (val) {
1000 pr_err("Enabling force_remove is not supported anymore. Please report to linux-acpi@vger.kernel.org if you depend on this functionality\n");
1001 return -EINVAL;
1002 }
1003 return size;
1004 }
1005
1006 static const struct kobj_attribute force_remove_attr = __ATTR_RW(force_remove);
1007
1008 int __init acpi_sysfs_init(void)
1009 {
1010 int result;
1011
1012 result = acpi_tables_sysfs_init();
1013 if (result)
1014 return result;
1015
1016 hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj);
1017 if (!hotplug_kobj)
1018 return -ENOMEM;
1019
1020 result = sysfs_create_file(hotplug_kobj, &force_remove_attr.attr);
1021 if (result)
1022 return result;
1023
1024 result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
1025 return result;
1026 }