diff options
Diffstat (limited to 'drivers/acpi/apei/ghes.c')
-rw-r--r-- | drivers/acpi/apei/ghes.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 4fb274bb209e..4c1d8e5e9ada 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -317,12 +317,12 @@ static int __ghes_check_estatus(struct ghes *ghes, return 0; } -static int ghes_read_estatus(struct ghes *ghes, - struct acpi_hest_generic_status *estatus, - u64 *buf_paddr, enum fixed_addresses fixmap_idx) +/* Read the CPER block, returning its address, and header in estatus. */ +static int __ghes_peek_estatus(struct ghes *ghes, + struct acpi_hest_generic_status *estatus, + u64 *buf_paddr, enum fixed_addresses fixmap_idx) { struct acpi_hest_generic *g = ghes->generic; - u32 len; int rc; rc = apei_read(buf_paddr, &g->error_status_address); @@ -343,14 +343,14 @@ static int ghes_read_estatus(struct ghes *ghes, return -ENOENT; } - rc = __ghes_check_estatus(ghes, estatus); - if (rc) - return rc; + return __ghes_check_estatus(ghes, estatus); +} - len = cper_estatus_len(estatus); - ghes_copy_tofrom_phys(estatus + 1, - *buf_paddr + sizeof(*estatus), - len - sizeof(*estatus), 1, fixmap_idx); +static int __ghes_read_estatus(struct acpi_hest_generic_status *estatus, + u64 buf_paddr, enum fixed_addresses fixmap_idx, + size_t buf_len) +{ + ghes_copy_tofrom_phys(estatus, buf_paddr, buf_len, 1, fixmap_idx); if (cper_estatus_check(estatus)) { pr_warn_ratelimited(FW_WARN GHES_PFX "Failed to read error status block!\n"); @@ -360,6 +360,24 @@ static int ghes_read_estatus(struct ghes *ghes, return 0; } +static int ghes_read_estatus(struct ghes *ghes, + struct acpi_hest_generic_status *estatus, + u64 *buf_paddr, enum fixed_addresses fixmap_idx) +{ + int rc; + + rc = __ghes_peek_estatus(ghes, estatus, buf_paddr, fixmap_idx); + if (rc) + return rc; + + rc = __ghes_check_estatus(ghes, estatus); + if (rc) + return rc; + + return __ghes_read_estatus(estatus, *buf_paddr, fixmap_idx, + cper_estatus_len(estatus)); +} + static void ghes_clear_estatus(struct ghes *ghes, struct acpi_hest_generic_status *estatus, u64 buf_paddr, enum fixed_addresses fixmap_idx) |