1
2
3
4
5
6#define pr_fmt(fmt) "ACPI: " fmt
7
8#include <linux/acpi.h>
9#include <linux/bitmap.h>
10#include <linux/init.h>
11#include <linux/kernel.h>
12#include <linux/moduleparam.h>
13
14#include "internal.h"
15
16#ifdef CONFIG_ACPI_DEBUG
17
18
19
20
21
22
23
24
25
26
27struct acpi_dlayer {
28 const char *name;
29 unsigned long value;
30};
31struct acpi_dlevel {
32 const char *name;
33 unsigned long value;
34};
35#define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
36
37static const struct acpi_dlayer acpi_debug_layers[] = {
38 ACPI_DEBUG_INIT(ACPI_UTILITIES),
39 ACPI_DEBUG_INIT(ACPI_HARDWARE),
40 ACPI_DEBUG_INIT(ACPI_EVENTS),
41 ACPI_DEBUG_INIT(ACPI_TABLES),
42 ACPI_DEBUG_INIT(ACPI_NAMESPACE),
43 ACPI_DEBUG_INIT(ACPI_PARSER),
44 ACPI_DEBUG_INIT(ACPI_DISPATCHER),
45 ACPI_DEBUG_INIT(ACPI_EXECUTER),
46 ACPI_DEBUG_INIT(ACPI_RESOURCES),
47 ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
48 ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
49 ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
50 ACPI_DEBUG_INIT(ACPI_COMPILER),
51 ACPI_DEBUG_INIT(ACPI_TOOLS),
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_POWER_COMPONENT),
57 ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT),
58 ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT),
59};
60
61static const struct acpi_dlevel acpi_debug_levels[] = {
62 ACPI_DEBUG_INIT(ACPI_LV_INIT),
63 ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
64 ACPI_DEBUG_INIT(ACPI_LV_INFO),
65 ACPI_DEBUG_INIT(ACPI_LV_REPAIR),
66 ACPI_DEBUG_INIT(ACPI_LV_TRACE_POINT),
67
68 ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
69 ACPI_DEBUG_INIT(ACPI_LV_PARSE),
70 ACPI_DEBUG_INIT(ACPI_LV_LOAD),
71 ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
72 ACPI_DEBUG_INIT(ACPI_LV_EXEC),
73 ACPI_DEBUG_INIT(ACPI_LV_NAMES),
74 ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
75 ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
76 ACPI_DEBUG_INIT(ACPI_LV_TABLES),
77 ACPI_DEBUG_INIT(ACPI_LV_VALUES),
78 ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
79 ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
80 ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
81 ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
82
83 ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
84 ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
85 ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
86
87 ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
88 ACPI_DEBUG_INIT(ACPI_LV_THREADS),
89 ACPI_DEBUG_INIT(ACPI_LV_IO),
90 ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
91
92 ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
93 ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
94 ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
95 ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
96};
97
98static int param_get_debug_layer(char *buffer, const struct kernel_param *kp)
99{
100 int result = 0;
101 int i;
102
103 result = sprintf(buffer, "%-25s\tHex SET\n", "Description");
104
105 for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
106 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n",
107 acpi_debug_layers[i].name,
108 acpi_debug_layers[i].value,
109 (acpi_dbg_layer & acpi_debug_layers[i].value)
110 ? '*' : ' ');
111 }
112 result +=
113 sprintf(buffer + result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
114 ACPI_ALL_DRIVERS,
115 (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
116 ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS)
117 == 0 ? ' ' : '-');
118 result +=
119 sprintf(buffer + result,
120 "--\ndebug_layer = 0x%08X ( * = enabled)\n",
121 acpi_dbg_layer);
122
123 return result;
124}
125
126static int param_get_debug_level(char *buffer, const struct kernel_param *kp)
127{
128 int result = 0;
129 int i;
130
131 result = sprintf(buffer, "%-25s\tHex SET\n", "Description");
132
133 for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
134 result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n",
135 acpi_debug_levels[i].name,
136 acpi_debug_levels[i].value,
137 (acpi_dbg_level & acpi_debug_levels[i].value)
138 ? '*' : ' ');
139 }
140 result +=
141 sprintf(buffer + result, "--\ndebug_level = 0x%08X (* = enabled)\n",
142 acpi_dbg_level);
143
144 return result;
145}
146
147static const struct kernel_param_ops param_ops_debug_layer = {
148 .set = param_set_uint,
149 .get = param_get_debug_layer,
150};
151
152static const struct kernel_param_ops param_ops_debug_level = {
153 .set = param_set_uint,
154 .get = param_get_debug_level,
155};
156
157module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644);
158module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644);
159
160static char trace_method_name[1024];
161
162static int param_set_trace_method_name(const char *val,
163 const struct kernel_param *kp)
164{
165 u32 saved_flags = 0;
166 bool is_abs_path = true;
167
168 if (*val != '\\')
169 is_abs_path = false;
170
171 if ((is_abs_path && strlen(val) > 1023) ||
172 (!is_abs_path && strlen(val) > 1022)) {
173 pr_err("%s: string parameter too long\n", kp->name);
174 return -ENOSPC;
175 }
176
177
178
179
180
181
182 saved_flags = acpi_gbl_trace_flags;
183 (void)acpi_debug_trace(NULL,
184 acpi_gbl_trace_dbg_level,
185 acpi_gbl_trace_dbg_layer,
186 0);
187
188
189 if (is_abs_path)
190 strcpy(trace_method_name, val);
191 else {
192 trace_method_name[0] = '\\';
193 strcpy(trace_method_name+1, val);
194 }
195
196
197 (void)acpi_debug_trace(trace_method_name,
198 acpi_gbl_trace_dbg_level,
199 acpi_gbl_trace_dbg_layer,
200 saved_flags);
201
202 return 0;
203}
204
205static int param_get_trace_method_name(char *buffer, const struct kernel_param *kp)
206{
207 return scnprintf(buffer, PAGE_SIZE, "%s\n", acpi_gbl_trace_method_name);
208}
209
210static const struct kernel_param_ops param_ops_trace_method = {
211 .set = param_set_trace_method_name,
212 .get = param_get_trace_method_name,
213};
214
215static const struct kernel_param_ops param_ops_trace_attrib = {
216 .set = param_set_uint,
217 .get = param_get_uint,
218};
219
220module_param_cb(trace_method_name, ¶m_ops_trace_method, &trace_method_name, 0644);
221module_param_cb(trace_debug_layer, ¶m_ops_trace_attrib, &acpi_gbl_trace_dbg_layer, 0644);
222module_param_cb(trace_debug_level, ¶m_ops_trace_attrib, &acpi_gbl_trace_dbg_level, 0644);
223
224static int param_set_trace_state(const char *val,
225 const struct kernel_param *kp)
226{
227 acpi_status status;
228 const char *method = trace_method_name;
229 u32 flags = 0;
230
231
232#define acpi_compare_param(val, key) \
233 strncmp((val), (key), sizeof(key) - 1)
234
235 if (!acpi_compare_param(val, "enable")) {
236 method = NULL;
237 flags = ACPI_TRACE_ENABLED;
238 } else if (!acpi_compare_param(val, "disable"))
239 method = NULL;
240 else if (!acpi_compare_param(val, "method-once"))
241 flags = ACPI_TRACE_ENABLED | ACPI_TRACE_ONESHOT;
242 else if (!acpi_compare_param(val, "method"))
243 flags = ACPI_TRACE_ENABLED;
244 else if (!acpi_compare_param(val, "opcode-once"))
245 flags = ACPI_TRACE_ENABLED | ACPI_TRACE_ONESHOT | ACPI_TRACE_OPCODE;
246 else if (!acpi_compare_param(val, "opcode"))
247 flags = ACPI_TRACE_ENABLED | ACPI_TRACE_OPCODE;
248 else
249 return -EINVAL;
250
251 status = acpi_debug_trace(method,
252 acpi_gbl_trace_dbg_level,
253 acpi_gbl_trace_dbg_layer,
254 flags);
255 if (ACPI_FAILURE(status))
256 return -EBUSY;
257
258 return 0;
259}
260
261static int param_get_trace_state(char *buffer, const struct kernel_param *kp)
262{
263 if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED))
264 return sprintf(buffer, "disable\n");
265 if (!acpi_gbl_trace_method_name)
266 return sprintf(buffer, "enable\n");
267 if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT)
268 return sprintf(buffer, "method-once\n");
269 else
270 return sprintf(buffer, "method\n");
271}
272
273module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
274 NULL, 0644);
275#endif
276
277
278
279
280module_param_named(aml_debug_output, acpi_gbl_enable_aml_debug_object,
281 byte, 0644);
282MODULE_PARM_DESC(aml_debug_output,
283 "To enable/disable the ACPI Debug Object output.");
284
285
286static int param_get_acpica_version(char *buffer,
287 const struct kernel_param *kp)
288{
289 int result;
290
291 result = sprintf(buffer, "%x\n", ACPI_CA_VERSION);
292
293 return result;
294}
295
296module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
297
298
299
300
301
302
303
304
305static LIST_HEAD(acpi_table_attr_list);
306static struct kobject *tables_kobj;
307static struct kobject *tables_data_kobj;
308static struct kobject *dynamic_tables_kobj;
309static struct kobject *hotplug_kobj;
310
311#define ACPI_MAX_TABLE_INSTANCES 999
312#define ACPI_INST_SIZE 4
313
314struct acpi_table_attr {
315 struct bin_attribute attr;
316 char name[ACPI_NAMESEG_SIZE];
317 int instance;
318 char filename[ACPI_NAMESEG_SIZE+ACPI_INST_SIZE];
319 struct list_head node;
320};
321
322struct acpi_data_attr {
323 struct bin_attribute attr;
324 u64 addr;
325};
326
327static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj,
328 struct bin_attribute *bin_attr, char *buf,
329 loff_t offset, size_t count)
330{
331 struct acpi_table_attr *table_attr =
332 container_of(bin_attr, struct acpi_table_attr, attr);
333 struct acpi_table_header *table_header = NULL;
334 acpi_status status;
335 ssize_t rc;
336
337 status = acpi_get_table(table_attr->name, table_attr->instance,
338 &table_header);
339 if (ACPI_FAILURE(status))
340 return -ENODEV;
341
342 rc = memory_read_from_buffer(buf, count, &offset, table_header,
343 table_header->length);
344 acpi_put_table(table_header);
345 return rc;
346}
347
348static int acpi_table_attr_init(struct kobject *tables_obj,
349 struct acpi_table_attr *table_attr,
350 struct acpi_table_header *table_header)
351{
352 struct acpi_table_header *header = NULL;
353 struct acpi_table_attr *attr = NULL;
354 char instance_str[ACPI_INST_SIZE];
355
356 sysfs_attr_init(&table_attr->attr.attr);
357 ACPI_COPY_NAMESEG(table_attr->name, table_header->signature);
358
359 list_for_each_entry(attr, &acpi_table_attr_list, node) {
360 if (ACPI_COMPARE_NAMESEG(table_attr->name, attr->name))
361 if (table_attr->instance < attr->instance)
362 table_attr->instance = attr->instance;
363 }
364 table_attr->instance++;
365 if (table_attr->instance > ACPI_MAX_TABLE_INSTANCES) {
366 pr_warn("%4.4s: too many table instances\n", table_attr->name);
367 return -ERANGE;
368 }
369
370 ACPI_COPY_NAMESEG(table_attr->filename, table_header->signature);
371 table_attr->filename[ACPI_NAMESEG_SIZE] = '\0';
372 if (table_attr->instance > 1 || (table_attr->instance == 1 &&
373 !acpi_get_table
374 (table_header->signature, 2, &header))) {
375 snprintf(instance_str, sizeof(instance_str), "%u",
376 table_attr->instance);
377 strcat(table_attr->filename, instance_str);
378 }
379
380 table_attr->attr.size = table_header->length;
381 table_attr->attr.read = acpi_table_show;
382 table_attr->attr.attr.name = table_attr->filename;
383 table_attr->attr.attr.mode = 0400;
384
385 return sysfs_create_bin_file(tables_obj, &table_attr->attr);
386}
387
388acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context)
389{
390 struct acpi_table_attr *table_attr;
391
392 switch (event) {
393 case ACPI_TABLE_EVENT_INSTALL:
394 table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL);
395 if (!table_attr)
396 return AE_NO_MEMORY;
397
398 if (acpi_table_attr_init(dynamic_tables_kobj,
399 table_attr, table)) {
400 kfree(table_attr);
401 return AE_ERROR;
402 }
403 list_add_tail(&table_attr->node, &acpi_table_attr_list);
404 break;
405 case ACPI_TABLE_EVENT_LOAD:
406 case ACPI_TABLE_EVENT_UNLOAD:
407 case ACPI_TABLE_EVENT_UNINSTALL:
408
409
410
411
412
413 break;
414 default:
415 return AE_BAD_PARAMETER;
416 }
417 return AE_OK;
418}
419
420static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
421 struct bin_attribute *bin_attr, char *buf,
422 loff_t offset, size_t count)
423{
424 struct acpi_data_attr *data_attr;
425 void *base;
426 ssize_t rc;
427
428 data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
429
430 base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size);
431 if (!base)
432 return -ENOMEM;
433 rc = memory_read_from_buffer(buf, count, &offset, base,
434 data_attr->attr.size);
435 acpi_os_unmap_memory(base, data_attr->attr.size);
436
437 return rc;
438}
439
440static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)
441{
442 struct acpi_table_bert *bert = th;
443
444 if (bert->header.length < sizeof(struct acpi_table_bert) ||
445 bert->region_length < sizeof(struct acpi_hest_generic_status)) {
446 kfree(data_attr);
447 return -EINVAL;
448 }
449 data_attr->addr = bert->address;
450 data_attr->attr.size = bert->region_length;
451 data_attr->attr.attr.name = "BERT";
452
453 return sysfs_create_bin_file(tables_data_kobj, &data_attr->attr);
454}
455
456static struct acpi_data_obj {
457 char *name;
458 int (*fn)(void *, struct acpi_data_attr *);
459} acpi_data_objs[] = {
460 { ACPI_SIG_BERT, acpi_bert_data_init },
461};
462
463#define NUM_ACPI_DATA_OBJS ARRAY_SIZE(acpi_data_objs)
464
465static int acpi_table_data_init(struct acpi_table_header *th)
466{
467 struct acpi_data_attr *data_attr;
468 int i;
469
470 for (i = 0; i < NUM_ACPI_DATA_OBJS; i++) {
471 if (ACPI_COMPARE_NAMESEG(th->signature, acpi_data_objs[i].name)) {
472 data_attr = kzalloc(sizeof(*data_attr), GFP_KERNEL);
473 if (!data_attr)
474 return -ENOMEM;
475 sysfs_attr_init(&data_attr->attr.attr);
476 data_attr->attr.read = acpi_data_show;
477 data_attr->attr.attr.mode = 0400;
478 return acpi_data_objs[i].fn(th, data_attr);
479 }
480 }
481 return 0;
482}
483
484static int acpi_tables_sysfs_init(void)
485{
486 struct acpi_table_attr *table_attr;
487 struct acpi_table_header *table_header = NULL;
488 int table_index;
489 acpi_status status;
490 int ret;
491
492 tables_kobj = kobject_create_and_add("tables", acpi_kobj);
493 if (!tables_kobj)
494 goto err;
495
496 tables_data_kobj = kobject_create_and_add("data", tables_kobj);
497 if (!tables_data_kobj)
498 goto err_tables_data;
499
500 dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj);
501 if (!dynamic_tables_kobj)
502 goto err_dynamic_tables;
503
504 for (table_index = 0;; table_index++) {
505 status = acpi_get_table_by_index(table_index, &table_header);
506
507 if (status == AE_BAD_PARAMETER)
508 break;
509
510 if (ACPI_FAILURE(status))
511 continue;
512
513 table_attr = kzalloc(sizeof(*table_attr), GFP_KERNEL);
514 if (!table_attr)
515 return -ENOMEM;
516
517 ret = acpi_table_attr_init(tables_kobj,
518 table_attr, table_header);
519 if (ret) {
520 kfree(table_attr);
521 return ret;
522 }
523 list_add_tail(&table_attr->node, &acpi_table_attr_list);
524 acpi_table_data_init(table_header);
525 }
526
527 kobject_uevent(tables_kobj, KOBJ_ADD);
528 kobject_uevent(tables_data_kobj, KOBJ_ADD);
529 kobject_uevent(dynamic_tables_kobj, KOBJ_ADD);
530
531 return 0;
532err_dynamic_tables:
533 kobject_put(tables_data_kobj);
534err_tables_data:
535 kobject_put(tables_kobj);
536err:
537 return -ENOMEM;
538}
539
540
541
542
543
544
545u32 acpi_irq_handled;
546u32 acpi_irq_not_handled;
547
548#define COUNT_GPE 0
549#define COUNT_SCI 1
550#define COUNT_SCI_NOT 2
551#define COUNT_ERROR 3
552#define NUM_COUNTERS_EXTRA 4
553
554struct event_counter {
555 u32 count;
556 u32 flags;
557};
558
559static struct event_counter *all_counters;
560static u32 num_gpes;
561static u32 num_counters;
562static struct attribute **all_attrs;
563static u32 acpi_gpe_count;
564
565static struct attribute_group interrupt_stats_attr_group = {
566 .name = "interrupts",
567};
568
569static struct kobj_attribute *counter_attrs;
570
571static void delete_gpe_attr_array(void)
572{
573 struct event_counter *tmp = all_counters;
574
575 all_counters = NULL;
576 kfree(tmp);
577
578 if (counter_attrs) {
579 int i;
580
581 for (i = 0; i < num_gpes; i++)
582 kfree(counter_attrs[i].attr.name);
583
584 kfree(counter_attrs);
585 }
586 kfree(all_attrs);
587}
588
589static void gpe_count(u32 gpe_number)
590{
591 acpi_gpe_count++;
592
593 if (!all_counters)
594 return;
595
596 if (gpe_number < num_gpes)
597 all_counters[gpe_number].count++;
598 else
599 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS +
600 COUNT_ERROR].count++;
601}
602
603static void fixed_event_count(u32 event_number)
604{
605 if (!all_counters)
606 return;
607
608 if (event_number < ACPI_NUM_FIXED_EVENTS)
609 all_counters[num_gpes + event_number].count++;
610 else
611 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS +
612 COUNT_ERROR].count++;
613}
614
615static void acpi_global_event_handler(u32 event_type, acpi_handle device,
616 u32 event_number, void *context)
617{
618 if (event_type == ACPI_EVENT_TYPE_GPE) {
619 gpe_count(event_number);
620 pr_debug("GPE event 0x%02x\n", event_number);
621 } else if (event_type == ACPI_EVENT_TYPE_FIXED) {
622 fixed_event_count(event_number);
623 pr_debug("Fixed event 0x%02x\n", event_number);
624 } else {
625 pr_debug("Other event 0x%02x\n", event_number);
626 }
627}
628
629static int get_status(u32 index, acpi_event_status *ret,
630 acpi_handle *handle)
631{
632 acpi_status status;
633
634 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
635 return -EINVAL;
636
637 if (index < num_gpes) {
638 status = acpi_get_gpe_device(index, handle);
639 if (ACPI_FAILURE(status)) {
640 pr_warn("Invalid GPE 0x%x", index);
641 return -ENXIO;
642 }
643 status = acpi_get_gpe_status(*handle, index, ret);
644 } else {
645 status = acpi_get_event_status(index - num_gpes, ret);
646 }
647 if (ACPI_FAILURE(status))
648 return -EIO;
649
650 return 0;
651}
652
653static ssize_t counter_show(struct kobject *kobj,
654 struct kobj_attribute *attr, char *buf)
655{
656 int index = attr - counter_attrs;
657 int size;
658 acpi_handle handle;
659 acpi_event_status status;
660 int result = 0;
661
662 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI].count =
663 acpi_irq_handled;
664 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT].count =
665 acpi_irq_not_handled;
666 all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE].count =
667 acpi_gpe_count;
668 size = sprintf(buf, "%8u", all_counters[index].count);
669
670
671 if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
672 goto end;
673
674 result = get_status(index, &status, &handle);
675 if (result)
676 goto end;
677
678 if (status & ACPI_EVENT_FLAG_ENABLE_SET)
679 size += sprintf(buf + size, " EN");
680 else
681 size += sprintf(buf + size, " ");
682 if (status & ACPI_EVENT_FLAG_STATUS_SET)
683 size += sprintf(buf + size, " STS");
684 else
685 size += sprintf(buf + size, " ");
686
687 if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER))
688 size += sprintf(buf + size, " invalid ");
689 else if (status & ACPI_EVENT_FLAG_ENABLED)
690 size += sprintf(buf + size, " enabled ");
691 else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED)
692 size += sprintf(buf + size, " wake_enabled");
693 else
694 size += sprintf(buf + size, " disabled ");
695 if (status & ACPI_EVENT_FLAG_MASKED)
696 size += sprintf(buf + size, " masked ");
697 else
698 size += sprintf(buf + size, " unmasked");
699
700end:
701 size += sprintf(buf + size, "\n");
702 return result ? result : size;
703}
704
705
706
707
708
709
710static ssize_t counter_set(struct kobject *kobj,
711 struct kobj_attribute *attr, const char *buf,
712 size_t size)
713{
714 int index = attr - counter_attrs;
715 acpi_event_status status;
716 acpi_handle handle;
717 int result = 0;
718 unsigned long tmp;
719
720 if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
721 int i;
722 for (i = 0; i < num_counters; ++i)
723 all_counters[i].count = 0;
724 acpi_gpe_count = 0;
725 acpi_irq_handled = 0;
726 acpi_irq_not_handled = 0;
727 goto end;
728 }
729
730
731 result = get_status(index, &status, &handle);
732 if (result)
733 goto end;
734
735 if (!(status & ACPI_EVENT_FLAG_HAS_HANDLER)) {
736 pr_warn("Can not change Invalid GPE/Fixed Event status\n");
737 return -EINVAL;
738 }
739
740 if (index < num_gpes) {
741 if (!strcmp(buf, "disable\n") &&
742 (status & ACPI_EVENT_FLAG_ENABLED))
743 result = acpi_disable_gpe(handle, index);
744 else if (!strcmp(buf, "enable\n") &&
745 !(status & ACPI_EVENT_FLAG_ENABLED))
746 result = acpi_enable_gpe(handle, index);
747 else if (!strcmp(buf, "clear\n") &&
748 (status & ACPI_EVENT_FLAG_STATUS_SET))
749 result = acpi_clear_gpe(handle, index);
750 else if (!strcmp(buf, "mask\n"))
751 result = acpi_mask_gpe(handle, index, TRUE);
752 else if (!strcmp(buf, "unmask\n"))
753 result = acpi_mask_gpe(handle, index, FALSE);
754 else if (!kstrtoul(buf, 0, &tmp))
755 all_counters[index].count = tmp;
756 else
757 result = -EINVAL;
758 } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
759 int event = index - num_gpes;
760 if (!strcmp(buf, "disable\n") &&
761 (status & ACPI_EVENT_FLAG_ENABLE_SET))
762 result = acpi_disable_event(event, ACPI_NOT_ISR);
763 else if (!strcmp(buf, "enable\n") &&
764 !(status & ACPI_EVENT_FLAG_ENABLE_SET))
765 result = acpi_enable_event(event, ACPI_NOT_ISR);
766 else if (!strcmp(buf, "clear\n") &&
767 (status & ACPI_EVENT_FLAG_STATUS_SET))
768 result = acpi_clear_event(event);
769 else if (!kstrtoul(buf, 0, &tmp))
770 all_counters[index].count = tmp;
771 else
772 result = -EINVAL;
773 } else
774 all_counters[index].count = strtoul(buf, NULL, 0);
775
776 if (ACPI_FAILURE(result))
777 result = -EINVAL;
778end:
779 return result ? result : size;
780}
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799#define ACPI_MASKABLE_GPE_MAX 0x100
800static DECLARE_BITMAP(acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX) __initdata;
801
802static int __init acpi_gpe_set_masked_gpes(char *val)
803{
804 int ret;
805 u8 gpe;
806
807 ret = kstrtou8(val, 0, &gpe);
808 if (ret) {
809 ret = bitmap_parselist(val, acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX);
810 if (ret)
811 return ret;
812 } else
813 set_bit(gpe, acpi_masked_gpes_map);
814
815 return 1;
816}
817__setup("acpi_mask_gpe=", acpi_gpe_set_masked_gpes);
818
819void __init acpi_gpe_apply_masked_gpes(void)
820{
821 acpi_handle handle;
822 acpi_status status;
823 u16 gpe;
824
825 for_each_set_bit(gpe, acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX) {
826 status = acpi_get_gpe_device(gpe, &handle);
827 if (ACPI_SUCCESS(status)) {
828 pr_info("Masking GPE 0x%x.\n", gpe);
829 (void)acpi_mask_gpe(handle, gpe, TRUE);
830 }
831 }
832}
833
834void acpi_irq_stats_init(void)
835{
836 acpi_status status;
837 int i;
838
839 if (all_counters)
840 return;
841
842 num_gpes = acpi_current_gpe_count;
843 num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA;
844
845 all_attrs = kcalloc(num_counters + 1, sizeof(*all_attrs), GFP_KERNEL);
846 if (all_attrs == NULL)
847 return;
848
849 all_counters = kcalloc(num_counters, sizeof(*all_counters), GFP_KERNEL);
850 if (all_counters == NULL)
851 goto fail;
852
853 status = acpi_install_global_event_handler(acpi_global_event_handler, NULL);
854 if (ACPI_FAILURE(status))
855 goto fail;
856
857 counter_attrs = kcalloc(num_counters, sizeof(*counter_attrs), GFP_KERNEL);
858 if (counter_attrs == NULL)
859 goto fail;
860
861 for (i = 0; i < num_counters; ++i) {
862 char buffer[12];
863 char *name;
864
865 if (i < num_gpes)
866 sprintf(buffer, "gpe%02X", i);
867 else if (i == num_gpes + ACPI_EVENT_PMTIMER)
868 sprintf(buffer, "ff_pmtimer");
869 else if (i == num_gpes + ACPI_EVENT_GLOBAL)
870 sprintf(buffer, "ff_gbl_lock");
871 else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON)
872 sprintf(buffer, "ff_pwr_btn");
873 else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON)
874 sprintf(buffer, "ff_slp_btn");
875 else if (i == num_gpes + ACPI_EVENT_RTC)
876 sprintf(buffer, "ff_rt_clk");
877 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE)
878 sprintf(buffer, "gpe_all");
879 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI)
880 sprintf(buffer, "sci");
881 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI_NOT)
882 sprintf(buffer, "sci_not");
883 else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR)
884 sprintf(buffer, "error");
885 else
886 sprintf(buffer, "bug%02X", i);
887
888 name = kstrdup(buffer, GFP_KERNEL);
889 if (name == NULL)
890 goto fail;
891
892 sysfs_attr_init(&counter_attrs[i].attr);
893 counter_attrs[i].attr.name = name;
894 counter_attrs[i].attr.mode = 0644;
895 counter_attrs[i].show = counter_show;
896 counter_attrs[i].store = counter_set;
897
898 all_attrs[i] = &counter_attrs[i].attr;
899 }
900
901 interrupt_stats_attr_group.attrs = all_attrs;
902 if (!sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group))
903 return;
904
905fail:
906 delete_gpe_attr_array();
907}
908
909static void __exit interrupt_stats_exit(void)
910{
911 sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group);
912
913 delete_gpe_attr_array();
914}
915
916static ssize_t pm_profile_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
917{
918 return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
919}
920
921static const struct kobj_attribute pm_profile_attr = __ATTR_RO(pm_profile);
922
923static ssize_t enabled_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
924{
925 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
926
927 return sprintf(buf, "%d\n", hotplug->enabled);
928}
929
930static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
931 const char *buf, size_t size)
932{
933 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
934 unsigned int val;
935
936 if (kstrtouint(buf, 10, &val) || val > 1)
937 return -EINVAL;
938
939 acpi_scan_hotplug_enabled(hotplug, val);
940 return size;
941}
942
943static struct kobj_attribute hotplug_enabled_attr = __ATTR_RW(enabled);
944
945static struct attribute *hotplug_profile_attrs[] = {
946 &hotplug_enabled_attr.attr,
947 NULL
948};
949
950static struct kobj_type acpi_hotplug_profile_ktype = {
951 .sysfs_ops = &kobj_sysfs_ops,
952 .default_attrs = hotplug_profile_attrs,
953};
954
955void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
956 const char *name)
957{
958 int error;
959
960 if (!hotplug_kobj)
961 goto err_out;
962
963 error = kobject_init_and_add(&hotplug->kobj,
964 &acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name);
965 if (error) {
966 kobject_put(&hotplug->kobj);
967 goto err_out;
968 }
969
970 kobject_uevent(&hotplug->kobj, KOBJ_ADD);
971 return;
972
973 err_out:
974 pr_err("Unable to add hotplug profile '%s'\n", name);
975}
976
977static ssize_t force_remove_show(struct kobject *kobj,
978 struct kobj_attribute *attr, char *buf)
979{
980 return sprintf(buf, "%d\n", 0);
981}
982
983static ssize_t force_remove_store(struct kobject *kobj,
984 struct kobj_attribute *attr,
985 const char *buf, size_t size)
986{
987 bool val;
988 int ret;
989
990 ret = strtobool(buf, &val);
991 if (ret < 0)
992 return ret;
993
994 if (val) {
995 pr_err("Enabling force_remove is not supported anymore. Please report to linux-acpi@vger.kernel.org if you depend on this functionality\n");
996 return -EINVAL;
997 }
998 return size;
999}
1000
1001static const struct kobj_attribute force_remove_attr = __ATTR_RW(force_remove);
1002
1003int __init acpi_sysfs_init(void)
1004{
1005 int result;
1006
1007 result = acpi_tables_sysfs_init();
1008 if (result)
1009 return result;
1010
1011 hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj);
1012 if (!hotplug_kobj)
1013 return -ENOMEM;
1014
1015 result = sysfs_create_file(hotplug_kobj, &force_remove_attr.attr);
1016 if (result)
1017 return result;
1018
1019 result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
1020 return result;
1021}
1022