diff options
Diffstat (limited to 'drivers')
-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()) |