linux/drivers/acpi/sysfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * sysfs.c - ACPI sysfs interface to userspace.
   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 * ACPI debug sysfs I/F, including:
  19 * /sys/modules/acpi/parameters/debug_layer
  20 * /sys/modules/acpi/parameters/debug_level
  21 * /sys/modules/acpi/parameters/trace_method_name
  22 * /sys/modules/acpi/parameters/trace_state
  23 * /sys/modules/acpi/parameters/trace_debug_layer
  24 * /sys/modules/acpi/parameters/trace_debug_level
  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, &param_ops_debug_layer, &acpi_dbg_layer, 0644);
 158module_param_cb(debug_level, &param_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         * It's not safe to update acpi_gbl_trace_method_name without
 179         * having the tracer stopped, so we save the original tracer
 180         * state and disable it.
 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        /* This is a hack.  We can't kmalloc in early boot. */
 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        /* Restore the original tracer state */
 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, &param_ops_trace_method, &trace_method_name, 0644);
 221module_param_cb(trace_debug_layer, &param_ops_trace_attrib, &acpi_gbl_trace_dbg_layer, 0644);
 222module_param_cb(trace_debug_level, &param_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/* So "xxx-once" comparison should go prior than "xxx" comparison */
 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 /* CONFIG_ACPI_DEBUG */
 276
 277
 278/* /sys/modules/acpi/parameters/aml_debug_output */
 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/* /sys/module/acpi/parameters/acpica_version */
 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 * ACPI table sysfs I/F:
 300 * /sys/firmware/acpi/tables/
 301 * /sys/firmware/acpi/tables/data/
 302 * /sys/firmware/acpi/tables/dynamic/
 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 /* including trailing 0 */
 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                 * we do not need to do anything right now
 410                 * because the table is not deleted from the
 411                 * global table list when unloading it.
 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 * Detailed ACPI IRQ counters:
 542 * /sys/firmware/acpi/interrupts/
 543 */
 544
 545u32 acpi_irq_handled;
 546u32 acpi_irq_not_handled;
 547
 548#define COUNT_GPE 0
 549#define COUNT_SCI 1             /* acpi_irq_handled */
 550#define COUNT_SCI_NOT 2         /* acpi_irq_not_handled */
 551#define COUNT_ERROR 3           /* other */
 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        /* "gpe_all" or "sci" */
 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 * counter_set() sets the specified counter.
 707 * setting the total "sci" file to any value clears all counters.
 708 * enable/disable/clear a gpe/fixed event in user space.
 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        /* show the event status for both GPEs and Fixed Events */
 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 * A Quirk Mechanism for GPE Flooding Prevention:
 784 *
 785 * Quirks may be needed to prevent GPE flooding on a specific GPE. The
 786 * flooding typically cannot be detected and automatically prevented by
 787 * ACPI_GPE_DISPATCH_NONE check because there is a _Lxx/_Exx prepared in
 788 * the AML tables. This normally indicates a feature gap in Linux, thus
 789 * instead of providing endless quirk tables, we provide a boot parameter
 790 * for those who want this quirk. For example, if the users want to prevent
 791 * the GPE flooding for GPE 00, they need to specify the following boot
 792 * parameter:
 793 *   acpi_mask_gpe=0x00
 794 * Note, the parameter can be a list (see bitmap_parselist() for the details).
 795 * The masking status can be modified by the following runtime controlling
 796 * interface:
 797 *   echo unmask > /sys/firmware/acpi/interrupts/gpe00
 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