8787 SETWA_FLAGS_APICID = 1 ,
8888 SETWA_FLAGS_MEM = 2 ,
8989 SETWA_FLAGS_PCIE_SBDF = 4 ,
90+ SETWA_FLAGS_EINJV2 = 8 ,
9091};
9192
9293/*
@@ -181,6 +182,7 @@ bool einj_initialized __ro_after_init;
181182
182183static void __iomem * einj_param ;
183184static u32 v5param_size ;
185+ static bool is_v2 ;
184186
185187static void einj_exec_ctx_init (struct apei_exec_context * ctx )
186188{
@@ -507,12 +509,20 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
507509 return rc ;
508510}
509511
512+ static bool is_end_of_list (u8 * val )
513+ {
514+ for (int i = 0 ; i < COMPONENT_LEN ; ++ i ) {
515+ if (val [i ] != 0xFF )
516+ return false;
517+ }
518+ return true;
519+ }
510520static int __einj_error_inject (u32 type , u32 flags , u64 param1 , u64 param2 ,
511521 u64 param3 , u64 param4 )
512522{
513523 struct apei_exec_context ctx ;
514524 u64 val , trigger_paddr , timeout = FIRMWARE_TIMEOUT ;
515- int rc ;
525+ int i , rc ;
516526
517527 einj_exec_ctx_init (& ctx );
518528
@@ -521,10 +531,10 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
521531 return rc ;
522532 apei_exec_ctx_set_input (& ctx , type );
523533 if (acpi5 ) {
524- struct set_error_type_with_address * v5param , v5_struct ;
534+ struct set_error_type_with_address * v5param ;
525535
526- v5param = & v5_struct ;
527- memcpy_fromio (v5param , einj_param , sizeof ( * v5param ) );
536+ v5param = kmalloc ( v5param_size , GFP_KERNEL ) ;
537+ memcpy_fromio (v5param , einj_param , v5param_size );
528538 v5param -> type = type ;
529539 if (type & ACPI5_VENDOR_BIT ) {
530540 switch (vendor_flags ) {
@@ -544,8 +554,21 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
544554 v5param -> flags = flags ;
545555 v5param -> memory_address = param1 ;
546556 v5param -> memory_address_range = param2 ;
547- v5param -> apicid = param3 ;
548- v5param -> pcie_sbdf = param4 ;
557+
558+ if (is_v2 ) {
559+ for (i = 0 ; i < max_nr_components ; i ++ ) {
560+ if (is_end_of_list (syndrome_data [i ].comp_id .acpi_id ))
561+ break ;
562+ v5param -> einjv2_struct .component_arr [i ].comp_id =
563+ syndrome_data [i ].comp_id ;
564+ v5param -> einjv2_struct .component_arr [i ].comp_synd =
565+ syndrome_data [i ].comp_synd ;
566+ }
567+ v5param -> einjv2_struct .component_arr_count = i ;
568+ } else {
569+ v5param -> apicid = param3 ;
570+ v5param -> pcie_sbdf = param4 ;
571+ }
549572 } else {
550573 switch (type ) {
551574 case ACPI_EINJ_PROCESSOR_CORRECTABLE :
@@ -569,7 +592,8 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
569592 break ;
570593 }
571594 }
572- memcpy_toio (einj_param , v5param , sizeof (* v5param ));
595+ memcpy_toio (einj_param , v5param , v5param_size );
596+ kfree (v5param );
573597 } else {
574598 rc = apei_exec_run (& ctx , ACPI_EINJ_SET_ERROR_TYPE );
575599 if (rc )
@@ -631,10 +655,15 @@ int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3,
631655 u64 base_addr , size ;
632656
633657 /* If user manually set "flags", make sure it is legal */
634- if (flags && (flags &
635- ~( SETWA_FLAGS_APICID | SETWA_FLAGS_MEM | SETWA_FLAGS_PCIE_SBDF )))
658+ if (flags && (flags & ~( SETWA_FLAGS_APICID | SETWA_FLAGS_MEM |
659+ SETWA_FLAGS_PCIE_SBDF | SETWA_FLAGS_EINJV2 )))
636660 return - EINVAL ;
637661
662+ /* check if type is a valid EINJv2 error type */
663+ if (is_v2 ) {
664+ if (!(type & available_error_type_v2 ))
665+ return - EINVAL ;
666+ }
638667 /*
639668 * We need extra sanity checks for memory errors.
640669 * Other types leap directly to injection.
@@ -743,7 +772,7 @@ static int available_error_type_show(struct seq_file *m, void *v)
743772 if (available_error_type & einj_error_type_string [pos ].mask )
744773 seq_printf (m , "0x%08x\t%s\n" , einj_error_type_string [pos ].mask ,
745774 einj_error_type_string [pos ].str );
746- if (available_error_type & ACPI65_EINJV2_SUPP ) {
775+ if (( available_error_type & ACPI65_EINJV2_SUPP ) && einj_v2_enabled ) {
747776 for (int pos = 0 ; pos < ARRAY_SIZE (einjv2_error_type_string ); pos ++ ) {
748777 if (available_error_type_v2 & einjv2_error_type_string [pos ].mask )
749778 seq_printf (m , "V2_0x%08x\t%s\n" , einjv2_error_type_string [pos ].mask ,
@@ -785,7 +814,7 @@ int einj_validate_error_type(u64 type)
785814 if (tval & (tval - 1 ))
786815 return - EINVAL ;
787816 if (!vendor )
788- if (!(type & available_error_type ))
817+ if (!(type & ( available_error_type | available_error_type_v2 ) ))
789818 return - EINVAL ;
790819
791820 return 0 ;
@@ -804,9 +833,11 @@ static ssize_t error_type_set(struct file *file, const char __user *buf,
804833 if (strncmp (einj_buf , "V2_" , 3 ) == 0 ) {
805834 if (!sscanf (einj_buf , "V2_%llx" , & val ))
806835 return - EINVAL ;
836+ is_v2 = true;
807837 } else {
808838 if (!sscanf (einj_buf , "%llx" , & val ))
809839 return - EINVAL ;
840+ is_v2 = false;
810841 }
811842
812843 rc = einj_validate_error_type (val );
@@ -828,6 +859,11 @@ static int error_inject_set(void *data, u64 val)
828859 if (!error_type )
829860 return - EINVAL ;
830861
862+ if (is_v2 )
863+ error_flags |= SETWA_FLAGS_EINJV2 ;
864+ else
865+ error_flags &= ~SETWA_FLAGS_EINJV2 ;
866+
831867 return einj_error_inject (error_type , error_flags , error_param1 , error_param2 ,
832868 error_param3 , error_param4 );
833869}
0 commit comments