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