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
Kirill Smelkov
linux
Commits
e227e152
Commit
e227e152
authored
Jul 14, 2004
by
Len Brown
Committed by
Len Brown
Jul 14, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[ACPI] ACPI bus support for wakeup GPE (David Shaohua Li)
http://bugzilla.kernel.org/show_bug.cgi?id=1415
parent
5ceb4762
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
243 additions
and
33 deletions
+243
-33
drivers/acpi/power.c
drivers/acpi/power.c
+80
-0
drivers/acpi/scan.c
drivers/acpi/scan.c
+137
-28
include/acpi/acpi_bus.h
include/acpi/acpi_bus.h
+24
-4
include/acpi/acpi_drivers.h
include/acpi/acpi_drivers.h
+2
-1
No files found.
drivers/acpi/power.c
View file @
e227e152
...
...
@@ -288,6 +288,86 @@ acpi_power_off_device (
return_VALUE
(
0
);
}
/*
* Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
* 1. Power on the power resources required for the wakeup device
* 2. Enable _PSW (power state wake) for the device if present
*/
int
acpi_enable_wakeup_device_power
(
struct
acpi_device
*
dev
)
{
union
acpi_object
arg
=
{
ACPI_TYPE_INTEGER
};
struct
acpi_object_list
arg_list
=
{
1
,
&
arg
};
acpi_status
status
=
AE_OK
;
int
i
;
int
ret
=
0
;
ACPI_FUNCTION_TRACE
(
"acpi_enable_wakeup_device_power"
);
if
(
!
dev
||
!
dev
->
wakeup
.
flags
.
valid
)
return
-
1
;
arg
.
integer
.
value
=
1
;
/* Open power resource */
for
(
i
=
0
;
i
<
dev
->
wakeup
.
resources
.
count
;
i
++
)
{
ret
=
acpi_power_on
(
dev
->
wakeup
.
resources
.
handles
[
i
]);
if
(
ret
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"Error transition power state
\n
"
));
dev
->
wakeup
.
flags
.
valid
=
0
;
return
-
1
;
}
}
/* Execute PSW */
status
=
acpi_evaluate_object
(
dev
->
handle
,
"_PSW"
,
&
arg_list
,
NULL
);
if
(
ACPI_FAILURE
(
status
)
&&
(
status
!=
AE_NOT_FOUND
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"Error evaluate _PSW
\n
"
));
dev
->
wakeup
.
flags
.
valid
=
0
;
ret
=
-
1
;
}
return
ret
;
}
/*
* Shutdown a wakeup device, counterpart of above method
* 1. Disable _PSW (power state wake)
* 2. Shutdown down the power resources
*/
int
acpi_disable_wakeup_device_power
(
struct
acpi_device
*
dev
)
{
union
acpi_object
arg
=
{
ACPI_TYPE_INTEGER
};
struct
acpi_object_list
arg_list
=
{
1
,
&
arg
};
acpi_status
status
=
AE_OK
;
int
i
;
int
ret
=
0
;
ACPI_FUNCTION_TRACE
(
"acpi_disable_wakeup_device_power"
);
if
(
!
dev
||
!
dev
->
wakeup
.
flags
.
valid
)
return
-
1
;
arg
.
integer
.
value
=
0
;
/* Execute PSW */
status
=
acpi_evaluate_object
(
dev
->
handle
,
"_PSW"
,
&
arg_list
,
NULL
);
if
(
ACPI_FAILURE
(
status
)
&&
(
status
!=
AE_NOT_FOUND
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"Error evaluate _PSW
\n
"
));
dev
->
wakeup
.
flags
.
valid
=
0
;
return
-
1
;
}
/* Close power resource */
for
(
i
=
0
;
i
<
dev
->
wakeup
.
resources
.
count
;
i
++
)
{
ret
=
acpi_power_off_device
(
dev
->
wakeup
.
resources
.
handles
[
i
]);
if
(
ret
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"Error transition power state
\n
"
));
dev
->
wakeup
.
flags
.
valid
=
0
;
return
-
1
;
}
}
return
ret
;
}
/* --------------------------------------------------------------------------
Device Power Management
...
...
drivers/acpi/scan.c
View file @
e227e152
...
...
@@ -23,7 +23,8 @@ extern struct acpi_device *acpi_root;
#define ACPI_BUS_DEVICE_NAME "System Bus"
static
LIST_HEAD
(
acpi_device_list
);
static
spinlock_t
acpi_device_lock
=
SPIN_LOCK_UNLOCKED
;
spinlock_t
acpi_device_lock
=
SPIN_LOCK_UNLOCKED
;
LIST_HEAD
(
acpi_wakeup_device_list
);
static
void
acpi_device_release
(
struct
kobject
*
kobj
)
{
...
...
@@ -115,9 +116,6 @@ acpi_bus_get_power_flags (
status
=
acpi_get_handle
(
device
->
handle
,
"_IRC"
,
&
handle
);
if
(
ACPI_SUCCESS
(
status
))
device
->
power
.
flags
.
inrush_current
=
1
;
status
=
acpi_get_handle
(
device
->
handle
,
"_PRW"
,
&
handle
);
if
(
ACPI_SUCCESS
(
status
))
device
->
power
.
flags
.
wake_capable
=
1
;
/*
* Enumerate supported power management states
...
...
@@ -163,6 +161,125 @@ acpi_bus_get_power_flags (
return
0
;
}
static
int
acpi_match_ids
(
struct
acpi_device
*
device
,
char
*
ids
)
{
int
error
=
0
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
if
(
device
->
flags
.
hardware_id
)
if
(
strstr
(
ids
,
device
->
pnp
.
hardware_id
))
goto
Done
;
if
(
device
->
flags
.
compatible_ids
)
{
struct
acpi_compatible_id_list
*
cid_list
=
device
->
pnp
.
cid_list
;
int
i
;
/* compare multiple _CID entries against driver ids */
for
(
i
=
0
;
i
<
cid_list
->
count
;
i
++
)
{
if
(
strstr
(
ids
,
cid_list
->
id
[
i
].
value
))
goto
Done
;
}
}
error
=
-
ENOENT
;
Done:
if
(
buffer
.
pointer
)
acpi_os_free
(
buffer
.
pointer
);
return
error
;
}
static
acpi_status
acpi_bus_extract_wakeup_device_power_package
(
struct
acpi_device
*
device
,
union
acpi_object
*
package
)
{
int
i
=
0
;
union
acpi_object
*
element
=
NULL
;
if
(
!
device
||
!
package
||
(
package
->
package
.
count
<
2
))
return
AE_BAD_PARAMETER
;
element
=
&
(
package
->
package
.
elements
[
0
]);
if
(
element
->
type
==
ACPI_TYPE_PACKAGE
)
{
if
((
element
->
package
.
count
<
2
)
||
(
element
->
package
.
elements
[
0
].
type
!=
ACPI_TYPE_LOCAL_REFERENCE
)
||
(
element
->
package
.
elements
[
1
].
type
!=
ACPI_TYPE_INTEGER
))
return
AE_BAD_DATA
;
device
->
wakeup
.
gpe_device
=
element
->
package
.
elements
[
0
].
reference
.
handle
;
device
->
wakeup
.
gpe_number
=
(
u32
)
element
->
package
.
elements
[
1
].
integer
.
value
;
}
else
if
(
element
->
type
==
ACPI_TYPE_INTEGER
)
{
device
->
wakeup
.
gpe_number
=
element
->
integer
.
value
;
}
else
return
AE_BAD_DATA
;
element
=
&
(
package
->
package
.
elements
[
1
]);
if
(
element
->
type
!=
ACPI_TYPE_INTEGER
)
{
return
AE_BAD_DATA
;
}
device
->
wakeup
.
sleep_state
=
element
->
integer
.
value
;
if
((
package
->
package
.
count
-
2
)
>
ACPI_MAX_HANDLES
)
{
return
AE_NO_MEMORY
;
}
device
->
wakeup
.
resources
.
count
=
package
->
package
.
count
-
2
;
for
(
i
=
0
;
i
<
device
->
wakeup
.
resources
.
count
;
i
++
)
{
element
=
&
(
package
->
package
.
elements
[
i
+
2
]);
if
(
element
->
type
!=
ACPI_TYPE_ANY
)
{
return
AE_BAD_DATA
;
}
device
->
wakeup
.
resources
.
handles
[
i
]
=
element
->
reference
.
handle
;
}
return
AE_OK
;
}
static
int
acpi_bus_get_wakeup_device_flags
(
struct
acpi_device
*
device
)
{
acpi_status
status
=
0
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
union
acpi_object
*
package
=
NULL
;
ACPI_FUNCTION_TRACE
(
"acpi_bus_get_wakeup_flags"
);
/* _PRW */
status
=
acpi_evaluate_object
(
device
->
handle
,
"_PRW"
,
NULL
,
&
buffer
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"Error evaluating _PRW
\n
"
));
goto
end
;
}
package
=
(
union
acpi_object
*
)
buffer
.
pointer
;
status
=
acpi_bus_extract_wakeup_device_power_package
(
device
,
package
);
if
(
ACPI_FAILURE
(
status
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_ERROR
,
"Error extracting _PRW package
\n
"
));
goto
end
;
}
acpi_os_free
(
buffer
.
pointer
);
device
->
wakeup
.
flags
.
valid
=
1
;
/* Power button, Lid switch always enable wakeup*/
if
(
!
acpi_match_ids
(
device
,
"PNP0C0D,PNP0C0C,PNP0C0E"
))
device
->
wakeup
.
flags
.
run_wake
=
1
;
/* TBD: lock */
INIT_LIST_HEAD
(
&
device
->
wakeup_list
);
spin_lock
(
&
acpi_device_lock
);
list_add_tail
(
&
device
->
wakeup_list
,
&
acpi_wakeup_device_list
);
spin_unlock
(
&
acpi_device_lock
);
end:
if
(
ACPI_FAILURE
(
status
))
device
->
flags
.
wake_capable
=
0
;
return
0
;
}
/* --------------------------------------------------------------------------
Performance Management
...
...
@@ -195,30 +312,7 @@ acpi_bus_match (
struct
acpi_device
*
device
,
struct
acpi_driver
*
driver
)
{
int
error
=
0
;
struct
acpi_buffer
buffer
=
{
ACPI_ALLOCATE_BUFFER
,
NULL
};
if
(
device
->
flags
.
hardware_id
)
if
(
strstr
(
driver
->
ids
,
device
->
pnp
.
hardware_id
))
goto
Done
;
if
(
device
->
flags
.
compatible_ids
)
{
struct
acpi_compatible_id_list
*
cid_list
=
device
->
pnp
.
cid_list
;
int
i
;
/* compare multiple _CID entries against driver ids */
for
(
i
=
0
;
i
<
cid_list
->
count
;
i
++
)
{
if
(
strstr
(
driver
->
ids
,
cid_list
->
id
[
i
].
value
))
goto
Done
;
}
}
error
=
-
ENOENT
;
Done:
if
(
buffer
.
pointer
)
acpi_os_free
(
buffer
.
pointer
);
return
error
;
return
acpi_match_ids
(
device
,
driver
->
ids
);
}
...
...
@@ -469,6 +563,11 @@ acpi_bus_get_flags (
if
(
ACPI_SUCCESS
(
status
))
device
->
flags
.
power_manageable
=
1
;
/* Presence of _PRW indicates wake capable */
status
=
acpi_get_handle
(
device
->
handle
,
"_PRW"
,
&
temp
);
if
(
ACPI_SUCCESS
(
status
))
device
->
flags
.
wake_capable
=
1
;
/* TBD: Peformance management */
return_VALUE
(
0
);
...
...
@@ -740,6 +839,16 @@ acpi_bus_add (
goto
end
;
}
/*
* Wakeup device management
*-----------------------
*/
if
(
device
->
flags
.
wake_capable
)
{
result
=
acpi_bus_get_wakeup_device_flags
(
device
);
if
(
result
)
goto
end
;
}
/*
* Performance Management
* ----------------------
...
...
include/acpi/acpi_bus.h
View file @
e227e152
...
...
@@ -157,7 +157,8 @@ struct acpi_device_flags {
u32
suprise_removal_ok
:
1
;
u32
power_manageable
:
1
;
u32
performance_manageable
:
1
;
u32
reserved
:
21
;
u32
wake_capable
:
1
;
/* Wakeup(_PRW) supported? */
u32
reserved
:
20
;
};
...
...
@@ -203,10 +204,8 @@ struct acpi_device_power_flags {
u32
explicit_get
:
1
;
/* _PSC present? */
u32
power_resources
:
1
;
/* Power resources */
u32
inrush_current
:
1
;
/* Serialize Dx->D0 */
u32
wake_capable
:
1
;
/* Wakeup supported? */
u32
wake_enabled
:
1
;
/* Enabled for wakeup */
u32
power_removed
:
1
;
/* Optimize Dx->D0 */
u32
reserved
:
2
6
;
u32
reserved
:
2
8
;
};
struct
acpi_device_power_state
{
...
...
@@ -250,6 +249,25 @@ struct acpi_device_perf {
struct
acpi_device_perf_state
*
states
;
};
/* Wakeup Management */
struct
acpi_device_wakeup_flags
{
u8
valid
:
1
;
/* Can successfully enable wakeup? */
u8
run_wake
:
1
;
/* Run-Wake GPE devices */
};
struct
acpi_device_wakeup_state
{
u8
enabled
:
1
;
u8
active
:
1
;
};
struct
acpi_device_wakeup
{
acpi_handle
gpe_device
;
acpi_integer
gpe_number
;;
acpi_integer
sleep_state
;
struct
acpi_handle_list
resources
;
struct
acpi_device_wakeup_state
state
;
struct
acpi_device_wakeup_flags
flags
;
};
/* Device */
...
...
@@ -258,11 +276,13 @@ struct acpi_device {
struct
acpi_device
*
parent
;
struct
list_head
children
;
struct
list_head
node
;
struct
list_head
wakeup_list
;
struct
list_head
g_list
;
struct
acpi_device_status
status
;
struct
acpi_device_flags
flags
;
struct
acpi_device_pnp
pnp
;
struct
acpi_device_power
power
;
struct
acpi_device_wakeup
wakeup
;
struct
acpi_device_perf
performance
;
struct
acpi_device_dir
dir
;
struct
acpi_device_ops
ops
;
...
...
include/acpi/acpi_drivers.h
View file @
e227e152
...
...
@@ -81,7 +81,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, int b
-------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_POWER
int
acpi_enable_wakeup_device_power
(
struct
acpi_device
*
dev
);
int
acpi_disable_wakeup_device_power
(
struct
acpi_device
*
dev
);
int
acpi_power_get_inferred_state
(
struct
acpi_device
*
device
);
int
acpi_power_transition
(
struct
acpi_device
*
device
,
int
state
);
#endif
...
...
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