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
1004879f
Commit
1004879f
authored
Feb 16, 2007
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Pull bugzilla-7122 into release branch
parents
f0e5ed7f
e8363f33
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
126 additions
and
21 deletions
+126
-21
drivers/acpi/power.c
drivers/acpi/power.c
+126
-21
No files found.
drivers/acpi/power.c
View file @
1004879f
...
@@ -56,6 +56,7 @@ ACPI_MODULE_NAME("power");
...
@@ -56,6 +56,7 @@ ACPI_MODULE_NAME("power");
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
static
int
acpi_power_add
(
struct
acpi_device
*
device
);
static
int
acpi_power_add
(
struct
acpi_device
*
device
);
static
int
acpi_power_remove
(
struct
acpi_device
*
device
,
int
type
);
static
int
acpi_power_remove
(
struct
acpi_device
*
device
,
int
type
);
static
int
acpi_power_resume
(
struct
acpi_device
*
device
);
static
int
acpi_power_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
acpi_power_open_fs
(
struct
inode
*
inode
,
struct
file
*
file
);
static
struct
acpi_driver
acpi_power_driver
=
{
static
struct
acpi_driver
acpi_power_driver
=
{
...
@@ -65,16 +66,23 @@ static struct acpi_driver acpi_power_driver = {
...
@@ -65,16 +66,23 @@ static struct acpi_driver acpi_power_driver = {
.
ops
=
{
.
ops
=
{
.
add
=
acpi_power_add
,
.
add
=
acpi_power_add
,
.
remove
=
acpi_power_remove
,
.
remove
=
acpi_power_remove
,
.
resume
=
acpi_power_resume
,
},
},
};
};
struct
acpi_power_reference
{
struct
list_head
node
;
struct
acpi_device
*
device
;
};
struct
acpi_power_resource
{
struct
acpi_power_resource
{
struct
acpi_device
*
device
;
struct
acpi_device
*
device
;
acpi_bus_id
name
;
acpi_bus_id
name
;
u32
system_level
;
u32
system_level
;
u32
order
;
u32
order
;
int
state
;
int
state
;
int
references
;
struct
mutex
resource_lock
;
struct
list_head
reference
;
};
};
static
struct
list_head
acpi_power_resource_list
;
static
struct
list_head
acpi_power_resource_list
;
...
@@ -170,22 +178,47 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
...
@@ -170,22 +178,47 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
return
result
;
return
result
;
}
}
static
int
acpi_power_on
(
acpi_handle
handle
)
static
int
acpi_power_on
(
acpi_handle
handle
,
struct
acpi_device
*
dev
)
{
{
int
result
=
0
;
int
result
=
0
;
int
found
=
0
;
acpi_status
status
=
AE_OK
;
acpi_status
status
=
AE_OK
;
struct
acpi_device
*
device
=
NULL
;
struct
acpi_power_resource
*
resource
=
NULL
;
struct
acpi_power_resource
*
resource
=
NULL
;
struct
list_head
*
node
,
*
next
;
struct
acpi_power_reference
*
ref
;
result
=
acpi_power_get_context
(
handle
,
&
resource
);
result
=
acpi_power_get_context
(
handle
,
&
resource
);
if
(
result
)
if
(
result
)
return
result
;
return
result
;
resource
->
references
++
;
mutex_lock
(
&
resource
->
resource_lock
);
list_for_each_safe
(
node
,
next
,
&
resource
->
reference
)
{
ref
=
container_of
(
node
,
struct
acpi_power_reference
,
node
);
if
(
dev
->
handle
==
ref
->
device
->
handle
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Device [%s] already referenced by resource [%s]
\n
"
,
dev
->
pnp
.
bus_id
,
resource
->
name
));
found
=
1
;
break
;
}
}
if
(
!
found
)
{
ref
=
kmalloc
(
sizeof
(
struct
acpi_power_reference
),
irqs_disabled
()
?
GFP_ATOMIC
:
GFP_KERNEL
);
if
(
!
ref
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"kmalloc() failed
\n
"
));
mutex_unlock
(
&
resource
->
resource_lock
);
return
-
ENOMEM
;
}
list_add_tail
(
&
ref
->
node
,
&
resource
->
reference
);
ref
->
device
=
dev
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Device [%s] added to resource [%s] references
\n
"
,
dev
->
pnp
.
bus_id
,
resource
->
name
));
}
mutex_unlock
(
&
resource
->
resource_lock
);
if
((
resource
->
references
>
1
)
if
(
resource
->
state
==
ACPI_POWER_RESOURCE_STATE_ON
)
{
||
(
resource
->
state
==
ACPI_POWER_RESOURCE_STATE_ON
))
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Resource [%s] already on
\n
"
,
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Resource [%s] already on
\n
"
,
resource
->
name
));
resource
->
name
));
return
0
;
return
0
;
...
@@ -202,38 +235,49 @@ static int acpi_power_on(acpi_handle handle)
...
@@ -202,38 +235,49 @@ static int acpi_power_on(acpi_handle handle)
return
-
ENOEXEC
;
return
-
ENOEXEC
;
/* Update the power resource's _device_ power state */
/* Update the power resource's _device_ power state */
device
=
resource
->
device
;
resource
->
device
->
power
.
state
=
ACPI_STATE_D0
;
resource
->
device
->
power
.
state
=
ACPI_STATE_D0
;
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Resource [%s] turned on
\n
"
,
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Resource [%s] turned on
\n
"
,
resource
->
name
));
resource
->
name
));
return
0
;
return
0
;
}
}
static
int
acpi_power_off_device
(
acpi_handle
handle
)
static
int
acpi_power_off_device
(
acpi_handle
handle
,
struct
acpi_device
*
dev
)
{
{
int
result
=
0
;
int
result
=
0
;
acpi_status
status
=
AE_OK
;
acpi_status
status
=
AE_OK
;
struct
acpi_power_resource
*
resource
=
NULL
;
struct
acpi_power_resource
*
resource
=
NULL
;
struct
list_head
*
node
,
*
next
;
struct
acpi_power_reference
*
ref
;
result
=
acpi_power_get_context
(
handle
,
&
resource
);
result
=
acpi_power_get_context
(
handle
,
&
resource
);
if
(
result
)
if
(
result
)
return
result
;
return
result
;
if
(
resource
->
references
)
mutex_lock
(
&
resource
->
resource_lock
);
resource
->
references
--
;
list_for_each_safe
(
node
,
next
,
&
resource
->
reference
)
{
ref
=
container_of
(
node
,
struct
acpi_power_reference
,
node
);
if
(
dev
->
handle
==
ref
->
device
->
handle
)
{
list_del
(
&
ref
->
node
);
kfree
(
ref
);
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Device [%s] removed from resource [%s] references
\n
"
,
dev
->
pnp
.
bus_id
,
resource
->
name
));
break
;
}
}
if
(
resource
->
references
)
{
if
(
!
list_empty
(
&
resource
->
reference
)
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Cannot turn resource [%s] off - resource is in use
\n
"
,
"Resource [%s] is still in use, dereferencing
\n
"
,
resource
->
name
));
resource
->
device
->
pnp
.
bus_id
)
);
mutex_unlock
(
&
resource
->
resource_lock
);
return
0
;
return
0
;
}
}
mutex_unlock
(
&
resource
->
resource_lock
);
if
(
resource
->
state
==
ACPI_POWER_RESOURCE_STATE_OFF
)
{
if
(
resource
->
state
==
ACPI_POWER_RESOURCE_STATE_OFF
)
{
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Resource [%s] already off
\n
"
,
ACPI_DEBUG_PRINT
((
ACPI_DB_INFO
,
"Resource [%s] already off
\n
"
,
resource
->
device
->
pnp
.
bus_id
));
resource
->
name
));
return
0
;
return
0
;
}
}
...
@@ -275,7 +319,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev)
...
@@ -275,7 +319,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev)
arg
.
integer
.
value
=
1
;
arg
.
integer
.
value
=
1
;
/* Open power resource */
/* Open power resource */
for
(
i
=
0
;
i
<
dev
->
wakeup
.
resources
.
count
;
i
++
)
{
for
(
i
=
0
;
i
<
dev
->
wakeup
.
resources
.
count
;
i
++
)
{
ret
=
acpi_power_on
(
dev
->
wakeup
.
resources
.
handles
[
i
]);
ret
=
acpi_power_on
(
dev
->
wakeup
.
resources
.
handles
[
i
]
,
dev
);
if
(
ret
)
{
if
(
ret
)
{
printk
(
KERN_ERR
PREFIX
"Transition power state
\n
"
);
printk
(
KERN_ERR
PREFIX
"Transition power state
\n
"
);
dev
->
wakeup
.
flags
.
valid
=
0
;
dev
->
wakeup
.
flags
.
valid
=
0
;
...
@@ -322,7 +366,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
...
@@ -322,7 +366,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
/* Close power resource */
/* Close power resource */
for
(
i
=
0
;
i
<
dev
->
wakeup
.
resources
.
count
;
i
++
)
{
for
(
i
=
0
;
i
<
dev
->
wakeup
.
resources
.
count
;
i
++
)
{
ret
=
acpi_power_off_device
(
dev
->
wakeup
.
resources
.
handles
[
i
]);
ret
=
acpi_power_off_device
(
dev
->
wakeup
.
resources
.
handles
[
i
]
,
dev
);
if
(
ret
)
{
if
(
ret
)
{
printk
(
KERN_ERR
PREFIX
"Transition power state
\n
"
);
printk
(
KERN_ERR
PREFIX
"Transition power state
\n
"
);
dev
->
wakeup
.
flags
.
valid
=
0
;
dev
->
wakeup
.
flags
.
valid
=
0
;
...
@@ -406,7 +450,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
...
@@ -406,7 +450,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
* (e.g. so the device doesn't lose power while transitioning).
* (e.g. so the device doesn't lose power while transitioning).
*/
*/
for
(
i
=
0
;
i
<
tl
->
count
;
i
++
)
{
for
(
i
=
0
;
i
<
tl
->
count
;
i
++
)
{
result
=
acpi_power_on
(
tl
->
handles
[
i
]);
result
=
acpi_power_on
(
tl
->
handles
[
i
]
,
device
);
if
(
result
)
if
(
result
)
goto
end
;
goto
end
;
}
}
...
@@ -415,7 +459,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
...
@@ -415,7 +459,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
* Then we dereference all power resources used in the current list.
* Then we dereference all power resources used in the current list.
*/
*/
for
(
i
=
0
;
i
<
cl
->
count
;
i
++
)
{
for
(
i
=
0
;
i
<
cl
->
count
;
i
++
)
{
result
=
acpi_power_off_device
(
cl
->
handles
[
i
]);
result
=
acpi_power_off_device
(
cl
->
handles
[
i
]
,
device
);
if
(
result
)
if
(
result
)
goto
end
;
goto
end
;
}
}
...
@@ -438,7 +482,11 @@ static struct proc_dir_entry *acpi_power_dir;
...
@@ -438,7 +482,11 @@ static struct proc_dir_entry *acpi_power_dir;
static
int
acpi_power_seq_show
(
struct
seq_file
*
seq
,
void
*
offset
)
static
int
acpi_power_seq_show
(
struct
seq_file
*
seq
,
void
*
offset
)
{
{
int
count
=
0
;
int
result
=
0
;
struct
acpi_power_resource
*
resource
=
NULL
;
struct
acpi_power_resource
*
resource
=
NULL
;
struct
list_head
*
node
,
*
next
;
struct
acpi_power_reference
*
ref
;
resource
=
seq
->
private
;
resource
=
seq
->
private
;
...
@@ -446,6 +494,10 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
...
@@ -446,6 +494,10 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
if
(
!
resource
)
if
(
!
resource
)
goto
end
;
goto
end
;
result
=
acpi_power_get_state
(
resource
);
if
(
result
)
goto
end
;
seq_puts
(
seq
,
"state: "
);
seq_puts
(
seq
,
"state: "
);
switch
(
resource
->
state
)
{
switch
(
resource
->
state
)
{
case
ACPI_POWER_RESOURCE_STATE_ON
:
case
ACPI_POWER_RESOURCE_STATE_ON
:
...
@@ -459,11 +511,18 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
...
@@ -459,11 +511,18 @@ static int acpi_power_seq_show(struct seq_file *seq, void *offset)
break
;
break
;
}
}
mutex_lock
(
&
resource
->
resource_lock
);
list_for_each_safe
(
node
,
next
,
&
resource
->
reference
)
{
ref
=
container_of
(
node
,
struct
acpi_power_reference
,
node
);
count
++
;
}
mutex_unlock
(
&
resource
->
resource_lock
);
seq_printf
(
seq
,
"system level: S%d
\n
"
seq_printf
(
seq
,
"system level: S%d
\n
"
"order: %d
\n
"
"order: %d
\n
"
"reference count: %d
\n
"
,
"reference count: %d
\n
"
,
resource
->
system_level
,
resource
->
system_level
,
resource
->
order
,
resource
->
references
);
resource
->
order
,
count
);
end:
end:
return
0
;
return
0
;
...
@@ -536,6 +595,8 @@ static int acpi_power_add(struct acpi_device *device)
...
@@ -536,6 +595,8 @@ static int acpi_power_add(struct acpi_device *device)
return
-
ENOMEM
;
return
-
ENOMEM
;
resource
->
device
=
device
;
resource
->
device
=
device
;
mutex_init
(
&
resource
->
resource_lock
);
INIT_LIST_HEAD
(
&
resource
->
reference
);
strcpy
(
resource
->
name
,
device
->
pnp
.
bus_id
);
strcpy
(
resource
->
name
,
device
->
pnp
.
bus_id
);
strcpy
(
acpi_device_name
(
device
),
ACPI_POWER_DEVICE_NAME
);
strcpy
(
acpi_device_name
(
device
),
ACPI_POWER_DEVICE_NAME
);
strcpy
(
acpi_device_class
(
device
),
ACPI_POWER_CLASS
);
strcpy
(
acpi_device_class
(
device
),
ACPI_POWER_CLASS
);
...
@@ -583,6 +644,7 @@ static int acpi_power_add(struct acpi_device *device)
...
@@ -583,6 +644,7 @@ static int acpi_power_add(struct acpi_device *device)
static
int
acpi_power_remove
(
struct
acpi_device
*
device
,
int
type
)
static
int
acpi_power_remove
(
struct
acpi_device
*
device
,
int
type
)
{
{
struct
acpi_power_resource
*
resource
=
NULL
;
struct
acpi_power_resource
*
resource
=
NULL
;
struct
list_head
*
node
,
*
next
;
if
(
!
device
||
!
acpi_driver_data
(
device
))
if
(
!
device
||
!
acpi_driver_data
(
device
))
...
@@ -592,11 +654,54 @@ static int acpi_power_remove(struct acpi_device *device, int type)
...
@@ -592,11 +654,54 @@ static int acpi_power_remove(struct acpi_device *device, int type)
acpi_power_remove_fs
(
device
);
acpi_power_remove_fs
(
device
);
mutex_lock
(
&
resource
->
resource_lock
);
list_for_each_safe
(
node
,
next
,
&
resource
->
reference
)
{
struct
acpi_power_reference
*
ref
=
container_of
(
node
,
struct
acpi_power_reference
,
node
);
list_del
(
&
ref
->
node
);
kfree
(
ref
);
}
mutex_unlock
(
&
resource
->
resource_lock
);
kfree
(
resource
);
kfree
(
resource
);
return
0
;
return
0
;
}
}
static
int
acpi_power_resume
(
struct
acpi_device
*
device
)
{
int
result
=
0
;
struct
acpi_power_resource
*
resource
=
NULL
;
struct
acpi_power_reference
*
ref
;
if
(
!
device
||
!
acpi_driver_data
(
device
))
return
-
EINVAL
;
resource
=
(
struct
acpi_power_resource
*
)
acpi_driver_data
(
device
);
result
=
acpi_power_get_state
(
resource
);
if
(
result
)
return
result
;
mutex_lock
(
&
resource
->
resource_lock
);
if
((
resource
->
state
==
ACPI_POWER_RESOURCE_STATE_ON
)
&&
list_empty
(
&
resource
->
reference
))
{
mutex_unlock
(
&
resource
->
resource_lock
);
result
=
acpi_power_off_device
(
device
->
handle
,
NULL
);
return
result
;
}
if
((
resource
->
state
==
ACPI_POWER_RESOURCE_STATE_OFF
)
&&
!
list_empty
(
&
resource
->
reference
))
{
ref
=
container_of
(
resource
->
reference
.
next
,
struct
acpi_power_reference
,
node
);
mutex_unlock
(
&
resource
->
resource_lock
);
result
=
acpi_power_on
(
device
->
handle
,
ref
->
device
);
return
result
;
}
mutex_unlock
(
&
resource
->
resource_lock
);
return
0
;
}
static
int
__init
acpi_power_init
(
void
)
static
int
__init
acpi_power_init
(
void
)
{
{
int
result
=
0
;
int
result
=
0
;
...
...
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