Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73f05330 authored by Len Brown's avatar Len Brown
Browse files

Merge branch 'apei' into release



Conflicts:
	drivers/acpi/apei/apei-base.c

This was a conflict between

15afae60
(CPI, APEI: Fix incorrect APEI register bit width check and usage)

and

653f4b53
(ACPICA: Expand OSL memory read/write interfaces to 64 bits)

The former changed a parameter in the call to acpi_os_read_memory64()
and the later replaced all calls to acpi_os_read_memory64()
with calls to acpi_os_read_memory().

Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parents 1a05e467 8cdde126
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -53,6 +53,14 @@ directory apei/einj. The following files are provided.
  This file is used to set the second error parameter value. Effect of
  parameter depends on error_type specified.

- notrigger
  The EINJ mechanism is a two step process. First inject the error, then
  perform some actions to trigger it. Setting "notrigger" to 1 skips the
  trigger phase, which *may* allow the user to cause the error in some other
  context by a simple access to the cpu, memory location, or device that is
  the target of the error injection. Whether this actually works depends
  on what operations the BIOS actually includes in the trigger phase.

BIOS versions based in the ACPI 4.0 specification have limited options
to control where the errors are injected.  Your BIOS may support an
extension (enabled with the param_extension=1 module parameter, or
+40 −21
Original line number Diff line number Diff line
@@ -558,33 +558,48 @@ void apei_resources_release(struct apei_resources *resources)
}
EXPORT_SYMBOL_GPL(apei_resources_release);

static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr,
				u32 *access_bit_width)
{
	u32 width, space_id;
	u32 bit_width, bit_offset, access_size_code, space_id;

	width = reg->bit_width;
	bit_width = reg->bit_width;
	bit_offset = reg->bit_offset;
	access_size_code = reg->access_width;
	space_id = reg->space_id;
	/* Handle possible alignment issues */
	memcpy(paddr, &reg->address, sizeof(*paddr));
	if (!*paddr) {
		pr_warning(FW_BUG APEI_PFX
			   "Invalid physical address in GAR [0x%llx/%u/%u]\n",
			   *paddr, width, space_id);
			   "Invalid physical address in GAR [0x%llx/%u/%u/%u/%u]\n",
			   *paddr, bit_width, bit_offset, access_size_code,
			   space_id);
		return -EINVAL;
	}

	if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) {
	if (access_size_code < 1 || access_size_code > 4) {
		pr_warning(FW_BUG APEI_PFX
			   "Invalid bit width in GAR [0x%llx/%u/%u]\n",
			   *paddr, width, space_id);
			   "Invalid access size code in GAR [0x%llx/%u/%u/%u/%u]\n",
			   *paddr, bit_width, bit_offset, access_size_code,
			   space_id);
		return -EINVAL;
	}
	*access_bit_width = 1UL << (access_size_code + 2);

	if ((bit_width + bit_offset) > *access_bit_width) {
		pr_warning(FW_BUG APEI_PFX
			   "Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n",
			   *paddr, bit_width, bit_offset, access_size_code,
			   space_id);
		return -EINVAL;
	}

	if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY &&
	    space_id != ACPI_ADR_SPACE_SYSTEM_IO) {
		pr_warning(FW_BUG APEI_PFX
			   "Invalid address space type in GAR [0x%llx/%u/%u]\n",
			   *paddr, width, space_id);
			   "Invalid address space type in GAR [0x%llx/%u/%u/%u/%u]\n",
			   *paddr, bit_width, bit_offset, access_size_code,
			   space_id);
		return -EINVAL;
	}

@@ -595,23 +610,25 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr)
int apei_read(u64 *val, struct acpi_generic_address *reg)
{
	int rc;
	u32 access_bit_width;
	u64 address;
	acpi_status status;

	rc = apei_check_gar(reg, &address);
	rc = apei_check_gar(reg, &address, &access_bit_width);
	if (rc)
		return rc;

	*val = 0;
	switch(reg->space_id) {
	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
		status = acpi_os_read_memory((acpi_physical_address)
					     address, val, reg->bit_width);
		status = acpi_os_read_memory((acpi_physical_address) address,
					       val, access_bit_width);
		if (ACPI_FAILURE(status))
			return -EIO;
		break;
	case ACPI_ADR_SPACE_SYSTEM_IO:
		status = acpi_os_read_port(address, (u32 *)val, reg->bit_width);
		status = acpi_os_read_port(address, (u32 *)val,
					   access_bit_width);
		if (ACPI_FAILURE(status))
			return -EIO;
		break;
@@ -627,22 +644,23 @@ EXPORT_SYMBOL_GPL(apei_read);
int apei_write(u64 val, struct acpi_generic_address *reg)
{
	int rc;
	u32 access_bit_width;
	u64 address;
	acpi_status status;

	rc = apei_check_gar(reg, &address);
	rc = apei_check_gar(reg, &address, &access_bit_width);
	if (rc)
		return rc;

	switch (reg->space_id) {
	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
		status = acpi_os_write_memory((acpi_physical_address)
					      address, val, reg->bit_width);
		status = acpi_os_write_memory((acpi_physical_address) address,
						val, access_bit_width);
		if (ACPI_FAILURE(status))
			return -EIO;
		break;
	case ACPI_ADR_SPACE_SYSTEM_IO:
		status = acpi_os_write_port(address, val, reg->bit_width);
		status = acpi_os_write_port(address, val, access_bit_width);
		if (ACPI_FAILURE(status))
			return -EIO;
		break;
@@ -661,23 +679,24 @@ static int collect_res_callback(struct apei_exec_context *ctx,
	struct apei_resources *resources = data;
	struct acpi_generic_address *reg = &entry->register_region;
	u8 ins = entry->instruction;
	u32 access_bit_width;
	u64 paddr;
	int rc;

	if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER))
		return 0;

	rc = apei_check_gar(reg, &paddr);
	rc = apei_check_gar(reg, &paddr, &access_bit_width);
	if (rc)
		return rc;

	switch (reg->space_id) {
	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
		return apei_res_add(&resources->iomem, paddr,
				    reg->bit_width / 8);
				    access_bit_width / 8);
	case ACPI_ADR_SPACE_SYSTEM_IO:
		return apei_res_add(&resources->ioport, paddr,
				    reg->bit_width / 8);
				    access_bit_width / 8);
	default:
		return -EINVAL;
	}
+2 −0
Original line number Diff line number Diff line
@@ -362,6 +362,7 @@ void apei_estatus_print(const char *pfx,
		gedata_len = gdata->error_data_length;
		apei_estatus_print_section(pfx, gdata, sec_no);
		data_len -= gedata_len + sizeof(*gdata);
		gdata = (void *)(gdata + 1) + gedata_len;
		sec_no++;
	}
}
@@ -396,6 +397,7 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
		if (gedata_len > data_len - sizeof(*gdata))
			return -EINVAL;
		data_len -= gedata_len + sizeof(*gdata);
		gdata = (void *)(gdata + 1) + gedata_len;
	}
	if (data_len)
		return -EINVAL;
+13 −4
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ struct vendor_error_type_extension {
	u8	reserved[3];
};

static u32 notrigger;

static u32 vendor_flags;
static struct debugfs_blob_wrapper vendor_blob;
static char vendor_dev[64];
@@ -238,7 +240,7 @@ static void *einj_get_parameter_address(void)
			return v5param;
		}
	}
	if (paddrv4) {
	if (param_extension && paddrv4) {
		struct einj_parameter *v4param;

		v4param = acpi_os_map_memory(paddrv4, sizeof(*v4param));
@@ -496,9 +498,11 @@ static int __einj_error_inject(u32 type, u64 param1, u64 param2)
	if (rc)
		return rc;
	trigger_paddr = apei_exec_ctx_get_output(&ctx);
	if (notrigger == 0) {
		rc = __einj_error_trigger(trigger_paddr, type, param1, param2);
		if (rc)
			return rc;
	}
	rc = apei_exec_run_optional(&ctx, ACPI_EINJ_END_OPERATION);

	return rc;
@@ -700,6 +704,11 @@ static int __init einj_init(void)
					    einj_debug_dir, &error_param2);
		if (!fentry)
			goto err_unmap;

		fentry = debugfs_create_x32("notrigger", S_IRUSR | S_IWUSR,
					    einj_debug_dir, &notrigger);
		if (!fentry)
			goto err_unmap;
	}

	if (vendor_dev[0]) {
+1 −1
Original line number Diff line number Diff line
@@ -917,7 +917,7 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
{
	if ((erst_tab->header_length !=
	     (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header)))
	    && (erst_tab->header_length != sizeof(struct acpi_table_einj)))
	    && (erst_tab->header_length != sizeof(struct acpi_table_erst)))
		return -EINVAL;
	if (erst_tab->header.length < sizeof(struct acpi_table_erst))
		return -EINVAL;