aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/apei/ghes.c184
1 files changed, 177 insertions, 7 deletions
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index d1a40218e17e..931410d31a96 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -60,6 +60,21 @@
60 60
61#define GHES_ESTATUS_POOL_MIN_ALLOC_ORDER 3 61#define GHES_ESTATUS_POOL_MIN_ALLOC_ORDER 3
62 62
63/* This is just an estimation for memory pool allocation */
64#define GHES_ESTATUS_CACHE_AVG_SIZE 512
65
66#define GHES_ESTATUS_CACHES_SIZE 4
67
68#define GHES_ESTATUS_IN_CACHE_MAX_NSEC (10 * NSEC_PER_SEC)
69/* Prevent too many caches are allocated because of RCU */
70#define GHES_ESTATUS_CACHE_ALLOCED_MAX (GHES_ESTATUS_CACHES_SIZE * 3 / 2)
71
72#define GHES_ESTATUS_CACHE_LEN(estatus_len) \
73 (sizeof(struct ghes_estatus_cache) + (estatus_len))
74#define GHES_ESTATUS_FROM_CACHE(estatus_cache) \
75 ((struct acpi_hest_generic_status *) \
76 ((struct ghes_estatus_cache *)(estatus_cache) + 1))
77
63#define GHES_ESTATUS_NODE_LEN(estatus_len) \ 78#define GHES_ESTATUS_NODE_LEN(estatus_len) \
64 (sizeof(struct ghes_estatus_node) + (estatus_len)) 79 (sizeof(struct ghes_estatus_node) + (estatus_len))
65#define GHES_ESTATUS_FROM_NODE(estatus_node) \ 80#define GHES_ESTATUS_FROM_NODE(estatus_node) \
@@ -94,6 +109,14 @@ struct ghes_estatus_node {
94 struct acpi_hest_generic *generic; 109 struct acpi_hest_generic *generic;
95}; 110};
96 111
112struct ghes_estatus_cache {
113 u32 estatus_len;
114 atomic_t count;
115 struct acpi_hest_generic *generic;
116 unsigned long long time_in;
117 struct rcu_head rcu;
118};
119
97int ghes_disable; 120int ghes_disable;
98module_param_named(disable, ghes_disable, bool, 0); 121module_param_named(disable, ghes_disable, bool, 0);
99 122
@@ -154,6 +177,9 @@ static unsigned long ghes_estatus_pool_size_request;
154static struct llist_head ghes_estatus_llist; 177static struct llist_head ghes_estatus_llist;
155static struct irq_work ghes_proc_irq_work; 178static struct irq_work ghes_proc_irq_work;
156 179
180struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
181static atomic_t ghes_estatus_cache_alloced;
182
157static int ghes_ioremap_init(void) 183static int ghes_ioremap_init(void)
158{ 184{
159 ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES, 185 ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES,
@@ -458,9 +484,9 @@ static void __ghes_print_estatus(const char *pfx,
458 apei_estatus_print(pfx, estatus); 484 apei_estatus_print(pfx, estatus);
459} 485}
460 486
461static void ghes_print_estatus(const char *pfx, 487static int ghes_print_estatus(const char *pfx,
462 const struct acpi_hest_generic *generic, 488 const struct acpi_hest_generic *generic,
463 const struct acpi_hest_generic_status *estatus) 489 const struct acpi_hest_generic_status *estatus)
464{ 490{
465 /* Not more than 2 messages every 5 seconds */ 491 /* Not more than 2 messages every 5 seconds */
466 static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2); 492 static DEFINE_RATELIMIT_STATE(ratelimit_corrected, 5*HZ, 2);
@@ -471,8 +497,137 @@ static void ghes_print_estatus(const char *pfx,
471 ratelimit = &ratelimit_corrected; 497 ratelimit = &ratelimit_corrected;
472 else 498 else
473 ratelimit = &ratelimit_uncorrected; 499 ratelimit = &ratelimit_uncorrected;
474 if (__ratelimit(ratelimit)) 500 if (__ratelimit(ratelimit)) {
475 __ghes_print_estatus(pfx, generic, estatus); 501 __ghes_print_estatus(pfx, generic, estatus);
502 return 1;
503 }
504 return 0;
505}
506
507/*
508 * GHES error status reporting throttle, to report more kinds of
509 * errors, instead of just most frequently occurred errors.
510 */
511static int ghes_estatus_cached(struct acpi_hest_generic_status *estatus)
512{
513 u32 len;
514 int i, cached = 0;
515 unsigned long long now;
516 struct ghes_estatus_cache *cache;
517 struct acpi_hest_generic_status *cache_estatus;
518
519 len = apei_estatus_len(estatus);
520 rcu_read_lock();
521 for (i = 0; i < GHES_ESTATUS_CACHES_SIZE; i++) {
522 cache = rcu_dereference(ghes_estatus_caches[i]);
523 if (cache == NULL)
524 continue;
525 if (len != cache->estatus_len)
526 continue;
527 cache_estatus = GHES_ESTATUS_FROM_CACHE(cache);
528 if (memcmp(estatus, cache_estatus, len))
529 continue;
530 atomic_inc(&cache->count);
531 now = sched_clock();
532 if (now - cache->time_in < GHES_ESTATUS_IN_CACHE_MAX_NSEC)
533 cached = 1;
534 break;
535 }
536 rcu_read_unlock();
537 return cached;
538}
539
540static struct ghes_estatus_cache *ghes_estatus_cache_alloc(
541 struct acpi_hest_generic *generic,
542 struct acpi_hest_generic_status *estatus)
543{
544 int alloced;
545 u32 len, cache_len;
546 struct ghes_estatus_cache *cache;
547 struct acpi_hest_generic_status *cache_estatus;
548
549 alloced = atomic_add_return(1, &ghes_estatus_cache_alloced);
550 if (alloced > GHES_ESTATUS_CACHE_ALLOCED_MAX) {
551 atomic_dec(&ghes_estatus_cache_alloced);
552 return NULL;
553 }
554 len = apei_estatus_len(estatus);
555 cache_len = GHES_ESTATUS_CACHE_LEN(len);
556 cache = (void *)gen_pool_alloc(ghes_estatus_pool, cache_len);
557 if (!cache) {
558 atomic_dec(&ghes_estatus_cache_alloced);
559 return NULL;
560 }
561 cache_estatus = GHES_ESTATUS_FROM_CACHE(cache);
562 memcpy(cache_estatus, estatus, len);
563 cache->estatus_len = len;
564 atomic_set(&cache->count, 0);
565 cache->generic = generic;
566 cache->time_in = sched_clock();
567 return cache;
568}
569
570static void ghes_estatus_cache_free(struct ghes_estatus_cache *cache)
571{
572 u32 len;
573
574 len = apei_estatus_len(GHES_ESTATUS_FROM_CACHE(cache));
575 len = GHES_ESTATUS_CACHE_LEN(len);
576 gen_pool_free(ghes_estatus_pool, (unsigned long)cache, len);
577 atomic_dec(&ghes_estatus_cache_alloced);
578}
579
580static void ghes_estatus_cache_rcu_free(struct rcu_head *head)
581{
582 struct ghes_estatus_cache *cache;
583
584 cache = container_of(head, struct ghes_estatus_cache, rcu);
585 ghes_estatus_cache_free(cache);
586}
587
588static void ghes_estatus_cache_add(
589 struct acpi_hest_generic *generic,
590 struct acpi_hest_generic_status *estatus)
591{
592 int i, slot = -1, count;
593 unsigned long long now, duration, period, max_period = 0;
594 struct ghes_estatus_cache *cache, *slot_cache = NULL, *new_cache;
595
596 new_cache = ghes_estatus_cache_alloc(generic, estatus);
597 if (new_cache == NULL)
598 return;
599 rcu_read_lock();
600 now = sched_clock();
601 for (i = 0; i < GHES_ESTATUS_CACHES_SIZE; i++) {
602 cache = rcu_dereference(ghes_estatus_caches[i]);
603 if (cache == NULL) {
604 slot = i;
605 slot_cache = NULL;
606 break;
607 }
608 duration = now - cache->time_in;
609 if (duration >= GHES_ESTATUS_IN_CACHE_MAX_NSEC) {
610 slot = i;
611 slot_cache = cache;
612 break;
613 }
614 count = atomic_read(&cache->count);
615 period = duration / (count + 1);
616 if (period > max_period) {
617 max_period = period;
618 slot = i;
619 slot_cache = cache;
620 }
621 }
622 /* new_cache must be put into array after its contents are written */
623 smp_wmb();
624 if (slot != -1 && cmpxchg(ghes_estatus_caches + slot,
625 slot_cache, new_cache) == slot_cache) {
626 if (slot_cache)
627 call_rcu(&slot_cache->rcu, ghes_estatus_cache_rcu_free);
628 } else
629 ghes_estatus_cache_free(new_cache);
630 rcu_read_unlock();
476} 631}
477 632
478static int ghes_proc(struct ghes *ghes) 633static int ghes_proc(struct ghes *ghes)
@@ -482,9 +637,11 @@ static int ghes_proc(struct ghes *ghes)
482 rc = ghes_read_estatus(ghes, 0); 637 rc = ghes_read_estatus(ghes, 0);
483 if (rc) 638 if (rc)
484 goto out; 639 goto out;
485 ghes_print_estatus(NULL, ghes->generic, ghes->estatus); 640 if (!ghes_estatus_cached(ghes->estatus)) {
641 if (ghes_print_estatus(NULL, ghes->generic, ghes->estatus))
642 ghes_estatus_cache_add(ghes->generic, ghes->estatus);
643 }
486 ghes_do_proc(ghes->estatus); 644 ghes_do_proc(ghes->estatus);
487
488out: 645out:
489 ghes_clear_estatus(ghes); 646 ghes_clear_estatus(ghes);
490 return 0; 647 return 0;
@@ -546,6 +703,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
546{ 703{
547 struct llist_node *llnode, *next, *tail = NULL; 704 struct llist_node *llnode, *next, *tail = NULL;
548 struct ghes_estatus_node *estatus_node; 705 struct ghes_estatus_node *estatus_node;
706 struct acpi_hest_generic *generic;
549 struct acpi_hest_generic_status *estatus; 707 struct acpi_hest_generic_status *estatus;
550 u32 len, node_len; 708 u32 len, node_len;
551 709
@@ -569,7 +727,11 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
569 len = apei_estatus_len(estatus); 727 len = apei_estatus_len(estatus);
570 node_len = GHES_ESTATUS_NODE_LEN(len); 728 node_len = GHES_ESTATUS_NODE_LEN(len);
571 ghes_do_proc(estatus); 729 ghes_do_proc(estatus);
572 ghes_print_estatus(NULL, estatus_node->generic, estatus); 730 if (!ghes_estatus_cached(estatus)) {
731 generic = estatus_node->generic;
732 if (ghes_print_estatus(NULL, generic, estatus))
733 ghes_estatus_cache_add(generic, estatus);
734 }
573 gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, 735 gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node,
574 node_len); 736 node_len);
575 llnode = next; 737 llnode = next;
@@ -622,6 +784,8 @@ static int ghes_notify_nmi(struct notifier_block *this,
622 if (!(ghes->flags & GHES_TO_CLEAR)) 784 if (!(ghes->flags & GHES_TO_CLEAR))
623 continue; 785 continue;
624#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG 786#ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
787 if (ghes_estatus_cached(ghes->estatus))
788 goto next;
625 /* Save estatus for further processing in IRQ context */ 789 /* Save estatus for further processing in IRQ context */
626 len = apei_estatus_len(ghes->estatus); 790 len = apei_estatus_len(ghes->estatus);
627 node_len = GHES_ESTATUS_NODE_LEN(len); 791 node_len = GHES_ESTATUS_NODE_LEN(len);
@@ -633,6 +797,7 @@ static int ghes_notify_nmi(struct notifier_block *this,
633 memcpy(estatus, ghes->estatus, len); 797 memcpy(estatus, ghes->estatus, len);
634 llist_add(&estatus_node->llnode, &ghes_estatus_llist); 798 llist_add(&estatus_node->llnode, &ghes_estatus_llist);
635 } 799 }
800next:
636#endif 801#endif
637 ghes_clear_estatus(ghes); 802 ghes_clear_estatus(ghes);
638 } 803 }
@@ -847,6 +1012,11 @@ static int __init ghes_init(void)
847 if (rc) 1012 if (rc)
848 goto err_ioremap_exit; 1013 goto err_ioremap_exit;
849 1014
1015 rc = ghes_estatus_pool_expand(GHES_ESTATUS_CACHE_AVG_SIZE *
1016 GHES_ESTATUS_CACHE_ALLOCED_MAX);
1017 if (rc)
1018 goto err_pool_exit;
1019
850 rc = platform_driver_register(&ghes_platform_driver); 1020 rc = platform_driver_register(&ghes_platform_driver);
851 if (rc) 1021 if (rc)
852 goto err_pool_exit; 1022 goto err_pool_exit;