40
40
#include <linux/sched/clock.h>
41
41
#include <linux/uuid.h>
42
42
#include <linux/ras.h>
43
+ #include <linux/task_work.h>
43
44
44
45
#include <acpi/actbl1.h>
45
46
#include <acpi/ghes.h>
@@ -414,23 +415,46 @@ static void ghes_clear_estatus(struct ghes *ghes,
414
415
ghes_ack_error (ghes -> generic_v2 );
415
416
}
416
417
417
- static void ghes_handle_memory_failure (struct acpi_hest_generic_data * gdata , int sev )
418
+ /*
419
+ * Called as task_work before returning to user-space.
420
+ * Ensure any queued work has been done before we return to the context that
421
+ * triggered the notification.
422
+ */
423
+ static void ghes_kick_task_work (struct callback_head * head )
424
+ {
425
+ struct acpi_hest_generic_status * estatus ;
426
+ struct ghes_estatus_node * estatus_node ;
427
+ u32 node_len ;
428
+
429
+ estatus_node = container_of (head , struct ghes_estatus_node , task_work );
430
+ if (IS_ENABLED (CONFIG_ACPI_APEI_MEMORY_FAILURE ))
431
+ memory_failure_queue_kick (estatus_node -> task_work_cpu );
432
+
433
+ estatus = GHES_ESTATUS_FROM_NODE (estatus_node );
434
+ node_len = GHES_ESTATUS_NODE_LEN (cper_estatus_len (estatus ));
435
+ gen_pool_free (ghes_estatus_pool , (unsigned long )estatus_node , node_len );
436
+ }
437
+
438
+ static bool ghes_handle_memory_failure (struct acpi_hest_generic_data * gdata ,
439
+ int sev )
418
440
{
419
- #ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
420
441
unsigned long pfn ;
421
442
int flags = -1 ;
422
443
int sec_sev = ghes_severity (gdata -> error_severity );
423
444
struct cper_sec_mem_err * mem_err = acpi_hest_get_payload (gdata );
424
445
446
+ if (!IS_ENABLED (CONFIG_ACPI_APEI_MEMORY_FAILURE ))
447
+ return false;
448
+
425
449
if (!(mem_err -> validation_bits & CPER_MEM_VALID_PA ))
426
- return ;
450
+ return false ;
427
451
428
452
pfn = mem_err -> physical_addr >> PAGE_SHIFT ;
429
453
if (!pfn_valid (pfn )) {
430
454
pr_warn_ratelimited (FW_WARN GHES_PFX
431
455
"Invalid address in generic error data: %#llx\n" ,
432
456
mem_err -> physical_addr );
433
- return ;
457
+ return false ;
434
458
}
435
459
436
460
/* iff following two events can be handled properly by now */
@@ -440,9 +464,12 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int
440
464
if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE )
441
465
flags = 0 ;
442
466
443
- if (flags != -1 )
467
+ if (flags != -1 ) {
444
468
memory_failure_queue (pfn , flags );
445
- #endif
469
+ return true;
470
+ }
471
+
472
+ return false;
446
473
}
447
474
448
475
/*
@@ -490,14 +517,15 @@ static void ghes_handle_aer(struct acpi_hest_generic_data *gdata)
490
517
#endif
491
518
}
492
519
493
- static void ghes_do_proc (struct ghes * ghes ,
520
+ static bool ghes_do_proc (struct ghes * ghes ,
494
521
const struct acpi_hest_generic_status * estatus )
495
522
{
496
523
int sev , sec_sev ;
497
524
struct acpi_hest_generic_data * gdata ;
498
525
guid_t * sec_type ;
499
526
const guid_t * fru_id = & guid_null ;
500
527
char * fru_text = "" ;
528
+ bool queued = false;
501
529
502
530
sev = ghes_severity (estatus -> error_severity );
503
531
apei_estatus_for_each_section (estatus , gdata ) {
@@ -515,7 +543,7 @@ static void ghes_do_proc(struct ghes *ghes,
515
543
ghes_edac_report_mem_error (sev , mem_err );
516
544
517
545
arch_apei_report_mem_error (sev , mem_err );
518
- ghes_handle_memory_failure (gdata , sev );
546
+ queued = ghes_handle_memory_failure (gdata , sev );
519
547
}
520
548
else if (guid_equal (sec_type , & CPER_SEC_PCIE )) {
521
549
ghes_handle_aer (gdata );
@@ -532,6 +560,8 @@ static void ghes_do_proc(struct ghes *ghes,
532
560
gdata -> error_data_length );
533
561
}
534
562
}
563
+
564
+ return queued ;
535
565
}
536
566
537
567
static void __ghes_print_estatus (const char * pfx ,
@@ -827,7 +857,9 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
827
857
struct ghes_estatus_node * estatus_node ;
828
858
struct acpi_hest_generic * generic ;
829
859
struct acpi_hest_generic_status * estatus ;
860
+ bool task_work_pending ;
830
861
u32 len , node_len ;
862
+ int ret ;
831
863
832
864
llnode = llist_del_all (& ghes_estatus_llist );
833
865
/*
@@ -842,14 +874,26 @@ static void ghes_proc_in_irq(struct irq_work *irq_work)
842
874
estatus = GHES_ESTATUS_FROM_NODE (estatus_node );
843
875
len = cper_estatus_len (estatus );
844
876
node_len = GHES_ESTATUS_NODE_LEN (len );
845
- ghes_do_proc (estatus_node -> ghes , estatus );
877
+ task_work_pending = ghes_do_proc (estatus_node -> ghes , estatus );
846
878
if (!ghes_estatus_cached (estatus )) {
847
879
generic = estatus_node -> generic ;
848
880
if (ghes_print_estatus (NULL , generic , estatus ))
849
881
ghes_estatus_cache_add (generic , estatus );
850
882
}
851
- gen_pool_free (ghes_estatus_pool , (unsigned long )estatus_node ,
852
- node_len );
883
+
884
+ if (task_work_pending && current -> mm != & init_mm ) {
885
+ estatus_node -> task_work .func = ghes_kick_task_work ;
886
+ estatus_node -> task_work_cpu = smp_processor_id ();
887
+ ret = task_work_add (current , & estatus_node -> task_work ,
888
+ true);
889
+ if (ret )
890
+ estatus_node -> task_work .func = NULL ;
891
+ }
892
+
893
+ if (!estatus_node -> task_work .func )
894
+ gen_pool_free (ghes_estatus_pool ,
895
+ (unsigned long )estatus_node , node_len );
896
+
853
897
llnode = next ;
854
898
}
855
899
}
@@ -909,6 +953,7 @@ static int ghes_in_nmi_queue_one_entry(struct ghes *ghes,
909
953
910
954
estatus_node -> ghes = ghes ;
911
955
estatus_node -> generic = ghes -> generic ;
956
+ estatus_node -> task_work .func = NULL ;
912
957
estatus = GHES_ESTATUS_FROM_NODE (estatus_node );
913
958
914
959
if (__ghes_read_estatus (estatus , buf_paddr , fixmap_idx , len )) {
0 commit comments