Commit 8cfb0cdf authored by Lv Zheng's avatar Lv Zheng Committed by Rafael J. Wysocki

ACPI / debugger: Add IO interface to access debugger functionalities

This patch adds /sys/kernel/debug/acpi/acpidbg, which can be used by
userspace programs to access ACPICA debugger functionalities.

Known issue:
1. IO flush support
   acpi_os_notify_command_complete() and acpi_os_wait_command_ready() can
   be used by acpi_dbg module to implement .flush() filesystem operation.
   While this patch doesn't go that far. It then becomes userspace tool's
   duty now to flush old commands before executing new batch mode commands.
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 8a2a2501
...@@ -58,8 +58,9 @@ config ACPI_CCA_REQUIRED ...@@ -58,8 +58,9 @@ config ACPI_CCA_REQUIRED
bool bool
config ACPI_DEBUGGER config ACPI_DEBUGGER
bool "AML debugger interface (EXPERIMENTAL)" bool "AML debugger interface"
select ACPI_DEBUG select ACPI_DEBUG
depends on DEBUG_FS
help help
Enable in-kernel debugging of AML facilities: statistics, internal Enable in-kernel debugging of AML facilities: statistics, internal
object dump, single step control method execution. object dump, single step control method execution.
......
...@@ -50,6 +50,7 @@ acpi-y += sysfs.o ...@@ -50,6 +50,7 @@ acpi-y += sysfs.o
acpi-y += property.o acpi-y += property.o
acpi-$(CONFIG_X86) += acpi_cmos_rtc.o acpi-$(CONFIG_X86) += acpi_cmos_rtc.o
acpi-$(CONFIG_DEBUG_FS) += debugfs.o acpi-$(CONFIG_DEBUG_FS) += debugfs.o
acpi-$(CONFIG_ACPI_DEBUGGER) += acpi_dbg.o
acpi-$(CONFIG_ACPI_NUMA) += numa.o acpi-$(CONFIG_ACPI_NUMA) += numa.o
acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
acpi-y += acpi_lpat.o acpi-y += acpi_lpat.o
......
This diff is collapsed.
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <acpi/apei.h> #include <acpi/apei.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/acpi_dbg.h>
#include "internal.h" #include "internal.h"
...@@ -1094,6 +1095,7 @@ static int __init acpi_init(void) ...@@ -1094,6 +1095,7 @@ static int __init acpi_init(void)
acpi_debugfs_init(); acpi_debugfs_init();
acpi_sleep_proc_init(); acpi_sleep_proc_init();
acpi_wakeup_device_init(); acpi_wakeup_device_init();
acpi_aml_init();
return 0; return 0;
} }
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/semaphore.h> #include <linux/semaphore.h>
#include <linux/acpi_dbg.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -234,7 +235,8 @@ void acpi_os_vprintf(const char *fmt, va_list args) ...@@ -234,7 +235,8 @@ void acpi_os_vprintf(const char *fmt, va_list args)
printk(KERN_CONT "%s", buffer); printk(KERN_CONT "%s", buffer);
} }
#else #else
printk(KERN_CONT "%s", buffer); if (acpi_aml_write_log(buffer) < 0)
printk(KERN_CONT "%s", buffer);
#endif #endif
} }
...@@ -1127,6 +1129,15 @@ acpi_status acpi_os_execute(acpi_execute_type type, ...@@ -1127,6 +1129,15 @@ acpi_status acpi_os_execute(acpi_execute_type type,
"Scheduling function [%p(%p)] for deferred execution.\n", "Scheduling function [%p(%p)] for deferred execution.\n",
function, context)); function, context));
if (type == OSL_DEBUGGER_MAIN_THREAD) {
ret = acpi_aml_create_thread(function, context);
if (ret) {
pr_err("Call to kthread_create() failed.\n");
status = AE_ERROR;
}
goto out_thread;
}
/* /*
* Allocate/initialize DPC structure. Note that this memory will be * Allocate/initialize DPC structure. Note that this memory will be
* freed by the callee. The kernel handles the work_struct list in a * freed by the callee. The kernel handles the work_struct list in a
...@@ -1151,11 +1162,17 @@ acpi_status acpi_os_execute(acpi_execute_type type, ...@@ -1151,11 +1162,17 @@ acpi_status acpi_os_execute(acpi_execute_type type,
if (type == OSL_NOTIFY_HANDLER) { if (type == OSL_NOTIFY_HANDLER) {
queue = kacpi_notify_wq; queue = kacpi_notify_wq;
INIT_WORK(&dpc->work, acpi_os_execute_deferred); INIT_WORK(&dpc->work, acpi_os_execute_deferred);
} else { } else if (type == OSL_GPE_HANDLER) {
queue = kacpid_wq; queue = kacpid_wq;
INIT_WORK(&dpc->work, acpi_os_execute_deferred); INIT_WORK(&dpc->work, acpi_os_execute_deferred);
} else {
pr_err("Unsupported os_execute type %d.\n", type);
status = AE_ERROR;
} }
if (ACPI_FAILURE(status))
goto err_workqueue;
/* /*
* On some machines, a software-initiated SMI causes corruption unless * On some machines, a software-initiated SMI causes corruption unless
* the SMI runs on CPU 0. An SMI can be initiated by any AML, but * the SMI runs on CPU 0. An SMI can be initiated by any AML, but
...@@ -1164,13 +1181,15 @@ acpi_status acpi_os_execute(acpi_execute_type type, ...@@ -1164,13 +1181,15 @@ acpi_status acpi_os_execute(acpi_execute_type type,
* queueing on CPU 0. * queueing on CPU 0.
*/ */
ret = queue_work_on(0, queue, &dpc->work); ret = queue_work_on(0, queue, &dpc->work);
if (!ret) { if (!ret) {
printk(KERN_ERR PREFIX printk(KERN_ERR PREFIX
"Call to queue_work() failed.\n"); "Call to queue_work() failed.\n");
status = AE_ERROR; status = AE_ERROR;
kfree(dpc);
} }
err_workqueue:
if (ACPI_FAILURE(status))
kfree(dpc);
out_thread:
return status; return status;
} }
EXPORT_SYMBOL(acpi_os_execute); EXPORT_SYMBOL(acpi_os_execute);
...@@ -1358,11 +1377,39 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read) ...@@ -1358,11 +1377,39 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read)
chars = strlen(buffer) - 1; chars = strlen(buffer) - 1;
buffer[chars] = '\0'; buffer[chars] = '\0';
} }
#else
int ret;
ret = acpi_aml_read_cmd(buffer, buffer_length);
if (ret < 0)
return AE_ERROR;
if (bytes_read)
*bytes_read = ret;
#endif #endif
return AE_OK; return AE_OK;
} }
acpi_status acpi_os_wait_command_ready(void)
{
int ret;
ret = acpi_aml_wait_command_ready();
if (ret < 0)
return AE_ERROR;
return AE_OK;
}
acpi_status acpi_os_notify_command_complete(void)
{
int ret;
ret = acpi_aml_notify_command_complete();
if (ret < 0)
return AE_ERROR;
return AE_OK;
}
acpi_status acpi_os_signal(u32 function, void *info) acpi_status acpi_os_signal(u32 function, void *info)
{ {
switch (function) { switch (function) {
......
...@@ -152,8 +152,6 @@ ...@@ -152,8 +152,6 @@
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_writable #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_writable
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize_command_signals #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize_command_signals
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate_command_signals #define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate_command_signals
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_command_ready
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_notify_command_complete
/* /*
* OSL interfaces used by utilities * OSL interfaces used by utilities
......
...@@ -138,16 +138,6 @@ static inline void acpi_os_terminate_command_signals(void) ...@@ -138,16 +138,6 @@ static inline void acpi_os_terminate_command_signals(void)
{ {
} }
static inline acpi_status acpi_os_wait_command_ready(void)
{
return AE_ERROR;
}
static inline acpi_status acpi_os_notify_command_complete(void)
{
return AE_ERROR;
}
/* /*
* OSL interfaces added by Linux * OSL interfaces added by Linux
*/ */
......
/*
* ACPI AML interfacing support
*
* Copyright (C) 2015, Intel Corporation
* Authors: Lv Zheng <lv.zheng@intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _LINUX_ACPI_DBG_H
#define _LINUX_ACPI_DBG_H
#include <linux/acpi.h>
#ifdef CONFIG_ACPI_DEBUGGER
int __init acpi_aml_init(void);
int acpi_aml_create_thread(acpi_osd_exec_callback function, void *context);
ssize_t acpi_aml_write_log(const char *msg);
ssize_t acpi_aml_read_cmd(char *buffer, size_t buffer_length);
int acpi_aml_wait_command_ready(void);
int acpi_aml_notify_command_complete(void);
#else
static int inline acpi_aml_init(void)
{
return 0;
}
static inline int acpi_aml_create_thread(acpi_osd_exec_callback function,
void *context)
{
return -ENODEV;
}
static inline int acpi_aml_write_log(const char *msg)
{
return -ENODEV;
}
static inline int acpi_aml_read_cmd(char *buffer, u32 buffer_length)
{
return -ENODEV;
}
static inline int acpi_aml_wait_command_ready(void)
{
return -ENODEV;
}
static inline int acpi_aml_notify_command_complete(void)
{
return -ENODEV;
}
#endif
#endif /* _LINUX_ACPI_DBG_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment