18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef GHES_H 38c2ecf20Sopenharmony_ci#define GHES_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <acpi/apei.h> 68c2ecf20Sopenharmony_ci#include <acpi/hed.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * One struct ghes is created for each generic hardware error source. 108c2ecf20Sopenharmony_ci * It provides the context for APEI hardware error timer/IRQ/SCI/NMI 118c2ecf20Sopenharmony_ci * handler. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * estatus: memory buffer for error status block, allocated during 148c2ecf20Sopenharmony_ci * HEST parsing. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci#define GHES_EXITING 0x0002 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistruct ghes { 198c2ecf20Sopenharmony_ci union { 208c2ecf20Sopenharmony_ci struct acpi_hest_generic *generic; 218c2ecf20Sopenharmony_ci struct acpi_hest_generic_v2 *generic_v2; 228c2ecf20Sopenharmony_ci }; 238c2ecf20Sopenharmony_ci struct acpi_hest_generic_status *estatus; 248c2ecf20Sopenharmony_ci unsigned long flags; 258c2ecf20Sopenharmony_ci union { 268c2ecf20Sopenharmony_ci struct list_head list; 278c2ecf20Sopenharmony_ci struct timer_list timer; 288c2ecf20Sopenharmony_ci unsigned int irq; 298c2ecf20Sopenharmony_ci }; 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistruct ghes_estatus_node { 338c2ecf20Sopenharmony_ci struct llist_node llnode; 348c2ecf20Sopenharmony_ci struct acpi_hest_generic *generic; 358c2ecf20Sopenharmony_ci struct ghes *ghes; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci int task_work_cpu; 388c2ecf20Sopenharmony_ci struct callback_head task_work; 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistruct ghes_estatus_cache { 428c2ecf20Sopenharmony_ci u32 estatus_len; 438c2ecf20Sopenharmony_ci atomic_t count; 448c2ecf20Sopenharmony_ci struct acpi_hest_generic *generic; 458c2ecf20Sopenharmony_ci unsigned long long time_in; 468c2ecf20Sopenharmony_ci struct rcu_head rcu; 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cienum { 508c2ecf20Sopenharmony_ci GHES_SEV_NO = 0x0, 518c2ecf20Sopenharmony_ci GHES_SEV_CORRECTED = 0x1, 528c2ecf20Sopenharmony_ci GHES_SEV_RECOVERABLE = 0x2, 538c2ecf20Sopenharmony_ci GHES_SEV_PANIC = 0x3, 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_APEI_GHES 578c2ecf20Sopenharmony_ci/** 588c2ecf20Sopenharmony_ci * ghes_register_vendor_record_notifier - register a notifier for vendor 598c2ecf20Sopenharmony_ci * records that the kernel would otherwise ignore. 608c2ecf20Sopenharmony_ci * @nb: pointer to the notifier_block structure of the event handler. 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * return 0 : SUCCESS, non-zero : FAIL 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ciint ghes_register_vendor_record_notifier(struct notifier_block *nb); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/** 678c2ecf20Sopenharmony_ci * ghes_unregister_vendor_record_notifier - unregister the previously 688c2ecf20Sopenharmony_ci * registered vendor record notifier. 698c2ecf20Sopenharmony_ci * @nb: pointer to the notifier_block structure of the vendor record handler. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_civoid ghes_unregister_vendor_record_notifier(struct notifier_block *nb); 728c2ecf20Sopenharmony_ci#endif 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ciint ghes_estatus_pool_init(unsigned int num_ghes); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* From drivers/edac/ghes_edac.c */ 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#ifdef CONFIG_EDAC_GHES 798c2ecf20Sopenharmony_civoid ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ciint ghes_edac_register(struct ghes *ghes, struct device *dev); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_civoid ghes_edac_unregister(struct ghes *ghes); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#else 868c2ecf20Sopenharmony_cistatic inline void ghes_edac_report_mem_error(int sev, 878c2ecf20Sopenharmony_ci struct cper_sec_mem_err *mem_err) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic inline int ghes_edac_register(struct ghes *ghes, struct device *dev) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci return -ENODEV; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic inline void ghes_edac_unregister(struct ghes *ghes) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci#endif 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic inline int acpi_hest_get_version(struct acpi_hest_generic_data *gdata) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci return gdata->revision >> 8; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic inline void *acpi_hest_get_payload(struct acpi_hest_generic_data *gdata) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci if (acpi_hest_get_version(gdata) >= 3) 1098c2ecf20Sopenharmony_ci return (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci return gdata + 1; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic inline int acpi_hest_get_error_length(struct acpi_hest_generic_data *gdata) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci return ((struct acpi_hest_generic_data *)(gdata))->error_data_length; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic inline int acpi_hest_get_size(struct acpi_hest_generic_data *gdata) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci if (acpi_hest_get_version(gdata) >= 3) 1228c2ecf20Sopenharmony_ci return sizeof(struct acpi_hest_generic_data_v300); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return sizeof(struct acpi_hest_generic_data); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic inline int acpi_hest_get_record_size(struct acpi_hest_generic_data *gdata) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci return (acpi_hest_get_size(gdata) + acpi_hest_get_error_length(gdata)); 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci return (void *)(gdata) + acpi_hest_get_record_size(gdata); 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci#define apei_estatus_for_each_section(estatus, section) \ 1388c2ecf20Sopenharmony_ci for (section = (struct acpi_hest_generic_data *)(estatus + 1); \ 1398c2ecf20Sopenharmony_ci (void *)section - (void *)(estatus + 1) < estatus->data_length; \ 1408c2ecf20Sopenharmony_ci section = acpi_hest_get_next(section)) 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI_APEI_SEA 1438c2ecf20Sopenharmony_ciint ghes_notify_sea(void); 1448c2ecf20Sopenharmony_ci#else 1458c2ecf20Sopenharmony_cistatic inline int ghes_notify_sea(void) { return -ENOENT; } 1468c2ecf20Sopenharmony_ci#endif 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci#endif /* GHES_H */ 149