aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/acpi/ec.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c145
1 files changed, 53 insertions, 92 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 354007d490d..b19a18dd994 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -71,6 +71,9 @@ enum ec_command {
71#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ 71#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
72#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ 72#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */
73 73
74#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts
75 per one transaction */
76
74enum { 77enum {
75 EC_FLAGS_QUERY_PENDING, /* Query is pending */ 78 EC_FLAGS_QUERY_PENDING, /* Query is pending */
76 EC_FLAGS_GPE_STORM, /* GPE storm detected */ 79 EC_FLAGS_GPE_STORM, /* GPE storm detected */
@@ -84,15 +87,6 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
84module_param(ec_delay, uint, 0644); 87module_param(ec_delay, uint, 0644);
85MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); 88MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
86 89
87/*
88 * If the number of false interrupts per one transaction exceeds
89 * this threshold, will think there is a GPE storm happened and
90 * will disable the GPE for normal transaction.
91 */
92static unsigned int ec_storm_threshold __read_mostly = 8;
93module_param(ec_storm_threshold, uint, 0644);
94MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
95
96/* If we find an EC via the ECDT, we need to keep a ptr to its context */ 90/* If we find an EC via the ECDT, we need to keep a ptr to its context */
97/* External interfaces use first EC only, so remember */ 91/* External interfaces use first EC only, so remember */
98typedef int (*acpi_ec_query_func) (void *data); 92typedef int (*acpi_ec_query_func) (void *data);
@@ -158,10 +152,10 @@ static int ec_transaction_done(struct acpi_ec *ec)
158{ 152{
159 unsigned long flags; 153 unsigned long flags;
160 int ret = 0; 154 int ret = 0;
161 spin_lock_irqsave(&ec->lock, flags); 155 spin_lock_irqsave(&ec->curr_lock, flags);
162 if (!ec->curr || ec->curr->done) 156 if (!ec->curr || ec->curr->done)
163 ret = 1; 157 ret = 1;
164 spin_unlock_irqrestore(&ec->lock, flags); 158 spin_unlock_irqrestore(&ec->curr_lock, flags);
165 return ret; 159 return ret;
166} 160}
167 161
@@ -175,38 +169,32 @@ static void start_transaction(struct acpi_ec *ec)
175static void advance_transaction(struct acpi_ec *ec, u8 status) 169static void advance_transaction(struct acpi_ec *ec, u8 status)
176{ 170{
177 unsigned long flags; 171 unsigned long flags;
178 struct transaction *t = ec->curr; 172 spin_lock_irqsave(&ec->curr_lock, flags);
179 173 if (!ec->curr)
180 spin_lock_irqsave(&ec->lock, flags);
181 if (!t)
182 goto unlock; 174 goto unlock;
183 if (t->wlen > t->wi) { 175 if (ec->curr->wlen > ec->curr->wi) {
184 if ((status & ACPI_EC_FLAG_IBF) == 0) 176 if ((status & ACPI_EC_FLAG_IBF) == 0)
185 acpi_ec_write_data(ec, 177 acpi_ec_write_data(ec,
186 t->wdata[t->wi++]); 178 ec->curr->wdata[ec->curr->wi++]);
187 else 179 else
188 goto err; 180 goto err;
189 } else if (t->rlen > t->ri) { 181 } else if (ec->curr->rlen > ec->curr->ri) {
190 if ((status & ACPI_EC_FLAG_OBF) == 1) { 182 if ((status & ACPI_EC_FLAG_OBF) == 1) {
191 t->rdata[t->ri++] = acpi_ec_read_data(ec); 183 ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec);
192 if (t->rlen == t->ri) 184 if (ec->curr->rlen == ec->curr->ri)
193 t->done = true; 185 ec->curr->done = true;
194 } else 186 } else
195 goto err; 187 goto err;
196 } else if (t->wlen == t->wi && 188 } else if (ec->curr->wlen == ec->curr->wi &&
197 (status & ACPI_EC_FLAG_IBF) == 0) 189 (status & ACPI_EC_FLAG_IBF) == 0)
198 t->done = true; 190 ec->curr->done = true;
199 goto unlock; 191 goto unlock;
200err: 192err:
201 /* 193 /* false interrupt, state didn't change */
202 * If SCI bit is set, then don't think it's a false IRQ 194 if (in_interrupt())
203 * otherwise will take a not handled IRQ as a false one. 195 ++ec->curr->irq_count;
204 */
205 if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI))
206 ++t->irq_count;
207
208unlock: 196unlock:
209 spin_unlock_irqrestore(&ec->lock, flags); 197 spin_unlock_irqrestore(&ec->curr_lock, flags);
210} 198}
211 199
212static int acpi_ec_sync_query(struct acpi_ec *ec); 200static int acpi_ec_sync_query(struct acpi_ec *ec);
@@ -244,9 +232,9 @@ static int ec_poll(struct acpi_ec *ec)
244 if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) 232 if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)
245 break; 233 break;
246 pr_debug(PREFIX "controller reset, restart transaction\n"); 234 pr_debug(PREFIX "controller reset, restart transaction\n");
247 spin_lock_irqsave(&ec->lock, flags); 235 spin_lock_irqsave(&ec->curr_lock, flags);
248 start_transaction(ec); 236 start_transaction(ec);
249 spin_unlock_irqrestore(&ec->lock, flags); 237 spin_unlock_irqrestore(&ec->curr_lock, flags);
250 } 238 }
251 return -ETIME; 239 return -ETIME;
252} 240}
@@ -259,17 +247,17 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
259 if (EC_FLAGS_MSI) 247 if (EC_FLAGS_MSI)
260 udelay(ACPI_EC_MSI_UDELAY); 248 udelay(ACPI_EC_MSI_UDELAY);
261 /* start transaction */ 249 /* start transaction */
262 spin_lock_irqsave(&ec->lock, tmp); 250 spin_lock_irqsave(&ec->curr_lock, tmp);
263 /* following two actions should be kept atomic */ 251 /* following two actions should be kept atomic */
264 ec->curr = t; 252 ec->curr = t;
265 start_transaction(ec); 253 start_transaction(ec);
266 if (ec->curr->command == ACPI_EC_COMMAND_QUERY) 254 if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
267 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); 255 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
268 spin_unlock_irqrestore(&ec->lock, tmp); 256 spin_unlock_irqrestore(&ec->curr_lock, tmp);
269 ret = ec_poll(ec); 257 ret = ec_poll(ec);
270 spin_lock_irqsave(&ec->lock, tmp); 258 spin_lock_irqsave(&ec->curr_lock, tmp);
271 ec->curr = NULL; 259 ec->curr = NULL;
272 spin_unlock_irqrestore(&ec->lock, tmp); 260 spin_unlock_irqrestore(&ec->curr_lock, tmp);
273 return ret; 261 return ret;
274} 262}
275 263
@@ -298,7 +286,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
298 return -EINVAL; 286 return -EINVAL;
299 if (t->rdata) 287 if (t->rdata)
300 memset(t->rdata, 0, t->rlen); 288 memset(t->rdata, 0, t->rlen);
301 mutex_lock(&ec->mutex); 289 mutex_lock(&ec->lock);
302 if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) { 290 if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) {
303 status = -EINVAL; 291 status = -EINVAL;
304 goto unlock; 292 goto unlock;
@@ -316,8 +304,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
316 status = -ETIME; 304 status = -ETIME;
317 goto end; 305 goto end;
318 } 306 }
319 pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n", 307 pr_debug(PREFIX "transaction start\n");
320 t->command, t->wdata ? t->wdata[0] : 0);
321 /* disable GPE during transaction if storm is detected */ 308 /* disable GPE during transaction if storm is detected */
322 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { 309 if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
323 /* It has to be disabled, so that it doesn't trigger. */ 310 /* It has to be disabled, so that it doesn't trigger. */
@@ -332,10 +319,9 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
332 msleep(1); 319 msleep(1);
333 /* It is safe to enable the GPE outside of the transaction. */ 320 /* It is safe to enable the GPE outside of the transaction. */
334 acpi_enable_gpe(NULL, ec->gpe); 321 acpi_enable_gpe(NULL, ec->gpe);
335 } else if (t->irq_count > ec_storm_threshold) { 322 } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) {
336 pr_info(PREFIX "GPE storm detected(%d GPEs), " 323 pr_info(PREFIX "GPE storm detected, "
337 "transactions will use polling mode\n", 324 "transactions will use polling mode\n");
338 t->irq_count);
339 set_bit(EC_FLAGS_GPE_STORM, &ec->flags); 325 set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
340 } 326 }
341 pr_debug(PREFIX "transaction end\n"); 327 pr_debug(PREFIX "transaction end\n");
@@ -343,7 +329,7 @@ end:
343 if (ec->global_lock) 329 if (ec->global_lock)
344 acpi_release_global_lock(glk); 330 acpi_release_global_lock(glk);
345unlock: 331unlock:
346 mutex_unlock(&ec->mutex); 332 mutex_unlock(&ec->lock);
347 return status; 333 return status;
348} 334}
349 335
@@ -411,7 +397,7 @@ int ec_burst_disable(void)
411 397
412EXPORT_SYMBOL(ec_burst_disable); 398EXPORT_SYMBOL(ec_burst_disable);
413 399
414int ec_read(u8 addr, u8 *val) 400int ec_read(u8 addr, u8 * val)
415{ 401{
416 int err; 402 int err;
417 u8 temp_data; 403 u8 temp_data;
@@ -459,16 +445,6 @@ int ec_transaction(u8 command,
459 445
460EXPORT_SYMBOL(ec_transaction); 446EXPORT_SYMBOL(ec_transaction);
461 447
462/* Get the handle to the EC device */
463acpi_handle ec_get_handle(void)
464{
465 if (!first_ec)
466 return NULL;
467 return first_ec->handle;
468}
469
470EXPORT_SYMBOL(ec_get_handle);
471
472void acpi_ec_block_transactions(void) 448void acpi_ec_block_transactions(void)
473{ 449{
474 struct acpi_ec *ec = first_ec; 450 struct acpi_ec *ec = first_ec;
@@ -476,10 +452,10 @@ void acpi_ec_block_transactions(void)
476 if (!ec) 452 if (!ec)
477 return; 453 return;
478 454
479 mutex_lock(&ec->mutex); 455 mutex_lock(&ec->lock);
480 /* Prevent transactions from being carried out */ 456 /* Prevent transactions from being carried out */
481 set_bit(EC_FLAGS_BLOCKED, &ec->flags); 457 set_bit(EC_FLAGS_BLOCKED, &ec->flags);
482 mutex_unlock(&ec->mutex); 458 mutex_unlock(&ec->lock);
483} 459}
484 460
485void acpi_ec_unblock_transactions(void) 461void acpi_ec_unblock_transactions(void)
@@ -489,10 +465,10 @@ void acpi_ec_unblock_transactions(void)
489 if (!ec) 465 if (!ec)
490 return; 466 return;
491 467
492 mutex_lock(&ec->mutex); 468 mutex_lock(&ec->lock);
493 /* Allow transactions to be carried out again */ 469 /* Allow transactions to be carried out again */
494 clear_bit(EC_FLAGS_BLOCKED, &ec->flags); 470 clear_bit(EC_FLAGS_BLOCKED, &ec->flags);
495 mutex_unlock(&ec->mutex); 471 mutex_unlock(&ec->lock);
496} 472}
497 473
498void acpi_ec_unblock_transactions_early(void) 474void acpi_ec_unblock_transactions_early(void)
@@ -544,9 +520,9 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
544 handler->handle = handle; 520 handler->handle = handle;
545 handler->func = func; 521 handler->func = func;
546 handler->data = data; 522 handler->data = data;
547 mutex_lock(&ec->mutex); 523 mutex_lock(&ec->lock);
548 list_add(&handler->node, &ec->list); 524 list_add(&handler->node, &ec->list);
549 mutex_unlock(&ec->mutex); 525 mutex_unlock(&ec->lock);
550 return 0; 526 return 0;
551} 527}
552 528
@@ -555,14 +531,14 @@ EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
555void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) 531void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
556{ 532{
557 struct acpi_ec_query_handler *handler, *tmp; 533 struct acpi_ec_query_handler *handler, *tmp;
558 mutex_lock(&ec->mutex); 534 mutex_lock(&ec->lock);
559 list_for_each_entry_safe(handler, tmp, &ec->list, node) { 535 list_for_each_entry_safe(handler, tmp, &ec->list, node) {
560 if (query_bit == handler->query_bit) { 536 if (query_bit == handler->query_bit) {
561 list_del(&handler->node); 537 list_del(&handler->node);
562 kfree(handler); 538 kfree(handler);
563 } 539 }
564 } 540 }
565 mutex_unlock(&ec->mutex); 541 mutex_unlock(&ec->lock);
566} 542}
567 543
568EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); 544EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
@@ -609,9 +585,9 @@ static void acpi_ec_gpe_query(void *ec_cxt)
609 struct acpi_ec *ec = ec_cxt; 585 struct acpi_ec *ec = ec_cxt;
610 if (!ec) 586 if (!ec)
611 return; 587 return;
612 mutex_lock(&ec->mutex); 588 mutex_lock(&ec->lock);
613 acpi_ec_sync_query(ec); 589 acpi_ec_sync_query(ec);
614 mutex_unlock(&ec->mutex); 590 mutex_unlock(&ec->lock);
615} 591}
616 592
617static int ec_check_sci(struct acpi_ec *ec, u8 state) 593static int ec_check_sci(struct acpi_ec *ec, u8 state)
@@ -630,11 +606,10 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
630 u32 gpe_number, void *data) 606 u32 gpe_number, void *data)
631{ 607{
632 struct acpi_ec *ec = data; 608 struct acpi_ec *ec = data;
633 u8 status = acpi_ec_read_status(ec);
634 609
635 pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status); 610 pr_debug(PREFIX "~~~> interrupt\n");
636 611
637 advance_transaction(ec, status); 612 advance_transaction(ec, acpi_ec_read_status(ec));
638 if (ec_transaction_done(ec) && 613 if (ec_transaction_done(ec) &&
639 (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { 614 (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
640 wake_up(&ec->wait); 615 wake_up(&ec->wait);
@@ -700,10 +675,10 @@ static struct acpi_ec *make_acpi_ec(void)
700 if (!ec) 675 if (!ec)
701 return NULL; 676 return NULL;
702 ec->flags = 1 << EC_FLAGS_QUERY_PENDING; 677 ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
703 mutex_init(&ec->mutex); 678 mutex_init(&ec->lock);
704 init_waitqueue_head(&ec->wait); 679 init_waitqueue_head(&ec->wait);
705 INIT_LIST_HEAD(&ec->list); 680 INIT_LIST_HEAD(&ec->list);
706 spin_lock_init(&ec->lock); 681 spin_lock_init(&ec->curr_lock);
707 return ec; 682 return ec;
708} 683}
709 684
@@ -837,10 +812,10 @@ static int acpi_ec_add(struct acpi_device *device)
837 first_ec = ec; 812 first_ec = ec;
838 device->driver_data = ec; 813 device->driver_data = ec;
839 814
840 ret = !!request_region(ec->data_addr, 1, "EC data"); 815 WARN(!request_region(ec->data_addr, 1, "EC data"),
841 WARN(!ret, "Could not request EC data io port 0x%lx", ec->data_addr); 816 "Could not request EC data io port 0x%lx", ec->data_addr);
842 ret = !!request_region(ec->command_addr, 1, "EC cmd"); 817 WARN(!request_region(ec->command_addr, 1, "EC cmd"),
843 WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); 818 "Could not request EC cmd io port 0x%lx", ec->command_addr);
844 819
845 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", 820 pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
846 ec->gpe, ec->command_addr, ec->data_addr); 821 ec->gpe, ec->command_addr, ec->data_addr);
@@ -862,12 +837,12 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
862 837
863 ec = acpi_driver_data(device); 838 ec = acpi_driver_data(device);
864 ec_remove_handlers(ec); 839 ec_remove_handlers(ec);
865 mutex_lock(&ec->mutex); 840 mutex_lock(&ec->lock);
866 list_for_each_entry_safe(handler, tmp, &ec->list, node) { 841 list_for_each_entry_safe(handler, tmp, &ec->list, node) {
867 list_del(&handler->node); 842 list_del(&handler->node);
868 kfree(handler); 843 kfree(handler);
869 } 844 }
870 mutex_unlock(&ec->mutex); 845 mutex_unlock(&ec->lock);
871 release_region(ec->data_addr, 1); 846 release_region(ec->data_addr, 1);
872 release_region(ec->command_addr, 1); 847 release_region(ec->command_addr, 1);
873 device->driver_data = NULL; 848 device->driver_data = NULL;
@@ -939,17 +914,6 @@ static int ec_flag_msi(const struct dmi_system_id *id)
939 return 0; 914 return 0;
940} 915}
941 916
942/*
943 * Clevo M720 notebook actually works ok with IRQ mode, if we lifted
944 * the GPE storm threshold back to 20
945 */
946static int ec_enlarge_storm_threshold(const struct dmi_system_id *id)
947{
948 pr_debug("Setting the EC GPE storm threshold to 20\n");
949 ec_storm_threshold = 20;
950 return 0;
951}
952
953static struct dmi_system_id __initdata ec_dmi_table[] = { 917static struct dmi_system_id __initdata ec_dmi_table[] = {
954 { 918 {
955 ec_skip_dsdt_scan, "Compal JFL92", { 919 ec_skip_dsdt_scan, "Compal JFL92", {
@@ -981,13 +945,10 @@ static struct dmi_system_id __initdata ec_dmi_table[] = {
981 { 945 {
982 ec_validate_ecdt, "ASUS hardware", { 946 ec_validate_ecdt, "ASUS hardware", {
983 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL}, 947 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL},
984 {
985 ec_enlarge_storm_threshold, "CLEVO hardware", {
986 DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
987 DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL},
988 {}, 948 {},
989}; 949};
990 950
951
991int __init acpi_ec_ecdt_probe(void) 952int __init acpi_ec_ecdt_probe(void)
992{ 953{
993 acpi_status status; 954 acpi_status status;