0001
0002 #ifndef GHES_H
0003 #define GHES_H
0004
0005 #include <acpi/apei.h>
0006 #include <acpi/hed.h>
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #define GHES_EXITING 0x0002
0017
0018 struct ghes {
0019 union {
0020 struct acpi_hest_generic *generic;
0021 struct acpi_hest_generic_v2 *generic_v2;
0022 };
0023 struct acpi_hest_generic_status *estatus;
0024 unsigned long flags;
0025 union {
0026 struct list_head list;
0027 struct timer_list timer;
0028 unsigned int irq;
0029 };
0030 };
0031
0032 struct ghes_estatus_node {
0033 struct llist_node llnode;
0034 struct acpi_hest_generic *generic;
0035 struct ghes *ghes;
0036
0037 int task_work_cpu;
0038 struct callback_head task_work;
0039 };
0040
0041 struct ghes_estatus_cache {
0042 u32 estatus_len;
0043 atomic_t count;
0044 struct acpi_hest_generic *generic;
0045 unsigned long long time_in;
0046 struct rcu_head rcu;
0047 };
0048
0049 enum {
0050 GHES_SEV_NO = 0x0,
0051 GHES_SEV_CORRECTED = 0x1,
0052 GHES_SEV_RECOVERABLE = 0x2,
0053 GHES_SEV_PANIC = 0x3,
0054 };
0055
0056 #ifdef CONFIG_ACPI_APEI_GHES
0057
0058
0059
0060
0061
0062
0063
0064 int ghes_register_vendor_record_notifier(struct notifier_block *nb);
0065
0066
0067
0068
0069
0070
0071 void ghes_unregister_vendor_record_notifier(struct notifier_block *nb);
0072 #endif
0073
0074 int ghes_estatus_pool_init(int num_ghes);
0075
0076
0077
0078 #ifdef CONFIG_EDAC_GHES
0079 void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err);
0080
0081 int ghes_edac_register(struct ghes *ghes, struct device *dev);
0082
0083 void ghes_edac_unregister(struct ghes *ghes);
0084
0085 #else
0086 static inline void ghes_edac_report_mem_error(int sev,
0087 struct cper_sec_mem_err *mem_err)
0088 {
0089 }
0090
0091 static inline int ghes_edac_register(struct ghes *ghes, struct device *dev)
0092 {
0093 return -ENODEV;
0094 }
0095
0096 static inline void ghes_edac_unregister(struct ghes *ghes)
0097 {
0098 }
0099 #endif
0100
0101 static inline int acpi_hest_get_version(struct acpi_hest_generic_data *gdata)
0102 {
0103 return gdata->revision >> 8;
0104 }
0105
0106 static inline void *acpi_hest_get_payload(struct acpi_hest_generic_data *gdata)
0107 {
0108 if (acpi_hest_get_version(gdata) >= 3)
0109 return (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1);
0110
0111 return gdata + 1;
0112 }
0113
0114 static inline int acpi_hest_get_error_length(struct acpi_hest_generic_data *gdata)
0115 {
0116 return ((struct acpi_hest_generic_data *)(gdata))->error_data_length;
0117 }
0118
0119 static inline int acpi_hest_get_size(struct acpi_hest_generic_data *gdata)
0120 {
0121 if (acpi_hest_get_version(gdata) >= 3)
0122 return sizeof(struct acpi_hest_generic_data_v300);
0123
0124 return sizeof(struct acpi_hest_generic_data);
0125 }
0126
0127 static inline int acpi_hest_get_record_size(struct acpi_hest_generic_data *gdata)
0128 {
0129 return (acpi_hest_get_size(gdata) + acpi_hest_get_error_length(gdata));
0130 }
0131
0132 static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata)
0133 {
0134 return (void *)(gdata) + acpi_hest_get_record_size(gdata);
0135 }
0136
0137 #define apei_estatus_for_each_section(estatus, section) \
0138 for (section = (struct acpi_hest_generic_data *)(estatus + 1); \
0139 (void *)section - (void *)(estatus + 1) < estatus->data_length; \
0140 section = acpi_hest_get_next(section))
0141
0142 #ifdef CONFIG_ACPI_APEI_SEA
0143 int ghes_notify_sea(void);
0144 #else
0145 static inline int ghes_notify_sea(void) { return -ENOENT; }
0146 #endif
0147
0148 #endif