3737#define MEM_ERROR_MASK (ACPI_EINJ_MEMORY_CORRECTABLE | \
3838 ACPI_EINJ_MEMORY_UNCORRECTABLE | \
3939 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)
4046
4147/*
4248 * ACPI version 5 provides a SET_ERROR_TYPE_WITH_ADDRESS action.
@@ -141,7 +147,7 @@ static DEFINE_MUTEX(einj_mutex);
141147/*
142148 * Exported APIs use this flag to exit early if einj_probe() failed.
143149 */
144- static bool einj_initialized __ro_after_init ;
150+ bool einj_initialized __ro_after_init ;
145151
146152static void * einj_param ;
147153
@@ -166,7 +172,7 @@ static int __einj_get_available_error_type(u32 *type)
166172}
167173
168174/* Get error injection capabilities of the platform */
169- static int einj_get_available_error_type (u32 * type )
175+ int einj_get_available_error_type (u32 * type )
170176{
171177 int rc ;
172178
@@ -536,8 +542,8 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
536542}
537543
538544/* Inject the specified hardware error */
539- static int einj_error_inject (u32 type , u32 flags , u64 param1 , u64 param2 ,
540- u64 param3 , u64 param4 )
545+ int einj_error_inject (u32 type , u32 flags , u64 param1 , u64 param2 , u64 param3 ,
546+ u64 param4 )
541547{
542548 int rc ;
543549 u64 base_addr , size ;
@@ -560,8 +566,17 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
560566 if (type & ACPI5_VENDOR_BIT ) {
561567 if (vendor_flags != SETWA_FLAGS_MEM )
562568 goto inject ;
563- } else if (!(type & MEM_ERROR_MASK ) && !(flags & SETWA_FLAGS_MEM ))
569+ } else if (!(type & MEM_ERROR_MASK ) && !(flags & SETWA_FLAGS_MEM )) {
564570 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 ;
565580
566581 /*
567582 * Disallow crazy address masks that give BIOS leeway to pick
@@ -593,6 +608,21 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
593608 return rc ;
594609}
595610
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+
596626static u32 error_type ;
597627static u32 error_flags ;
598628static u64 error_param1 ;
@@ -613,12 +643,6 @@ static struct { u32 mask; const char *str; } const einj_error_type_string[] = {
613643 { BIT (9 ), "Platform Correctable" },
614644 { BIT (10 ), "Platform Uncorrectable non-fatal" },
615645 { BIT (11 ), "Platform Uncorrectable fatal" },
616- { BIT (12 ), "CXL.cache Protocol Correctable" },
617- { BIT (13 ), "CXL.cache Protocol Uncorrectable non-fatal" },
618- { BIT (14 ), "CXL.cache Protocol Uncorrectable fatal" },
619- { BIT (15 ), "CXL.mem Protocol Correctable" },
620- { BIT (16 ), "CXL.mem Protocol Uncorrectable non-fatal" },
621- { BIT (17 ), "CXL.mem Protocol Uncorrectable fatal" },
622646 { BIT (31 ), "Vendor Defined Error Types" },
623647};
624648
@@ -647,22 +671,26 @@ static int error_type_get(void *data, u64 *val)
647671 return 0 ;
648672}
649673
650- static int error_type_set (void * data , u64 val )
674+ bool einj_is_cxl_error_type (u64 type )
675+ {
676+ return (type & CXL_ERROR_MASK ) && (!(type & ACPI5_VENDOR_BIT ));
677+ }
678+
679+ int einj_validate_error_type (u64 type )
651680{
681+ u32 tval , vendor , available_error_type = 0 ;
652682 int rc ;
653- u32 available_error_type = 0 ;
654- u32 tval , vendor ;
655683
656684 /* Only low 32 bits for error type are valid */
657- if (val & GENMASK_ULL (63 , 32 ))
685+ if (type & GENMASK_ULL (63 , 32 ))
658686 return - EINVAL ;
659687
660688 /*
661689 * Vendor defined types have 0x80000000 bit set, and
662690 * are not enumerated by ACPI_EINJ_GET_ERROR_TYPE
663691 */
664- vendor = val & ACPI5_VENDOR_BIT ;
665- tval = val & 0x7fffffff ;
692+ vendor = type & ACPI5_VENDOR_BIT ;
693+ tval = type & GENMASK ( 30 , 0 ) ;
666694
667695 /* Only one error type can be specified */
668696 if (tval & (tval - 1 ))
@@ -671,9 +699,21 @@ static int error_type_set(void *data, u64 val)
671699 rc = einj_get_available_error_type (& available_error_type );
672700 if (rc )
673701 return rc ;
674- if (!(val & available_error_type ))
702+ if (!(type & available_error_type ))
675703 return - EINVAL ;
676704 }
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+
677717 error_type = val ;
678718
679719 return 0 ;
0 commit comments