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
e5e54bc8
Commit
e5e54bc8
authored
Feb 07, 2008
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'release' and 'stats' into release
parents
70ec75c5
5229e87d
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
325 additions
and
9 deletions
+325
-9
Documentation/ABI/testing/sysfs-firmware-acpi
Documentation/ABI/testing/sysfs-firmware-acpi
+99
-0
drivers/acpi/events/evevent.c
drivers/acpi/events/evevent.c
+1
-1
drivers/acpi/events/evgpe.c
drivers/acpi/events/evgpe.c
+1
-1
drivers/acpi/osl.c
drivers/acpi/osl.c
+11
-1
drivers/acpi/system.c
drivers/acpi/system.c
+208
-0
drivers/acpi/utilities/utglobal.c
drivers/acpi/utilities/utglobal.c
+0
-2
include/acpi/acglobal.h
include/acpi/acglobal.h
+0
-4
include/acpi/acpiosxf.h
include/acpi/acpiosxf.h
+3
-0
include/linux/acpi.h
include/linux/acpi.h
+2
-0
No files found.
Documentation/ABI/testing/sysfs-firmware-acpi
0 → 100644
View file @
e5e54bc8
What: /sys/firmware/acpi/interrupts/
Date: February 2008
Contact: Len Brown <lenb@kernel.org>
Description:
All ACPI interrupts are handled via a single IRQ,
the System Control Interrupt (SCI), which appears
as "acpi" in /proc/interrupts.
However, one of the main functions of ACPI is to make
the platform understand random hardware without
special driver support. So while the SCI handles a few
well known (fixed feature) interrupts sources, such
as the power button, it can also handle a variable
number of a "General Purpose Events" (GPE).
A GPE vectors to a specified handler in AML, which
can do a anything the BIOS writer wants from
OS context. GPE 0x12, for example, would vector
to a level or edge handler called _L12 or _E12.
The handler may do its business and return.
Or the handler may send send a Notify event
to a Linux device driver registered on an ACPI device,
such as a battery, or a processor.
To figure out where all the SCI's are coming from,
/sys/firmware/acpi/interrupts contains a file listing
every possible source, and the count of how many
times it has triggered.
$ cd /sys/firmware/acpi/interrupts
$ grep . *
error:0
ff_gbl_lock:0
ff_pmtimer:0
ff_pwr_btn:0
ff_rt_clk:0
ff_slp_btn:0
gpe00:0
gpe01:0
gpe02:0
gpe03:0
gpe04:0
gpe05:0
gpe06:0
gpe07:0
gpe08:0
gpe09:174
gpe0A:0
gpe0B:0
gpe0C:0
gpe0D:0
gpe0E:0
gpe0F:0
gpe10:0
gpe11:60
gpe12:0
gpe13:0
gpe14:0
gpe15:0
gpe16:0
gpe17:0
gpe18:0
gpe19:7
gpe1A:0
gpe1B:0
gpe1C:0
gpe1D:0
gpe1E:0
gpe1F:0
gpe_all:241
sci:241
sci - The total number of times the ACPI SCI
has claimed an interrupt.
gpe_all - count of SCI caused by GPEs.
gpeXX - count for individual GPE source
ff_gbl_lock - Global Lock
ff_pmtimer - PM Timer
ff_pwr_btn - Power Button
ff_rt_clk - Real Time Clock
ff_slp_btn - Sleep Button
error - an interrupt that can't be accounted for above.
Root has permission to clear any of these counters. Eg.
# echo 0 > gpe11
All counters can be cleared by clearing the total "sci":
# echo 0 > sci
None of these counters has an effect on the function
of the system, they are simply statistics.
drivers/acpi/events/evevent.c
View file @
e5e54bc8
...
...
@@ -259,7 +259,7 @@ u32 acpi_ev_fixed_event_detect(void)
enable_bit_mask
))
{
/* Found an active (signalled) event */
acpi_os_fixed_event_count
(
i
);
int_status
|=
acpi_ev_fixed_event_dispatch
((
u32
)
i
);
}
}
...
...
drivers/acpi/events/evgpe.c
View file @
e5e54bc8
...
...
@@ -627,7 +627,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
ACPI_FUNCTION_TRACE
(
ev_gpe_dispatch
);
acpi_
gpe_count
++
;
acpi_
os_gpe_count
(
gpe_number
)
;
/*
* If edge-triggered, clear the GPE status bit now. Note that
...
...
drivers/acpi/osl.c
View file @
e5e54bc8
...
...
@@ -337,7 +337,15 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
static
irqreturn_t
acpi_irq
(
int
irq
,
void
*
dev_id
)
{
return
(
*
acpi_irq_handler
)
(
acpi_irq_context
)
?
IRQ_HANDLED
:
IRQ_NONE
;
u32
handled
;
handled
=
(
*
acpi_irq_handler
)
(
acpi_irq_context
);
if
(
handled
)
{
acpi_irq_handled
++
;
return
IRQ_HANDLED
;
}
else
return
IRQ_NONE
;
}
acpi_status
...
...
@@ -346,6 +354,8 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
{
unsigned
int
irq
;
acpi_irq_stats_init
();
/*
* Ignore the GSI from the core, and use the value in our copy of the
* FADT. It may not be the same if an interrupt source override exists
...
...
drivers/acpi/system.c
View file @
e5e54bc8
...
...
@@ -40,6 +40,8 @@ ACPI_MODULE_NAME("system");
#define ACPI_SYSTEM_CLASS "system"
#define ACPI_SYSTEM_DEVICE_NAME "System"
u32
acpi_irq_handled
;
/*
* Make ACPICA version work as module param
*/
...
...
@@ -166,6 +168,212 @@ static int acpi_system_sysfs_init(void)
return
0
;
}
/*
* Detailed ACPI IRQ counters in /sys/firmware/acpi/interrupts/
* See Documentation/ABI/testing/sysfs-firmware-acpi
*/
#define COUNT_GPE 0
#define COUNT_SCI 1
/* acpi_irq_handled */
#define COUNT_ERROR 2
/* other */
#define NUM_COUNTERS_EXTRA 3
static
u32
*
all_counters
;
static
u32
num_gpes
;
static
u32
num_counters
;
static
struct
attribute
**
all_attrs
;
static
u32
acpi_gpe_count
;
static
struct
attribute_group
interrupt_stats_attr_group
=
{
.
name
=
"interrupts"
,
};
static
struct
kobj_attribute
*
counter_attrs
;
static
int
count_num_gpes
(
void
)
{
int
count
=
0
;
struct
acpi_gpe_xrupt_info
*
gpe_xrupt_info
;
struct
acpi_gpe_block_info
*
gpe_block
;
acpi_cpu_flags
flags
;
flags
=
acpi_os_acquire_lock
(
acpi_gbl_gpe_lock
);
gpe_xrupt_info
=
acpi_gbl_gpe_xrupt_list_head
;
while
(
gpe_xrupt_info
)
{
gpe_block
=
gpe_xrupt_info
->
gpe_block_list_head
;
while
(
gpe_block
)
{
count
+=
gpe_block
->
register_count
*
ACPI_GPE_REGISTER_WIDTH
;
gpe_block
=
gpe_block
->
next
;
}
gpe_xrupt_info
=
gpe_xrupt_info
->
next
;
}
acpi_os_release_lock
(
acpi_gbl_gpe_lock
,
flags
);
return
count
;
}
static
void
delete_gpe_attr_array
(
void
)
{
u32
*
tmp
=
all_counters
;
all_counters
=
NULL
;
kfree
(
tmp
);
if
(
counter_attrs
)
{
int
i
;
for
(
i
=
0
;
i
<
num_gpes
;
i
++
)
kfree
(
counter_attrs
[
i
].
attr
.
name
);
kfree
(
counter_attrs
);
}
kfree
(
all_attrs
);
return
;
}
void
acpi_os_gpe_count
(
u32
gpe_number
)
{
acpi_gpe_count
++
;
if
(
!
all_counters
)
return
;
if
(
gpe_number
<
num_gpes
)
all_counters
[
gpe_number
]
++
;
else
all_counters
[
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
COUNT_ERROR
]
++
;
return
;
}
void
acpi_os_fixed_event_count
(
u32
event_number
)
{
if
(
!
all_counters
)
return
;
if
(
event_number
<
ACPI_NUM_FIXED_EVENTS
)
all_counters
[
num_gpes
+
event_number
]
++
;
else
all_counters
[
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
COUNT_ERROR
]
++
;
return
;
}
static
ssize_t
counter_show
(
struct
kobject
*
kobj
,
struct
kobj_attribute
*
attr
,
char
*
buf
)
{
all_counters
[
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
COUNT_SCI
]
=
acpi_irq_handled
;
all_counters
[
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
COUNT_GPE
]
=
acpi_gpe_count
;
return
sprintf
(
buf
,
"%d
\n
"
,
all_counters
[
attr
-
counter_attrs
]);
}
/*
* counter_set() sets the specified counter.
* setting the total "sci" file to any value clears all counters.
*/
static
ssize_t
counter_set
(
struct
kobject
*
kobj
,
struct
kobj_attribute
*
attr
,
const
char
*
buf
,
size_t
size
)
{
int
index
=
attr
-
counter_attrs
;
if
(
index
==
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
COUNT_SCI
)
{
int
i
;
for
(
i
=
0
;
i
<
num_counters
;
++
i
)
all_counters
[
i
]
=
0
;
acpi_gpe_count
=
0
;
acpi_irq_handled
=
0
;
}
else
all_counters
[
index
]
=
strtoul
(
buf
,
NULL
,
0
);
return
size
;
}
void
acpi_irq_stats_init
(
void
)
{
int
i
;
if
(
all_counters
)
return
;
num_gpes
=
count_num_gpes
();
num_counters
=
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
NUM_COUNTERS_EXTRA
;
all_attrs
=
kzalloc
(
sizeof
(
struct
attribute
*
)
*
(
num_counters
+
1
),
GFP_KERNEL
);
if
(
all_attrs
==
NULL
)
return
;
all_counters
=
kzalloc
(
sizeof
(
u32
)
*
(
num_counters
),
GFP_KERNEL
);
if
(
all_counters
==
NULL
)
goto
fail
;
counter_attrs
=
kzalloc
(
sizeof
(
struct
kobj_attribute
)
*
(
num_counters
),
GFP_KERNEL
);
if
(
counter_attrs
==
NULL
)
goto
fail
;
for
(
i
=
0
;
i
<
num_counters
;
++
i
)
{
char
buffer
[
10
];
char
*
name
;
if
(
i
<
num_gpes
)
sprintf
(
buffer
,
"gpe%02X"
,
i
);
else
if
(
i
==
num_gpes
+
ACPI_EVENT_PMTIMER
)
sprintf
(
buffer
,
"ff_pmtimer"
);
else
if
(
i
==
num_gpes
+
ACPI_EVENT_GLOBAL
)
sprintf
(
buffer
,
"ff_gbl_lock"
);
else
if
(
i
==
num_gpes
+
ACPI_EVENT_POWER_BUTTON
)
sprintf
(
buffer
,
"ff_pwr_btn"
);
else
if
(
i
==
num_gpes
+
ACPI_EVENT_SLEEP_BUTTON
)
sprintf
(
buffer
,
"ff_slp_btn"
);
else
if
(
i
==
num_gpes
+
ACPI_EVENT_RTC
)
sprintf
(
buffer
,
"ff_rt_clk"
);
else
if
(
i
==
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
COUNT_GPE
)
sprintf
(
buffer
,
"gpe_all"
);
else
if
(
i
==
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
COUNT_SCI
)
sprintf
(
buffer
,
"sci"
);
else
if
(
i
==
num_gpes
+
ACPI_NUM_FIXED_EVENTS
+
COUNT_ERROR
)
sprintf
(
buffer
,
"error"
);
else
sprintf
(
buffer
,
"bug%02X"
,
i
);
name
=
kzalloc
(
strlen
(
buffer
)
+
1
,
GFP_KERNEL
);
if
(
name
==
NULL
)
goto
fail
;
strncpy
(
name
,
buffer
,
strlen
(
buffer
)
+
1
);
counter_attrs
[
i
].
attr
.
name
=
name
;
counter_attrs
[
i
].
attr
.
mode
=
0644
;
counter_attrs
[
i
].
show
=
counter_show
;
counter_attrs
[
i
].
store
=
counter_set
;
all_attrs
[
i
]
=
&
counter_attrs
[
i
].
attr
;
}
interrupt_stats_attr_group
.
attrs
=
all_attrs
;
sysfs_create_group
(
acpi_kobj
,
&
interrupt_stats_attr_group
);
return
;
fail:
delete_gpe_attr_array
();
return
;
}
static
void
__exit
interrupt_stats_exit
(
void
)
{
sysfs_remove_group
(
acpi_kobj
,
&
interrupt_stats_attr_group
);
delete_gpe_attr_array
();
return
;
}
/* --------------------------------------------------------------------------
FS Interface (/proc)
-------------------------------------------------------------------------- */
...
...
drivers/acpi/utilities/utglobal.c
View file @
e5e54bc8
...
...
@@ -671,7 +671,6 @@ void acpi_ut_init_globals(void)
/* GPE support */
acpi_gpe_count
=
0
;
acpi_gbl_gpe_xrupt_list_head
=
NULL
;
acpi_gbl_gpe_fadt_blocks
[
0
]
=
NULL
;
acpi_gbl_gpe_fadt_blocks
[
1
]
=
NULL
;
...
...
@@ -735,4 +734,3 @@ void acpi_ut_init_globals(void)
ACPI_EXPORT_SYMBOL
(
acpi_dbg_level
)
ACPI_EXPORT_SYMBOL
(
acpi_dbg_layer
)
ACPI_EXPORT_SYMBOL
(
acpi_gpe_count
)
include/acpi/acglobal.h
View file @
e5e54bc8
...
...
@@ -117,10 +117,6 @@ extern u32 acpi_dbg_layer;
extern
u32
acpi_gbl_nesting_level
;
/* Event counters */
ACPI_EXTERN
u32
acpi_gpe_count
;
/* Support for dynamic control method tracing mechanism */
ACPI_EXTERN
u32
acpi_gbl_original_dbg_level
;
...
...
include/acpi/acpiosxf.h
View file @
e5e54bc8
...
...
@@ -181,6 +181,9 @@ acpi_os_install_interrupt_handler(u32 gsi,
acpi_status
acpi_os_remove_interrupt_handler
(
u32
gsi
,
acpi_osd_handler
service_routine
);
void
acpi_os_gpe_count
(
u32
gpe_number
);
void
acpi_os_fixed_event_count
(
u32
fixed_event_number
);
/*
* Threads and Scheduling
*/
...
...
include/linux/acpi.h
View file @
e5e54bc8
...
...
@@ -114,7 +114,9 @@ int acpi_unmap_lsapic(int cpu);
int
acpi_register_ioapic
(
acpi_handle
handle
,
u64
phys_addr
,
u32
gsi_base
);
int
acpi_unregister_ioapic
(
acpi_handle
handle
,
u32
gsi_base
);
void
acpi_irq_stats_init
(
void
);
extern
u32
acpi_irq_handled
;
extern
int
acpi_mp_config
;
extern
struct
acpi_mcfg_allocation
*
pci_mmcfg_config
;
...
...
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