提交 af3fd140 编写于 作者: A Alexey Starikovskiy 提交者: Len Brown

ACPI: ec: Remove expect_event and all races around it.

Signed-off-by: NLen Brown <len.brown@intel.com>
上级 bec5a1e0
...@@ -46,6 +46,9 @@ ACPI_MODULE_NAME("acpi_ec") ...@@ -46,6 +46,9 @@ ACPI_MODULE_NAME("acpi_ec")
#define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_DEVICE_NAME "Embedded Controller"
#define ACPI_EC_FILE_INFO "info" #define ACPI_EC_FILE_INFO "info"
#undef PREFIX
#define PREFIX "ACPI: EC: "
/* EC status register */ /* EC status register */
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
...@@ -101,7 +104,6 @@ struct acpi_ec { ...@@ -101,7 +104,6 @@ struct acpi_ec {
unsigned long data_addr; unsigned long data_addr;
unsigned long global_lock; unsigned long global_lock;
struct semaphore sem; struct semaphore sem;
unsigned int expect_event;
atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
wait_queue_head_t wait; wait_queue_head_t wait;
} *ec_ecdt; } *ec_ecdt;
...@@ -155,34 +157,25 @@ static int acpi_ec_check_status(struct acpi_ec *ec, u8 event) ...@@ -155,34 +157,25 @@ static int acpi_ec_check_status(struct acpi_ec *ec, u8 event)
static int acpi_ec_wait(struct acpi_ec *ec, u8 event) static int acpi_ec_wait(struct acpi_ec *ec, u8 event)
{ {
int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0; if (acpi_ec_mode == EC_POLL) {
long time_left; int i;
for (i = 0; i < ACPI_EC_UDELAY_COUNT; ++i) {
ec->expect_event = event; if (acpi_ec_check_status(ec, event))
if (acpi_ec_check_status(ec, event)) {
ec->expect_event = 0;
return 0;
}
do {
if (acpi_ec_mode == EC_POLL) {
udelay(ACPI_EC_UDELAY);
} else {
time_left = wait_event_timeout(ec->wait,
!ec->expect_event,
msecs_to_jiffies(ACPI_EC_DELAY));
if (time_left > 0) {
ec->expect_event = 0;
return 0; return 0;
} udelay(ACPI_EC_UDELAY);
} }
if (acpi_ec_check_status(ec, event)) { } else {
ec->expect_event = 0; if (wait_event_timeout(ec->wait,
acpi_ec_check_status(ec, event),
msecs_to_jiffies(ACPI_EC_DELAY)) ||
acpi_ec_check_status(ec, event)) {
return 0; return 0;
} else {
printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
" status = %d, expect_event = %d\n",
acpi_ec_read_status(ec), event);
} }
} while (--i > 0); }
ec->expect_event = 0;
return -ETIME; return -ETIME;
} }
...@@ -243,32 +236,41 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, ...@@ -243,32 +236,41 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
const u8 *wdata, unsigned wdata_len, const u8 *wdata, unsigned wdata_len,
u8 *rdata, unsigned rdata_len) u8 *rdata, unsigned rdata_len)
{ {
int result; int result = 0;
acpi_ec_write_cmd(ec, command); acpi_ec_write_cmd(ec, command);
for (; wdata_len > 0; wdata_len --) { for (; wdata_len > 0; wdata_len --) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
if (result) if (result) {
return result; printk(KERN_ERR PREFIX "write_cmd timeout, command = %d\n",
command);
goto end;
}
acpi_ec_write_data(ec, *(wdata++)); acpi_ec_write_data(ec, *(wdata++));
} }
if (!rdata_len) { if (!rdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0);
if (result) if (result) {
return result; printk(KERN_ERR PREFIX "finish-write timeout, command = %d\n",
command);
goto end;
}
} }
for (; rdata_len > 0; rdata_len --) { for (; rdata_len > 0; rdata_len --) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1);
if (result) if (result) {
return result; printk(KERN_ERR PREFIX "read timeout, command = %d\n",
command);
goto end;
}
*(rdata++) = acpi_ec_read_data(ec); *(rdata++) = acpi_ec_read_data(ec);
} }
end:
return 0; return result;
} }
static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
...@@ -419,11 +421,6 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data) ...@@ -419,11 +421,6 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
Event Management Event Management
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
struct acpi_ec_query_data {
acpi_handle handle;
u8 data;
};
static void acpi_ec_gpe_query(void *ec_cxt) static void acpi_ec_gpe_query(void *ec_cxt)
{ {
struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
...@@ -443,7 +440,7 @@ static void acpi_ec_gpe_query(void *ec_cxt) ...@@ -443,7 +440,7 @@ static void acpi_ec_gpe_query(void *ec_cxt)
snprintf(object_name, 8, "_Q%2.2X", value); snprintf(object_name, 8, "_Q%2.2X", value);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); printk(KERN_INFO PREFIX "evaluating %s\n", object_name);
acpi_evaluate_object(ec->handle, object_name, NULL, NULL); acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
...@@ -460,17 +457,12 @@ static u32 acpi_ec_gpe_handler(void *data) ...@@ -460,17 +457,12 @@ static u32 acpi_ec_gpe_handler(void *data)
acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR);
if (acpi_ec_mode == EC_INTR) { if (acpi_ec_mode == EC_INTR) {
if (acpi_ec_check_status(ec, ec->expect_event)) { wake_up(&ec->wait);
ec->expect_event = 0;
wake_up(&ec->wait);
}
} }
value = acpi_ec_read_status(ec); value = acpi_ec_read_status(ec);
if (value & ACPI_EC_FLAG_SCI) { if (value & ACPI_EC_FLAG_SCI) {
status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
return status == AE_OK ?
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
} }
acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
return status == AE_OK ? return status == AE_OK ?
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册