Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
49897dee
Commit
49897dee
authored
Jan 20, 2010
by
Len Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'bugzilla-14858' into release
parents
378fa825
a62e8f19
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
77 additions
and
45 deletions
+77
-45
drivers/acpi/ec.c
drivers/acpi/ec.c
+77
-45
No files found.
drivers/acpi/ec.c
View file @
49897dee
...
...
@@ -201,14 +201,13 @@ unlock:
spin_unlock_irqrestore
(
&
ec
->
curr_lock
,
flags
);
}
static
void
acpi_ec_gpe_query
(
void
*
ec_cxt
);
static
int
acpi_ec_sync_query
(
struct
acpi_ec
*
ec
);
static
int
ec_check_sci
(
struct
acpi_ec
*
ec
,
u8
state
)
static
int
ec_check_sci
_sync
(
struct
acpi_ec
*
ec
,
u8
state
)
{
if
(
state
&
ACPI_EC_FLAG_SCI
)
{
if
(
!
test_and_set_bit
(
EC_FLAGS_QUERY_PENDING
,
&
ec
->
flags
))
return
acpi_os_execute
(
OSL_EC_BURST_HANDLER
,
acpi_ec_gpe_query
,
ec
);
return
acpi_ec_sync_query
(
ec
);
}
return
0
;
}
...
...
@@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
{
unsigned
long
tmp
;
int
ret
=
0
;
pr_debug
(
PREFIX
"transaction start
\n
"
);
/* disable GPE during transaction if storm is detected */
if
(
test_bit
(
EC_FLAGS_GPE_STORM
,
&
ec
->
flags
))
{
acpi_disable_gpe
(
NULL
,
ec
->
gpe
);
}
if
(
EC_FLAGS_MSI
)
udelay
(
ACPI_EC_MSI_UDELAY
);
/* start transaction */
...
...
@@ -269,16 +263,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
spin_lock_irqsave
(
&
ec
->
curr_lock
,
tmp
);
ec
->
curr
=
NULL
;
spin_unlock_irqrestore
(
&
ec
->
curr_lock
,
tmp
);
if
(
test_bit
(
EC_FLAGS_GPE_STORM
,
&
ec
->
flags
))
{
/* check if we received SCI during transaction */
ec_check_sci
(
ec
,
acpi_ec_read_status
(
ec
));
/* it is safe to enable GPE outside of transaction */
acpi_enable_gpe
(
NULL
,
ec
->
gpe
);
}
else
if
(
t
->
irq_count
>
ACPI_EC_STORM_THRESHOLD
)
{
pr_info
(
PREFIX
"GPE storm detected, "
"transactions will use polling mode
\n
"
);
set_bit
(
EC_FLAGS_GPE_STORM
,
&
ec
->
flags
);
}
return
ret
;
}
...
...
@@ -321,7 +305,24 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
status
=
-
ETIME
;
goto
end
;
}
pr_debug
(
PREFIX
"transaction start
\n
"
);
/* disable GPE during transaction if storm is detected */
if
(
test_bit
(
EC_FLAGS_GPE_STORM
,
&
ec
->
flags
))
{
acpi_disable_gpe
(
NULL
,
ec
->
gpe
);
}
status
=
acpi_ec_transaction_unlocked
(
ec
,
t
);
/* check if we received SCI during transaction */
ec_check_sci_sync
(
ec
,
acpi_ec_read_status
(
ec
));
if
(
test_bit
(
EC_FLAGS_GPE_STORM
,
&
ec
->
flags
))
{
/* it is safe to enable GPE outside of transaction */
acpi_enable_gpe
(
NULL
,
ec
->
gpe
);
}
else
if
(
t
->
irq_count
>
ACPI_EC_STORM_THRESHOLD
)
{
pr_info
(
PREFIX
"GPE storm detected, "
"transactions will use polling mode
\n
"
);
set_bit
(
EC_FLAGS_GPE_STORM
,
&
ec
->
flags
);
}
end:
if
(
ec
->
global_lock
)
acpi_release_global_lock
(
glk
);
...
...
@@ -443,7 +444,7 @@ int ec_transaction(u8 command,
EXPORT_SYMBOL
(
ec_transaction
);
static
int
acpi_ec_query
(
struct
acpi_ec
*
ec
,
u8
*
data
)
static
int
acpi_ec_query
_unlocked
(
struct
acpi_ec
*
ec
,
u8
*
data
)
{
int
result
;
u8
d
;
...
...
@@ -452,20 +453,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
.
wlen
=
0
,
.
rlen
=
1
};
if
(
!
ec
||
!
data
)
return
-
EINVAL
;
/*
* Query the EC to find out which _Qxx method we need to evaluate.
* Note that successful completion of the query causes the ACPI_EC_SCI
* bit to be cleared (and thus clearing the interrupt source).
*/
result
=
acpi_ec_transaction
(
ec
,
&
t
);
result
=
acpi_ec_transaction_unlocked
(
ec
,
&
t
);
if
(
result
)
return
result
;
if
(
!
d
)
return
-
ENODATA
;
*
data
=
d
;
return
0
;
}
...
...
@@ -509,43 +506,78 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
EXPORT_SYMBOL_GPL
(
acpi_ec_remove_query_handler
);
static
void
acpi_ec_
gpe_query
(
void
*
ec_
cxt
)
static
void
acpi_ec_
run
(
void
*
cxt
)
{
struct
acpi_ec
*
ec
=
ec_cxt
;
u8
value
=
0
;
struct
acpi_ec_query_handler
*
handler
,
copy
;
if
(
!
ec
||
acpi_ec_query
(
ec
,
&
value
))
struct
acpi_ec_query_handler
*
handler
=
cxt
;
if
(
!
handler
)
return
;
mutex_lock
(
&
ec
->
lock
);
pr_debug
(
PREFIX
"start query execution
\n
"
);
if
(
handler
->
func
)
handler
->
func
(
handler
->
data
);
else
if
(
handler
->
handle
)
acpi_evaluate_object
(
handler
->
handle
,
NULL
,
NULL
,
NULL
);
pr_debug
(
PREFIX
"stop query execution
\n
"
);
kfree
(
handler
);
}
static
int
acpi_ec_sync_query
(
struct
acpi_ec
*
ec
)
{
u8
value
=
0
;
int
status
;
struct
acpi_ec_query_handler
*
handler
,
*
copy
;
if
((
status
=
acpi_ec_query_unlocked
(
ec
,
&
value
)))
return
status
;
list_for_each_entry
(
handler
,
&
ec
->
list
,
node
)
{
if
(
value
==
handler
->
query_bit
)
{
/* have custom handler for this bit */
memcpy
(
&
copy
,
handler
,
sizeof
(
copy
));
mutex_unlock
(
&
ec
->
lock
);
if
(
copy
.
func
)
{
copy
.
func
(
copy
.
data
);
}
else
if
(
copy
.
handle
)
{
acpi_evaluate_object
(
copy
.
handle
,
NULL
,
NULL
,
NULL
);
}
return
;
copy
=
kmalloc
(
sizeof
(
*
handler
),
GFP_KERNEL
);
if
(
!
copy
)
return
-
ENOMEM
;
memcpy
(
copy
,
handler
,
sizeof
(
*
copy
));
pr_debug
(
PREFIX
"push query execution (0x%2x) on queue
\n
"
,
value
);
return
acpi_os_execute
(
OSL_GPE_HANDLER
,
acpi_ec_run
,
copy
);
}
}
return
0
;
}
static
void
acpi_ec_gpe_query
(
void
*
ec_cxt
)
{
struct
acpi_ec
*
ec
=
ec_cxt
;
if
(
!
ec
)
return
;
mutex_lock
(
&
ec
->
lock
);
acpi_ec_sync_query
(
ec
);
mutex_unlock
(
&
ec
->
lock
);
}
static
void
acpi_ec_gpe_query
(
void
*
ec_cxt
);
static
int
ec_check_sci
(
struct
acpi_ec
*
ec
,
u8
state
)
{
if
(
state
&
ACPI_EC_FLAG_SCI
)
{
if
(
!
test_and_set_bit
(
EC_FLAGS_QUERY_PENDING
,
&
ec
->
flags
))
{
pr_debug
(
PREFIX
"push gpe query to the queue
\n
"
);
return
acpi_os_execute
(
OSL_NOTIFY_HANDLER
,
acpi_ec_gpe_query
,
ec
);
}
}
return
0
;
}
static
u32
acpi_ec_gpe_handler
(
void
*
data
)
{
struct
acpi_ec
*
ec
=
data
;
u8
status
;
pr_debug
(
PREFIX
"~~~> interrupt
\n
"
);
status
=
acpi_ec_read_status
(
ec
);
advance_transaction
(
ec
,
status
);
if
(
ec_transaction_done
(
ec
)
&&
(
status
&
ACPI_EC_FLAG_IBF
)
==
0
)
advance_transaction
(
ec
,
acpi_ec_read_status
(
ec
));
if
(
ec_transaction_done
(
ec
)
&&
(
acpi_ec_read_status
(
ec
)
&
ACPI_EC_FLAG_IBF
)
==
0
)
{
wake_up
(
&
ec
->
wait
);
ec_check_sci
(
ec
,
status
);
ec_check_sci
(
ec
,
acpi_ec_read_status
(
ec
));
}
return
ACPI_INTERRUPT_HANDLED
;
}
...
...
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