Lines 161-168
struct transaction {
Link Here
|
161 |
u8 flags; |
161 |
u8 flags; |
162 |
}; |
162 |
}; |
163 |
|
163 |
|
|
|
164 |
struct acpi_ec_query { |
165 |
struct transaction transaction; |
166 |
struct work_struct work; |
167 |
struct acpi_ec_query_handler *handler; |
168 |
}; |
169 |
|
164 |
static int acpi_ec_query(struct acpi_ec *ec, u8 *data); |
170 |
static int acpi_ec_query(struct acpi_ec *ec, u8 *data); |
165 |
static void advance_transaction(struct acpi_ec *ec); |
171 |
static void advance_transaction(struct acpi_ec *ec); |
|
|
172 |
static void acpi_ec_event_handler(struct work_struct *work); |
173 |
static void acpi_ec_event_processor(struct work_struct *work); |
166 |
|
174 |
|
167 |
struct acpi_ec *boot_ec, *first_ec; |
175 |
struct acpi_ec *boot_ec, *first_ec; |
168 |
EXPORT_SYMBOL(first_ec); |
176 |
EXPORT_SYMBOL(first_ec); |
Lines 974-1033
void acpi_ec_remove_query_handler(struct
Link Here
|
974 |
} |
982 |
} |
975 |
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); |
983 |
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); |
976 |
|
984 |
|
977 |
static void acpi_ec_run(void *cxt) |
985 |
static struct acpi_ec_query *acpi_ec_create_query(u8 *pval) |
978 |
{ |
986 |
{ |
979 |
struct acpi_ec_query_handler *handler = cxt; |
987 |
struct acpi_ec_query *q; |
|
|
988 |
struct transaction *t; |
989 |
|
990 |
q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL); |
991 |
if (!q) |
992 |
return NULL; |
993 |
INIT_WORK(&q->work, acpi_ec_event_processor); |
994 |
t = &q->transaction; |
995 |
t->command = ACPI_EC_COMMAND_QUERY; |
996 |
t->rdata = pval; |
997 |
t->rlen = 1; |
998 |
return q; |
999 |
} |
1000 |
|
1001 |
static void acpi_ec_delete_query(struct acpi_ec_query *q) |
1002 |
{ |
1003 |
if (q) { |
1004 |
if (q->handler) |
1005 |
acpi_ec_put_query_handler(q->handler); |
1006 |
kfree(q); |
1007 |
} |
1008 |
} |
1009 |
|
1010 |
static void acpi_ec_event_processor(struct work_struct *work) |
1011 |
{ |
1012 |
struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work); |
1013 |
struct acpi_ec_query_handler *handler = q->handler; |
980 |
|
1014 |
|
981 |
if (!handler) |
|
|
982 |
return; |
983 |
ec_dbg_evt("Query(0x%02x) started", handler->query_bit); |
1015 |
ec_dbg_evt("Query(0x%02x) started", handler->query_bit); |
984 |
if (handler->func) |
1016 |
if (handler->func) |
985 |
handler->func(handler->data); |
1017 |
handler->func(handler->data); |
986 |
else if (handler->handle) |
1018 |
else if (handler->handle) |
987 |
acpi_evaluate_object(handler->handle, NULL, NULL, NULL); |
1019 |
acpi_evaluate_object(handler->handle, NULL, NULL, NULL); |
988 |
ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit); |
1020 |
ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit); |
989 |
acpi_ec_put_query_handler(handler); |
1021 |
acpi_ec_delete_query(q); |
990 |
} |
1022 |
} |
991 |
|
1023 |
|
992 |
static int acpi_ec_query(struct acpi_ec *ec, u8 *data) |
1024 |
static int acpi_ec_query(struct acpi_ec *ec, u8 *data) |
993 |
{ |
1025 |
{ |
994 |
u8 value = 0; |
1026 |
u8 value = 0; |
995 |
int result; |
1027 |
int result; |
996 |
acpi_status status; |
|
|
997 |
struct acpi_ec_query_handler *handler; |
1028 |
struct acpi_ec_query_handler *handler; |
998 |
struct transaction t = {.command = ACPI_EC_COMMAND_QUERY, |
1029 |
struct acpi_ec_query *q; |
999 |
.wdata = NULL, .rdata = &value, |
1030 |
|
1000 |
.wlen = 0, .rlen = 1}; |
1031 |
q = acpi_ec_create_query(&value); |
|
|
1032 |
if (!q) |
1033 |
return -ENOMEM; |
1001 |
|
1034 |
|
1002 |
/* |
1035 |
/* |
1003 |
* Query the EC to find out which _Qxx method we need to evaluate. |
1036 |
* Query the EC to find out which _Qxx method we need to evaluate. |
1004 |
* Note that successful completion of the query causes the ACPI_EC_SCI |
1037 |
* Note that successful completion of the query causes the ACPI_EC_SCI |
1005 |
* bit to be cleared (and thus clearing the interrupt source). |
1038 |
* bit to be cleared (and thus clearing the interrupt source). |
1006 |
*/ |
1039 |
*/ |
1007 |
result = acpi_ec_transaction(ec, &t); |
1040 |
result = acpi_ec_transaction(ec, &q->transaction); |
1008 |
if (result) |
|
|
1009 |
return result; |
1010 |
if (data) |
1011 |
*data = value; |
1012 |
if (!value) |
1041 |
if (!value) |
1013 |
return -ENODATA; |
1042 |
result = -ENODATA; |
|
|
1043 |
if (result) |
1044 |
goto err_exit; |
1014 |
|
1045 |
|
1015 |
mutex_lock(&ec->mutex); |
1046 |
mutex_lock(&ec->mutex); |
1016 |
list_for_each_entry(handler, &ec->list, node) { |
1047 |
list_for_each_entry(handler, &ec->list, node) { |
1017 |
if (value == handler->query_bit) { |
1048 |
if (value == handler->query_bit) { |
1018 |
/* have custom handler for this bit */ |
1049 |
q->handler = acpi_ec_get_query_handler(handler); |
1019 |
handler = acpi_ec_get_query_handler(handler); |
|
|
1020 |
ec_dbg_evt("Query(0x%02x) scheduled", |
1050 |
ec_dbg_evt("Query(0x%02x) scheduled", |
1021 |
handler->query_bit); |
1051 |
q->handler->query_bit); |
1022 |
status = acpi_os_execute((handler->func) ? |
1052 |
/* |
1023 |
OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, |
1053 |
* It is reported that _Qxx are evaluated in a |
1024 |
acpi_ec_run, handler); |
1054 |
* parallel way on Windows: |
1025 |
if (ACPI_FAILURE(status)) |
1055 |
* https://bugzilla.kernel.org/show_bug.cgi?id=94411 |
|
|
1056 |
*/ |
1057 |
if (!schedule_work(&q->work)) |
1026 |
result = -EBUSY; |
1058 |
result = -EBUSY; |
1027 |
break; |
1059 |
break; |
1028 |
} |
1060 |
} |
1029 |
} |
1061 |
} |
1030 |
mutex_unlock(&ec->mutex); |
1062 |
mutex_unlock(&ec->mutex); |
|
|
1063 |
|
1064 |
err_exit: |
1065 |
if (result && q) |
1066 |
acpi_ec_delete_query(q); |
1067 |
if (data) |
1068 |
*data = value; |
1031 |
return result; |
1069 |
return result; |
1032 |
} |
1070 |
} |
1033 |
|
1071 |
|