Unverified Commit d9460047 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!5040 [OLK-6.6] Add support for Vendor Defined Error Types in Einj Module

Merge Pull Request from: @kile2009 
 
This patchset adds support for Vendor Defined Error types in the einj module by exporting a binary blob file in module's debugfs directory.

https://gitee.com/openeuler/kernel/issues/I96PUG 
 
Link:https://gitee.com/openeuler/kernel/pulls/5040

 

Reviewed-by: default avatarXiaoFei Tan <tanxiaofei@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents 55c36f20 f0f012bc
Loading
Loading
Loading
Loading
+48 −23
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ static u32 notrigger;

static u32 vendor_flags;
static struct debugfs_blob_wrapper vendor_blob;
static struct debugfs_blob_wrapper vendor_errors;
static char vendor_dev[64];

/*
@@ -182,6 +183,21 @@ static int einj_timedout(u64 *t)
	return 0;
}

static void get_oem_vendor_struct(u64 paddr, int offset,
				  struct vendor_error_type_extension *v)
{
	unsigned long vendor_size;
	u64 target_pa = paddr + offset + sizeof(struct vendor_error_type_extension);

	vendor_size = v->length - sizeof(struct vendor_error_type_extension);

	if (vendor_size)
		vendor_errors.data = acpi_os_map_memory(target_pa, vendor_size);

	if (vendor_errors.data)
		vendor_errors.size = vendor_size;
}

static void check_vendor_extension(u64 paddr,
				   struct set_error_type_with_address *v5param)
{
@@ -194,6 +210,7 @@ static void check_vendor_extension(u64 paddr,
	v = acpi_os_map_iomem(paddr + offset, sizeof(*v));
	if (!v)
		return;
	get_oem_vendor_struct(paddr, offset, v);
	sbdf = v->pcie_sbdf;
	sprintf(vendor_dev, "%x:%x:%x.%x vendor_id=%x device_id=%x rev_id=%x\n",
		sbdf >> 24, (sbdf >> 16) & 0xff,
@@ -577,38 +594,40 @@ static u64 error_param2;
static u64 error_param3;
static u64 error_param4;
static struct dentry *einj_debug_dir;
static const char * const einj_error_type_string[] = {
	"0x00000001\tProcessor Correctable\n",
	"0x00000002\tProcessor Uncorrectable non-fatal\n",
	"0x00000004\tProcessor Uncorrectable fatal\n",
	"0x00000008\tMemory Correctable\n",
	"0x00000010\tMemory Uncorrectable non-fatal\n",
	"0x00000020\tMemory Uncorrectable fatal\n",
	"0x00000040\tPCI Express Correctable\n",
	"0x00000080\tPCI Express Uncorrectable non-fatal\n",
	"0x00000100\tPCI Express Uncorrectable fatal\n",
	"0x00000200\tPlatform Correctable\n",
	"0x00000400\tPlatform Uncorrectable non-fatal\n",
	"0x00000800\tPlatform Uncorrectable fatal\n",
	"0x00001000\tCXL.cache Protocol Correctable\n",
	"0x00002000\tCXL.cache Protocol Uncorrectable non-fatal\n",
	"0x00004000\tCXL.cache Protocol Uncorrectable fatal\n",
	"0x00008000\tCXL.mem Protocol Correctable\n",
	"0x00010000\tCXL.mem Protocol Uncorrectable non-fatal\n",
	"0x00020000\tCXL.mem Protocol Uncorrectable fatal\n",
static struct { u32 mask; const char *str; } const einj_error_type_string[] = {
	{ BIT(0), "Processor Correctable" },
	{ BIT(1), "Processor Uncorrectable non-fatal" },
	{ BIT(2), "Processor Uncorrectable fatal" },
	{ BIT(3), "Memory Correctable" },
	{ BIT(4), "Memory Uncorrectable non-fatal" },
	{ BIT(5), "Memory Uncorrectable fatal" },
	{ BIT(6), "PCI Express Correctable" },
	{ BIT(7), "PCI Express Uncorrectable non-fatal" },
	{ BIT(8), "PCI Express Uncorrectable fatal" },
	{ BIT(9), "Platform Correctable" },
	{ BIT(10), "Platform Uncorrectable non-fatal" },
	{ BIT(11), "Platform Uncorrectable fatal"},
	{ BIT(12), "CXL.cache Protocol Correctable" },
	{ BIT(13), "CXL.cache Protocol Uncorrectable non-fatal" },
	{ BIT(14), "CXL.cache Protocol Uncorrectable fatal" },
	{ BIT(15), "CXL.mem Protocol Correctable" },
	{ BIT(16), "CXL.mem Protocol Uncorrectable non-fatal" },
	{ BIT(17), "CXL.mem Protocol Uncorrectable fatal" },
	{ BIT(31), "Vendor Defined Error Types" },
};

static int available_error_type_show(struct seq_file *m, void *v)
{
	int rc;
	u32 available_error_type = 0;
	u32 error_type = 0;

	rc = einj_get_available_error_type(&available_error_type);
	rc = einj_get_available_error_type(&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 (error_type & einj_error_type_string[pos].mask)
			seq_printf(m, "0x%08x\t%s\n", einj_error_type_string[pos].mask,
				   einj_error_type_string[pos].str);

	return 0;
}
@@ -767,6 +786,10 @@ static int __init einj_init(void)
				   einj_debug_dir, &vendor_flags);
	}

	if (vendor_errors.size)
		debugfs_create_blob("oem_error", 0600, einj_debug_dir,
				    &vendor_errors);

	pr_info("Error INJection is initialized.\n");

	return 0;
@@ -792,6 +815,8 @@ static void __exit einj_exit(void)
			sizeof(struct einj_parameter);

		acpi_os_unmap_iomem(einj_param, size);
		if (vendor_errors.size)
			acpi_os_unmap_memory(vendor_errors.data, vendor_errors.size);
	}
	einj_exec_ctx_init(&ctx);
	apei_exec_post_unmap_gars(&ctx);
+1 −1
Original line number Diff line number Diff line
@@ -454,7 +454,7 @@ static int cros_ec_create_panicinfo(struct cros_ec_debugfs *debug_info)
	debug_info->panicinfo_blob.data = data;
	debug_info->panicinfo_blob.size = ret;

	debugfs_create_blob("panicinfo", S_IFREG | 0444, debug_info->dir,
	debugfs_create_blob("panicinfo", 0444, debug_info->dir,
			    &debug_info->panicinfo_blob);

	return 0;
+23 −5
Original line number Diff line number Diff line
@@ -1008,17 +1008,35 @@ static ssize_t read_file_blob(struct file *file, char __user *user_buf,
	return r;
}

static ssize_t write_file_blob(struct file *file, const char __user *user_buf,
			       size_t count, loff_t *ppos)
{
	struct debugfs_blob_wrapper *blob = file->private_data;
	struct dentry *dentry = F_DENTRY(file);
	ssize_t r;

	r = debugfs_file_get(dentry);
	if (unlikely(r))
		return r;
	r = simple_write_to_buffer(blob->data, blob->size, ppos, user_buf,
				   count);

	debugfs_file_put(dentry);
	return r;
}

static const struct file_operations fops_blob = {
	.read =		read_file_blob,
	.write =	write_file_blob,
	.open =		simple_open,
	.llseek =	default_llseek,
};

/**
 * debugfs_create_blob - create a debugfs file that is used to read a binary blob
 * debugfs_create_blob - create a debugfs file that is used to read and write
 * a binary blob
 * @name: a pointer to a string containing the name of the file to create.
 * @mode: the read permission that the file should have (other permissions are
 *	  masked out)
 * @mode: the permission that the file should have
 * @parent: a pointer to the parent dentry for this file.  This should be a
 *          directory dentry if set.  If this parameter is %NULL, then the
 *          file will be created in the root of the debugfs filesystem.
@@ -1027,7 +1045,7 @@ static const struct file_operations fops_blob = {
 *
 * This function creates a file in debugfs with the given name that exports
 * @blob->data as a binary blob. If the @mode variable is so set it can be
 * read from. Writing is not supported.
 * read from and written to.
 *
 * This function will return a pointer to a dentry if it succeeds.  This
 * pointer must be passed to the debugfs_remove() function when the file is
@@ -1042,7 +1060,7 @@ struct dentry *debugfs_create_blob(const char *name, umode_t mode,
				   struct dentry *parent,
				   struct debugfs_blob_wrapper *blob)
{
	return debugfs_create_file_unsafe(name, mode & 0444, parent, blob, &fops_blob);
	return debugfs_create_file_unsafe(name, mode & 0644, parent, blob, &fops_blob);
}
EXPORT_SYMBOL_GPL(debugfs_create_blob);