View | Details | Raw Unified | Return to bug 94411 | Differences between
and this patch

Collapse All | Expand All

(-)linux-acpica/drivers/acpi/ec.c (-22 / +60 lines)
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

Return to bug 94411