Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef GHES_H
0003 #define GHES_H
0004 
0005 #include <acpi/apei.h>
0006 #include <acpi/hed.h>
0007 
0008 /*
0009  * One struct ghes is created for each generic hardware error source.
0010  * It provides the context for APEI hardware error timer/IRQ/SCI/NMI
0011  * handler.
0012  *
0013  * estatus: memory buffer for error status block, allocated during
0014  * HEST parsing.
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  * ghes_register_vendor_record_notifier - register a notifier for vendor
0059  * records that the kernel would otherwise ignore.
0060  * @nb: pointer to the notifier_block structure of the event handler.
0061  *
0062  * return 0 : SUCCESS, non-zero : FAIL
0063  */
0064 int ghes_register_vendor_record_notifier(struct notifier_block *nb);
0065 
0066 /**
0067  * ghes_unregister_vendor_record_notifier - unregister the previously
0068  * registered vendor record notifier.
0069  * @nb: pointer to the notifier_block structure of the vendor record handler.
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 /* From drivers/edac/ghes_edac.c */
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 /* GHES_H */