Пример #1
0
int __init erst_init(void)
{
	int rc = 0;
	acpi_status status;
	struct apei_exec_context ctx;

	if (acpi_disabled)
		return -ENODEV;

	status = acpi_get_table(ACPI_SIG_ERST, 0,
				(struct acpi_table_header **)&erst_tab);
	if (status == AE_NOT_FOUND) {
		printk(KERN_INFO "ERST table was not found\n");
		return -ENODEV;
	} else if (ACPI_FAILURE(status)) {
		const char *msg = acpi_format_exception(status);
		printk(KERN_WARNING "Failed to get ERST table: %s\n", msg);
		return -EINVAL;
	}

	rc = erst_check_table(erst_tab);
	if (rc) {
		printk(KERN_ERR "ERST table is invalid\n");
		return rc;
	}

	erst_exec_ctx_init(&ctx);
	rc = apei_exec_pre_map_gars(&ctx);
	if (rc)
		return rc;

	rc = erst_get_erange(&erst_erange);
	if (rc) {
		if (rc == -ENODEV)
			printk(KERN_INFO
			"The corresponding hardware device or firmware "
			"implementation is not available.\n");
		else
			printk(KERN_ERR
			       "Failed to get Error Log Address Range.\n");
		goto err_unmap_reg;
	}

	erst_erange.vaddr = apei_pre_map(erst_erange.base, erst_erange.size);
	if (!erst_erange.vaddr) {
		rc = -ENOMEM;
		goto err_unmap_reg;
	}

	printk(KERN_INFO "Xen ERST support is initialized.\n");
	erst_enabled = 1;

	return 0;

err_unmap_reg:
	apei_exec_post_unmap_gars(&ctx);
	return rc;
}
Пример #2
0
static ssize_t __erst_get_record_count(void)
{
	struct apei_exec_context ctx;
	int rc;

	erst_exec_ctx_init(&ctx);
	rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_COUNT);
	if (rc)
		return rc;
	return apei_exec_ctx_get_output(&ctx);
}
Пример #3
0
static int __erst_get_next_record_id(u64 *record_id)
{
    struct apei_exec_context ctx;
    int rc;

    erst_exec_ctx_init(&ctx);
    rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_ID);
    if (rc)
        return rc;
    *record_id = apei_exec_ctx_get_output(&ctx);

    return 0;
}
Пример #4
0
static int __erst_read_from_storage(u64 record_id, u64 offset)
{
    struct apei_exec_context ctx;
    u64 timeout = FIRMWARE_TIMEOUT;
    u64 val;
    int rc;

    erst_exec_ctx_init(&ctx);
    rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_READ);
    if (rc)
        return rc;
    apei_exec_ctx_set_input(&ctx, offset);
    rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_OFFSET);
    if (rc)
        return rc;
    apei_exec_ctx_set_input(&ctx, record_id);
    rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_ID);
    if (rc)
        return rc;
    rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION);
    if (rc)
        return rc;
    for (;;) {
        rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS);
        if (rc)
            return rc;
        val = apei_exec_ctx_get_output(&ctx);
        if (!val)
            break;
        if (erst_timedout(&timeout, SPIN_UNIT))
            return -EIO;
    };
    rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS);
    if (rc)
        return rc;
    val = apei_exec_ctx_get_output(&ctx);
    rc = apei_exec_run(&ctx, ACPI_ERST_END);
    if (rc)
        return rc;

    return erst_errno(val);
}
Пример #5
0
static int erst_get_erange(struct erst_erange *range)
{
	struct apei_exec_context ctx;
	int rc;

	erst_exec_ctx_init(&ctx);
	rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_RANGE);
	if (rc)
		return rc;
	range->base = apei_exec_ctx_get_output(&ctx);
	rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_LENGTH);
	if (rc)
		return rc;
	range->size = apei_exec_ctx_get_output(&ctx);
	rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_ATTRIBUTES);
	if (rc)
		return rc;
	range->attr = apei_exec_ctx_get_output(&ctx);

	return 0;
}
Пример #6
0
static int __init erst_init(void)
{
    int rc = 0;
    acpi_status status;
    struct apei_exec_context ctx;
    struct apei_resources erst_resources;
    struct resource *r;

    if (acpi_disabled)
        goto err;

    if (erst_disable) {
        pr_info(ERST_PFX
                "Error Record Serialization Table (ERST) support is disabled.\n");
        goto err;
    }

    status = acpi_get_table(ACPI_SIG_ERST, 0,
                            (struct acpi_table_header **)&erst_tab);
    if (status == AE_NOT_FOUND) {
        pr_info(ERST_PFX "Table is not found!\n");
        goto err;
    } else if (ACPI_FAILURE(status)) {
        const char *msg = acpi_format_exception(status);
        pr_err(ERST_PFX "Failed to get table, %s\n", msg);
        rc = -EINVAL;
        goto err;
    }

    rc = erst_check_table(erst_tab);
    if (rc) {
        pr_err(FW_BUG ERST_PFX "ERST table is invalid\n");
        goto err;
    }

    apei_resources_init(&erst_resources);
    erst_exec_ctx_init(&ctx);
    rc = apei_exec_collect_resources(&ctx, &erst_resources);
    if (rc)
        goto err_fini;
    rc = apei_resources_request(&erst_resources, "APEI ERST");
    if (rc)
        goto err_fini;
    rc = apei_exec_pre_map_gars(&ctx);
    if (rc)
        goto err_release;
    rc = erst_get_erange(&erst_erange);
    if (rc) {
        if (rc == -ENODEV)
            pr_info(ERST_PFX
                    "The corresponding hardware device or firmware implementation "
                    "is not available.\n");
        else
            pr_err(ERST_PFX
                   "Failed to get Error Log Address Range.\n");
        goto err_unmap_reg;
    }

    r = request_mem_region(erst_erange.base, erst_erange.size, "APEI ERST");
    if (!r) {
        pr_err(ERST_PFX
               "Can not request iomem region <0x%16llx-0x%16llx> for ERST.\n",
               (unsigned long long)erst_erange.base,
               (unsigned long long)erst_erange.base + erst_erange.size);
        rc = -EIO;
        goto err_unmap_reg;
    }
    rc = -ENOMEM;
    erst_erange.vaddr = ioremap_cache(erst_erange.base,
                                      erst_erange.size);
    if (!erst_erange.vaddr)
        goto err_release_erange;

    pr_info(ERST_PFX
            "Error Record Serialization Table (ERST) support is initialized.\n");

    return 0;

err_release_erange:
    release_mem_region(erst_erange.base, erst_erange.size);
err_unmap_reg:
    apei_exec_post_unmap_gars(&ctx);
err_release:
    apei_resources_release(&erst_resources);
err_fini:
    apei_resources_fini(&erst_resources);
err:
    erst_disable = 1;
    return rc;
}