diff options
-rw-r--r-- | drivers/acpi/osl.c | 8 | ||||
-rw-r--r-- | drivers/acpi/sysfs.c | 136 |
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; | |||
83 | static struct workqueue_struct *kacpid_wq; | 83 | static struct workqueue_struct *kacpid_wq; |
84 | static struct workqueue_struct *kacpi_notify_wq; | 84 | static struct workqueue_struct *kacpi_notify_wq; |
85 | static struct workqueue_struct *kacpi_hotplug_wq; | 85 | static struct workqueue_struct *kacpi_hotplug_wq; |
86 | static 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 = { | |||
163 | module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644); | 164 | module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644); |
164 | module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644); | 165 | module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644); |
165 | 166 | ||
166 | static char trace_method_name[6]; | 167 | static char* trace_method_name; |
167 | module_param_string(trace_method_name, trace_method_name, 6, 0644); | 168 | static bool trace_method_kmalloced; |
168 | static unsigned int trace_debug_layer; | ||
169 | module_param(trace_debug_layer, uint, 0644); | ||
170 | static unsigned int trace_debug_level; | ||
171 | module_param(trace_debug_level, uint, 0644); | ||
172 | 169 | ||
173 | static int param_set_trace_state(const char *val, struct kernel_param *kp) | 170 | int 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; |
203 | exit: | 211 | } |
204 | return result; | 212 | |
213 | static 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 | |||
218 | static 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 | |||
223 | static const struct kernel_param_ops param_ops_trace_attrib = { | ||
224 | .set = param_set_uint, | ||
225 | .get = param_get_uint, | ||
226 | }; | ||
227 | |||
228 | module_param_cb(trace_method_name, ¶m_ops_trace_method, &trace_method_name, 0644); | ||
229 | module_param_cb(trace_debug_layer, ¶m_ops_trace_attrib, &acpi_gbl_trace_dbg_layer, 0644); | ||
230 | module_param_cb(trace_debug_level, ¶m_ops_trace_attrib, &acpi_gbl_trace_dbg_level, 0644); | ||
231 | |||
232 | static 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 | ||
207 | static int param_get_trace_state(char *buffer, struct kernel_param *kp) | 268 | static 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; |