Skip to content

Commit 0c6176e

Browse files
zaidal-ampererafaeljw
authored andcommitted
ACPI: APEI: EINJ: Enable the discovery of EINJv2 capabilities
Enable the driver to show all supported error injections for EINJ and EINJv2 at the same time. EINJv2 capabilities can be discovered by checking the return value of get_error_type, where bit 30 set indicates EINJv2 support. Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Zaid Alali <zaidal@os.amperecomputing.com> Link: https://patch.msgid.link/20250617193026.637510-3-zaidal@os.amperecomputing.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 1a35c88 commit 0c6176e

3 files changed

Lines changed: 63 additions & 16 deletions

File tree

drivers/acpi/apei/apei-internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus)
131131

132132
int apei_osc_setup(void);
133133

134-
int einj_get_available_error_type(u32 *type);
134+
int einj_get_available_error_type(u32 *type, int einj_action);
135135
int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3,
136136
u64 param4);
137137
int einj_cxl_rch_error_inject(u32 type, u32 flags, u64 param1, u64 param2,

drivers/acpi/apei/einj-core.c

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
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;
8485
static char vendor_dev[64];
8586

8687
static 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+
188207
static int einj_timedout(u64 *t)
189208
{
190209
if ((s64)*t < SLEEP_UNIT_MIN) {
@@ -646,6 +665,7 @@ static u64 error_param2;
646665
static u64 error_param3;
647666
static u64 error_param4;
648667
static struct dentry *einj_debug_dir;
668+
static char einj_buf[32];
649669
static 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+
665691
static 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

676708
DEFINE_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

685716
bool 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

731778
static 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

drivers/acpi/apei/einj-cxl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ int einj_cxl_available_error_type_show(struct seq_file *m, void *v)
3030
int cxl_err, rc;
3131
u32 available_error_type = 0;
3232

33-
rc = einj_get_available_error_type(&available_error_type);
33+
rc = einj_get_available_error_type(&available_error_type, ACPI_EINJ_GET_ERROR_TYPE);
3434
if (rc)
3535
return rc;
3636

0 commit comments

Comments
 (0)