diff options
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r-- | drivers/acpi/ec.c | 123 |
1 files changed, 87 insertions, 36 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a8dd2f763382..220d6406c9e9 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -137,6 +137,50 @@ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ | |||
137 | static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ | 137 | static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ |
138 | 138 | ||
139 | /* -------------------------------------------------------------------------- | 139 | /* -------------------------------------------------------------------------- |
140 | * Logging/Debugging | ||
141 | * -------------------------------------------------------------------------- */ | ||
142 | |||
143 | /* | ||
144 | * Splitters used by the developers to track the boundary of the EC | ||
145 | * handling processes. | ||
146 | */ | ||
147 | #ifdef DEBUG | ||
148 | #define EC_DBG_SEP " " | ||
149 | #define EC_DBG_DRV "+++++" | ||
150 | #define EC_DBG_STM "=====" | ||
151 | #define EC_DBG_REQ "*****" | ||
152 | #define EC_DBG_EVT "#####" | ||
153 | #else | ||
154 | #define EC_DBG_SEP "" | ||
155 | #define EC_DBG_DRV | ||
156 | #define EC_DBG_STM | ||
157 | #define EC_DBG_REQ | ||
158 | #define EC_DBG_EVT | ||
159 | #endif | ||
160 | |||
161 | #define ec_log_raw(fmt, ...) \ | ||
162 | pr_info(fmt "\n", ##__VA_ARGS__) | ||
163 | #define ec_dbg_raw(fmt, ...) \ | ||
164 | pr_debug(fmt "\n", ##__VA_ARGS__) | ||
165 | #define ec_log(filter, fmt, ...) \ | ||
166 | ec_log_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__) | ||
167 | #define ec_dbg(filter, fmt, ...) \ | ||
168 | ec_dbg_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__) | ||
169 | |||
170 | #define ec_log_drv(fmt, ...) \ | ||
171 | ec_log(EC_DBG_DRV, fmt, ##__VA_ARGS__) | ||
172 | #define ec_dbg_drv(fmt, ...) \ | ||
173 | ec_dbg(EC_DBG_DRV, fmt, ##__VA_ARGS__) | ||
174 | #define ec_dbg_stm(fmt, ...) \ | ||
175 | ec_dbg(EC_DBG_STM, fmt, ##__VA_ARGS__) | ||
176 | #define ec_dbg_req(fmt, ...) \ | ||
177 | ec_dbg(EC_DBG_REQ, fmt, ##__VA_ARGS__) | ||
178 | #define ec_dbg_evt(fmt, ...) \ | ||
179 | ec_dbg(EC_DBG_EVT, fmt, ##__VA_ARGS__) | ||
180 | #define ec_dbg_ref(ec, fmt, ...) \ | ||
181 | ec_dbg_raw("%lu: " fmt, ec->reference_count, ## __VA_ARGS__) | ||
182 | |||
183 | /* -------------------------------------------------------------------------- | ||
140 | * Device Flags | 184 | * Device Flags |
141 | * -------------------------------------------------------------------------- */ | 185 | * -------------------------------------------------------------------------- */ |
142 | 186 | ||
@@ -159,14 +203,14 @@ static inline u8 acpi_ec_read_status(struct acpi_ec *ec) | |||
159 | { | 203 | { |
160 | u8 x = inb(ec->command_addr); | 204 | u8 x = inb(ec->command_addr); |
161 | 205 | ||
162 | pr_debug("EC_SC(R) = 0x%2.2x " | 206 | ec_dbg_raw("EC_SC(R) = 0x%2.2x " |
163 | "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n", | 207 | "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d", |
164 | x, | 208 | x, |
165 | !!(x & ACPI_EC_FLAG_SCI), | 209 | !!(x & ACPI_EC_FLAG_SCI), |
166 | !!(x & ACPI_EC_FLAG_BURST), | 210 | !!(x & ACPI_EC_FLAG_BURST), |
167 | !!(x & ACPI_EC_FLAG_CMD), | 211 | !!(x & ACPI_EC_FLAG_CMD), |
168 | !!(x & ACPI_EC_FLAG_IBF), | 212 | !!(x & ACPI_EC_FLAG_IBF), |
169 | !!(x & ACPI_EC_FLAG_OBF)); | 213 | !!(x & ACPI_EC_FLAG_OBF)); |
170 | return x; | 214 | return x; |
171 | } | 215 | } |
172 | 216 | ||
@@ -175,20 +219,20 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec) | |||
175 | u8 x = inb(ec->data_addr); | 219 | u8 x = inb(ec->data_addr); |
176 | 220 | ||
177 | ec->curr->timestamp = jiffies; | 221 | ec->curr->timestamp = jiffies; |
178 | pr_debug("EC_DATA(R) = 0x%2.2x\n", x); | 222 | ec_dbg_raw("EC_DATA(R) = 0x%2.2x", x); |
179 | return x; | 223 | return x; |
180 | } | 224 | } |
181 | 225 | ||
182 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) | 226 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) |
183 | { | 227 | { |
184 | pr_debug("EC_SC(W) = 0x%2.2x\n", command); | 228 | ec_dbg_raw("EC_SC(W) = 0x%2.2x", command); |
185 | outb(command, ec->command_addr); | 229 | outb(command, ec->command_addr); |
186 | ec->curr->timestamp = jiffies; | 230 | ec->curr->timestamp = jiffies; |
187 | } | 231 | } |
188 | 232 | ||
189 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) | 233 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) |
190 | { | 234 | { |
191 | pr_debug("EC_DATA(W) = 0x%2.2x\n", data); | 235 | ec_dbg_raw("EC_DATA(W) = 0x%2.2x", data); |
192 | outb(data, ec->data_addr); | 236 | outb(data, ec->data_addr); |
193 | ec->curr->timestamp = jiffies; | 237 | ec->curr->timestamp = jiffies; |
194 | } | 238 | } |
@@ -240,7 +284,7 @@ static inline void acpi_ec_enable_gpe(struct acpi_ec *ec, bool open) | |||
240 | * software need to manually trigger a pseudo GPE event on | 284 | * software need to manually trigger a pseudo GPE event on |
241 | * EN=1 writes. | 285 | * EN=1 writes. |
242 | */ | 286 | */ |
243 | pr_debug("***** Polling quirk *****\n"); | 287 | ec_dbg_raw("Polling quirk"); |
244 | advance_transaction(ec); | 288 | advance_transaction(ec); |
245 | } | 289 | } |
246 | } | 290 | } |
@@ -299,7 +343,7 @@ static void acpi_ec_set_storm(struct acpi_ec *ec, u8 flag) | |||
299 | { | 343 | { |
300 | if (!test_bit(flag, &ec->flags)) { | 344 | if (!test_bit(flag, &ec->flags)) { |
301 | acpi_ec_disable_gpe(ec, false); | 345 | acpi_ec_disable_gpe(ec, false); |
302 | pr_debug("+++++ Polling enabled +++++\n"); | 346 | ec_dbg_drv("Polling enabled"); |
303 | set_bit(flag, &ec->flags); | 347 | set_bit(flag, &ec->flags); |
304 | } | 348 | } |
305 | } | 349 | } |
@@ -309,7 +353,7 @@ static void acpi_ec_clear_storm(struct acpi_ec *ec, u8 flag) | |||
309 | if (test_bit(flag, &ec->flags)) { | 353 | if (test_bit(flag, &ec->flags)) { |
310 | clear_bit(flag, &ec->flags); | 354 | clear_bit(flag, &ec->flags); |
311 | acpi_ec_enable_gpe(ec, false); | 355 | acpi_ec_enable_gpe(ec, false); |
312 | pr_debug("+++++ Polling disabled +++++\n"); | 356 | ec_dbg_drv("Polling disabled"); |
313 | } | 357 | } |
314 | } | 358 | } |
315 | 359 | ||
@@ -335,7 +379,7 @@ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec) | |||
335 | static void acpi_ec_submit_query(struct acpi_ec *ec) | 379 | static void acpi_ec_submit_query(struct acpi_ec *ec) |
336 | { | 380 | { |
337 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { | 381 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { |
338 | pr_debug("***** Event started *****\n"); | 382 | ec_dbg_req("Event started"); |
339 | schedule_work(&ec->work); | 383 | schedule_work(&ec->work); |
340 | } | 384 | } |
341 | } | 385 | } |
@@ -344,7 +388,7 @@ static void acpi_ec_complete_query(struct acpi_ec *ec) | |||
344 | { | 388 | { |
345 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { | 389 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { |
346 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 390 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
347 | pr_debug("***** Event stopped *****\n"); | 391 | ec_dbg_req("Event stopped"); |
348 | } | 392 | } |
349 | } | 393 | } |
350 | 394 | ||
@@ -366,8 +410,8 @@ static void advance_transaction(struct acpi_ec *ec) | |||
366 | u8 status; | 410 | u8 status; |
367 | bool wakeup = false; | 411 | bool wakeup = false; |
368 | 412 | ||
369 | pr_debug("===== %s (%d) =====\n", | 413 | ec_dbg_stm("%s (%d)", in_interrupt() ? "IRQ" : "TASK", |
370 | in_interrupt() ? "IRQ" : "TASK", smp_processor_id()); | 414 | smp_processor_id()); |
371 | /* | 415 | /* |
372 | * By always clearing STS before handling all indications, we can | 416 | * By always clearing STS before handling all indications, we can |
373 | * ensure a hardware STS 0->1 change after this clearing can always | 417 | * ensure a hardware STS 0->1 change after this clearing can always |
@@ -390,8 +434,8 @@ static void advance_transaction(struct acpi_ec *ec) | |||
390 | if (t->rlen == t->ri) { | 434 | if (t->rlen == t->ri) { |
391 | t->flags |= ACPI_EC_COMMAND_COMPLETE; | 435 | t->flags |= ACPI_EC_COMMAND_COMPLETE; |
392 | if (t->command == ACPI_EC_COMMAND_QUERY) | 436 | if (t->command == ACPI_EC_COMMAND_QUERY) |
393 | pr_debug("***** Command(%s) hardware completion *****\n", | 437 | ec_dbg_req("Command(%s) hardware completion", |
394 | acpi_ec_cmd_string(t->command)); | 438 | acpi_ec_cmd_string(t->command)); |
395 | wakeup = true; | 439 | wakeup = true; |
396 | } | 440 | } |
397 | } else | 441 | } else |
@@ -410,8 +454,8 @@ static void advance_transaction(struct acpi_ec *ec) | |||
410 | acpi_ec_complete_query(ec); | 454 | acpi_ec_complete_query(ec); |
411 | t->rdata[t->ri++] = 0x00; | 455 | t->rdata[t->ri++] = 0x00; |
412 | t->flags |= ACPI_EC_COMMAND_COMPLETE; | 456 | t->flags |= ACPI_EC_COMMAND_COMPLETE; |
413 | pr_debug("***** Command(%s) software completion *****\n", | 457 | ec_dbg_req("Command(%s) software completion", |
414 | acpi_ec_cmd_string(t->command)); | 458 | acpi_ec_cmd_string(t->command)); |
415 | wakeup = true; | 459 | wakeup = true; |
416 | } else if ((status & ACPI_EC_FLAG_IBF) == 0) { | 460 | } else if ((status & ACPI_EC_FLAG_IBF) == 0) { |
417 | acpi_ec_write_cmd(ec, t->command); | 461 | acpi_ec_write_cmd(ec, t->command); |
@@ -502,21 +546,21 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
502 | ret = -EINVAL; | 546 | ret = -EINVAL; |
503 | goto unlock; | 547 | goto unlock; |
504 | } | 548 | } |
549 | ec_dbg_ref(ec, "Increase command"); | ||
505 | /* following two actions should be kept atomic */ | 550 | /* following two actions should be kept atomic */ |
506 | ec->curr = t; | 551 | ec->curr = t; |
507 | pr_debug("***** Command(%s) started *****\n", | 552 | ec_dbg_req("Command(%s) started", acpi_ec_cmd_string(t->command)); |
508 | acpi_ec_cmd_string(t->command)); | ||
509 | start_transaction(ec); | 553 | start_transaction(ec); |
510 | spin_unlock_irqrestore(&ec->lock, tmp); | 554 | spin_unlock_irqrestore(&ec->lock, tmp); |
511 | ret = ec_poll(ec); | 555 | ret = ec_poll(ec); |
512 | spin_lock_irqsave(&ec->lock, tmp); | 556 | spin_lock_irqsave(&ec->lock, tmp); |
513 | if (t->irq_count == ec_storm_threshold) | 557 | if (t->irq_count == ec_storm_threshold) |
514 | acpi_ec_clear_storm(ec, EC_FLAGS_COMMAND_STORM); | 558 | acpi_ec_clear_storm(ec, EC_FLAGS_COMMAND_STORM); |
515 | pr_debug("***** Command(%s) stopped *****\n", | 559 | ec_dbg_req("Command(%s) stopped", acpi_ec_cmd_string(t->command)); |
516 | acpi_ec_cmd_string(t->command)); | ||
517 | ec->curr = NULL; | 560 | ec->curr = NULL; |
518 | /* Disable GPE for command processing (IBF=0/OBF=1) */ | 561 | /* Disable GPE for command processing (IBF=0/OBF=1) */ |
519 | acpi_ec_complete_request(ec); | 562 | acpi_ec_complete_request(ec); |
563 | ec_dbg_ref(ec, "Decrease command"); | ||
520 | unlock: | 564 | unlock: |
521 | spin_unlock_irqrestore(&ec->lock, tmp); | 565 | spin_unlock_irqrestore(&ec->lock, tmp); |
522 | return ret; | 566 | return ret; |
@@ -676,11 +720,13 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming) | |||
676 | 720 | ||
677 | spin_lock_irqsave(&ec->lock, flags); | 721 | spin_lock_irqsave(&ec->lock, flags); |
678 | if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags)) { | 722 | if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags)) { |
679 | pr_debug("+++++ Starting EC +++++\n"); | 723 | ec_dbg_drv("Starting EC"); |
680 | /* Enable GPE for event processing (SCI_EVT=1) */ | 724 | /* Enable GPE for event processing (SCI_EVT=1) */ |
681 | if (!resuming) | 725 | if (!resuming) { |
682 | acpi_ec_submit_request(ec); | 726 | acpi_ec_submit_request(ec); |
683 | pr_debug("EC started\n"); | 727 | ec_dbg_ref(ec, "Increase driver"); |
728 | } | ||
729 | ec_log_drv("EC started"); | ||
684 | } | 730 | } |
685 | spin_unlock_irqrestore(&ec->lock, flags); | 731 | spin_unlock_irqrestore(&ec->lock, flags); |
686 | } | 732 | } |
@@ -702,17 +748,19 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending) | |||
702 | 748 | ||
703 | spin_lock_irqsave(&ec->lock, flags); | 749 | spin_lock_irqsave(&ec->lock, flags); |
704 | if (acpi_ec_started(ec)) { | 750 | if (acpi_ec_started(ec)) { |
705 | pr_debug("+++++ Stopping EC +++++\n"); | 751 | ec_dbg_drv("Stopping EC"); |
706 | set_bit(EC_FLAGS_STOPPED, &ec->flags); | 752 | set_bit(EC_FLAGS_STOPPED, &ec->flags); |
707 | spin_unlock_irqrestore(&ec->lock, flags); | 753 | spin_unlock_irqrestore(&ec->lock, flags); |
708 | wait_event(ec->wait, acpi_ec_stopped(ec)); | 754 | wait_event(ec->wait, acpi_ec_stopped(ec)); |
709 | spin_lock_irqsave(&ec->lock, flags); | 755 | spin_lock_irqsave(&ec->lock, flags); |
710 | /* Disable GPE for event processing (SCI_EVT=1) */ | 756 | /* Disable GPE for event processing (SCI_EVT=1) */ |
711 | if (!suspending) | 757 | if (!suspending) { |
712 | acpi_ec_complete_request(ec); | 758 | acpi_ec_complete_request(ec); |
759 | ec_dbg_ref(ec, "Decrease driver"); | ||
760 | } | ||
713 | clear_bit(EC_FLAGS_STARTED, &ec->flags); | 761 | clear_bit(EC_FLAGS_STARTED, &ec->flags); |
714 | clear_bit(EC_FLAGS_STOPPED, &ec->flags); | 762 | clear_bit(EC_FLAGS_STOPPED, &ec->flags); |
715 | pr_debug("EC stopped\n"); | 763 | ec_log_drv("EC stopped"); |
716 | } | 764 | } |
717 | spin_unlock_irqrestore(&ec->lock, flags); | 765 | spin_unlock_irqrestore(&ec->lock, flags); |
718 | } | 766 | } |
@@ -824,12 +872,12 @@ static void acpi_ec_run(void *cxt) | |||
824 | 872 | ||
825 | if (!handler) | 873 | if (!handler) |
826 | return; | 874 | return; |
827 | pr_debug("##### Query(0x%02x) started #####\n", handler->query_bit); | 875 | ec_dbg_evt("Query(0x%02x) started", handler->query_bit); |
828 | if (handler->func) | 876 | if (handler->func) |
829 | handler->func(handler->data); | 877 | handler->func(handler->data); |
830 | else if (handler->handle) | 878 | else if (handler->handle) |
831 | acpi_evaluate_object(handler->handle, NULL, NULL, NULL); | 879 | acpi_evaluate_object(handler->handle, NULL, NULL, NULL); |
832 | pr_debug("##### Query(0x%02x) stopped #####\n", handler->query_bit); | 880 | ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit); |
833 | acpi_ec_put_query_handler(handler); | 881 | acpi_ec_put_query_handler(handler); |
834 | } | 882 | } |
835 | 883 | ||
@@ -861,8 +909,8 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data) | |||
861 | if (value == handler->query_bit) { | 909 | if (value == handler->query_bit) { |
862 | /* have custom handler for this bit */ | 910 | /* have custom handler for this bit */ |
863 | handler = acpi_ec_get_query_handler(handler); | 911 | handler = acpi_ec_get_query_handler(handler); |
864 | pr_debug("##### Query(0x%02x) scheduled #####\n", | 912 | ec_dbg_evt("Query(0x%02x) scheduled", |
865 | handler->query_bit); | 913 | handler->query_bit); |
866 | status = acpi_os_execute((handler->func) ? | 914 | status = acpi_os_execute((handler->func) ? |
867 | OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, | 915 | OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, |
868 | acpi_ec_run, handler); | 916 | acpi_ec_run, handler); |
@@ -1099,6 +1147,9 @@ static int acpi_ec_add(struct acpi_device *device) | |||
1099 | 1147 | ||
1100 | ret = ec_install_handlers(ec); | 1148 | ret = ec_install_handlers(ec); |
1101 | 1149 | ||
1150 | /* Reprobe devices depending on the EC */ | ||
1151 | acpi_walk_dep_device_list(ec->handle); | ||
1152 | |||
1102 | /* EC is fully operational, allow queries */ | 1153 | /* EC is fully operational, allow queries */ |
1103 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 1154 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
1104 | 1155 | ||