21
21
#include <linux/nmi.h>
22
22
#include <linux/delay.h>
23
23
#include <linux/mm.h>
24
+ #include <linux/platform_device.h>
24
25
#include <asm/unaligned.h>
25
26
26
27
#include "apei-internal.h"
36
37
#define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \
37
38
ACPI_EINJ_MEMORY_UNCORRECTABLE | \
38
39
ACPI_EINJ_MEMORY_FATAL)
40
+ #define CXL_ERROR_MASK (ACPI_EINJ_CXL_CACHE_CORRECTABLE | \
41
+ ACPI_EINJ_CXL_CACHE_UNCORRECTABLE | \
42
+ ACPI_EINJ_CXL_CACHE_FATAL | \
43
+ ACPI_EINJ_CXL_MEM_CORRECTABLE | \
44
+ ACPI_EINJ_CXL_MEM_UNCORRECTABLE | \
45
+ ACPI_EINJ_CXL_MEM_FATAL)
39
46
40
47
/*
41
48
* ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action.
@@ -137,6 +144,11 @@ static struct apei_exec_ins_type einj_ins_type[] = {
137
144
*/
138
145
static DEFINE_MUTEX (einj_mutex );
139
146
147
+ /*
148
+ * Exported APIs use this flag to exit early if einj_probe() failed.
149
+ */
150
+ bool einj_initialized __ro_after_init ;
151
+
140
152
static void * einj_param ;
141
153
142
154
static void einj_exec_ctx_init (struct apei_exec_context * ctx )
@@ -160,7 +172,7 @@ static int __einj_get_available_error_type(u32 *type)
160
172
}
161
173
162
174
/* Get error injection capabilities of the platform */
163
- static int einj_get_available_error_type (u32 * type )
175
+ int einj_get_available_error_type (u32 * type )
164
176
{
165
177
int rc ;
166
178
@@ -530,8 +542,8 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
530
542
}
531
543
532
544
/* Inject the specified hardware error */
533
- static int einj_error_inject (u32 type , u32 flags , u64 param1 , u64 param2 ,
534
- u64 param3 , u64 param4 )
545
+ int einj_error_inject (u32 type , u32 flags , u64 param1 , u64 param2 , u64 param3 ,
546
+ u64 param4 )
535
547
{
536
548
int rc ;
537
549
u64 base_addr , size ;
@@ -554,8 +566,17 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
554
566
if (type & ACPI5_VENDOR_BIT ) {
555
567
if (vendor_flags != SETWA_FLAGS_MEM )
556
568
goto inject ;
557
- } else if (!(type & MEM_ERROR_MASK ) && !(flags & SETWA_FLAGS_MEM ))
569
+ } else if (!(type & MEM_ERROR_MASK ) && !(flags & SETWA_FLAGS_MEM )) {
558
570
goto inject ;
571
+ }
572
+
573
+ /*
574
+ * Injections targeting a CXL 1.0/1.1 port have to be injected
575
+ * via the einj_cxl_rch_error_inject() path as that does the proper
576
+ * validation of the given RCRB base (MMIO) address.
577
+ */
578
+ if (einj_is_cxl_error_type (type ) && (flags & SETWA_FLAGS_MEM ))
579
+ return - EINVAL ;
559
580
560
581
/*
561
582
* Disallow crazy address masks that give BIOS leeway to pick
@@ -587,6 +608,21 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
587
608
return rc ;
588
609
}
589
610
611
+ int einj_cxl_rch_error_inject (u32 type , u32 flags , u64 param1 , u64 param2 ,
612
+ u64 param3 , u64 param4 )
613
+ {
614
+ int rc ;
615
+
616
+ if (!(einj_is_cxl_error_type (type ) && (flags & SETWA_FLAGS_MEM )))
617
+ return - EINVAL ;
618
+
619
+ mutex_lock (& einj_mutex );
620
+ rc = __einj_error_inject (type , flags , param1 , param2 , param3 , param4 );
621
+ mutex_unlock (& einj_mutex );
622
+
623
+ return rc ;
624
+ }
625
+
590
626
static u32 error_type ;
591
627
static u32 error_flags ;
592
628
static u64 error_param1 ;
@@ -607,12 +643,6 @@ static struct { u32 mask; const char *str; } const einj_error_type_string[] = {
607
643
{ BIT (9 ), "Platform Correctable" },
608
644
{ BIT (10 ), "Platform Uncorrectable non-fatal" },
609
645
{ BIT (11 ), "Platform Uncorrectable fatal" },
610
- { BIT (12 ), "CXL.cache Protocol Correctable" },
611
- { BIT (13 ), "CXL.cache Protocol Uncorrectable non-fatal" },
612
- { BIT (14 ), "CXL.cache Protocol Uncorrectable fatal" },
613
- { BIT (15 ), "CXL.mem Protocol Correctable" },
614
- { BIT (16 ), "CXL.mem Protocol Uncorrectable non-fatal" },
615
- { BIT (17 ), "CXL.mem Protocol Uncorrectable fatal" },
616
646
{ BIT (31 ), "Vendor Defined Error Types" },
617
647
};
618
648
@@ -641,22 +671,26 @@ static int error_type_get(void *data, u64 *val)
641
671
return 0 ;
642
672
}
643
673
644
- static int error_type_set ( void * data , u64 val )
674
+ bool einj_is_cxl_error_type ( u64 type )
645
675
{
676
+ return (type & CXL_ERROR_MASK ) && (!(type & ACPI5_VENDOR_BIT ));
677
+ }
678
+
679
+ int einj_validate_error_type (u64 type )
680
+ {
681
+ u32 tval , vendor , available_error_type = 0 ;
646
682
int rc ;
647
- u32 available_error_type = 0 ;
648
- u32 tval , vendor ;
649
683
650
684
/* Only low 32 bits for error type are valid */
651
- if (val & GENMASK_ULL (63 , 32 ))
685
+ if (type & GENMASK_ULL (63 , 32 ))
652
686
return - EINVAL ;
653
687
654
688
/*
655
689
* Vendor defined types have 0x80000000 bit set, and
656
690
* are not enumerated by ACPI_EINJ_GET_ERROR_TYPE
657
691
*/
658
- vendor = val & ACPI5_VENDOR_BIT ;
659
- tval = val & 0x7fffffff ;
692
+ vendor = type & ACPI5_VENDOR_BIT ;
693
+ tval = type & GENMASK ( 30 , 0 ) ;
660
694
661
695
/* Only one error type can be specified */
662
696
if (tval & (tval - 1 ))
@@ -665,9 +699,21 @@ static int error_type_set(void *data, u64 val)
665
699
rc = einj_get_available_error_type (& available_error_type );
666
700
if (rc )
667
701
return rc ;
668
- if (!(val & available_error_type ))
702
+ if (!(type & available_error_type ))
669
703
return - EINVAL ;
670
704
}
705
+
706
+ return 0 ;
707
+ }
708
+
709
+ static int error_type_set (void * data , u64 val )
710
+ {
711
+ int rc ;
712
+
713
+ rc = einj_validate_error_type (val );
714
+ if (rc )
715
+ return rc ;
716
+
671
717
error_type = val ;
672
718
673
719
return 0 ;
@@ -703,21 +749,21 @@ static int einj_check_table(struct acpi_table_einj *einj_tab)
703
749
return 0 ;
704
750
}
705
751
706
- static int __init einj_init ( void )
752
+ static int __init einj_probe ( struct platform_device * pdev )
707
753
{
708
754
int rc ;
709
755
acpi_status status ;
710
756
struct apei_exec_context ctx ;
711
757
712
758
if (acpi_disabled ) {
713
- pr_info ("ACPI disabled.\n" );
759
+ pr_debug ("ACPI disabled.\n" );
714
760
return - ENODEV ;
715
761
}
716
762
717
763
status = acpi_get_table (ACPI_SIG_EINJ , 0 ,
718
764
(struct acpi_table_header * * )& einj_tab );
719
765
if (status == AE_NOT_FOUND ) {
720
- pr_warn ("EINJ table not found.\n" );
766
+ pr_debug ("EINJ table not found.\n" );
721
767
return - ENODEV ;
722
768
} else if (ACPI_FAILURE (status )) {
723
769
pr_err ("Failed to get EINJ table: %s\n" ,
@@ -805,7 +851,7 @@ static int __init einj_init(void)
805
851
return rc ;
806
852
}
807
853
808
- static void __exit einj_exit ( void )
854
+ static void __exit einj_remove ( struct platform_device * pdev )
809
855
{
810
856
struct apei_exec_context ctx ;
811
857
@@ -826,6 +872,40 @@ static void __exit einj_exit(void)
826
872
acpi_put_table ((struct acpi_table_header * )einj_tab );
827
873
}
828
874
875
+ static struct platform_device * einj_dev ;
876
+ static struct platform_driver einj_driver = {
877
+ .remove_new = einj_remove ,
878
+ .driver = {
879
+ .name = "acpi-einj" ,
880
+ },
881
+ };
882
+
883
+ static int __init einj_init (void )
884
+ {
885
+ struct platform_device_info einj_dev_info = {
886
+ .name = "acpi-einj" ,
887
+ .id = -1 ,
888
+ };
889
+ int rc ;
890
+
891
+ einj_dev = platform_device_register_full (& einj_dev_info );
892
+ if (IS_ERR (einj_dev ))
893
+ return PTR_ERR (einj_dev );
894
+
895
+ rc = platform_driver_probe (& einj_driver , einj_probe );
896
+ einj_initialized = rc == 0 ;
897
+
898
+ return 0 ;
899
+ }
900
+
901
+ static void __exit einj_exit (void )
902
+ {
903
+ if (einj_initialized )
904
+ platform_driver_unregister (& einj_driver );
905
+
906
+ platform_device_del (einj_dev );
907
+ }
908
+
829
909
module_init (einj_init );
830
910
module_exit (einj_exit );
831
911
0 commit comments