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