| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * APEI Hardware Error Souce Table support |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 12 | 13 | * |
|---|
| 13 | 14 | * Copyright 2009 Intel Corp. |
|---|
| 14 | 15 | * Author: Huang Ying <ying.huang@intel.com> |
|---|
| 15 | | - * |
|---|
| 16 | | - * This program is free software; you can redistribute it and/or |
|---|
| 17 | | - * modify it under the terms of the GNU General Public License version |
|---|
| 18 | | - * 2 as published by the Free Software Foundation; |
|---|
| 19 | | - * |
|---|
| 20 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 21 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 22 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 23 | | - * GNU General Public License for more details. |
|---|
| 24 | 16 | */ |
|---|
| 25 | 17 | |
|---|
| 26 | 18 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 32 | 24 | #include <linux/io.h> |
|---|
| 33 | 25 | #include <linux/platform_device.h> |
|---|
| 34 | 26 | #include <acpi/apei.h> |
|---|
| 27 | +#include <acpi/ghes.h> |
|---|
| 35 | 28 | |
|---|
| 36 | 29 | #include "apei-internal.h" |
|---|
| 37 | 30 | |
|---|
| .. | .. |
|---|
| 53 | 46 | [ACPI_HEST_TYPE_AER_BRIDGE] = sizeof(struct acpi_hest_aer_bridge), |
|---|
| 54 | 47 | [ACPI_HEST_TYPE_GENERIC_ERROR] = sizeof(struct acpi_hest_generic), |
|---|
| 55 | 48 | [ACPI_HEST_TYPE_GENERIC_ERROR_V2] = sizeof(struct acpi_hest_generic_v2), |
|---|
| 49 | + [ACPI_HEST_TYPE_IA32_DEFERRED_CHECK] = -1, |
|---|
| 56 | 50 | }; |
|---|
| 57 | 51 | |
|---|
| 58 | 52 | static int hest_esrc_len(struct acpi_hest_header *hest_hdr) |
|---|
| .. | .. |
|---|
| 75 | 69 | mc = (struct acpi_hest_ia_machine_check *)hest_hdr; |
|---|
| 76 | 70 | len = sizeof(*mc) + mc->num_hardware_banks * |
|---|
| 77 | 71 | sizeof(struct acpi_hest_ia_error_bank); |
|---|
| 72 | + } else if (hest_type == ACPI_HEST_TYPE_IA32_DEFERRED_CHECK) { |
|---|
| 73 | + struct acpi_hest_ia_deferred_check *mc; |
|---|
| 74 | + mc = (struct acpi_hest_ia_deferred_check *)hest_hdr; |
|---|
| 75 | + len = sizeof(*mc) + mc->num_hardware_banks * |
|---|
| 76 | + sizeof(struct acpi_hest_ia_error_bank); |
|---|
| 78 | 77 | } |
|---|
| 79 | 78 | BUG_ON(len == -1); |
|---|
| 80 | 79 | |
|---|
| .. | .. |
|---|
| 93 | 92 | for (i = 0; i < hest_tab->error_source_count; i++) { |
|---|
| 94 | 93 | len = hest_esrc_len(hest_hdr); |
|---|
| 95 | 94 | if (!len) { |
|---|
| 96 | | - pr_warning(FW_WARN HEST_PFX |
|---|
| 97 | | - "Unknown or unused hardware error source " |
|---|
| 98 | | - "type: %d for hardware error source: %d.\n", |
|---|
| 99 | | - hest_hdr->type, hest_hdr->source_id); |
|---|
| 95 | + pr_warn(FW_WARN HEST_PFX |
|---|
| 96 | + "Unknown or unused hardware error source " |
|---|
| 97 | + "type: %d for hardware error source: %d.\n", |
|---|
| 98 | + hest_hdr->type, hest_hdr->source_id); |
|---|
| 100 | 99 | return -EINVAL; |
|---|
| 101 | 100 | } |
|---|
| 102 | 101 | if ((void *)hest_hdr + len > |
|---|
| 103 | 102 | (void *)hest_tab + hest_tab->header.length) { |
|---|
| 104 | | - pr_warning(FW_BUG HEST_PFX |
|---|
| 103 | + pr_warn(FW_BUG HEST_PFX |
|---|
| 105 | 104 | "Table contents overflow for hardware error source: %d.\n", |
|---|
| 106 | 105 | hest_hdr->source_id); |
|---|
| 107 | 106 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 165 | 164 | ghes_dev = ghes_arr->ghes_devs[i]; |
|---|
| 166 | 165 | hdr = *(struct acpi_hest_header **)ghes_dev->dev.platform_data; |
|---|
| 167 | 166 | if (hdr->source_id == hest_hdr->source_id) { |
|---|
| 168 | | - pr_warning(FW_WARN HEST_PFX "Duplicated hardware error source ID: %d.\n", |
|---|
| 169 | | - hdr->source_id); |
|---|
| 167 | + pr_warn(FW_WARN HEST_PFX "Duplicated hardware error source ID: %d.\n", |
|---|
| 168 | + hdr->source_id); |
|---|
| 170 | 169 | return -EIO; |
|---|
| 171 | 170 | } |
|---|
| 172 | 171 | } |
|---|
| .. | .. |
|---|
| 203 | 202 | rc = apei_hest_parse(hest_parse_ghes, &ghes_arr); |
|---|
| 204 | 203 | if (rc) |
|---|
| 205 | 204 | goto err; |
|---|
| 205 | + |
|---|
| 206 | + rc = ghes_estatus_pool_init(ghes_count); |
|---|
| 207 | + if (rc) |
|---|
| 208 | + goto err; |
|---|
| 209 | + |
|---|
| 206 | 210 | out: |
|---|
| 207 | 211 | kfree(ghes_arr.ghes_devs); |
|---|
| 208 | 212 | return rc; |
|---|
| .. | .. |
|---|
| 215 | 219 | static int __init setup_hest_disable(char *str) |
|---|
| 216 | 220 | { |
|---|
| 217 | 221 | hest_disable = HEST_DISABLED; |
|---|
| 218 | | - return 0; |
|---|
| 222 | + return 1; |
|---|
| 219 | 223 | } |
|---|
| 220 | 224 | |
|---|
| 221 | 225 | __setup("hest_disable", setup_hest_disable); |
|---|
| .. | .. |
|---|
| 223 | 227 | void __init acpi_hest_init(void) |
|---|
| 224 | 228 | { |
|---|
| 225 | 229 | acpi_status status; |
|---|
| 226 | | - int rc = -ENODEV; |
|---|
| 230 | + int rc; |
|---|
| 227 | 231 | unsigned int ghes_count = 0; |
|---|
| 228 | 232 | |
|---|
| 229 | 233 | if (hest_disable) { |
|---|
| .. | .. |
|---|
| 239 | 243 | } else if (ACPI_FAILURE(status)) { |
|---|
| 240 | 244 | const char *msg = acpi_format_exception(status); |
|---|
| 241 | 245 | pr_err(HEST_PFX "Failed to get table, %s\n", msg); |
|---|
| 242 | | - rc = -EINVAL; |
|---|
| 243 | | - goto err; |
|---|
| 246 | + hest_disable = HEST_DISABLED; |
|---|
| 247 | + return; |
|---|
| 244 | 248 | } |
|---|
| 245 | 249 | |
|---|
| 246 | 250 | rc = apei_hest_parse(hest_parse_cmc, NULL); |
|---|
| .. | .. |
|---|
| 251 | 255 | rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count); |
|---|
| 252 | 256 | if (rc) |
|---|
| 253 | 257 | goto err; |
|---|
| 254 | | - rc = hest_ghes_dev_register(ghes_count); |
|---|
| 258 | + |
|---|
| 259 | + if (ghes_count) |
|---|
| 260 | + rc = hest_ghes_dev_register(ghes_count); |
|---|
| 255 | 261 | if (rc) |
|---|
| 256 | 262 | goto err; |
|---|
| 257 | 263 | } |
|---|
| .. | .. |
|---|
| 260 | 266 | return; |
|---|
| 261 | 267 | err: |
|---|
| 262 | 268 | hest_disable = HEST_DISABLED; |
|---|
| 269 | + acpi_put_table((struct acpi_table_header *)hest_tab); |
|---|
| 263 | 270 | } |
|---|