1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef GHES_H
3*4882a593Smuzhiyun #define GHES_H
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <acpi/apei.h>
6*4882a593Smuzhiyun #include <acpi/hed.h>
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun * One struct ghes is created for each generic hardware error source.
10*4882a593Smuzhiyun * It provides the context for APEI hardware error timer/IRQ/SCI/NMI
11*4882a593Smuzhiyun * handler.
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * estatus: memory buffer for error status block, allocated during
14*4882a593Smuzhiyun * HEST parsing.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun #define GHES_EXITING 0x0002
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun struct ghes {
19*4882a593Smuzhiyun union {
20*4882a593Smuzhiyun struct acpi_hest_generic *generic;
21*4882a593Smuzhiyun struct acpi_hest_generic_v2 *generic_v2;
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun struct acpi_hest_generic_status *estatus;
24*4882a593Smuzhiyun unsigned long flags;
25*4882a593Smuzhiyun union {
26*4882a593Smuzhiyun struct list_head list;
27*4882a593Smuzhiyun struct timer_list timer;
28*4882a593Smuzhiyun unsigned int irq;
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun struct ghes_estatus_node {
33*4882a593Smuzhiyun struct llist_node llnode;
34*4882a593Smuzhiyun struct acpi_hest_generic *generic;
35*4882a593Smuzhiyun struct ghes *ghes;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun int task_work_cpu;
38*4882a593Smuzhiyun struct callback_head task_work;
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun struct ghes_estatus_cache {
42*4882a593Smuzhiyun u32 estatus_len;
43*4882a593Smuzhiyun atomic_t count;
44*4882a593Smuzhiyun struct acpi_hest_generic *generic;
45*4882a593Smuzhiyun unsigned long long time_in;
46*4882a593Smuzhiyun struct rcu_head rcu;
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun enum {
50*4882a593Smuzhiyun GHES_SEV_NO = 0x0,
51*4882a593Smuzhiyun GHES_SEV_CORRECTED = 0x1,
52*4882a593Smuzhiyun GHES_SEV_RECOVERABLE = 0x2,
53*4882a593Smuzhiyun GHES_SEV_PANIC = 0x3,
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #ifdef CONFIG_ACPI_APEI_GHES
57*4882a593Smuzhiyun /**
58*4882a593Smuzhiyun * ghes_register_vendor_record_notifier - register a notifier for vendor
59*4882a593Smuzhiyun * records that the kernel would otherwise ignore.
60*4882a593Smuzhiyun * @nb: pointer to the notifier_block structure of the event handler.
61*4882a593Smuzhiyun *
62*4882a593Smuzhiyun * return 0 : SUCCESS, non-zero : FAIL
63*4882a593Smuzhiyun */
64*4882a593Smuzhiyun int ghes_register_vendor_record_notifier(struct notifier_block *nb);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /**
67*4882a593Smuzhiyun * ghes_unregister_vendor_record_notifier - unregister the previously
68*4882a593Smuzhiyun * registered vendor record notifier.
69*4882a593Smuzhiyun * @nb: pointer to the notifier_block structure of the vendor record handler.
70*4882a593Smuzhiyun */
71*4882a593Smuzhiyun void ghes_unregister_vendor_record_notifier(struct notifier_block *nb);
72*4882a593Smuzhiyun #endif
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun int ghes_estatus_pool_init(unsigned int num_ghes);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* From drivers/edac/ghes_edac.c */
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun #ifdef CONFIG_EDAC_GHES
79*4882a593Smuzhiyun void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err);
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun int ghes_edac_register(struct ghes *ghes, struct device *dev);
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun void ghes_edac_unregister(struct ghes *ghes);
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun #else
ghes_edac_report_mem_error(int sev,struct cper_sec_mem_err * mem_err)86*4882a593Smuzhiyun static inline void ghes_edac_report_mem_error(int sev,
87*4882a593Smuzhiyun struct cper_sec_mem_err *mem_err)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
ghes_edac_register(struct ghes * ghes,struct device * dev)91*4882a593Smuzhiyun static inline int ghes_edac_register(struct ghes *ghes, struct device *dev)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun return -ENODEV;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
ghes_edac_unregister(struct ghes * ghes)96*4882a593Smuzhiyun static inline void ghes_edac_unregister(struct ghes *ghes)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun #endif
100*4882a593Smuzhiyun
acpi_hest_get_version(struct acpi_hest_generic_data * gdata)101*4882a593Smuzhiyun static inline int acpi_hest_get_version(struct acpi_hest_generic_data *gdata)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun return gdata->revision >> 8;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
acpi_hest_get_payload(struct acpi_hest_generic_data * gdata)106*4882a593Smuzhiyun static inline void *acpi_hest_get_payload(struct acpi_hest_generic_data *gdata)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun if (acpi_hest_get_version(gdata) >= 3)
109*4882a593Smuzhiyun return (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun return gdata + 1;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
acpi_hest_get_error_length(struct acpi_hest_generic_data * gdata)114*4882a593Smuzhiyun static inline int acpi_hest_get_error_length(struct acpi_hest_generic_data *gdata)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun return ((struct acpi_hest_generic_data *)(gdata))->error_data_length;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
acpi_hest_get_size(struct acpi_hest_generic_data * gdata)119*4882a593Smuzhiyun static inline int acpi_hest_get_size(struct acpi_hest_generic_data *gdata)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun if (acpi_hest_get_version(gdata) >= 3)
122*4882a593Smuzhiyun return sizeof(struct acpi_hest_generic_data_v300);
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return sizeof(struct acpi_hest_generic_data);
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
acpi_hest_get_record_size(struct acpi_hest_generic_data * gdata)127*4882a593Smuzhiyun static inline int acpi_hest_get_record_size(struct acpi_hest_generic_data *gdata)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun return (acpi_hest_get_size(gdata) + acpi_hest_get_error_length(gdata));
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
acpi_hest_get_next(struct acpi_hest_generic_data * gdata)132*4882a593Smuzhiyun static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun return (void *)(gdata) + acpi_hest_get_record_size(gdata);
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun #define apei_estatus_for_each_section(estatus, section) \
138*4882a593Smuzhiyun for (section = (struct acpi_hest_generic_data *)(estatus + 1); \
139*4882a593Smuzhiyun (void *)section - (void *)(estatus + 1) < estatus->data_length; \
140*4882a593Smuzhiyun section = acpi_hest_get_next(section))
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun #ifdef CONFIG_ACPI_APEI_SEA
143*4882a593Smuzhiyun int ghes_notify_sea(void);
144*4882a593Smuzhiyun #else
ghes_notify_sea(void)145*4882a593Smuzhiyun static inline int ghes_notify_sea(void) { return -ENOENT; }
146*4882a593Smuzhiyun #endif
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun #endif /* GHES_H */
149