aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorZhang Rui <rui.zhang@intel.com>2009-12-02 00:31:00 -0500
committerLen Brown <len.brown@intel.com>2009-12-11 01:50:08 -0500
commita1a541d86f50a9957beeedb122a035870d602647 (patch)
treebc3bd16c6d1bbb8c1fcc561a436b2c322ec098d4 /drivers/acpi
parent22763c5cf3690a681551162c15d34d935308c8d7 (diff)
ACPI: support customizing ACPI control methods at runtime
Introduce a new debugfs I/F (/sys/kernel/debug/acpi/custom_method) for ACPI, which can be used to customize the ACPI control methods at runtime. We can use this to debug the AML code level bugs instead of overriding the whole DSDT table, without rebuilding/rebooting kernel any more. Detailed description about how to use this debugfs I/F is stated in Documentation/acpi/method-customizing.txt Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/debug.c83
1 files changed, 82 insertions, 1 deletions
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index 8a690c3b8e23..0bedd1554f2f 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -8,6 +8,7 @@
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10#include <linux/moduleparam.h> 10#include <linux/moduleparam.h>
11#include <linux/debugfs.h>
11#include <asm/uaccess.h> 12#include <asm/uaccess.h>
12#include <acpi/acpi_drivers.h> 13#include <acpi/acpi_drivers.h>
13 14
@@ -196,6 +197,79 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
196 NULL, 0644); 197 NULL, 0644);
197 198
198/* -------------------------------------------------------------------------- 199/* --------------------------------------------------------------------------
200 DebugFS Interface
201 -------------------------------------------------------------------------- */
202
203static ssize_t cm_write(struct file *file, const char __user *user_buf,
204 size_t count, loff_t *ppos)
205{
206 static char *buf;
207 static int uncopied_bytes;
208 struct acpi_table_header table;
209 acpi_status status;
210
211 if (!(*ppos)) {
212 /* parse the table header to get the table length */
213 if (count <= sizeof(struct acpi_table_header))
214 return -EINVAL;
215 if (copy_from_user(&table, user_buf,
216 sizeof(struct acpi_table_header)))
217 return -EFAULT;
218 uncopied_bytes = table.length;
219 buf = kzalloc(uncopied_bytes, GFP_KERNEL);
220 if (!buf)
221 return -ENOMEM;
222 }
223
224 if (uncopied_bytes < count) {
225 kfree(buf);
226 return -EINVAL;
227 }
228
229 if (copy_from_user(buf + (*ppos), user_buf, count)) {
230 kfree(buf);
231 return -EFAULT;
232 }
233
234 uncopied_bytes -= count;
235 *ppos += count;
236
237 if (!uncopied_bytes) {
238 status = acpi_install_method(buf);
239 kfree(buf);
240 if (ACPI_FAILURE(status))
241 return -EINVAL;
242 }
243
244 return count;
245}
246
247static const struct file_operations cm_fops = {
248 .write = cm_write,
249};
250
251static int acpi_debugfs_init(void)
252{
253 struct dentry *acpi_dir, *cm_dentry;
254
255 acpi_dir = debugfs_create_dir("acpi", NULL);
256 if (!acpi_dir)
257 goto err;
258
259 cm_dentry = debugfs_create_file("custom_method", S_IWUGO,
260 acpi_dir, NULL, &cm_fops);
261 if (!cm_dentry)
262 goto err;
263
264 return 0;
265
266err:
267 if (acpi_dir)
268 debugfs_remove(acpi_dir);
269 return -EINVAL;
270}
271
272/* --------------------------------------------------------------------------
199 FS Interface (/proc) 273 FS Interface (/proc)
200 -------------------------------------------------------------------------- */ 274 -------------------------------------------------------------------------- */
201#ifdef CONFIG_ACPI_PROCFS 275#ifdef CONFIG_ACPI_PROCFS
@@ -286,7 +360,7 @@ static const struct file_operations acpi_system_debug_proc_fops = {
286}; 360};
287#endif 361#endif
288 362
289int __init acpi_debug_init(void) 363int __init acpi_procfs_init(void)
290{ 364{
291#ifdef CONFIG_ACPI_PROCFS 365#ifdef CONFIG_ACPI_PROCFS
292 struct proc_dir_entry *entry; 366 struct proc_dir_entry *entry;
@@ -321,3 +395,10 @@ int __init acpi_debug_init(void)
321 return 0; 395 return 0;
322#endif 396#endif
323} 397}
398
399int __init acpi_debug_init(void)
400{
401 acpi_debugfs_init();
402 acpi_procfs_init();
403 return 0;
404}