diff options
| author | Alexey Starikovskiy <astarikovskiy@suse.de> | 2008-03-21 10:07:15 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2008-03-24 20:49:48 -0400 |
| commit | b77d81b2678950077088956da4638c26853389fc (patch) | |
| tree | 6042a45ab53f06fb4518611609eef72fe1c3d801 | |
| parent | dc0e8490fe884a9378b8ee04a5b5f905f06f4633 (diff) | |
ACPI: EC: Replace broken controller workarounds with poll mode.
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | drivers/acpi/ec.c | 61 |
1 files changed, 12 insertions, 49 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 1a7949c757b3..7f07b6806ac0 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -79,11 +79,7 @@ enum { | |||
| 79 | EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ | 79 | EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ |
| 80 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ | 80 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ |
| 81 | EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ | 81 | EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ |
| 82 | EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */ | 82 | EC_FLAGS_NO_GPE, /* Don't use GPE mode */ |
| 83 | EC_FLAGS_ADDRESS, /* Address is being written */ | ||
| 84 | EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ | ||
| 85 | EC_FLAGS_WDATA, /* Data is being written */ | ||
| 86 | EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ | ||
| 87 | EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ | 83 | EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ |
| 88 | }; | 84 | }; |
| 89 | 85 | ||
| @@ -189,6 +185,7 @@ static void ec_schedule_ec_poll(struct acpi_ec *ec) | |||
| 189 | 185 | ||
| 190 | static void ec_switch_to_poll_mode(struct acpi_ec *ec) | 186 | static void ec_switch_to_poll_mode(struct acpi_ec *ec) |
| 191 | { | 187 | { |
| 188 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); | ||
| 192 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 189 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
| 193 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | 190 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); |
| 194 | set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); | 191 | set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); |
| @@ -196,65 +193,34 @@ static void ec_switch_to_poll_mode(struct acpi_ec *ec) | |||
| 196 | 193 | ||
| 197 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | 194 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) |
| 198 | { | 195 | { |
| 199 | int ret = 0; | ||
| 200 | |||
| 201 | if (unlikely(event == ACPI_EC_EVENT_OBF_1 && | ||
| 202 | test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) | ||
| 203 | force_poll = 1; | ||
| 204 | if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && | ||
| 205 | test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) | ||
| 206 | force_poll = 1; | ||
| 207 | if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) && | ||
| 208 | test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags))) | ||
| 209 | force_poll = 1; | ||
| 210 | if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && | 196 | if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && |
| 211 | likely(!force_poll)) { | 197 | likely(!force_poll)) { |
| 212 | if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), | 198 | if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), |
| 213 | msecs_to_jiffies(ACPI_EC_DELAY))) | 199 | msecs_to_jiffies(ACPI_EC_DELAY))) |
| 214 | goto end; | 200 | return 0; |
| 215 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 201 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
| 216 | if (acpi_ec_check_status(ec, event)) { | 202 | if (acpi_ec_check_status(ec, event)) { |
| 217 | if (event == ACPI_EC_EVENT_OBF_1) { | 203 | /* missing GPEs, switch back to poll mode */ |
| 218 | /* miss OBF_1 GPE, don't expect it */ | 204 | if (printk_ratelimit()) |
| 219 | pr_info(PREFIX "missing OBF confirmation, " | 205 | pr_info(PREFIX "missing confirmations, " |
| 220 | "don't expect it any longer.\n"); | ||
| 221 | set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags); | ||
| 222 | } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { | ||
| 223 | /* miss address GPE, don't expect it anymore */ | ||
| 224 | pr_info(PREFIX "missing address confirmation, " | ||
| 225 | "don't expect it any longer.\n"); | ||
| 226 | set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags); | ||
| 227 | } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) { | ||
| 228 | /* miss write data GPE, don't expect it */ | ||
| 229 | pr_info(PREFIX "missing write data confirmation, " | ||
| 230 | "don't expect it any longer.\n"); | ||
| 231 | set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags); | ||
| 232 | } else { | ||
| 233 | /* missing GPEs, switch back to poll mode */ | ||
| 234 | if (printk_ratelimit()) | ||
| 235 | pr_info(PREFIX "missing confirmations, " | ||
| 236 | "switch off interrupt mode.\n"); | 206 | "switch off interrupt mode.\n"); |
| 237 | ec_switch_to_poll_mode(ec); | 207 | ec_switch_to_poll_mode(ec); |
| 238 | ec_schedule_ec_poll(ec); | 208 | ec_schedule_ec_poll(ec); |
| 239 | } | 209 | return 0; |
| 240 | goto end; | ||
| 241 | } | 210 | } |
| 242 | } else { | 211 | } else { |
| 243 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 212 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); |
| 244 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 213 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
| 245 | while (time_before(jiffies, delay)) { | 214 | while (time_before(jiffies, delay)) { |
| 246 | if (acpi_ec_check_status(ec, event)) | 215 | if (acpi_ec_check_status(ec, event)) |
| 247 | goto end; | 216 | return 0; |
| 248 | udelay(ACPI_EC_UDELAY); | 217 | udelay(ACPI_EC_UDELAY); |
| 249 | } | 218 | } |
| 250 | } | 219 | } |
| 251 | pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", | 220 | pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", |
| 252 | acpi_ec_read_status(ec), | 221 | acpi_ec_read_status(ec), |
| 253 | (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); | 222 | (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); |
| 254 | ret = -ETIME; | 223 | return -ETIME; |
| 255 | end: | ||
| 256 | clear_bit(EC_FLAGS_ADDRESS, &ec->flags); | ||
| 257 | return ret; | ||
| 258 | } | 224 | } |
| 259 | 225 | ||
| 260 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | 226 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, |
| @@ -273,15 +239,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
| 273 | "write_cmd timeout, command = %d\n", command); | 239 | "write_cmd timeout, command = %d\n", command); |
| 274 | goto end; | 240 | goto end; |
| 275 | } | 241 | } |
| 276 | /* mark the address byte written to EC */ | ||
| 277 | if (rdata_len + wdata_len > 1) | ||
| 278 | set_bit(EC_FLAGS_ADDRESS, &ec->flags); | ||
| 279 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 242 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
| 280 | acpi_ec_write_data(ec, *(wdata++)); | 243 | acpi_ec_write_data(ec, *(wdata++)); |
| 281 | } | 244 | } |
| 282 | 245 | ||
| 283 | if (!rdata_len) { | 246 | if (!rdata_len) { |
| 284 | set_bit(EC_FLAGS_WDATA, &ec->flags); | ||
| 285 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); | 247 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); |
| 286 | if (result) { | 248 | if (result) { |
| 287 | pr_err(PREFIX | 249 | pr_err(PREFIX |
| @@ -558,6 +520,7 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
| 558 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, | 520 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, |
| 559 | acpi_ec_gpe_query, ec); | 521 | acpi_ec_gpe_query, ec); |
| 560 | } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && | 522 | } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
| 523 | !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && | ||
| 561 | in_interrupt()) { | 524 | in_interrupt()) { |
| 562 | /* this is non-query, must be confirmation */ | 525 | /* this is non-query, must be confirmation */ |
| 563 | if (printk_ratelimit()) | 526 | if (printk_ratelimit()) |
