3333#define SLEEP_UNIT_MAX 5000 /* 5ms */
3434/* Firmware should respond within 1 seconds */
3535#define FIRMWARE_TIMEOUT (1 * USEC_PER_SEC)
36+ #define ACPI65_EINJV2_SUPP BIT(30)
3637#define ACPI5_VENDOR_BIT BIT(31)
3738#define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \
3839 ACPI_EINJ_MEMORY_UNCORRECTABLE | \
@@ -84,6 +85,7 @@ static struct debugfs_blob_wrapper vendor_errors;
8485static char vendor_dev [64 ];
8586
8687static u32 available_error_type ;
88+ static u32 available_error_type_v2 ;
8789
8890/*
8991 * Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the
@@ -159,13 +161,13 @@ static void einj_exec_ctx_init(struct apei_exec_context *ctx)
159161 EINJ_TAB_ENTRY (einj_tab ), einj_tab -> entries );
160162}
161163
162- static int __einj_get_available_error_type (u32 * type )
164+ static int __einj_get_available_error_type (u32 * type , int einj_action )
163165{
164166 struct apei_exec_context ctx ;
165167 int rc ;
166168
167169 einj_exec_ctx_init (& ctx );
168- rc = apei_exec_run (& ctx , ACPI_EINJ_GET_ERROR_TYPE );
170+ rc = apei_exec_run (& ctx , einj_action );
169171 if (rc )
170172 return rc ;
171173 * type = apei_exec_ctx_get_output (& ctx );
@@ -174,17 +176,34 @@ static int __einj_get_available_error_type(u32 *type)
174176}
175177
176178/* Get error injection capabilities of the platform */
177- int einj_get_available_error_type (u32 * type )
179+ int einj_get_available_error_type (u32 * type , int einj_action )
178180{
179181 int rc ;
180182
181183 mutex_lock (& einj_mutex );
182- rc = __einj_get_available_error_type (type );
184+ rc = __einj_get_available_error_type (type , einj_action );
183185 mutex_unlock (& einj_mutex );
184186
185187 return rc ;
186188}
187189
190+ static int einj_get_available_error_types (u32 * type1 , u32 * type2 )
191+ {
192+ int rc ;
193+
194+ rc = einj_get_available_error_type (type1 , ACPI_EINJ_GET_ERROR_TYPE );
195+ if (rc )
196+ return rc ;
197+ if (* type1 & ACPI65_EINJV2_SUPP ) {
198+ rc = einj_get_available_error_type (type2 ,
199+ ACPI_EINJV2_GET_ERROR_TYPE );
200+ if (rc )
201+ return rc ;
202+ }
203+
204+ return 0 ;
205+ }
206+
188207static int einj_timedout (u64 * t )
189208{
190209 if ((s64 )* t < SLEEP_UNIT_MIN ) {
@@ -646,6 +665,7 @@ static u64 error_param2;
646665static u64 error_param3 ;
647666static u64 error_param4 ;
648667static struct dentry * einj_debug_dir ;
668+ static char einj_buf [32 ];
649669static struct { u32 mask ; const char * str ; } const einj_error_type_string [] = {
650670 { BIT (0 ), "Processor Correctable" },
651671 { BIT (1 ), "Processor Uncorrectable non-fatal" },
@@ -662,24 +682,35 @@ static struct { u32 mask; const char *str; } const einj_error_type_string[] = {
662682 { BIT (31 ), "Vendor Defined Error Types" },
663683};
664684
685+ static struct { u32 mask ; const char * str ; } const einjv2_error_type_string [] = {
686+ { BIT (0 ), "EINJV2 Processor Error" },
687+ { BIT (1 ), "EINJV2 Memory Error" },
688+ { BIT (2 ), "EINJV2 PCI Express Error" },
689+ };
690+
665691static int available_error_type_show (struct seq_file * m , void * v )
666692{
667693
668694 for (int pos = 0 ; pos < ARRAY_SIZE (einj_error_type_string ); pos ++ )
669695 if (available_error_type & einj_error_type_string [pos ].mask )
670696 seq_printf (m , "0x%08x\t%s\n" , einj_error_type_string [pos ].mask ,
671697 einj_error_type_string [pos ].str );
672-
698+ if (available_error_type & ACPI65_EINJV2_SUPP ) {
699+ for (int pos = 0 ; pos < ARRAY_SIZE (einjv2_error_type_string ); pos ++ ) {
700+ if (available_error_type_v2 & einjv2_error_type_string [pos ].mask )
701+ seq_printf (m , "V2_0x%08x\t%s\n" , einjv2_error_type_string [pos ].mask ,
702+ einjv2_error_type_string [pos ].str );
703+ }
704+ }
673705 return 0 ;
674706}
675707
676708DEFINE_SHOW_ATTRIBUTE (available_error_type );
677709
678- static int error_type_get (void * data , u64 * val )
710+ static ssize_t error_type_get (struct file * file , char __user * buf ,
711+ size_t count , loff_t * ppos )
679712{
680- * val = error_type ;
681-
682- return 0 ;
713+ return simple_read_from_buffer (buf , count , ppos , einj_buf , strlen (einj_buf ));
683714}
684715
685716bool einj_is_cxl_error_type (u64 type )
@@ -712,21 +743,37 @@ int einj_validate_error_type(u64 type)
712743 return 0 ;
713744}
714745
715- static int error_type_set (void * data , u64 val )
746+ static ssize_t error_type_set (struct file * file , const char __user * buf ,
747+ size_t count , loff_t * ppos )
716748{
717749 int rc ;
750+ u64 val ;
751+
752+ memset (einj_buf , 0 , sizeof (einj_buf ));
753+ if (copy_from_user (einj_buf , buf , count ))
754+ return - EFAULT ;
755+
756+ if (strncmp (einj_buf , "V2_" , 3 ) == 0 ) {
757+ if (!sscanf (einj_buf , "V2_%llx" , & val ))
758+ return - EINVAL ;
759+ } else {
760+ if (!sscanf (einj_buf , "%llx" , & val ))
761+ return - EINVAL ;
762+ }
718763
719764 rc = einj_validate_error_type (val );
720765 if (rc )
721766 return rc ;
722767
723768 error_type = val ;
724769
725- return 0 ;
770+ return count ;
726771}
727772
728- DEFINE_DEBUGFS_ATTRIBUTE (error_type_fops , error_type_get , error_type_set ,
729- "0x%llx\n" );
773+ static const struct file_operations error_type_fops = {
774+ .read = error_type_get ,
775+ .write = error_type_set ,
776+ };
730777
731778static int error_inject_set (void * data , u64 val )
732779{
@@ -778,7 +825,7 @@ static int __init einj_probe(struct faux_device *fdev)
778825 goto err_put_table ;
779826 }
780827
781- rc = einj_get_available_error_type (& available_error_type );
828+ rc = einj_get_available_error_types (& available_error_type , & available_error_type_v2 );
782829 if (rc )
783830 goto err_put_table ;
784831
0 commit comments