aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Morse <james.morse@arm.com>2019-01-29 13:48:44 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-02-07 17:10:45 -0500
commit5cc6c68287ae4be22c40b41cf6844746cddebbcc (patch)
tree5ea68b0589cb1385c4a422fdb15908ff8452440c
parent7d49f2c75af22f980fd716a13634a16cfb7dd8a7 (diff)
ACPI / APEI: Don't update struct ghes' flags in read/clear estatus
ghes_read_estatus() sets a flag in struct ghes if the buffer of CPER records needs to be cleared once the records have been processed. This flag value is a problem if a struct ghes can be processed concurrently, as happens at probe time if an NMI arrives for the same error source. The NMI clears the flag, meaning the interrupted handler may never do the ghes_estatus_clear() work. The GHES_TO_CLEAR flags is only set at the same time as buffer_paddr, which is now owned by the caller and passed to ghes_clear_estatus(). Use this value as the flag. A non-zero buf_paddr returned by ghes_read_estatus() means ghes_clear_estatus() should clear this address. ghes_read_estatus() already checks for a read of error_status_address being zero, so CPER records cannot be written here. Signed-off-by: James Morse <james.morse@arm.com> Reviewed-by: Borislav Petkov <bp@suse.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/apei/ghes.c5
-rw-r--r--include/acpi/ghes.h1
2 files changed, 0 insertions, 6 deletions
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index c20e1d0947b1..af3c10f47f20 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -329,8 +329,6 @@ static int ghes_read_estatus(struct ghes *ghes, u64 *buf_paddr)
329 return -ENOENT; 329 return -ENOENT;
330 } 330 }
331 331
332 ghes->flags |= GHES_TO_CLEAR;
333
334 rc = -EIO; 332 rc = -EIO;
335 len = cper_estatus_len(ghes->estatus); 333 len = cper_estatus_len(ghes->estatus);
336 if (len < sizeof(*ghes->estatus)) 334 if (len < sizeof(*ghes->estatus))
@@ -357,15 +355,12 @@ err_read_block:
357static void ghes_clear_estatus(struct ghes *ghes, u64 buf_paddr) 355static void ghes_clear_estatus(struct ghes *ghes, u64 buf_paddr)
358{ 356{
359 ghes->estatus->block_status = 0; 357 ghes->estatus->block_status = 0;
360 if (!(ghes->flags & GHES_TO_CLEAR))
361 return;
362 358
363 if (!buf_paddr) 359 if (!buf_paddr)
364 return; 360 return;
365 361
366 ghes_copy_tofrom_phys(ghes->estatus, buf_paddr, 362 ghes_copy_tofrom_phys(ghes->estatus, buf_paddr,
367 sizeof(ghes->estatus->block_status), 0); 363 sizeof(ghes->estatus->block_status), 0);
368 ghes->flags &= ~GHES_TO_CLEAR;
369} 364}
370 365
371static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev) 366static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev)
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index f82f4a7ddd90..e3f1cddb4ac8 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -13,7 +13,6 @@
13 * estatus: memory buffer for error status block, allocated during 13 * estatus: memory buffer for error status block, allocated during
14 * HEST parsing. 14 * HEST parsing.
15 */ 15 */
16#define GHES_TO_CLEAR 0x0001
17#define GHES_EXITING 0x0002 16#define GHES_EXITING 0x0002
18 17
19struct ghes { 18struct ghes {