Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI / sysfs: Update method tracing facility.

This patch updates the method tracing facility as the acpi_debug_trace()
API has been updated to allow it to trace AML interpreter execution, the
meanings and the usages of the API parameters are changed due to the
updates.

The new API:
1. Uses ACPI_TRACE_ENABLED flag to indicate the enabling of the tracer;
2. Allows tracer still can be enabled when method name is not specified so
that the AML interpreter execution can be traced without knowing the
method name, which is useful for kernel boot tracing;
3. Supports arbitrary full path name, it doesn't need to be a name related
to an entrance of acpi_evaluate_object().

Note that the sysfs parameters are also updated so that when reading the
attribute files, ACPICA internal settings are returned.

In order to make the sysfs parameters (acpi.trace_state) available during
boot, this patch adds code to bypass ACPICA semaphore/mutex invocations
when acpi mutex utilities haven't been initialized.

This patch doesn't update documentation of method tracing facility, it will
be updated by further patches.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Lv Zheng and committed by
Rafael J. Wysocki
7901a052 93d98831

+108 -36
+8
drivers/acpi/osl.c
··· 83 83 static struct workqueue_struct *kacpid_wq; 84 84 static struct workqueue_struct *kacpi_notify_wq; 85 85 static struct workqueue_struct *kacpi_hotplug_wq; 86 + static bool acpi_os_initialized; 86 87 87 88 /* 88 89 * This list of permanent mappings is for memory that may be accessed from ··· 1317 1316 long jiffies; 1318 1317 int ret = 0; 1319 1318 1319 + if (!acpi_os_initialized) 1320 + return AE_OK; 1321 + 1320 1322 if (!sem || (units < 1)) 1321 1323 return AE_BAD_PARAMETER; 1322 1324 ··· 1358 1354 acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units) 1359 1355 { 1360 1356 struct semaphore *sem = (struct semaphore *)handle; 1357 + 1358 + if (!acpi_os_initialized) 1359 + return AE_OK; 1361 1360 1362 1361 if (!sem || (units < 1)) 1363 1362 return AE_BAD_PARAMETER; ··· 1870 1863 rv = acpi_os_map_generic_address(&acpi_gbl_FADT.reset_register); 1871 1864 pr_debug(PREFIX "%s: map reset_reg status %d\n", __func__, rv); 1872 1865 } 1866 + acpi_os_initialized = true; 1873 1867 1874 1868 return AE_OK; 1875 1869 }
+100 -36
drivers/acpi/sysfs.c
··· 70 70 ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT), 71 71 ACPI_DEBUG_INIT(ACPI_LV_INFO), 72 72 ACPI_DEBUG_INIT(ACPI_LV_REPAIR), 73 + ACPI_DEBUG_INIT(ACPI_LV_TRACE_POINT), 73 74 74 75 ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES), 75 76 ACPI_DEBUG_INIT(ACPI_LV_PARSE), ··· 164 163 module_param_cb(debug_layer, &param_ops_debug_layer, &acpi_dbg_layer, 0644); 165 164 module_param_cb(debug_level, &param_ops_debug_level, &acpi_dbg_level, 0644); 166 165 167 - static char trace_method_name[6]; 168 - module_param_string(trace_method_name, trace_method_name, 6, 0644); 169 - static unsigned int trace_debug_layer; 170 - module_param(trace_debug_layer, uint, 0644); 171 - static unsigned int trace_debug_level; 172 - module_param(trace_debug_level, uint, 0644); 166 + static char* trace_method_name; 167 + static bool trace_method_kmalloced; 168 + 169 + int param_set_trace_method_name(const char *val, const struct kernel_param *kp) 170 + { 171 + u32 saved_flags = 0; 172 + 173 + if (strlen(val) > 1024) { 174 + pr_err("%s: string parameter too long\n", kp->name); 175 + return -ENOSPC; 176 + } 177 + 178 + /* 179 + * It's not safe to update acpi_gbl_trace_method_name without 180 + * having the tracer stopped, so we save the original tracer 181 + * state and disable it. 182 + */ 183 + saved_flags = acpi_gbl_trace_flags; 184 + (void)acpi_debug_trace(NULL, 185 + acpi_gbl_trace_dbg_level, 186 + acpi_gbl_trace_dbg_layer, 187 + 0); 188 + 189 + if (trace_method_kmalloced) 190 + kfree(trace_method_name); 191 + trace_method_name = NULL; 192 + trace_method_kmalloced = false; 193 + 194 + /* This is a hack. We can't kmalloc in early boot. */ 195 + if (slab_is_available()) { 196 + trace_method_name = kstrdup(val, GFP_KERNEL); 197 + if (!trace_method_name) 198 + return -ENOMEM; 199 + trace_method_kmalloced = true; 200 + } else 201 + trace_method_name = (char *)val; 202 + 203 + /* Restore the original tracer state */ 204 + (void)acpi_debug_trace(trace_method_name, 205 + acpi_gbl_trace_dbg_level, 206 + acpi_gbl_trace_dbg_layer, 207 + saved_flags); 208 + 209 + return 0; 210 + } 211 + 212 + static int param_get_trace_method_name(char *buffer, const struct kernel_param *kp) 213 + { 214 + return scnprintf(buffer, PAGE_SIZE, "%s", acpi_gbl_trace_method_name); 215 + } 216 + 217 + static const struct kernel_param_ops param_ops_trace_method = { 218 + .set = param_set_trace_method_name, 219 + .get = param_get_trace_method_name, 220 + }; 221 + 222 + static const struct kernel_param_ops param_ops_trace_attrib = { 223 + .set = param_set_uint, 224 + .get = param_get_uint, 225 + }; 226 + 227 + module_param_cb(trace_method_name, &param_ops_trace_method, &trace_method_name, 0644); 228 + module_param_cb(trace_debug_layer, &param_ops_trace_attrib, &acpi_gbl_trace_dbg_layer, 0644); 229 + module_param_cb(trace_debug_level, &param_ops_trace_attrib, &acpi_gbl_trace_dbg_level, 0644); 173 230 174 231 static int param_set_trace_state(const char *val, struct kernel_param *kp) 175 232 { 176 - int result = 0; 233 + acpi_status status; 234 + const char *method = trace_method_name; 235 + u32 flags = 0; 177 236 178 - if (!strncmp(val, "enable", sizeof("enable") - 1)) { 179 - result = acpi_debug_trace(trace_method_name, trace_debug_level, 180 - trace_debug_layer, 0); 181 - if (result) 182 - result = -EBUSY; 183 - goto exit; 184 - } 237 + /* So "xxx-once" comparison should go prior than "xxx" comparison */ 238 + #define acpi_compare_param(val, key) \ 239 + strncmp((val), (key), sizeof(key) - 1) 185 240 186 - if (!strncmp(val, "disable", sizeof("disable") - 1)) { 187 - int name = 0; 188 - result = acpi_debug_trace((char *)&name, trace_debug_level, 189 - trace_debug_layer, 0); 190 - if (result) 191 - result = -EBUSY; 192 - goto exit; 193 - } 241 + if (!acpi_compare_param(val, "enable")) { 242 + method = NULL; 243 + flags = ACPI_TRACE_ENABLED; 244 + } else if (!acpi_compare_param(val, "disable")) 245 + method = NULL; 246 + else if (!acpi_compare_param(val, "method-once")) 247 + flags = ACPI_TRACE_ENABLED | ACPI_TRACE_ONESHOT; 248 + else if (!acpi_compare_param(val, "method")) 249 + flags = ACPI_TRACE_ENABLED; 250 + else if (!acpi_compare_param(val, "opcode-once")) 251 + flags = ACPI_TRACE_ENABLED | ACPI_TRACE_ONESHOT | ACPI_TRACE_OPCODE; 252 + else if (!acpi_compare_param(val, "opcode")) 253 + flags = ACPI_TRACE_ENABLED | ACPI_TRACE_OPCODE; 254 + else 255 + return -EINVAL; 194 256 195 - if (!strncmp(val, "1", 1)) { 196 - result = acpi_debug_trace(trace_method_name, trace_debug_level, 197 - trace_debug_layer, 1); 198 - if (result) 199 - result = -EBUSY; 200 - goto exit; 201 - } 257 + status = acpi_debug_trace(method, 258 + acpi_gbl_trace_dbg_level, 259 + acpi_gbl_trace_dbg_layer, 260 + flags); 261 + if (ACPI_FAILURE(status)) 262 + return -EBUSY; 202 263 203 - result = -EINVAL; 204 - exit: 205 - return result; 264 + return 0; 206 265 } 207 266 208 267 static int param_get_trace_state(char *buffer, struct kernel_param *kp) 209 268 { 210 - if (!acpi_gbl_trace_method_name) 269 + if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) 211 270 return sprintf(buffer, "disable"); 212 271 else { 213 - if (acpi_gbl_trace_flags & 1) 214 - return sprintf(buffer, "1"); 215 - else 272 + if (acpi_gbl_trace_method_name) { 273 + if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) 274 + return sprintf(buffer, "method-once"); 275 + else 276 + return sprintf(buffer, "method"); 277 + } else 216 278 return sprintf(buffer, "enable"); 217 279 } 218 280 return 0;