Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
b17629db
Commit
b17629db
authored
Jan 01, 2016
by
Rafael J. Wysocki
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'acpi-debug' into acpica
parents
74bf8efb
59adb398
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1793 additions
and
211 deletions
+1793
-211
drivers/acpi/Kconfig
drivers/acpi/Kconfig
+14
-3
drivers/acpi/Makefile
drivers/acpi/Makefile
+1
-0
drivers/acpi/acpi_dbg.c
drivers/acpi/acpi_dbg.c
+804
-0
drivers/acpi/acpica/acdebug.h
drivers/acpi/acpica/acdebug.h
+25
-11
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/acglobal.h
+0
-5
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/acmacros.h
+0
-11
drivers/acpi/acpica/dbdisply.c
drivers/acpi/acpica/dbdisply.c
+12
-0
drivers/acpi/acpica/dbinput.c
drivers/acpi/acpica/dbinput.c
+19
-81
drivers/acpi/acpica/dbxface.c
drivers/acpi/acpica/dbxface.c
+48
-45
drivers/acpi/acpica/dscontrol.c
drivers/acpi/acpica/dscontrol.c
+2
-8
drivers/acpi/acpica/dsutils.c
drivers/acpi/acpica/dsutils.c
+8
-8
drivers/acpi/acpica/dswexec.c
drivers/acpi/acpica/dswexec.c
+7
-9
drivers/acpi/acpica/utmutex.c
drivers/acpi/acpica/utmutex.c
+0
-17
drivers/acpi/bus.c
drivers/acpi/bus.c
+1
-0
drivers/acpi/osl.c
drivers/acpi/osl.c
+246
-4
include/acpi/acpiosxf.h
include/acpi/acpiosxf.h
+17
-1
include/acpi/acpixf.h
include/acpi/acpixf.h
+34
-0
include/acpi/platform/aclinux.h
include/acpi/platform/aclinux.h
+2
-0
include/acpi/platform/aclinuxex.h
include/acpi/platform/aclinuxex.h
+9
-0
include/linux/acpi.h
include/linux/acpi.h
+71
-0
tools/power/acpi/Makefile
tools/power/acpi/Makefile
+8
-8
tools/power/acpi/tools/acpidbg/Makefile
tools/power/acpi/tools/acpidbg/Makefile
+27
-0
tools/power/acpi/tools/acpidbg/acpidbg.c
tools/power/acpi/tools/acpidbg/acpidbg.c
+438
-0
No files found.
drivers/acpi/Kconfig
View file @
b17629db
...
...
@@ -58,14 +58,25 @@ config ACPI_CCA_REQUIRED
bool
config ACPI_DEBUGGER
bool "AML debugger interface
(EXPERIMENTAL)
"
bool "AML debugger interface"
select ACPI_DEBUG
help
Enable in-kernel debugging of AML facilities: statistics,
internal
object dump, single step control method execution.
Enable in-kernel debugging of AML facilities: statistics,
internal
object dump, single step control method execution.
This is still under development, currently enabling this only
results in the compilation of the ACPICA debugger files.
if ACPI_DEBUGGER
config ACPI_DEBUGGER_USER
tristate "Userspace debugger accessiblity"
depends on DEBUG_FS
help
Export /sys/kernel/debug/acpi/acpidbg for userspace utilities
to access the debugger functionalities.
endif
config ACPI_SLEEP
bool
depends on SUSPEND || HIBERNATION
...
...
drivers/acpi/Makefile
View file @
b17629db
...
...
@@ -79,6 +79,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)
+=
custom_method.o
obj-$(CONFIG_ACPI_BGRT)
+=
bgrt.o
obj-$(CONFIG_ACPI_CPPC_LIB)
+=
cppc_acpi.o
obj-$(CONFIG_ACPI_DEBUGGER_USER)
+=
acpi_dbg.o
# processor has its own "processor." module_param namespace
processor-y
:=
processor_driver.o
...
...
drivers/acpi/acpi_dbg.c
0 → 100644
View file @
b17629db
/*
* 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.
*/
/* #define DEBUG */
#define pr_fmt(fmt) "ACPI : AML: " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/proc_fs.h>
#include <linux/debugfs.h>
#include <linux/circ_buf.h>
#include <linux/acpi.h>
#include "internal.h"
#define ACPI_AML_BUF_ALIGN (sizeof (acpi_size))
#define ACPI_AML_BUF_SIZE PAGE_SIZE
#define circ_count(circ) \
(CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
#define circ_count_to_end(circ) \
(CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
#define circ_space(circ) \
(CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
#define circ_space_to_end(circ) \
(CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
#define ACPI_AML_OPENED 0x0001
#define ACPI_AML_CLOSED 0x0002
#define ACPI_AML_IN_USER 0x0004
/* user space is writing cmd */
#define ACPI_AML_IN_KERN 0x0008
/* kernel space is reading cmd */
#define ACPI_AML_OUT_USER 0x0010
/* user space is reading log */
#define ACPI_AML_OUT_KERN 0x0020
/* kernel space is writing log */
#define ACPI_AML_USER (ACPI_AML_IN_USER | ACPI_AML_OUT_USER)
#define ACPI_AML_KERN (ACPI_AML_IN_KERN | ACPI_AML_OUT_KERN)
#define ACPI_AML_BUSY (ACPI_AML_USER | ACPI_AML_KERN)
#define ACPI_AML_OPEN (ACPI_AML_OPENED | ACPI_AML_CLOSED)
struct
acpi_aml_io
{
wait_queue_head_t
wait
;
unsigned
long
flags
;
unsigned
long
users
;
struct
mutex
lock
;
struct
task_struct
*
thread
;
char
out_buf
[
ACPI_AML_BUF_SIZE
]
__aligned
(
ACPI_AML_BUF_ALIGN
);
struct
circ_buf
out_crc
;
char
in_buf
[
ACPI_AML_BUF_SIZE
]
__aligned
(
ACPI_AML_BUF_ALIGN
);
struct
circ_buf
in_crc
;
acpi_osd_exec_callback
function
;
void
*
context
;
unsigned
long
usages
;
};
static
struct
acpi_aml_io
acpi_aml_io
;
static
bool
acpi_aml_initialized
;
static
struct
file
*
acpi_aml_active_reader
;
static
struct
dentry
*
acpi_aml_dentry
;
static
inline
bool
__acpi_aml_running
(
void
)
{
return
acpi_aml_io
.
thread
?
true
:
false
;
}
static
inline
bool
__acpi_aml_access_ok
(
unsigned
long
flag
)
{
/*
* The debugger interface is in opened state (OPENED && !CLOSED),
* then it is allowed to access the debugger buffers from either
* user space or the kernel space.
* In addition, for the kernel space, only the debugger thread
* (thread ID matched) is allowed to access.
*/
if
(
!
(
acpi_aml_io
.
flags
&
ACPI_AML_OPENED
)
||
(
acpi_aml_io
.
flags
&
ACPI_AML_CLOSED
)
||
!
__acpi_aml_running
())
return
false
;
if
((
flag
&
ACPI_AML_KERN
)
&&
current
!=
acpi_aml_io
.
thread
)
return
false
;
return
true
;
}
static
inline
bool
__acpi_aml_readable
(
struct
circ_buf
*
circ
,
unsigned
long
flag
)
{
/*
* Another read is not in progress and there is data in buffer
* available for read.
*/
if
(
!
(
acpi_aml_io
.
flags
&
flag
)
&&
circ_count
(
circ
))
return
true
;
return
false
;
}
static
inline
bool
__acpi_aml_writable
(
struct
circ_buf
*
circ
,
unsigned
long
flag
)
{
/*
* Another write is not in progress and there is buffer space
* available for write.
*/
if
(
!
(
acpi_aml_io
.
flags
&
flag
)
&&
circ_space
(
circ
))
return
true
;
return
false
;
}
static
inline
bool
__acpi_aml_busy
(
void
)
{
if
(
acpi_aml_io
.
flags
&
ACPI_AML_BUSY
)
return
true
;
return
false
;
}
static
inline
bool
__acpi_aml_opened
(
void
)
{
if
(
acpi_aml_io
.
flags
&
ACPI_AML_OPEN
)
return
true
;
return
false
;
}
static
inline
bool
__acpi_aml_used
(
void
)
{
return
acpi_aml_io
.
usages
?
true
:
false
;
}
static
inline
bool
acpi_aml_running
(
void
)
{
bool
ret
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
ret
=
__acpi_aml_running
();
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
bool
acpi_aml_busy
(
void
)
{
bool
ret
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
ret
=
__acpi_aml_busy
();
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
bool
acpi_aml_used
(
void
)
{
bool
ret
;
/*
* The usage count is prepared to avoid race conditions between the
* starts and the stops of the debugger thread.
*/
mutex_lock
(
&
acpi_aml_io
.
lock
);
ret
=
__acpi_aml_used
();
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
bool
acpi_aml_kern_readable
(
void
)
{
bool
ret
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
ret
=
!
__acpi_aml_access_ok
(
ACPI_AML_IN_KERN
)
||
__acpi_aml_readable
(
&
acpi_aml_io
.
in_crc
,
ACPI_AML_IN_KERN
);
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
bool
acpi_aml_kern_writable
(
void
)
{
bool
ret
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
ret
=
!
__acpi_aml_access_ok
(
ACPI_AML_OUT_KERN
)
||
__acpi_aml_writable
(
&
acpi_aml_io
.
out_crc
,
ACPI_AML_OUT_KERN
);
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
bool
acpi_aml_user_readable
(
void
)
{
bool
ret
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
ret
=
!
__acpi_aml_access_ok
(
ACPI_AML_OUT_USER
)
||
__acpi_aml_readable
(
&
acpi_aml_io
.
out_crc
,
ACPI_AML_OUT_USER
);
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
bool
acpi_aml_user_writable
(
void
)
{
bool
ret
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
ret
=
!
__acpi_aml_access_ok
(
ACPI_AML_IN_USER
)
||
__acpi_aml_writable
(
&
acpi_aml_io
.
in_crc
,
ACPI_AML_IN_USER
);
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
int
acpi_aml_lock_write
(
struct
circ_buf
*
circ
,
unsigned
long
flag
)
{
int
ret
=
0
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
if
(
!
__acpi_aml_access_ok
(
flag
))
{
ret
=
-
EFAULT
;
goto
out
;
}
if
(
!
__acpi_aml_writable
(
circ
,
flag
))
{
ret
=
-
EAGAIN
;
goto
out
;
}
acpi_aml_io
.
flags
|=
flag
;
out:
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
int
acpi_aml_lock_read
(
struct
circ_buf
*
circ
,
unsigned
long
flag
)
{
int
ret
=
0
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
if
(
!
__acpi_aml_access_ok
(
flag
))
{
ret
=
-
EFAULT
;
goto
out
;
}
if
(
!
__acpi_aml_readable
(
circ
,
flag
))
{
ret
=
-
EAGAIN
;
goto
out
;
}
acpi_aml_io
.
flags
|=
flag
;
out:
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
ret
;
}
static
void
acpi_aml_unlock_fifo
(
unsigned
long
flag
,
bool
wakeup
)
{
mutex_lock
(
&
acpi_aml_io
.
lock
);
acpi_aml_io
.
flags
&=
~
flag
;
if
(
wakeup
)
wake_up_interruptible
(
&
acpi_aml_io
.
wait
);
mutex_unlock
(
&
acpi_aml_io
.
lock
);
}
static
int
acpi_aml_write_kern
(
const
char
*
buf
,
int
len
)
{
int
ret
;
struct
circ_buf
*
crc
=
&
acpi_aml_io
.
out_crc
;
int
n
;
char
*
p
;
ret
=
acpi_aml_lock_write
(
crc
,
ACPI_AML_OUT_KERN
);
if
(
IS_ERR_VALUE
(
ret
))
return
ret
;
/* sync tail before inserting logs */
smp_mb
();
p
=
&
crc
->
buf
[
crc
->
head
];
n
=
min
(
len
,
circ_space_to_end
(
crc
));
memcpy
(
p
,
buf
,
n
);
/* sync head after inserting logs */
smp_wmb
();
crc
->
head
=
(
crc
->
head
+
n
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
acpi_aml_unlock_fifo
(
ACPI_AML_OUT_KERN
,
true
);
return
n
;
}
static
int
acpi_aml_readb_kern
(
void
)
{
int
ret
;
struct
circ_buf
*
crc
=
&
acpi_aml_io
.
in_crc
;
char
*
p
;
ret
=
acpi_aml_lock_read
(
crc
,
ACPI_AML_IN_KERN
);
if
(
IS_ERR_VALUE
(
ret
))
return
ret
;
/* sync head before removing cmds */
smp_rmb
();
p
=
&
crc
->
buf
[
crc
->
tail
];
ret
=
(
int
)
*
p
;
/* sync tail before inserting cmds */
smp_mb
();
crc
->
tail
=
(
crc
->
tail
+
1
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
acpi_aml_unlock_fifo
(
ACPI_AML_IN_KERN
,
true
);
return
ret
;
}
/*
* acpi_aml_write_log() - Capture debugger output
* @msg: the debugger output
*
* This function should be used to implement acpi_os_printf() to filter out
* the debugger output and store the output into the debugger interface
* buffer. Return the size of stored logs or errno.
*/
static
ssize_t
acpi_aml_write_log
(
const
char
*
msg
)
{
int
ret
=
0
;
int
count
=
0
,
size
=
0
;
if
(
!
acpi_aml_initialized
)
return
-
ENODEV
;
if
(
msg
)
count
=
strlen
(
msg
);
while
(
count
>
0
)
{
again:
ret
=
acpi_aml_write_kern
(
msg
+
size
,
count
);
if
(
ret
==
-
EAGAIN
)
{
ret
=
wait_event_interruptible
(
acpi_aml_io
.
wait
,
acpi_aml_kern_writable
());
/*
* We need to retry when the condition
* becomes true.
*/
if
(
ret
==
0
)
goto
again
;
break
;
}
if
(
IS_ERR_VALUE
(
ret
))
break
;
size
+=
ret
;
count
-=
ret
;
}
return
size
>
0
?
size
:
ret
;
}
/*
* acpi_aml_read_cmd() - Capture debugger input
* @msg: the debugger input
* @size: the size of the debugger input
*
* This function should be used to implement acpi_os_get_line() to capture
* the debugger input commands and store the input commands into the
* debugger interface buffer. Return the size of stored commands or errno.
*/
static
ssize_t
acpi_aml_read_cmd
(
char
*
msg
,
size_t
count
)
{
int
ret
=
0
;
int
size
=
0
;
/*
* This is ensured by the running fact of the debugger thread
* unless a bug is introduced.
*/
BUG_ON
(
!
acpi_aml_initialized
);
while
(
count
>
0
)
{
again:
/*
* Check each input byte to find the end of the command.
*/
ret
=
acpi_aml_readb_kern
();
if
(
ret
==
-
EAGAIN
)
{
ret
=
wait_event_interruptible
(
acpi_aml_io
.
wait
,
acpi_aml_kern_readable
());
/*
* We need to retry when the condition becomes
* true.
*/
if
(
ret
==
0
)
goto
again
;
}
if
(
IS_ERR_VALUE
(
ret
))
break
;
*
(
msg
+
size
)
=
(
char
)
ret
;
size
++
;
count
--
;
if
(
ret
==
'\n'
)
{
/*
* acpi_os_get_line() requires a zero terminated command
* string.
*/
*
(
msg
+
size
-
1
)
=
'\0'
;
break
;
}
}
return
size
>
0
?
size
:
ret
;
}
static
int
acpi_aml_thread
(
void
*
unsed
)
{
acpi_osd_exec_callback
function
=
NULL
;
void
*
context
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
if
(
acpi_aml_io
.
function
)
{
acpi_aml_io
.
usages
++
;
function
=
acpi_aml_io
.
function
;
context
=
acpi_aml_io
.
context
;
}
mutex_unlock
(
&
acpi_aml_io
.
lock
);
if
(
function
)
function
(
context
);
mutex_lock
(
&
acpi_aml_io
.
lock
);
acpi_aml_io
.
usages
--
;
if
(
!
__acpi_aml_used
())
{
acpi_aml_io
.
thread
=
NULL
;
wake_up
(
&
acpi_aml_io
.
wait
);
}
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
0
;
}
/*
* acpi_aml_create_thread() - Create AML debugger thread
* @function: the debugger thread callback
* @context: the context to be passed to the debugger thread
*
* This function should be used to implement acpi_os_execute() which is
* used by the ACPICA debugger to create the debugger thread.
*/
static
int
acpi_aml_create_thread
(
acpi_osd_exec_callback
function
,
void
*
context
)
{
struct
task_struct
*
t
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
acpi_aml_io
.
function
=
function
;
acpi_aml_io
.
context
=
context
;
mutex_unlock
(
&
acpi_aml_io
.
lock
);
t
=
kthread_create
(
acpi_aml_thread
,
NULL
,
"aml"
);
if
(
IS_ERR
(
t
))
{
pr_err
(
"Failed to create AML debugger thread.
\n
"
);
return
PTR_ERR
(
t
);
}
mutex_lock
(
&
acpi_aml_io
.
lock
);
acpi_aml_io
.
thread
=
t
;
acpi_set_debugger_thread_id
((
acpi_thread_id
)(
unsigned
long
)
t
);
wake_up_process
(
t
);
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
0
;
}
static
int
acpi_aml_wait_command_ready
(
bool
single_step
,
char
*
buffer
,
size_t
length
)
{
acpi_status
status
;
if
(
single_step
)
acpi_os_printf
(
"
\n
%1c "
,
ACPI_DEBUGGER_EXECUTE_PROMPT
);
else
acpi_os_printf
(
"
\n
%1c "
,
ACPI_DEBUGGER_COMMAND_PROMPT
);
status
=
acpi_os_get_line
(
buffer
,
length
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
return
-
EINVAL
;
return
0
;
}
static
int
acpi_aml_notify_command_complete
(
void
)
{
return
0
;
}
static
int
acpi_aml_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
ret
=
0
;
acpi_status
status
;
mutex_lock
(
&
acpi_aml_io
.
lock
);
/*
* The debugger interface is being closed, no new user is allowed
* during this period.
*/
if
(
acpi_aml_io
.
flags
&
ACPI_AML_CLOSED
)
{
ret
=
-
EBUSY
;
goto
err_lock
;
}
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_WRONLY
)
{
/*
* Only one reader is allowed to initiate the debugger
* thread.
*/
if
(
acpi_aml_active_reader
)
{
ret
=
-
EBUSY
;
goto
err_lock
;
}
else
{
pr_debug
(
"Opening debugger reader.
\n
"
);
acpi_aml_active_reader
=
file
;
}
}
else
{
/*
* No writer is allowed unless the debugger thread is
* ready.
*/
if
(
!
(
acpi_aml_io
.
flags
&
ACPI_AML_OPENED
))
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
}
if
(
acpi_aml_active_reader
==
file
)
{
pr_debug
(
"Opening debugger interface.
\n
"
);
mutex_unlock
(
&
acpi_aml_io
.
lock
);
pr_debug
(
"Initializing debugger thread.
\n
"
);
status
=
acpi_initialize_debugger
();
if
(
ACPI_FAILURE
(
status
))
{
pr_err
(
"Failed to initialize debugger.
\n
"
);
ret
=
-
EINVAL
;
goto
err_exit
;
}
pr_debug
(
"Debugger thread initialized.
\n
"
);
mutex_lock
(
&
acpi_aml_io
.
lock
);
acpi_aml_io
.
flags
|=
ACPI_AML_OPENED
;
acpi_aml_io
.
out_crc
.
head
=
acpi_aml_io
.
out_crc
.
tail
=
0
;
acpi_aml_io
.
in_crc
.
head
=
acpi_aml_io
.
in_crc
.
tail
=
0
;
pr_debug
(
"Debugger interface opened.
\n
"
);
}
acpi_aml_io
.
users
++
;
err_lock:
if
(
IS_ERR_VALUE
(
ret
))
{
if
(
acpi_aml_active_reader
==
file
)
acpi_aml_active_reader
=
NULL
;
}
mutex_unlock
(
&
acpi_aml_io
.
lock
);
err_exit:
return
ret
;
}
static
int
acpi_aml_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
mutex_lock
(
&
acpi_aml_io
.
lock
);
acpi_aml_io
.
users
--
;
if
(
file
==
acpi_aml_active_reader
)
{
pr_debug
(
"Closing debugger reader.
\n
"
);
acpi_aml_active_reader
=
NULL
;
pr_debug
(
"Closing debugger interface.
\n
"
);
acpi_aml_io
.
flags
|=
ACPI_AML_CLOSED
;
/*
* Wake up all user space/kernel space blocked
* readers/writers.
*/
wake_up_interruptible
(
&
acpi_aml_io
.
wait
);
mutex_unlock
(
&
acpi_aml_io
.
lock
);
/*
* Wait all user space/kernel space readers/writers to
* stop so that ACPICA command loop of the debugger thread
* should fail all its command line reads after this point.
*/
wait_event
(
acpi_aml_io
.
wait
,
!
acpi_aml_busy
());
/*
* Then we try to terminate the debugger thread if it is
* not terminated.
*/
pr_debug
(
"Terminating debugger thread.
\n
"
);
acpi_terminate_debugger
();
wait_event
(
acpi_aml_io
.
wait
,
!
acpi_aml_used
());
pr_debug
(
"Debugger thread terminated.
\n
"
);
mutex_lock
(
&
acpi_aml_io
.
lock
);
acpi_aml_io
.
flags
&=
~
ACPI_AML_OPENED
;
}
if
(
acpi_aml_io
.
users
==
0
)
{
pr_debug
(
"Debugger interface closed.
\n
"
);
acpi_aml_io
.
flags
&=
~
ACPI_AML_CLOSED
;
}
mutex_unlock
(
&
acpi_aml_io
.
lock
);
return
0
;
}
static
int
acpi_aml_read_user
(
char
__user
*
buf
,
int
len
)
{
int
ret
;
struct
circ_buf
*
crc
=
&
acpi_aml_io
.
out_crc
;
int
n
;
char
*
p
;
ret
=
acpi_aml_lock_read
(
crc
,
ACPI_AML_OUT_USER
);
if
(
IS_ERR_VALUE
(
ret
))
return
ret
;
/* sync head before removing logs */
smp_rmb
();
p
=
&
crc
->
buf
[
crc
->
tail
];
n
=
min
(
len
,
circ_count_to_end
(
crc
));
if
(
copy_to_user
(
buf
,
p
,
n
))
{
ret
=
-
EFAULT
;
goto
out
;
}
/* sync tail after removing logs */
smp_mb
();
crc
->
tail
=
(
crc
->
tail
+
n
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
ret
=
n
;
out:
acpi_aml_unlock_fifo
(
ACPI_AML_OUT_USER
,
!
IS_ERR_VALUE
(
ret
));
return
ret
;
}
static
ssize_t
acpi_aml_read
(
struct
file
*
file
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
int
ret
=
0
;
int
size
=
0
;
if
(
!
count
)
return
0
;
if
(
!
access_ok
(
VERIFY_WRITE
,
buf
,
count
))
return
-
EFAULT
;
while
(
count
>
0
)
{
again:
ret
=
acpi_aml_read_user
(
buf
+
size
,
count
);
if
(
ret
==
-
EAGAIN
)
{
if
(
file
->
f_flags
&
O_NONBLOCK
)
break
;
else
{
ret
=
wait_event_interruptible
(
acpi_aml_io
.
wait
,
acpi_aml_user_readable
());
/*
* We need to retry when the condition
* becomes true.
*/
if
(
ret
==
0
)
goto
again
;
}
}
if
(
IS_ERR_VALUE
(
ret
))
{
if
(
!
acpi_aml_running
())
ret
=
0
;
break
;
}
if
(
ret
)
{
size
+=
ret
;
count
-=
ret
;
*
ppos
+=
ret
;
break
;
}
}
return
size
>
0
?
size
:
ret
;
}
static
int
acpi_aml_write_user
(
const
char
__user
*
buf
,
int
len
)
{
int
ret
;
struct
circ_buf
*
crc
=
&
acpi_aml_io
.
in_crc
;
int
n
;
char
*
p
;
ret
=
acpi_aml_lock_write
(
crc
,
ACPI_AML_IN_USER
);
if
(
IS_ERR_VALUE
(
ret
))
return
ret
;
/* sync tail before inserting cmds */
smp_mb
();
p
=
&
crc
->
buf
[
crc
->
head
];
n
=
min
(
len
,
circ_space_to_end
(
crc
));
if
(
copy_from_user
(
p
,
buf
,
n
))
{
ret
=
-
EFAULT
;
goto
out
;
}
/* sync head after inserting cmds */
smp_wmb
();
crc
->
head
=
(
crc
->
head
+
n
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
ret
=
n
;
out:
acpi_aml_unlock_fifo
(
ACPI_AML_IN_USER
,
!
IS_ERR_VALUE
(
ret
));
return
n
;
}
static
ssize_t
acpi_aml_write
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
int
ret
=
0
;
int
size
=
0
;
if
(
!
count
)
return
0
;
if
(
!
access_ok
(
VERIFY_READ
,
buf
,
count
))
return
-
EFAULT
;
while
(
count
>
0
)
{
again:
ret
=
acpi_aml_write_user
(
buf
+
size
,
count
);
if
(
ret
==
-
EAGAIN
)
{
if
(
file
->
f_flags
&
O_NONBLOCK
)
break
;
else
{
ret
=
wait_event_interruptible
(
acpi_aml_io
.
wait
,
acpi_aml_user_writable
());
/*
* We need to retry when the condition
* becomes true.
*/
if
(
ret
==
0
)
goto
again
;
}
}
if
(
IS_ERR_VALUE
(
ret
))
{
if
(
!
acpi_aml_running
())
ret
=
0
;
break
;
}
if
(
ret
)
{
size
+=
ret
;
count
-=
ret
;
*
ppos
+=
ret
;
}
}
return
size
>
0
?
size
:
ret
;
}
static
unsigned
int
acpi_aml_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
int
masks
=
0
;
poll_wait
(
file
,
&
acpi_aml_io
.
wait
,
wait
);
if
(
acpi_aml_user_readable
())
masks
|=
POLLIN
|
POLLRDNORM
;
if
(
acpi_aml_user_writable
())
masks
|=
POLLOUT
|
POLLWRNORM
;
return
masks
;
}
static
const
struct
file_operations
acpi_aml_operations
=
{
.
read
=
acpi_aml_read
,
.
write
=
acpi_aml_write
,
.
poll
=
acpi_aml_poll
,
.
open
=
acpi_aml_open
,
.
release
=
acpi_aml_release
,
.
llseek
=
generic_file_llseek
,
};
static
const
struct
acpi_debugger_ops
acpi_aml_debugger
=
{
.
create_thread
=
acpi_aml_create_thread
,
.
read_cmd
=
acpi_aml_read_cmd
,
.
write_log
=
acpi_aml_write_log
,
.
wait_command_ready
=
acpi_aml_wait_command_ready
,
.
notify_command_complete
=
acpi_aml_notify_command_complete
,
};
int
__init
acpi_aml_init
(
void
)
{
int
ret
=
0
;
if
(
!
acpi_debugfs_dir
)
{
ret
=
-
ENOENT
;
goto
err_exit
;
}
/* Initialize AML IO interface */
mutex_init
(
&
acpi_aml_io
.
lock
);
init_waitqueue_head
(
&
acpi_aml_io
.
wait
);
acpi_aml_io
.
out_crc
.
buf
=
acpi_aml_io
.
out_buf
;
acpi_aml_io
.
in_crc
.
buf
=
acpi_aml_io
.
in_buf
;
acpi_aml_dentry
=
debugfs_create_file
(
"acpidbg"
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
acpi_debugfs_dir
,
NULL
,
&
acpi_aml_operations
);
if
(
acpi_aml_dentry
==
NULL
)
{
ret
=
-
ENODEV
;
goto
err_exit
;
}
ret
=
acpi_register_debugger
(
THIS_MODULE
,
&
acpi_aml_debugger
);
if
(
ret
)
goto
err_fs
;
acpi_aml_initialized
=
true
;
err_fs:
if
(
ret
)
{
debugfs_remove
(
acpi_aml_dentry
);
acpi_aml_dentry
=
NULL
;
}
err_exit:
return
ret
;
}
void
__exit
acpi_aml_exit
(
void
)
{
if
(
acpi_aml_initialized
)
{
acpi_unregister_debugger
(
&
acpi_aml_debugger
);
if
(
acpi_aml_dentry
)
{
debugfs_remove
(
acpi_aml_dentry
);
acpi_aml_dentry
=
NULL
;
}
acpi_aml_initialized
=
false
;
}
}
module_init
(
acpi_aml_init
);
module_exit
(
acpi_aml_exit
);
MODULE_AUTHOR
(
"Lv Zheng"
);
MODULE_DESCRIPTION
(
"ACPI debugger userspace IO driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/acpi/acpica/acdebug.h
View file @
b17629db
...
...
@@ -80,9 +80,15 @@ struct acpi_db_execute_walk {
/*
* dbxface - external debugger interfaces
*/
acpi_status
acpi_db_single_step
(
struct
acpi_walk_state
*
walk_state
,
union
acpi_parse_object
*
op
,
u32
op_type
);
ACPI_DBR_DEPENDENT_RETURN_OK
(
acpi_status
acpi_db_single_step
(
struct
acpi_walk_state
*
walk_state
,
union
acpi_parse_object
*
op
,
u32
op_type
))
ACPI_DBR_DEPENDENT_RETURN_VOID
(
void
acpi_db_signal_break_point
(
struct
acpi_walk_state
*
walk_state
))
/*
* dbcmds - debug commands and output routines
...
...
@@ -182,11 +188,15 @@ void acpi_db_display_method_info(union acpi_parse_object *op);
void
acpi_db_decode_and_display_object
(
char
*
target
,
char
*
output_type
);
void
acpi_db_display_result_object
(
union
acpi_operand_object
*
obj_desc
,
struct
acpi_walk_state
*
walk_state
);
ACPI_DBR_DEPENDENT_RETURN_VOID
(
void
acpi_db_display_result_object
(
union
acpi_operand_object
*
obj_desc
,
struct
acpi_walk_state
*
walk_state
))
acpi_status
acpi_db_display_all_methods
(
char
*
display_count_arg
);
acpi_status
acpi_db_display_all_methods
(
char
*
display_count_arg
);
void
acpi_db_display_arguments
(
void
);
...
...
@@ -198,9 +208,13 @@ void acpi_db_display_calling_tree(void);
void
acpi_db_display_object_type
(
char
*
object_arg
);
void
acpi_db_display_argument_object
(
union
acpi_operand_object
*
obj_desc
,
struct
acpi_walk_state
*
walk_state
);
ACPI_DBR_DEPENDENT_RETURN_VOID
(
void
acpi_db_display_argument_object
(
union
acpi_operand_object
*
obj_desc
,
struct
acpi_walk_state
*
walk_state
))
/*
* dbexec - debugger control method execution
...
...
@@ -257,7 +271,7 @@ acpi_db_command_dispatch(char *input_buffer,
void
ACPI_SYSTEM_XFACE
acpi_db_execute_thread
(
void
*
context
);
acpi_status
acpi_db_user_commands
(
char
prompt
,
union
acpi_parse_object
*
op
);
acpi_status
acpi_db_user_commands
(
void
);
char
*
acpi_db_get_next_token
(
char
*
string
,
char
**
next
,
acpi_object_type
*
return_type
);
...
...
drivers/acpi/acpica/acglobal.h
View file @
b17629db
...
...
@@ -326,7 +326,6 @@ ACPI_GLOBAL(struct acpi_external_file *, acpi_gbl_external_file_list);
#ifdef ACPI_DEBUGGER
ACPI_INIT_GLOBAL
(
u8
,
acpi_gbl_abort_method
,
FALSE
);
ACPI_INIT_GLOBAL
(
u8
,
acpi_gbl_method_executing
,
FALSE
);
ACPI_INIT_GLOBAL
(
acpi_thread_id
,
acpi_gbl_db_thread_id
,
ACPI_INVALID_THREAD_ID
);
ACPI_GLOBAL
(
u8
,
acpi_gbl_db_opt_no_ini_methods
);
...
...
@@ -345,7 +344,6 @@ ACPI_GLOBAL(acpi_object_type, acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]);
/* These buffers should all be the same size */
ACPI_GLOBAL
(
char
,
acpi_gbl_db_line_buf
[
ACPI_DB_LINE_BUFFER_SIZE
]);
ACPI_GLOBAL
(
char
,
acpi_gbl_db_parsed_buf
[
ACPI_DB_LINE_BUFFER_SIZE
]);
ACPI_GLOBAL
(
char
,
acpi_gbl_db_scope_buf
[
ACPI_DB_LINE_BUFFER_SIZE
]);
ACPI_GLOBAL
(
char
,
acpi_gbl_db_debug_filename
[
ACPI_DB_LINE_BUFFER_SIZE
]);
...
...
@@ -360,9 +358,6 @@ ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc);
ACPI_GLOBAL
(
u32
,
acpi_gbl_num_nodes
);
ACPI_GLOBAL
(
u32
,
acpi_gbl_num_objects
);
ACPI_GLOBAL
(
acpi_mutex
,
acpi_gbl_db_command_ready
);
ACPI_GLOBAL
(
acpi_mutex
,
acpi_gbl_db_command_complete
);
#endif
/* ACPI_DEBUGGER */
/*****************************************************************************
...
...
drivers/acpi/acpica/acmacros.h
View file @
b17629db
...
...
@@ -400,17 +400,6 @@
#define ACPI_HW_OPTIONAL_FUNCTION(addr) NULL
#endif
/*
* Some code only gets executed when the debugger is built in.
* Note that this is entirely independent of whether the
* DEBUG_PRINT stuff (set by ACPI_DEBUG_OUTPUT) is on, or not.
*/
#ifdef ACPI_DEBUGGER
#define ACPI_DEBUGGER_EXEC(a) a
#else
#define ACPI_DEBUGGER_EXEC(a)
#endif
/*
* Macros used for ACPICA utilities only
*/
...
...
drivers/acpi/acpica/dbdisply.c
View file @
b17629db
...
...
@@ -679,6 +679,12 @@ acpi_db_display_result_object(union acpi_operand_object *obj_desc,
struct
acpi_walk_state
*
walk_state
)
{
#ifndef ACPI_APPLICATION
if
(
acpi_gbl_db_thread_id
!=
acpi_os_get_thread_id
())
{
return
;
}
#endif
/* Only display if single stepping */
if
(
!
acpi_gbl_cm_single_step
)
{
...
...
@@ -708,6 +714,12 @@ acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
struct
acpi_walk_state
*
walk_state
)
{
#ifndef ACPI_APPLICATION
if
(
acpi_gbl_db_thread_id
!=
acpi_os_get_thread_id
())
{
return
;
}
#endif
if
(
!
acpi_gbl_cm_single_step
)
{
return
;
}
...
...
drivers/acpi/acpica/dbinput.c
View file @
b17629db
...
...
@@ -53,8 +53,6 @@ static u32 acpi_db_get_line(char *input_buffer);
static
u32
acpi_db_match_command
(
char
*
user_command
);
static
void
acpi_db_single_thread
(
void
);
static
void
acpi_db_display_command_info
(
char
*
command
,
u8
display_all
);
static
void
acpi_db_display_help
(
char
*
command
);
...
...
@@ -1149,55 +1147,16 @@ acpi_db_command_dispatch(char *input_buffer,
void
ACPI_SYSTEM_XFACE
acpi_db_execute_thread
(
void
*
context
)
{
acpi_status
status
=
AE_OK
;
acpi_status
Mstatus
;
while
(
status
!=
AE_CTRL_TERMINATE
&&
!
acpi_gbl_db_terminate_loop
)
{
acpi_gbl_method_executing
=
FALSE
;
acpi_gbl_step_to_next_call
=
FALSE
;
Mstatus
=
acpi_os_acquire_mutex
(
acpi_gbl_db_command_ready
,
ACPI_WAIT_FOREVER
);
if
(
ACPI_FAILURE
(
Mstatus
))
{
return
;
}
status
=
acpi_db_command_dispatch
(
acpi_gbl_db_line_buf
,
NULL
,
NULL
);
acpi_os_release_mutex
(
acpi_gbl_db_command_complete
);
}
(
void
)
acpi_db_user_commands
();
acpi_gbl_db_threads_terminated
=
TRUE
;
}
/*******************************************************************************
*
* FUNCTION: acpi_db_single_thread
*
* PARAMETERS: None
*
* RETURN: None
*
* DESCRIPTION: Debugger execute thread. Waits for a command line, then
* simply dispatches it.
*
******************************************************************************/
static
void
acpi_db_single_thread
(
void
)
{
acpi_gbl_method_executing
=
FALSE
;
acpi_gbl_step_to_next_call
=
FALSE
;
(
void
)
acpi_db_command_dispatch
(
acpi_gbl_db_line_buf
,
NULL
,
NULL
);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_user_commands
*
* PARAMETERS: prompt - User prompt (depends on mode)
* op - Current executing parse op
* PARAMETERS: None
*
* RETURN: None
*
...
...
@@ -1206,7 +1165,7 @@ static void acpi_db_single_thread(void)
*
******************************************************************************/
acpi_status
acpi_db_user_commands
(
char
prompt
,
union
acpi_parse_object
*
op
)
acpi_status
acpi_db_user_commands
(
void
)
{
acpi_status
status
=
AE_OK
;
...
...
@@ -1216,52 +1175,31 @@ acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op)
while
(
!
acpi_gbl_db_terminate_loop
)
{
/* Force output to console until a command is entered */
acpi_db_set_output_destination
(
ACPI_DB_CONSOLE_OUTPUT
);
/* Different prompt if method is executing */
if
(
!
acpi_gbl_method_executing
)
{
acpi_os_printf
(
"%1c "
,
ACPI_DEBUGGER_COMMAND_PROMPT
);
}
else
{
acpi_os_printf
(
"%1c "
,
ACPI_DEBUGGER_EXECUTE_PROMPT
);
}
/* Get the user input line */
/* Wait the readiness of the command */
status
=
acpi_os_get_line
(
acpi_gbl_db_line_buf
,
ACPI_DB_LINE_BUFFER_SIZE
,
NULL
);
status
=
acpi_os_wait_command_ready
();
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"While parsing command line"
));
return
(
status
);
break
;
}
/*
Check for single or multithreaded debug
*/
/*
Just call to the command line interpreter
*/
if
(
acpi_gbl_debugger_configuration
&
DEBUGGER_MULTI_THREADED
)
{
/*
* Signal the debug thread that we have a command to execute,
* and wait for the command to complete.
*/
acpi_os_release_mutex
(
acpi_gbl_db_command_ready
);
if
(
ACPI_FAILURE
(
status
))
{
return
(
status
);
}
acpi_gbl_method_executing
=
FALSE
;
acpi_gbl_step_to_next_call
=
FALSE
;
status
=
acpi_os_acquire_mutex
(
acpi_gbl_db_command_complete
,
ACPI_WAIT_FOREVER
);
if
(
ACPI_FAILURE
(
status
))
{
return
(
status
);
}
}
else
{
/* Just call to the command line interpreter */
(
void
)
acpi_db_command_dispatch
(
acpi_gbl_db_line_buf
,
NULL
,
NULL
);
/* Notify the completion of the command */
acpi_db_single_thread
();
status
=
acpi_os_notify_command_complete
();
if
(
ACPI_FAILURE
(
status
))
{
break
;
}
}
if
(
ACPI_FAILURE
(
status
)
&&
status
!=
AE_CTRL_TERMINATE
)
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"While parsing command line"
));
}
return
(
status
);
}
drivers/acpi/acpica/dbxface.c
View file @
b17629db
...
...
@@ -85,46 +85,21 @@ acpi_db_start_command(struct acpi_walk_state *walk_state,
acpi_gbl_method_executing
=
TRUE
;
status
=
AE_CTRL_TRUE
;
while
(
status
==
AE_CTRL_TRUE
)
{
if
(
acpi_gbl_debugger_configuration
==
DEBUGGER_MULTI_THREADED
)
{
/* Handshake with the front-end that gets user command lines */
acpi_os_release_mutex
(
acpi_gbl_db_command_complete
);
status
=
acpi_os_acquire_mutex
(
acpi_gbl_db_command_ready
,
ACPI_WAIT_FOREVER
);
if
(
ACPI_FAILURE
(
status
))
{
return
(
status
);
}
}
else
{
/* Single threaded, we must get a command line ourselves */
/* Force output to console until a command is entered */
acpi_db_set_output_destination
(
ACPI_DB_CONSOLE_OUTPUT
);
while
(
status
==
AE_CTRL_TRUE
)
{
/* Different prompt if method is executing
*/
/* Notify the completion of the command
*/
if
(
!
acpi_gbl_method_executing
)
{
acpi_os_printf
(
"%1c "
,
ACPI_DEBUGGER_COMMAND_PROMPT
);
}
else
{
acpi_os_printf
(
"%1c "
,
ACPI_DEBUGGER_EXECUTE_PROMPT
);
}
status
=
acpi_os_notify_command_complete
();
if
(
ACPI_FAILURE
(
status
))
{
goto
error_exit
;
}
/* Get the user input line
*/
/* Wait the readiness of the command
*/
status
=
acpi_os_get_line
(
acpi_gbl_db_line_buf
,
ACPI_DB_LINE_BUFFER_SIZE
,
NULL
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"While parsing command line"
));
return
(
status
);
}
status
=
acpi_os_wait_command_ready
();
if
(
ACPI_FAILURE
(
status
))
{
goto
error_exit
;
}
status
=
...
...
@@ -134,9 +109,44 @@ acpi_db_start_command(struct acpi_walk_state *walk_state,
/* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
error_exit:
if
(
ACPI_FAILURE
(
status
)
&&
status
!=
AE_CTRL_TERMINATE
)
{
ACPI_EXCEPTION
((
AE_INFO
,
status
,
"While parsing/handling command line"
));
}
return
(
status
);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_signal_break_point
*
* PARAMETERS: walk_state - Current walk
*
* RETURN: Status
*
* DESCRIPTION: Called for AML_BREAK_POINT_OP
*
******************************************************************************/
void
acpi_db_signal_break_point
(
struct
acpi_walk_state
*
walk_state
)
{
#ifndef ACPI_APPLICATION
if
(
acpi_gbl_db_thread_id
!=
acpi_os_get_thread_id
())
{
return
;
}
#endif
/*
* Set the single-step flag. This will cause the debugger (if present)
* to break to the console within the AML debugger at the start of the
* next AML instruction.
*/
acpi_gbl_cm_single_step
=
TRUE
;
acpi_os_printf
(
"**break** Executed AML BreakPoint opcode
\n
"
);
}
/*******************************************************************************
*
* FUNCTION: acpi_db_single_step
...
...
@@ -420,15 +430,7 @@ acpi_status acpi_initialize_debugger(void)
/* These were created with one unit, grab it */
status
=
acpi_os_acquire_mutex
(
acpi_gbl_db_command_complete
,
ACPI_WAIT_FOREVER
);
if
(
ACPI_FAILURE
(
status
))
{
acpi_os_printf
(
"Could not get debugger mutex
\n
"
);
return_ACPI_STATUS
(
status
);
}
status
=
acpi_os_acquire_mutex
(
acpi_gbl_db_command_ready
,
ACPI_WAIT_FOREVER
);
status
=
acpi_os_initialize_command_signals
();
if
(
ACPI_FAILURE
(
status
))
{
acpi_os_printf
(
"Could not get debugger mutex
\n
"
);
return_ACPI_STATUS
(
status
);
...
...
@@ -473,13 +475,14 @@ void acpi_terminate_debugger(void)
acpi_gbl_db_terminate_loop
=
TRUE
;
if
(
acpi_gbl_debugger_configuration
&
DEBUGGER_MULTI_THREADED
)
{
acpi_os_release_mutex
(
acpi_gbl_db_command_ready
);
/* Wait the AML Debugger threads */
while
(
!
acpi_gbl_db_threads_terminated
)
{
acpi_os_sleep
(
100
);
}
acpi_os_terminate_command_signals
();
}
if
(
acpi_gbl_db_buffer
)
{
...
...
drivers/acpi/acpica/dscontrol.c
View file @
b17629db
...
...
@@ -47,6 +47,7 @@
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acdebug.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME
(
"dscontrol"
)
...
...
@@ -348,14 +349,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
case
AML_BREAK_POINT_OP
:
/*
* Set the single-step flag. This will cause the debugger (if present)
* to break to the console within the AML debugger at the start of the
* next AML instruction.
*/
ACPI_DEBUGGER_EXEC
(
acpi_gbl_cm_single_step
=
TRUE
);
ACPI_DEBUGGER_EXEC
(
acpi_os_printf
(
"**break** Executed AML BreakPoint opcode
\n
"
));
acpi_db_signal_break_point
(
walk_state
);
/* Call to the OSL in case OS wants a piece of the action */
...
...
drivers/acpi/acpica/dsutils.c
View file @
b17629db
...
...
@@ -605,8 +605,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
if
(
ACPI_FAILURE
(
status
))
{
return_ACPI_STATUS
(
status
);
}
ACPI_DEBUGGER_EXEC
(
acpi_db_display_argument_object
(
obj_desc
,
walk_state
)
);
acpi_db_display_argument_object
(
obj_desc
,
walk_state
);
}
else
{
/* Check for null name case */
...
...
@@ -638,10 +638,11 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
ACPI_DEBUG_PRINT
((
ACPI_DB_DISPATCH
,
"Argument previously created, already stacked
\n
"
));
ACPI_DEBUGGER_EXEC
(
acpi_db_display_argument_object
(
walk_state
->
operands
[
walk_state
->
num_operands
-
1
],
walk_state
));
acpi_db_display_argument_object
(
walk_state
->
operands
[
walk_state
->
num_operands
-
1
],
walk_state
);
/*
* Use value that was already previously returned
...
...
@@ -685,8 +686,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
return_ACPI_STATUS
(
status
);
}
ACPI_DEBUGGER_EXEC
(
acpi_db_display_argument_object
(
obj_desc
,
walk_state
));
acpi_db_display_argument_object
(
obj_desc
,
walk_state
);
}
return_ACPI_STATUS
(
AE_OK
);
...
...
drivers/acpi/acpica/dswexec.c
View file @
b17629db
...
...
@@ -178,8 +178,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
/* Break to debugger to display result */
ACPI_DEBUGGER_EXEC
(
acpi_db_display_result_object
(
local_obj_desc
,
walk_state
));
acpi_db_display_result_object
(
local_obj_desc
,
walk_state
);
/*
* Delete the predicate result object (we know that
...
...
@@ -386,11 +385,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
/* Call debugger for single step support (DEBUG build only) */
ACPI_DEBUGGER_EXEC
(
status
=
acpi_db_single_step
(
walk_state
,
op
,
op_class
));
ACPI_DEBUGGER_EXEC
(
if
(
ACPI_FAILURE
(
status
))
{
return_ACPI_STATUS
(
status
);}
)
;
status
=
acpi_db_single_step
(
walk_state
,
op
,
op_class
);
if
(
ACPI_FAILURE
(
status
))
{
return_ACPI_STATUS
(
status
);
}
/* Decode the Opcode Class */
...
...
@@ -728,8 +726,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
/* Break to debugger to display result */
ACPI_DEBUGGER_EXEC
(
acpi_db_display_result_object
(
walk_state
->
result_obj
,
walk_state
)
);
acpi_db_display_result_object
(
walk_state
->
result_obj
,
walk_state
);
/*
* Delete the result op if and only if:
...
...
drivers/acpi/acpica/utmutex.c
View file @
b17629db
...
...
@@ -111,17 +111,6 @@ acpi_status acpi_ut_mutex_initialize(void)
if
(
ACPI_FAILURE
(
status
))
{
return_ACPI_STATUS
(
status
);
}
#ifdef ACPI_DEBUGGER
/* Debugger Support */
status
=
acpi_os_create_mutex
(
&
acpi_gbl_db_command_ready
);
if
(
ACPI_FAILURE
(
status
))
{
return_ACPI_STATUS
(
status
);
}
status
=
acpi_os_create_mutex
(
&
acpi_gbl_db_command_complete
);
#endif
return_ACPI_STATUS
(
status
);
}
...
...
@@ -162,12 +151,6 @@ void acpi_ut_mutex_terminate(void)
/* Delete the reader/writer lock */
acpi_ut_delete_rw_lock
(
&
acpi_gbl_namespace_rw_lock
);
#ifdef ACPI_DEBUGGER
acpi_os_delete_mutex
(
acpi_gbl_db_command_ready
);
acpi_os_delete_mutex
(
acpi_gbl_db_command_complete
);
#endif
return_VOID
;
}
...
...
drivers/acpi/bus.c
View file @
b17629db
...
...
@@ -1094,6 +1094,7 @@ static int __init acpi_init(void)
acpi_debugfs_init
();
acpi_sleep_proc_init
();
acpi_wakeup_device_init
();
acpi_debugger_init
();
return
0
;
}
...
...
drivers/acpi/osl.c
View file @
b17629db
...
...
@@ -220,6 +220,7 @@ void acpi_os_printf(const char *fmt, ...)
acpi_os_vprintf
(
fmt
,
args
);
va_end
(
args
);
}
EXPORT_SYMBOL
(
acpi_os_printf
);
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
);
}
#else
printk
(
KERN_CONT
"%s"
,
buffer
);
if
(
acpi_debugger_write_log
(
buffer
)
<
0
)
printk
(
KERN_CONT
"%s"
,
buffer
);
#endif
}
...
...
@@ -1101,6 +1103,200 @@ static void acpi_os_execute_deferred(struct work_struct *work)
kfree
(
dpc
);
}
#ifdef CONFIG_ACPI_DEBUGGER
static
struct
acpi_debugger
acpi_debugger
;
static
bool
acpi_debugger_initialized
;
int
acpi_register_debugger
(
struct
module
*
owner
,
const
struct
acpi_debugger_ops
*
ops
)
{
int
ret
=
0
;
mutex_lock
(
&
acpi_debugger
.
lock
);
if
(
acpi_debugger
.
ops
)
{
ret
=
-
EBUSY
;
goto
err_lock
;
}
acpi_debugger
.
owner
=
owner
;
acpi_debugger
.
ops
=
ops
;
err_lock:
mutex_unlock
(
&
acpi_debugger
.
lock
);
return
ret
;
}
EXPORT_SYMBOL
(
acpi_register_debugger
);
void
acpi_unregister_debugger
(
const
struct
acpi_debugger_ops
*
ops
)
{
mutex_lock
(
&
acpi_debugger
.
lock
);
if
(
ops
==
acpi_debugger
.
ops
)
{
acpi_debugger
.
ops
=
NULL
;
acpi_debugger
.
owner
=
NULL
;
}
mutex_unlock
(
&
acpi_debugger
.
lock
);
}
EXPORT_SYMBOL
(
acpi_unregister_debugger
);
int
acpi_debugger_create_thread
(
acpi_osd_exec_callback
function
,
void
*
context
)
{
int
ret
;
int
(
*
func
)(
acpi_osd_exec_callback
,
void
*
);
struct
module
*
owner
;
if
(
!
acpi_debugger_initialized
)
return
-
ENODEV
;
mutex_lock
(
&
acpi_debugger
.
lock
);
if
(
!
acpi_debugger
.
ops
)
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
if
(
!
try_module_get
(
acpi_debugger
.
owner
))
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
func
=
acpi_debugger
.
ops
->
create_thread
;
owner
=
acpi_debugger
.
owner
;
mutex_unlock
(
&
acpi_debugger
.
lock
);
ret
=
func
(
function
,
context
);
mutex_lock
(
&
acpi_debugger
.
lock
);
module_put
(
owner
);
err_lock:
mutex_unlock
(
&
acpi_debugger
.
lock
);
return
ret
;
}
ssize_t
acpi_debugger_write_log
(
const
char
*
msg
)
{
ssize_t
ret
;
ssize_t
(
*
func
)(
const
char
*
);
struct
module
*
owner
;
if
(
!
acpi_debugger_initialized
)
return
-
ENODEV
;
mutex_lock
(
&
acpi_debugger
.
lock
);
if
(
!
acpi_debugger
.
ops
)
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
if
(
!
try_module_get
(
acpi_debugger
.
owner
))
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
func
=
acpi_debugger
.
ops
->
write_log
;
owner
=
acpi_debugger
.
owner
;
mutex_unlock
(
&
acpi_debugger
.
lock
);
ret
=
func
(
msg
);
mutex_lock
(
&
acpi_debugger
.
lock
);
module_put
(
owner
);
err_lock:
mutex_unlock
(
&
acpi_debugger
.
lock
);
return
ret
;
}
ssize_t
acpi_debugger_read_cmd
(
char
*
buffer
,
size_t
buffer_length
)
{
ssize_t
ret
;
ssize_t
(
*
func
)(
char
*
,
size_t
);
struct
module
*
owner
;
if
(
!
acpi_debugger_initialized
)
return
-
ENODEV
;
mutex_lock
(
&
acpi_debugger
.
lock
);
if
(
!
acpi_debugger
.
ops
)
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
if
(
!
try_module_get
(
acpi_debugger
.
owner
))
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
func
=
acpi_debugger
.
ops
->
read_cmd
;
owner
=
acpi_debugger
.
owner
;
mutex_unlock
(
&
acpi_debugger
.
lock
);
ret
=
func
(
buffer
,
buffer_length
);
mutex_lock
(
&
acpi_debugger
.
lock
);
module_put
(
owner
);
err_lock:
mutex_unlock
(
&
acpi_debugger
.
lock
);
return
ret
;
}
int
acpi_debugger_wait_command_ready
(
void
)
{
int
ret
;
int
(
*
func
)(
bool
,
char
*
,
size_t
);
struct
module
*
owner
;
if
(
!
acpi_debugger_initialized
)
return
-
ENODEV
;
mutex_lock
(
&
acpi_debugger
.
lock
);
if
(
!
acpi_debugger
.
ops
)
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
if
(
!
try_module_get
(
acpi_debugger
.
owner
))
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
func
=
acpi_debugger
.
ops
->
wait_command_ready
;
owner
=
acpi_debugger
.
owner
;
mutex_unlock
(
&
acpi_debugger
.
lock
);
ret
=
func
(
acpi_gbl_method_executing
,
acpi_gbl_db_line_buf
,
ACPI_DB_LINE_BUFFER_SIZE
);
mutex_lock
(
&
acpi_debugger
.
lock
);
module_put
(
owner
);
err_lock:
mutex_unlock
(
&
acpi_debugger
.
lock
);
return
ret
;
}
int
acpi_debugger_notify_command_complete
(
void
)
{
int
ret
;
int
(
*
func
)(
void
);
struct
module
*
owner
;
if
(
!
acpi_debugger_initialized
)
return
-
ENODEV
;
mutex_lock
(
&
acpi_debugger
.
lock
);
if
(
!
acpi_debugger
.
ops
)
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
if
(
!
try_module_get
(
acpi_debugger
.
owner
))
{
ret
=
-
ENODEV
;
goto
err_lock
;
}
func
=
acpi_debugger
.
ops
->
notify_command_complete
;
owner
=
acpi_debugger
.
owner
;
mutex_unlock
(
&
acpi_debugger
.
lock
);
ret
=
func
();
mutex_lock
(
&
acpi_debugger
.
lock
);
module_put
(
owner
);
err_lock:
mutex_unlock
(
&
acpi_debugger
.
lock
);
return
ret
;
}
int
__init
acpi_debugger_init
(
void
)
{
mutex_init
(
&
acpi_debugger
.
lock
);
acpi_debugger_initialized
=
true
;
return
0
;
}
#endif
/*******************************************************************************
*
* FUNCTION: acpi_os_execute
...
...
@@ -1127,6 +1323,15 @@ acpi_status acpi_os_execute(acpi_execute_type type,
"Scheduling function [%p(%p)] for deferred execution.
\n
"
,
function
,
context
));
if
(
type
==
OSL_DEBUGGER_MAIN_THREAD
)
{
ret
=
acpi_debugger_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
* freed by the callee. The kernel handles the work_struct list in a
...
...
@@ -1151,11 +1356,17 @@ acpi_status acpi_os_execute(acpi_execute_type type,
if
(
type
==
OSL_NOTIFY_HANDLER
)
{
queue
=
kacpi_notify_wq
;
INIT_WORK
(
&
dpc
->
work
,
acpi_os_execute_deferred
);
}
else
{
}
else
if
(
type
==
OSL_GPE_HANDLER
)
{
queue
=
kacpid_wq
;
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
* the SMI runs on CPU 0. An SMI can be initiated by any AML, but
...
...
@@ -1164,13 +1375,15 @@ acpi_status acpi_os_execute(acpi_execute_type type,
* queueing on CPU 0.
*/
ret
=
queue_work_on
(
0
,
queue
,
&
dpc
->
work
);
if
(
!
ret
)
{
printk
(
KERN_ERR
PREFIX
"Call to queue_work() failed.
\n
"
);
status
=
AE_ERROR
;
kfree
(
dpc
);
}
err_workqueue:
if
(
ACPI_FAILURE
(
status
))
kfree
(
dpc
);
out_thread:
return
status
;
}
EXPORT_SYMBOL
(
acpi_os_execute
);
...
...
@@ -1358,10 +1571,39 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read)
chars
=
strlen
(
buffer
)
-
1
;
buffer
[
chars
]
=
'\0'
;
}
#else
int
ret
;
ret
=
acpi_debugger_read_cmd
(
buffer
,
buffer_length
);
if
(
ret
<
0
)
return
AE_ERROR
;
if
(
bytes_read
)
*
bytes_read
=
ret
;
#endif
return
AE_OK
;
}
EXPORT_SYMBOL
(
acpi_os_get_line
);
acpi_status
acpi_os_wait_command_ready
(
void
)
{
int
ret
;
ret
=
acpi_debugger_wait_command_ready
();
if
(
ret
<
0
)
return
AE_ERROR
;
return
AE_OK
;
}
acpi_status
acpi_os_notify_command_complete
(
void
)
{
int
ret
;
ret
=
acpi_debugger_notify_command_complete
();
if
(
ret
<
0
)
return
AE_ERROR
;
return
AE_OK
;
}
acpi_status
acpi_os_signal
(
u32
function
,
void
*
info
)
{
...
...
include/acpi/acpiosxf.h
View file @
b17629db
...
...
@@ -349,12 +349,28 @@ void acpi_os_redirect_output(void *destination);
#endif
/*
* Debug
input
* Debug
IO
*/
#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_line
acpi_status
acpi_os_get_line
(
char
*
buffer
,
u32
buffer_length
,
u32
*
bytes_read
);
#endif
#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize_command_signals
acpi_status
acpi_os_initialize_command_signals
(
void
);
#endif
#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate_command_signals
void
acpi_os_terminate_command_signals
(
void
);
#endif
#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_command_ready
acpi_status
acpi_os_wait_command_ready
(
void
);
#endif
#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_notify_command_complete
acpi_status
acpi_os_notify_command_complete
(
void
);
#endif
/*
* Obtain ACPI table(s)
*/
...
...
include/acpi/acpixf.h
View file @
b17629db
...
...
@@ -263,6 +263,15 @@ ACPI_INIT_GLOBAL(u32, acpi_gbl_trace_dbg_layer, ACPI_TRACE_LAYER_DEFAULT);
ACPI_INIT_GLOBAL
(
u32
,
acpi_dbg_level
,
ACPI_DEBUG_DEFAULT
);
ACPI_INIT_GLOBAL
(
u32
,
acpi_dbg_layer
,
0
);
/*
* Debugger command handshake globals. Host OSes need to access these
* variables to implement their own command handshake mechanism.
*/
#ifdef ACPI_DEBUGGER
ACPI_INIT_GLOBAL
(
u8
,
acpi_gbl_method_executing
,
FALSE
);
ACPI_GLOBAL
(
char
,
acpi_gbl_db_line_buf
[
ACPI_DB_LINE_BUFFER_SIZE
]);
#endif
/*
* Other miscellaneous globals
*/
...
...
@@ -366,6 +375,29 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running);
#endif
/* ACPI_APPLICATION */
/*
* Debugger prototypes
*
* All interfaces used by debugger will be configured
* out of the ACPICA build unless the ACPI_DEBUGGER
* flag is defined.
*/
#ifdef ACPI_DEBUGGER
#define ACPI_DBR_DEPENDENT_RETURN_OK(prototype) \
ACPI_EXTERNAL_RETURN_OK(prototype)
#define ACPI_DBR_DEPENDENT_RETURN_VOID(prototype) \
ACPI_EXTERNAL_RETURN_VOID(prototype)
#else
#define ACPI_DBR_DEPENDENT_RETURN_OK(prototype) \
static ACPI_INLINE prototype {return(AE_OK);}
#define ACPI_DBR_DEPENDENT_RETURN_VOID(prototype) \
static ACPI_INLINE prototype {return;}
#endif
/* ACPI_DEBUGGER */
/*****************************************************************************
*
* ACPICA public interface prototypes
...
...
@@ -929,6 +961,8 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status
void
**
data
,
void
(
*
callback
)(
void
*
)))
void
acpi_run_debugger
(
char
*
batch_buffer
);
void
acpi_set_debugger_thread_id
(
acpi_thread_id
thread_id
);
#endif
/* __ACXFACE_H__ */
include/acpi/platform/aclinux.h
View file @
b17629db
...
...
@@ -150,6 +150,8 @@
*/
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_readable
#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_terminate_command_signals
/*
* OSL interfaces used by utilities
...
...
include/acpi/platform/aclinuxex.h
View file @
b17629db
...
...
@@ -129,6 +129,15 @@ static inline u8 acpi_os_readable(void *pointer, acpi_size length)
return
TRUE
;
}
static
inline
acpi_status
acpi_os_initialize_command_signals
(
void
)
{
return
AE_OK
;
}
static
inline
void
acpi_os_terminate_command_signals
(
void
)
{
}
/*
* OSL interfaces added by Linux
*/
...
...
include/linux/acpi.h
View file @
b17629db
...
...
@@ -37,6 +37,8 @@
#include <linux/list.h>
#include <linux/mod_devicetable.h>
#include <linux/dynamic_debug.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
...
...
@@ -119,6 +121,75 @@ typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);
typedef
int
(
*
acpi_tbl_entry_handler
)(
struct
acpi_subtable_header
*
header
,
const
unsigned
long
end
);
/* Debugger support */
struct
acpi_debugger_ops
{
int
(
*
create_thread
)(
acpi_osd_exec_callback
function
,
void
*
context
);
ssize_t
(
*
write_log
)(
const
char
*
msg
);
ssize_t
(
*
read_cmd
)(
char
*
buffer
,
size_t
length
);
int
(
*
wait_command_ready
)(
bool
single_step
,
char
*
buffer
,
size_t
length
);
int
(
*
notify_command_complete
)(
void
);
};
struct
acpi_debugger
{
const
struct
acpi_debugger_ops
*
ops
;
struct
module
*
owner
;
struct
mutex
lock
;
};
#ifdef CONFIG_ACPI_DEBUGGER
int
__init
acpi_debugger_init
(
void
);
int
acpi_register_debugger
(
struct
module
*
owner
,
const
struct
acpi_debugger_ops
*
ops
);
void
acpi_unregister_debugger
(
const
struct
acpi_debugger_ops
*
ops
);
int
acpi_debugger_create_thread
(
acpi_osd_exec_callback
function
,
void
*
context
);
ssize_t
acpi_debugger_write_log
(
const
char
*
msg
);
ssize_t
acpi_debugger_read_cmd
(
char
*
buffer
,
size_t
buffer_length
);
int
acpi_debugger_wait_command_ready
(
void
);
int
acpi_debugger_notify_command_complete
(
void
);
#else
static
inline
int
acpi_debugger_init
(
void
)
{
return
-
ENODEV
;
}
static
inline
int
acpi_register_debugger
(
struct
module
*
owner
,
const
struct
acpi_debugger_ops
*
ops
)
{
return
-
ENODEV
;
}
static
inline
void
acpi_unregister_debugger
(
const
struct
acpi_debugger_ops
*
ops
)
{
}
static
inline
int
acpi_debugger_create_thread
(
acpi_osd_exec_callback
function
,
void
*
context
)
{
return
-
ENODEV
;
}
static
inline
int
acpi_debugger_write_log
(
const
char
*
msg
)
{
return
-
ENODEV
;
}
static
inline
int
acpi_debugger_read_cmd
(
char
*
buffer
,
u32
buffer_length
)
{
return
-
ENODEV
;
}
static
inline
int
acpi_debugger_wait_command_ready
(
void
)
{
return
-
ENODEV
;
}
static
inline
int
acpi_debugger_notify_command_complete
(
void
)
{
return
-
ENODEV
;
}
#endif
#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
void
acpi_initrd_override
(
void
*
data
,
size_t
size
);
#else
...
...
tools/power/acpi/Makefile
View file @
b17629db
...
...
@@ -10,18 +10,18 @@
include
../../scripts/Makefile.include
all
:
acpidump ec
clean
:
acpidump_clean ec_clean
install
:
acpidump_install ec_install
uninstall
:
acpidump_uninstall ec_uninstall
all
:
acpid
bg acpid
ump ec
clean
:
acpid
bg_clean acpid
ump_clean ec_clean
install
:
acpid
bg_install acpid
ump_install ec_install
uninstall
:
acpid
bg_uninstall acpid
ump_uninstall ec_uninstall
acpidump ec
:
FORCE
acpid
bg acpid
ump ec
:
FORCE
$(
call
descend,tools/
$@
,all
)
acpidump_clean ec_clean
:
acpid
bg_clean acpid
ump_clean ec_clean
:
$(
call
descend,tools/
$
(
@:_clean
=
)
,clean
)
acpidump_install ec_install
:
acpid
bg_install acpid
ump_install ec_install
:
$(
call
descend,tools/
$
(
@:_install
=
)
,install
)
acpidump_uninstall ec_uninstall
:
acpid
bg_uninstall acpid
ump_uninstall ec_uninstall
:
$(
call
descend,tools/
$
(
@:_uninstall
=
)
,uninstall
)
.PHONY
:
FORCE
tools/power/acpi/tools/acpidbg/Makefile
0 → 100644
View file @
b17629db
# tools/power/acpi/tools/acpidbg/Makefile - ACPI tool Makefile
#
# Copyright (c) 2015, Intel Corporation
# Author: 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
# as published by the Free Software Foundation; version 2
# of the License.
include
../../Makefile.config
TOOL
=
acpidbg
vpath
%.c
\
../../../../../drivers/acpi/acpica\
../../common\
../../os_specific/service_layers\
.
CFLAGS
+=
-DACPI_APPLICATION
-DACPI_SINGLE_THREAD
-DACPI_DEBUGGER
\
-I
.
\
-I
../../../../../drivers/acpi/acpica
\
-I
../../../../../include
LDFLAGS
+=
-lpthread
TOOL_OBJS
=
\
acpidbg.o
include
../../Makefile.rules
tools/power/acpi/tools/acpidbg/acpidbg.c
0 → 100644
View file @
b17629db
/*
* ACPI AML interfacing userspace utility
*
* 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.
*/
#include <acpi/acpi.h>
/* Headers not included by include/acpi/platform/aclinux.h */
#include <stdbool.h>
#include <fcntl.h>
#include <assert.h>
#include <linux/circ_buf.h>
#define ACPI_AML_FILE "/sys/kernel/debug/acpi/acpidbg"
#define ACPI_AML_SEC_TICK 1
#define ACPI_AML_USEC_PEEK 200
#define ACPI_AML_BUF_SIZE 4096
#define ACPI_AML_BATCH_WRITE_CMD 0x00
/* Write command to kernel */
#define ACPI_AML_BATCH_READ_LOG 0x01
/* Read log from kernel */
#define ACPI_AML_BATCH_WRITE_LOG 0x02
/* Write log to console */
#define ACPI_AML_LOG_START 0x00
#define ACPI_AML_PROMPT_START 0x01
#define ACPI_AML_PROMPT_STOP 0x02
#define ACPI_AML_LOG_STOP 0x03
#define ACPI_AML_PROMPT_ROLL 0x04
#define ACPI_AML_INTERACTIVE 0x00
#define ACPI_AML_BATCH 0x01
#define circ_count(circ) \
(CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
#define circ_count_to_end(circ) \
(CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
#define circ_space(circ) \
(CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
#define circ_space_to_end(circ) \
(CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
#define acpi_aml_cmd_count() circ_count(&acpi_aml_cmd_crc)
#define acpi_aml_log_count() circ_count(&acpi_aml_log_crc)
#define acpi_aml_cmd_space() circ_space(&acpi_aml_cmd_crc)
#define acpi_aml_log_space() circ_space(&acpi_aml_log_crc)
#define ACPI_AML_DO(_fd, _op, _buf, _ret) \
do { \
_ret = acpi_aml_##_op(_fd, &acpi_aml_##_buf##_crc); \
if (_ret == 0) { \
fprintf(stderr, \
"%s %s pipe closed.\n", #_buf, #_op); \
return; \
} \
} while (0)
#define ACPI_AML_BATCH_DO(_fd, _op, _buf, _ret) \
do { \
_ret = acpi_aml_##_op##_batch_##_buf(_fd, \
&acpi_aml_##_buf##_crc); \
if (_ret == 0) \
return; \
} while (0)
static
char
acpi_aml_cmd_buf
[
ACPI_AML_BUF_SIZE
];
static
char
acpi_aml_log_buf
[
ACPI_AML_BUF_SIZE
];
static
struct
circ_buf
acpi_aml_cmd_crc
=
{
.
buf
=
acpi_aml_cmd_buf
,
.
head
=
0
,
.
tail
=
0
,
};
static
struct
circ_buf
acpi_aml_log_crc
=
{
.
buf
=
acpi_aml_log_buf
,
.
head
=
0
,
.
tail
=
0
,
};
static
const
char
*
acpi_aml_file_path
=
ACPI_AML_FILE
;
static
unsigned
long
acpi_aml_mode
=
ACPI_AML_INTERACTIVE
;
static
bool
acpi_aml_exit
;
static
bool
acpi_aml_batch_drain
;
static
unsigned
long
acpi_aml_batch_state
;
static
char
acpi_aml_batch_prompt
;
static
char
acpi_aml_batch_roll
;
static
unsigned
long
acpi_aml_log_state
;
static
char
*
acpi_aml_batch_cmd
=
NULL
;
static
char
*
acpi_aml_batch_pos
=
NULL
;
static
int
acpi_aml_set_fl
(
int
fd
,
int
flags
)
{
int
ret
;
ret
=
fcntl
(
fd
,
F_GETFL
,
0
);
if
(
ret
<
0
)
{
perror
(
"fcntl(F_GETFL)"
);
return
ret
;
}
flags
|=
ret
;
ret
=
fcntl
(
fd
,
F_SETFL
,
flags
);
if
(
ret
<
0
)
{
perror
(
"fcntl(F_SETFL)"
);
return
ret
;
}
return
ret
;
}
static
int
acpi_aml_set_fd
(
int
fd
,
int
maxfd
,
fd_set
*
set
)
{
if
(
fd
>
maxfd
)
maxfd
=
fd
;
FD_SET
(
fd
,
set
);
return
maxfd
;
}
static
int
acpi_aml_read
(
int
fd
,
struct
circ_buf
*
crc
)
{
char
*
p
;
int
len
;
p
=
&
crc
->
buf
[
crc
->
head
];
len
=
circ_space_to_end
(
crc
);
len
=
read
(
fd
,
p
,
len
);
if
(
len
<
0
)
perror
(
"read"
);
else
if
(
len
>
0
)
crc
->
head
=
(
crc
->
head
+
len
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
return
len
;
}
static
int
acpi_aml_read_batch_cmd
(
int
unused
,
struct
circ_buf
*
crc
)
{
char
*
p
;
int
len
;
int
remained
=
strlen
(
acpi_aml_batch_pos
);
p
=
&
crc
->
buf
[
crc
->
head
];
len
=
circ_space_to_end
(
crc
);
if
(
len
>
remained
)
{
memcpy
(
p
,
acpi_aml_batch_pos
,
remained
);
acpi_aml_batch_pos
+=
remained
;
len
=
remained
;
}
else
{
memcpy
(
p
,
acpi_aml_batch_pos
,
len
);
acpi_aml_batch_pos
+=
len
;
}
if
(
len
>
0
)
crc
->
head
=
(
crc
->
head
+
len
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
return
len
;
}
static
int
acpi_aml_read_batch_log
(
int
fd
,
struct
circ_buf
*
crc
)
{
char
*
p
;
int
len
;
int
ret
=
0
;
p
=
&
crc
->
buf
[
crc
->
head
];
len
=
circ_space_to_end
(
crc
);
while
(
ret
<
len
&&
acpi_aml_log_state
!=
ACPI_AML_LOG_STOP
)
{
if
(
acpi_aml_log_state
==
ACPI_AML_PROMPT_ROLL
)
{
*
p
=
acpi_aml_batch_roll
;
len
=
1
;
crc
->
head
=
(
crc
->
head
+
1
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
ret
+=
1
;
acpi_aml_log_state
=
ACPI_AML_LOG_START
;
}
else
{
len
=
read
(
fd
,
p
,
1
);
if
(
len
<=
0
)
{
if
(
len
<
0
)
perror
(
"read"
);
ret
=
len
;
break
;
}
}
switch
(
acpi_aml_log_state
)
{
case
ACPI_AML_LOG_START
:
if
(
*
p
==
'\n'
)
acpi_aml_log_state
=
ACPI_AML_PROMPT_START
;
crc
->
head
=
(
crc
->
head
+
1
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
ret
+=
1
;
break
;
case
ACPI_AML_PROMPT_START
:
if
(
*
p
==
ACPI_DEBUGGER_COMMAND_PROMPT
||
*
p
==
ACPI_DEBUGGER_EXECUTE_PROMPT
)
{
acpi_aml_batch_prompt
=
*
p
;
acpi_aml_log_state
=
ACPI_AML_PROMPT_STOP
;
}
else
{
if
(
*
p
!=
'\n'
)
acpi_aml_log_state
=
ACPI_AML_LOG_START
;
crc
->
head
=
(
crc
->
head
+
1
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
ret
+=
1
;
}
break
;
case
ACPI_AML_PROMPT_STOP
:
if
(
*
p
==
' '
)
{
acpi_aml_log_state
=
ACPI_AML_LOG_STOP
;
acpi_aml_exit
=
true
;
}
else
{
/* Roll back */
acpi_aml_log_state
=
ACPI_AML_PROMPT_ROLL
;
acpi_aml_batch_roll
=
*
p
;
*
p
=
acpi_aml_batch_prompt
;
crc
->
head
=
(
crc
->
head
+
1
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
ret
+=
1
;
}
break
;
default:
assert
(
0
);
break
;
}
}
return
ret
;
}
static
int
acpi_aml_write
(
int
fd
,
struct
circ_buf
*
crc
)
{
char
*
p
;
int
len
;
p
=
&
crc
->
buf
[
crc
->
tail
];
len
=
circ_count_to_end
(
crc
);
len
=
write
(
fd
,
p
,
len
);
if
(
len
<
0
)
perror
(
"write"
);
else
if
(
len
>
0
)
crc
->
tail
=
(
crc
->
tail
+
len
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
return
len
;
}
static
int
acpi_aml_write_batch_log
(
int
fd
,
struct
circ_buf
*
crc
)
{
char
*
p
;
int
len
;
p
=
&
crc
->
buf
[
crc
->
tail
];
len
=
circ_count_to_end
(
crc
);
if
(
!
acpi_aml_batch_drain
)
{
len
=
write
(
fd
,
p
,
len
);
if
(
len
<
0
)
perror
(
"write"
);
}
if
(
len
>
0
)
crc
->
tail
=
(
crc
->
tail
+
len
)
&
(
ACPI_AML_BUF_SIZE
-
1
);
return
len
;
}
static
int
acpi_aml_write_batch_cmd
(
int
fd
,
struct
circ_buf
*
crc
)
{
int
len
;
len
=
acpi_aml_write
(
fd
,
crc
);
if
(
circ_count_to_end
(
crc
)
==
0
)
acpi_aml_batch_state
=
ACPI_AML_BATCH_READ_LOG
;
return
len
;
}
static
void
acpi_aml_loop
(
int
fd
)
{
fd_set
rfds
;
fd_set
wfds
;
struct
timeval
tv
;
int
ret
;
int
maxfd
=
0
;
if
(
acpi_aml_mode
==
ACPI_AML_BATCH
)
{
acpi_aml_log_state
=
ACPI_AML_LOG_START
;
acpi_aml_batch_pos
=
acpi_aml_batch_cmd
;
if
(
acpi_aml_batch_drain
)
acpi_aml_batch_state
=
ACPI_AML_BATCH_READ_LOG
;
else
acpi_aml_batch_state
=
ACPI_AML_BATCH_WRITE_CMD
;
}
acpi_aml_exit
=
false
;
while
(
!
acpi_aml_exit
)
{
tv
.
tv_sec
=
ACPI_AML_SEC_TICK
;
tv
.
tv_usec
=
0
;
FD_ZERO
(
&
rfds
);
FD_ZERO
(
&
wfds
);
if
(
acpi_aml_cmd_space
())
{
if
(
acpi_aml_mode
==
ACPI_AML_INTERACTIVE
)
maxfd
=
acpi_aml_set_fd
(
STDIN_FILENO
,
maxfd
,
&
rfds
);
else
if
(
strlen
(
acpi_aml_batch_pos
)
&&
acpi_aml_batch_state
==
ACPI_AML_BATCH_WRITE_CMD
)
ACPI_AML_BATCH_DO
(
STDIN_FILENO
,
read
,
cmd
,
ret
);
}
if
(
acpi_aml_cmd_count
()
&&
(
acpi_aml_mode
==
ACPI_AML_INTERACTIVE
||
acpi_aml_batch_state
==
ACPI_AML_BATCH_WRITE_CMD
))
maxfd
=
acpi_aml_set_fd
(
fd
,
maxfd
,
&
wfds
);
if
(
acpi_aml_log_space
()
&&
(
acpi_aml_mode
==
ACPI_AML_INTERACTIVE
||
acpi_aml_batch_state
==
ACPI_AML_BATCH_READ_LOG
))
maxfd
=
acpi_aml_set_fd
(
fd
,
maxfd
,
&
rfds
);
if
(
acpi_aml_log_count
())
maxfd
=
acpi_aml_set_fd
(
STDOUT_FILENO
,
maxfd
,
&
wfds
);
ret
=
select
(
maxfd
+
1
,
&
rfds
,
&
wfds
,
NULL
,
&
tv
);
if
(
ret
<
0
)
{
perror
(
"select"
);
break
;
}
if
(
ret
>
0
)
{
if
(
FD_ISSET
(
STDIN_FILENO
,
&
rfds
))
ACPI_AML_DO
(
STDIN_FILENO
,
read
,
cmd
,
ret
);
if
(
FD_ISSET
(
fd
,
&
wfds
))
{
if
(
acpi_aml_mode
==
ACPI_AML_BATCH
)
ACPI_AML_BATCH_DO
(
fd
,
write
,
cmd
,
ret
);
else
ACPI_AML_DO
(
fd
,
write
,
cmd
,
ret
);
}
if
(
FD_ISSET
(
fd
,
&
rfds
))
{
if
(
acpi_aml_mode
==
ACPI_AML_BATCH
)
ACPI_AML_BATCH_DO
(
fd
,
read
,
log
,
ret
);
else
ACPI_AML_DO
(
fd
,
read
,
log
,
ret
);
}
if
(
FD_ISSET
(
STDOUT_FILENO
,
&
wfds
))
{
if
(
acpi_aml_mode
==
ACPI_AML_BATCH
)
ACPI_AML_BATCH_DO
(
STDOUT_FILENO
,
write
,
log
,
ret
);
else
ACPI_AML_DO
(
STDOUT_FILENO
,
write
,
log
,
ret
);
}
}
}
}
static
bool
acpi_aml_readable
(
int
fd
)
{
fd_set
rfds
;
struct
timeval
tv
;
int
ret
;
int
maxfd
=
0
;
tv
.
tv_sec
=
0
;
tv
.
tv_usec
=
ACPI_AML_USEC_PEEK
;
FD_ZERO
(
&
rfds
);
maxfd
=
acpi_aml_set_fd
(
fd
,
maxfd
,
&
rfds
);
ret
=
select
(
maxfd
+
1
,
&
rfds
,
NULL
,
NULL
,
&
tv
);
if
(
ret
<
0
)
perror
(
"select"
);
if
(
ret
>
0
&&
FD_ISSET
(
fd
,
&
rfds
))
return
true
;
return
false
;
}
/*
* This is a userspace IO flush implementation, replying on the prompt
* characters and can be turned into a flush() call after kernel implements
* .flush() filesystem operation.
*/
static
void
acpi_aml_flush
(
int
fd
)
{
while
(
acpi_aml_readable
(
fd
))
{
acpi_aml_batch_drain
=
true
;
acpi_aml_loop
(
fd
);
acpi_aml_batch_drain
=
false
;
}
}
void
usage
(
FILE
*
file
,
char
*
progname
)
{
fprintf
(
file
,
"usage: %s [-b cmd] [-f file] [-h]
\n
"
,
progname
);
fprintf
(
file
,
"
\n
Options:
\n
"
);
fprintf
(
file
,
" -b Specify command to be executed in batch mode
\n
"
);
fprintf
(
file
,
" -f Specify interface file other than"
);
fprintf
(
file
,
" /sys/kernel/debug/acpi/acpidbg
\n
"
);
fprintf
(
file
,
" -h Print this help message
\n
"
);
}
int
main
(
int
argc
,
char
**
argv
)
{
int
fd
=
0
;
int
ch
;
int
len
;
int
ret
=
EXIT_SUCCESS
;
while
((
ch
=
getopt
(
argc
,
argv
,
"b:f:h"
))
!=
-
1
)
{
switch
(
ch
)
{
case
'b'
:
if
(
acpi_aml_batch_cmd
)
{
fprintf
(
stderr
,
"Already specify %s
\n
"
,
acpi_aml_batch_cmd
);
ret
=
EXIT_FAILURE
;
goto
exit
;
}
len
=
strlen
(
optarg
);
acpi_aml_batch_cmd
=
calloc
(
len
+
2
,
1
);
if
(
!
acpi_aml_batch_cmd
)
{
perror
(
"calloc"
);
ret
=
EXIT_FAILURE
;
goto
exit
;
}
memcpy
(
acpi_aml_batch_cmd
,
optarg
,
len
);
acpi_aml_batch_cmd
[
len
]
=
'\n'
;
acpi_aml_mode
=
ACPI_AML_BATCH
;
break
;
case
'f'
:
acpi_aml_file_path
=
optarg
;
break
;
case
'h'
:
usage
(
stdout
,
argv
[
0
]);
goto
exit
;
break
;
case
'?'
:
default:
usage
(
stderr
,
argv
[
0
]);
ret
=
EXIT_FAILURE
;
goto
exit
;
break
;
}
}
fd
=
open
(
acpi_aml_file_path
,
O_RDWR
|
O_NONBLOCK
);
if
(
fd
<
0
)
{
perror
(
"open"
);
ret
=
EXIT_FAILURE
;
goto
exit
;
}
acpi_aml_set_fl
(
STDIN_FILENO
,
O_NONBLOCK
);
acpi_aml_set_fl
(
STDOUT_FILENO
,
O_NONBLOCK
);
if
(
acpi_aml_mode
==
ACPI_AML_BATCH
)
acpi_aml_flush
(
fd
);
acpi_aml_loop
(
fd
);
exit:
if
(
fd
<
0
)
close
(
fd
);
if
(
acpi_aml_batch_cmd
)
free
(
acpi_aml_batch_cmd
);
return
ret
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment