[PATCH] ACPI: APEI: EINJ: EINJV2 support added

Piyush Malgujar posted 1 patch 2 years, 9 months ago
There is a newer version of this series
drivers/acpi/apei/einj.c | 172 +++++++++++++++++++++++++++++++++++----
include/acpi/actbl1.h    |   4 +-
2 files changed, 157 insertions(+), 19 deletions(-)
[PATCH] ACPI: APEI: EINJ: EINJV2 support added
Posted by Piyush Malgujar 2 years, 9 months ago
Added changes to support EINJV2 from ACPI V6.5. This adds
new additional actions: EINJV2_SET_ERROR_TYPE and
EINJV2_GET_ERROR_TYPE which supports PCIe,processor and
memory error for single component syndrome.

Signed-off-by: Piyush Malgujar <pmalgujar@marvell.com>
---
 drivers/acpi/apei/einj.c | 172 +++++++++++++++++++++++++++++++++++----
 include/acpi/actbl1.h    |   4 +-
 2 files changed, 157 insertions(+), 19 deletions(-)

diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 013eb621dc92a7c11b00577a890c06fc64453a2c..97f87ad125af79b2a6f73c0741f728cb9c799992 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -32,6 +32,7 @@
 #define SLEEP_UNIT_MAX		5000			/* 5ms */
 /* Firmware should respond within 1 seconds */
 #define FIRMWARE_TIMEOUT	(1 * USEC_PER_SEC)
+#define ACPI65_EINJV2_SUPP	BIT(30)
 #define ACPI5_VENDOR_BIT	BIT(31)
 #define MEM_ERROR_MASK		(ACPI_EINJ_MEMORY_CORRECTABLE | \
 				ACPI_EINJ_MEMORY_UNCORRECTABLE | \
@@ -42,6 +43,51 @@
  */
 static int acpi5;
 
+/*
+ * ACPI version 6.5 provides a EINJV2_SET_ERROR_TYPE action.
+ */
+static int einjv2_supp;
+
+struct syndrome_array {
+	union {
+		u32	acpi_id;
+		u32	device_id;
+		u32	pcie_sbdf;
+		u8	fru_id[16];
+	} comp_id;
+	union {
+		u32	proc_synd;
+		u32	mem_synd;
+		u32	pcie_synd;
+		u8	vendor_synd[16];
+	} comp_synd;
+};
+
+struct einjv2_set_error_type {
+	u32	type;
+	u8	type_code;
+	u8	flags[3];
+	u32	length;
+	u32	severity;
+	u64	memory_address;
+	u64	memory_address_range;
+	u32	syndrome_count;
+	struct	syndrome_array array[0];
+};
+
+enum {
+	EINJV2_PROCESSOR_ERROR = 0x1,
+	EINJV2_MEMORY_ERROR = 0x2,
+	EINJV2_PCIE_ERROR = 0x4,
+};
+
+enum {
+	EINJV2_FLAG_ADD_VALID = 0x1,
+	EINJV2_FLAG_ADD_RANGE_VALID = 0x2,
+	EINJV2_FLAG_SEVERITY_VALID = 0x4,
+	EINJV2_FLAG_COMP_VALID = 0x8,
+};
+
 struct set_error_type_with_address {
 	u32	type;
 	u32	vendor_extension;
@@ -155,6 +201,13 @@ static int __einj_get_available_error_type(u32 *type)
 		return rc;
 	*type = apei_exec_ctx_get_output(&ctx);
 
+	if (*type & ACPI65_EINJV2_SUPP) {
+		rc = apei_exec_run(&ctx, ACPI_EINJV2_GET_ERROR_TYPE);
+		if (rc)
+			return rc;
+		*type = apei_exec_ctx_get_output(&ctx);
+	}
+
 	return 0;
 }
 
@@ -205,7 +258,7 @@ static void check_vendor_extension(u64 paddr,
 static void *einj_get_parameter_address(void)
 {
 	int i;
-	u64 pa_v4 = 0, pa_v5 = 0;
+	u64 pa_v4 = 0, pa_v5 = 0, pa_v65 = 0;
 	struct acpi_whea_header *entry;
 
 	entry = EINJ_TAB_ENTRY(einj_tab);
@@ -220,8 +273,22 @@ static void *einj_get_parameter_address(void)
 		    entry->register_region.space_id ==
 		    ACPI_ADR_SPACE_SYSTEM_MEMORY)
 			pa_v5 = get_unaligned(&entry->register_region.address);
+		if (entry->action == ACPI_EINJV2_SET_ERROR_TYPE &&
+		    entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
+		    entry->register_region.space_id ==
+		    ACPI_ADR_SPACE_SYSTEM_MEMORY)
+			pa_v65 = get_unaligned(&entry->register_region.address);
 		entry++;
 	}
+	if (pa_v65) {
+		struct einjv2_set_error_type *v65param;
+
+		v65param = acpi_os_map_iomem(pa_v65, sizeof(*v65param));
+		if (v65param) {
+			einjv2_supp = 1;
+			return v65param;
+		}
+	}
 	if (pa_v5) {
 		struct set_error_type_with_address *v5param;
 
@@ -356,7 +423,9 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
 	 * This will cause resource conflict with regular memory.  So
 	 * remove it from trigger table resources.
 	 */
-	if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) {
+	if ((param_extension || acpi5 || einjv2_supp) &&
+	    ((einjv2_supp && (type & EINJV2_MEMORY_ERROR)) ||
+	     type & MEM_ERROR_MASK) && param2) {
 		struct apei_resources addr_resources;
 
 		apei_resources_init(&addr_resources);
@@ -402,7 +471,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
 }
 
 static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
-			       u64 param3, u64 param4)
+			       u64 param3, u64 param4, u64 param5)
 {
 	struct apei_exec_context ctx;
 	u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT;
@@ -414,7 +483,46 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
 	if (rc)
 		return rc;
 	apei_exec_ctx_set_input(&ctx, type);
-	if (acpi5) {
+
+	if (einjv2_supp) {
+		struct einjv2_set_error_type *v65param = einj_param;
+
+		v65param->type = type;
+		v65param->flags[0] = flags;
+
+		if (v65param->flags[0] & EINJV2_FLAG_COMP_VALID) {
+			switch (v65param->type) {
+			case EINJV2_PROCESSOR_ERROR:
+				v65param->array[0].comp_id.acpi_id = param1;
+				v65param->array[0].comp_synd.proc_synd = param2;
+				break;
+			case EINJV2_MEMORY_ERROR:
+				v65param->array[0].comp_id.device_id = param3;
+				v65param->array[0].comp_synd.mem_synd = param4;
+				break;
+			case EINJV2_PCIE_ERROR:
+				v65param->array[0].comp_id.pcie_sbdf = param1;
+				v65param->array[0].comp_synd.pcie_synd = param2;
+				break;
+			}
+		}
+
+		if (v65param->type & EINJV2_MEMORY_ERROR) {
+			if (v65param->flags[0] & EINJV2_FLAG_ADD_VALID)
+				v65param->memory_address = param1;
+			if (v65param->flags[0] & EINJV2_FLAG_ADD_RANGE_VALID)
+				v65param->memory_address_range = param2;
+			if (v65param->flags[0] & EINJV2_FLAG_SEVERITY_VALID)
+				v65param->severity = param5;
+		} else {
+			if (v65param->flags[0] & EINJV2_FLAG_SEVERITY_VALID)
+				v65param->severity = param3;
+		}
+		v65param->syndrome_count = 1;
+		v65param->length = sizeof(struct einjv2_set_error_type) +
+				  ((v65param->syndrome_count) *
+				  sizeof(struct syndrome_array));
+	} else if (acpi5) {
 		struct set_error_type_with_address *v5param = einj_param;
 
 		v5param->type = type;
@@ -514,15 +622,23 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
 
 /* Inject the specified hardware error */
 static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
-			     u64 param3, u64 param4)
+			     u64 param3, u64 param4, u64 param5)
 {
 	int rc;
 	u64 base_addr, size;
 
 	/* If user manually set "flags", make sure it is legal */
-	if (flags && (flags &
-		~(SETWA_FLAGS_APICID|SETWA_FLAGS_MEM|SETWA_FLAGS_PCIE_SBDF)))
-		return -EINVAL;
+	if (einjv2_supp) {
+		if (flags && (flags &
+			~(EINJV2_FLAG_ADD_VALID | EINJV2_FLAG_ADD_RANGE_VALID |
+			  EINJV2_FLAG_SEVERITY_VALID | EINJV2_FLAG_COMP_VALID)))
+			return -EINVAL;
+	} else {
+		if (flags && (flags &
+			~(SETWA_FLAGS_APICID | SETWA_FLAGS_MEM |
+			  SETWA_FLAGS_PCIE_SBDF)))
+			return -EINVAL;
+	}
 
 	/*
 	 * We need extra sanity checks for memory errors.
@@ -530,11 +646,13 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
 	 */
 
 	/* ensure param1/param2 existed */
-	if (!(param_extension || acpi5))
+	if (!(param_extension || acpi5 || einjv2_supp))
 		goto inject;
 
 	/* ensure injection is memory related */
-	if (type & ACPI5_VENDOR_BIT) {
+	if (einjv2_supp && !(type & EINJV2_MEMORY_ERROR)) {
+		goto inject;
+	} else if (type & ACPI5_VENDOR_BIT) {
 		if (vendor_flags != SETWA_FLAGS_MEM)
 			goto inject;
 	} else if (!(type & MEM_ERROR_MASK) && !(flags & SETWA_FLAGS_MEM))
@@ -564,7 +682,7 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
 
 inject:
 	mutex_lock(&einj_mutex);
-	rc = __einj_error_inject(type, flags, param1, param2, param3, param4);
+	rc = __einj_error_inject(type, flags, param1, param2, param3, param4, param5);
 	mutex_unlock(&einj_mutex);
 
 	return rc;
@@ -576,7 +694,15 @@ static u64 error_param1;
 static u64 error_param2;
 static u64 error_param3;
 static u64 error_param4;
+static u64 error_param5;
 static struct dentry *einj_debug_dir;
+
+static const char * const einjv2_error_type_string[] = {
+	"0x00000001\tEINJV2 Processor Error\n",
+	"0x00000002\tEINJV2 Memory Error\n",
+	"0x00000004\tEINJV2 PCI Express Error\n",
+};
+
 static const char * const einj_error_type_string[] = {
 	"0x00000001\tProcessor Correctable\n",
 	"0x00000002\tProcessor Uncorrectable non-fatal\n",
@@ -600,15 +726,22 @@ static const char * const einj_error_type_string[] = {
 
 static int available_error_type_show(struct seq_file *m, void *v)
 {
-	int rc;
+	int rc, pos;
 	u32 available_error_type = 0;
 
 	rc = einj_get_available_error_type(&available_error_type);
 	if (rc)
 		return rc;
-	for (int pos = 0; pos < ARRAY_SIZE(einj_error_type_string); pos++)
-		if (available_error_type & BIT(pos))
-			seq_puts(m, einj_error_type_string[pos]);
+
+	if (einjv2_supp) {
+		for (pos = 0; pos < ARRAY_SIZE(einjv2_error_type_string); pos++)
+			if (available_error_type & BIT(pos))
+				seq_puts(m, einjv2_error_type_string[pos]);
+	} else {
+		for (pos = 0; pos < ARRAY_SIZE(einj_error_type_string); pos++)
+			if (available_error_type & BIT(pos))
+				seq_puts(m, einj_error_type_string[pos]);
+	}
 
 	return 0;
 }
@@ -662,8 +795,9 @@ static int error_inject_set(void *data, u64 val)
 	if (!error_type)
 		return -EINVAL;
 
-	return einj_error_inject(error_type, error_flags, error_param1, error_param2,
-		error_param3, error_param4);
+	return einj_error_inject(error_type, error_flags, error_param1,
+				 error_param2, error_param3, error_param4,
+				 error_param5);
 }
 
 DEFINE_DEBUGFS_ATTRIBUTE(error_inject_fops, NULL, error_inject_set, "%llu\n");
@@ -743,7 +877,7 @@ static int __init einj_init(void)
 	}
 
 	einj_param = einj_get_parameter_address();
-	if ((param_extension || acpi5) && einj_param) {
+	if ((param_extension || acpi5 || einjv2_supp) && einj_param) {
 		debugfs_create_x32("flags", S_IRUSR | S_IWUSR, einj_debug_dir,
 				   &error_flags);
 		debugfs_create_x64("param1", S_IRUSR | S_IWUSR, einj_debug_dir,
@@ -754,6 +888,8 @@ static int __init einj_init(void)
 				   &error_param3);
 		debugfs_create_x64("param4", S_IRUSR | S_IWUSR, einj_debug_dir,
 				   &error_param4);
+		debugfs_create_x64("param5", S_IRUSR | S_IWUSR, einj_debug_dir,
+				   &error_param5);
 		debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
 				   einj_debug_dir, &notrigger);
 	}
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index 58b0490a2ad12e26cab30209e461429a1f5dec30..de89c18f3443489683c9aafaf6a894e60d98374b 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -1026,7 +1026,9 @@ enum acpi_einj_actions {
 	ACPI_EINJ_GET_COMMAND_STATUS = 7,
 	ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS = 8,
 	ACPI_EINJ_GET_EXECUTE_TIMINGS = 9,
-	ACPI_EINJ_ACTION_RESERVED = 10,	/* 10 and greater are reserved */
+	ACPI_EINJV2_SET_ERROR_TYPE = 0x10,
+	ACPI_EINJV2_GET_ERROR_TYPE = 0x11,
+	ACPI_EINJ_ACTION_RESERVED = 0x12, /* 12 and greater are reserved */
 	ACPI_EINJ_TRIGGER_ERROR = 0xFF	/* Except for this value */
 };
 
-- 
2.17.1
Re: [PATCH] ACPI: APEI: EINJ: EINJV2 support added
Posted by kernel test robot 2 years, 9 months ago
Hi Piyush,

kernel test robot noticed the following build warnings:

[auto build test WARNING on rafael-pm/linux-next]
[also build test WARNING on linus/master v6.4-rc1 next-20230508]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Piyush-Malgujar/ACPI-APEI-EINJ-EINJV2-support-added/20230503-223915
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
patch link:    https://lore.kernel.org/r/20230503143759.10485-1-pmalgujar%40marvell.com
patch subject: [PATCH] ACPI: APEI: EINJ: EINJV2 support added
config: x86_64-randconfig-s022 (https://download.01.org/0day-ci/archive/20230509/202305090445.WSd683gm-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/ca5bbbdcc074577ee88ccaa2d078a37eb5eec36f
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Piyush-Malgujar/ACPI-APEI-EINJ-EINJV2-support-added/20230503-223915
        git checkout ca5bbbdcc074577ee88ccaa2d078a37eb5eec36f
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=x86_64 olddefconfig
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/acpi/apei/ drivers/platform/x86/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202305090445.WSd683gm-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/acpi/apei/einj.c:247:11: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct vendor_error_type_extension *v @@     got void [noderef] __iomem * @@
   drivers/acpi/apei/einj.c:247:11: sparse:     expected struct vendor_error_type_extension *v
   drivers/acpi/apei/einj.c:247:11: sparse:     got void [noderef] __iomem *
   drivers/acpi/apei/einj.c:255:29: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __iomem *virt @@     got struct vendor_error_type_extension *v @@
   drivers/acpi/apei/einj.c:255:29: sparse:     expected void [noderef] __iomem *virt
   drivers/acpi/apei/einj.c:255:29: sparse:     got struct vendor_error_type_extension *v
>> drivers/acpi/apei/einj.c:286:26: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct einjv2_set_error_type *v65param @@     got void [noderef] __iomem * @@
   drivers/acpi/apei/einj.c:286:26: sparse:     expected struct einjv2_set_error_type *v65param
   drivers/acpi/apei/einj.c:286:26: sparse:     got void [noderef] __iomem *
   drivers/acpi/apei/einj.c:295:25: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct set_error_type_with_address *v5param @@     got void [noderef] __iomem * @@
   drivers/acpi/apei/einj.c:295:25: sparse:     expected struct set_error_type_with_address *v5param
   drivers/acpi/apei/einj.c:295:25: sparse:     got void [noderef] __iomem *
   drivers/acpi/apei/einj.c:305:25: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct einj_parameter *v4param @@     got void [noderef] __iomem * @@
   drivers/acpi/apei/einj.c:305:25: sparse:     expected struct einj_parameter *v4param
   drivers/acpi/apei/einj.c:305:25: sparse:     got void [noderef] __iomem *
   drivers/acpi/apei/einj.c:309:45: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __iomem *virt @@     got struct einj_parameter *v4param @@
   drivers/acpi/apei/einj.c:309:45: sparse:     expected void [noderef] __iomem *virt
   drivers/acpi/apei/einj.c:309:45: sparse:     got struct einj_parameter *v4param
   drivers/acpi/apei/einj.c:376:21: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct acpi_einj_trigger *trigger_tab @@     got void [noderef] __iomem * @@
   drivers/acpi/apei/einj.c:376:21: sparse:     expected struct acpi_einj_trigger *trigger_tab
   drivers/acpi/apei/einj.c:376:21: sparse:     got void [noderef] __iomem *
   drivers/acpi/apei/einj.c:402:17: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got struct acpi_einj_trigger *trigger_tab @@
   drivers/acpi/apei/einj.c:402:17: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/acpi/apei/einj.c:402:17: sparse:     got struct acpi_einj_trigger *trigger_tab
   drivers/acpi/apei/einj.c:403:21: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected struct acpi_einj_trigger *trigger_tab @@     got void [noderef] __iomem * @@
   drivers/acpi/apei/einj.c:403:21: sparse:     expected struct acpi_einj_trigger *trigger_tab
   drivers/acpi/apei/einj.c:403:21: sparse:     got void [noderef] __iomem *
   drivers/acpi/apei/einj.c:468:25: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void volatile [noderef] __iomem *addr @@     got struct acpi_einj_trigger *trigger_tab @@
   drivers/acpi/apei/einj.c:468:25: sparse:     expected void volatile [noderef] __iomem *addr
   drivers/acpi/apei/einj.c:468:25: sparse:     got struct acpi_einj_trigger *trigger_tab
   drivers/acpi/apei/einj.c:930:37: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void [noderef] __iomem *virt @@     got void *static [assigned] [toplevel] einj_param @@
   drivers/acpi/apei/einj.c:930:37: sparse:     expected void [noderef] __iomem *virt
   drivers/acpi/apei/einj.c:930:37: sparse:     got void *static [assigned] [toplevel] einj_param

vim +286 drivers/acpi/apei/einj.c

   237	
   238	static void check_vendor_extension(u64 paddr,
   239					   struct set_error_type_with_address *v5param)
   240	{
   241		int	offset = v5param->vendor_extension;
   242		struct	vendor_error_type_extension *v;
   243		u32	sbdf;
   244	
   245		if (!offset)
   246			return;
 > 247		v = acpi_os_map_iomem(paddr + offset, sizeof(*v));
   248		if (!v)
   249			return;
   250		sbdf = v->pcie_sbdf;
   251		sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n",
   252			sbdf >> 24, (sbdf >> 16) & 0xff,
   253			(sbdf >> 11) & 0x1f, (sbdf >> 8) & 0x7,
   254			 v->vendor_id, v->device_id, v->rev_id);
   255		acpi_os_unmap_iomem(v, sizeof(*v));
   256	}
   257	
   258	static void *einj_get_parameter_address(void)
   259	{
   260		int i;
   261		u64 pa_v4 = 0, pa_v5 = 0, pa_v65 = 0;
   262		struct acpi_whea_header *entry;
   263	
   264		entry = EINJ_TAB_ENTRY(einj_tab);
   265		for (i = 0; i < einj_tab->entries; i++) {
   266			if (entry->action == ACPI_EINJ_SET_ERROR_TYPE &&
   267			    entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
   268			    entry->register_region.space_id ==
   269			    ACPI_ADR_SPACE_SYSTEM_MEMORY)
   270				pa_v4 = get_unaligned(&entry->register_region.address);
   271			if (entry->action == ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS &&
   272			    entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
   273			    entry->register_region.space_id ==
   274			    ACPI_ADR_SPACE_SYSTEM_MEMORY)
   275				pa_v5 = get_unaligned(&entry->register_region.address);
   276			if (entry->action == ACPI_EINJV2_SET_ERROR_TYPE &&
   277			    entry->instruction == ACPI_EINJ_WRITE_REGISTER &&
   278			    entry->register_region.space_id ==
   279			    ACPI_ADR_SPACE_SYSTEM_MEMORY)
   280				pa_v65 = get_unaligned(&entry->register_region.address);
   281			entry++;
   282		}
   283		if (pa_v65) {
   284			struct einjv2_set_error_type *v65param;
   285	
 > 286			v65param = acpi_os_map_iomem(pa_v65, sizeof(*v65param));
   287			if (v65param) {
   288				einjv2_supp = 1;
   289				return v65param;
   290			}
   291		}
   292		if (pa_v5) {
   293			struct set_error_type_with_address *v5param;
   294	
   295			v5param = acpi_os_map_iomem(pa_v5, sizeof(*v5param));
   296			if (v5param) {
   297				acpi5 = 1;
   298				check_vendor_extension(pa_v5, v5param);
   299				return v5param;
   300			}
   301		}
   302		if (param_extension && pa_v4) {
   303			struct einj_parameter *v4param;
   304	
   305			v4param = acpi_os_map_iomem(pa_v4, sizeof(*v4param));
   306			if (!v4param)
   307				return NULL;
   308			if (v4param->reserved1 || v4param->reserved2) {
   309				acpi_os_unmap_iomem(v4param, sizeof(*v4param));
   310				return NULL;
   311			}
   312			return v4param;
   313		}
   314	
   315		return NULL;
   316	}
   317	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests
RE: [PATCH] ACPI: APEI: EINJ: EINJV2 support added
Posted by Luck, Tony 2 years, 9 months ago
> drivers/acpi/apei/einj.c | 172 +++++++++++++++++++++++++++++++++++----
> include/acpi/actbl1.h    |   4 +-
> 2 files changed, 157 insertions(+), 19 deletions(-)

Needs an update to Documentation/firmware-guide/acpi/apei/einj.rst
with some example of how to use the EINJV2 injection. It appears that
param3 and param4 are now used for memory injection instead of
(or as well as?) param1 and param2. But it isn't all that obvious what
they do.

-Tony