1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
27edda088STyler Baicar #ifndef GHES_H
37edda088STyler Baicar #define GHES_H
47edda088STyler Baicar
540e06415SMauro Carvalho Chehab #include <acpi/apei.h>
640e06415SMauro Carvalho Chehab #include <acpi/hed.h>
740e06415SMauro Carvalho Chehab
840e06415SMauro Carvalho Chehab /*
940e06415SMauro Carvalho Chehab * One struct ghes is created for each generic hardware error source.
1040e06415SMauro Carvalho Chehab * It provides the context for APEI hardware error timer/IRQ/SCI/NMI
1140e06415SMauro Carvalho Chehab * handler.
1240e06415SMauro Carvalho Chehab *
1340e06415SMauro Carvalho Chehab * estatus: memory buffer for error status block, allocated during
1440e06415SMauro Carvalho Chehab * HEST parsing.
1540e06415SMauro Carvalho Chehab */
1640e06415SMauro Carvalho Chehab #define GHES_EXITING 0x0002
1740e06415SMauro Carvalho Chehab
1840e06415SMauro Carvalho Chehab struct ghes {
1942aa5604STyler Baicar union {
2040e06415SMauro Carvalho Chehab struct acpi_hest_generic *generic;
2142aa5604STyler Baicar struct acpi_hest_generic_v2 *generic_v2;
2242aa5604STyler Baicar };
230a00fd5eSLv Zheng struct acpi_hest_generic_status *estatus;
2440e06415SMauro Carvalho Chehab unsigned long flags;
2540e06415SMauro Carvalho Chehab union {
2640e06415SMauro Carvalho Chehab struct list_head list;
2740e06415SMauro Carvalho Chehab struct timer_list timer;
2840e06415SMauro Carvalho Chehab unsigned int irq;
2940e06415SMauro Carvalho Chehab };
309057a3f7SJia He struct device *dev;
319057a3f7SJia He struct list_head elist;
3240e06415SMauro Carvalho Chehab };
3340e06415SMauro Carvalho Chehab
3440e06415SMauro Carvalho Chehab struct ghes_estatus_node {
3540e06415SMauro Carvalho Chehab struct llist_node llnode;
3640e06415SMauro Carvalho Chehab struct acpi_hest_generic *generic;
3721480547SMauro Carvalho Chehab struct ghes *ghes;
387f17b4a1SJames Morse
397f17b4a1SJames Morse int task_work_cpu;
407f17b4a1SJames Morse struct callback_head task_work;
4140e06415SMauro Carvalho Chehab };
4240e06415SMauro Carvalho Chehab
4340e06415SMauro Carvalho Chehab struct ghes_estatus_cache {
4440e06415SMauro Carvalho Chehab u32 estatus_len;
4540e06415SMauro Carvalho Chehab atomic_t count;
4640e06415SMauro Carvalho Chehab struct acpi_hest_generic *generic;
4740e06415SMauro Carvalho Chehab unsigned long long time_in;
4840e06415SMauro Carvalho Chehab struct rcu_head rcu;
4940e06415SMauro Carvalho Chehab };
5040e06415SMauro Carvalho Chehab
5140e06415SMauro Carvalho Chehab enum {
5240e06415SMauro Carvalho Chehab GHES_SEV_NO = 0x0,
5340e06415SMauro Carvalho Chehab GHES_SEV_CORRECTED = 0x1,
5440e06415SMauro Carvalho Chehab GHES_SEV_RECOVERABLE = 0x2,
5540e06415SMauro Carvalho Chehab GHES_SEV_PANIC = 0x3,
5640e06415SMauro Carvalho Chehab };
5721480547SMauro Carvalho Chehab
589aa9cf3eSShiju Jose #ifdef CONFIG_ACPI_APEI_GHES
599aa9cf3eSShiju Jose /**
609aa9cf3eSShiju Jose * ghes_register_vendor_record_notifier - register a notifier for vendor
619aa9cf3eSShiju Jose * records that the kernel would otherwise ignore.
629aa9cf3eSShiju Jose * @nb: pointer to the notifier_block structure of the event handler.
639aa9cf3eSShiju Jose *
649aa9cf3eSShiju Jose * return 0 : SUCCESS, non-zero : FAIL
659aa9cf3eSShiju Jose */
669aa9cf3eSShiju Jose int ghes_register_vendor_record_notifier(struct notifier_block *nb);
679aa9cf3eSShiju Jose
689aa9cf3eSShiju Jose /**
699aa9cf3eSShiju Jose * ghes_unregister_vendor_record_notifier - unregister the previously
709aa9cf3eSShiju Jose * registered vendor record notifier.
719aa9cf3eSShiju Jose * @nb: pointer to the notifier_block structure of the vendor record handler.
729aa9cf3eSShiju Jose */
739aa9cf3eSShiju Jose void ghes_unregister_vendor_record_notifier(struct notifier_block *nb);
74802e7f1dSJia He
75802e7f1dSJia He struct list_head *ghes_get_devices(void);
76*b7765b0aSShiju Jose
77*b7765b0aSShiju Jose void ghes_estatus_pool_region_free(unsigned long addr, u32 size);
78802e7f1dSJia He #else
ghes_get_devices(void)79802e7f1dSJia He static inline struct list_head *ghes_get_devices(void) { return NULL; }
80*b7765b0aSShiju Jose
ghes_estatus_pool_region_free(unsigned long addr,u32 size)81*b7765b0aSShiju Jose static inline void ghes_estatus_pool_region_free(unsigned long addr, u32 size) { return; }
829aa9cf3eSShiju Jose #endif
839aa9cf3eSShiju Jose
8443d27483SAshish Kalra int ghes_estatus_pool_init(unsigned int num_ghes);
85e147133aSJames Morse
acpi_hest_get_version(struct acpi_hest_generic_data * gdata)86bbcc2e7bSTyler Baicar static inline int acpi_hest_get_version(struct acpi_hest_generic_data *gdata)
87bbcc2e7bSTyler Baicar {
88bbcc2e7bSTyler Baicar return gdata->revision >> 8;
89bbcc2e7bSTyler Baicar }
90bbcc2e7bSTyler Baicar
acpi_hest_get_payload(struct acpi_hest_generic_data * gdata)91bbcc2e7bSTyler Baicar static inline void *acpi_hest_get_payload(struct acpi_hest_generic_data *gdata)
92bbcc2e7bSTyler Baicar {
93bbcc2e7bSTyler Baicar if (acpi_hest_get_version(gdata) >= 3)
94bbcc2e7bSTyler Baicar return (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1);
95bbcc2e7bSTyler Baicar
96bbcc2e7bSTyler Baicar return gdata + 1;
97bbcc2e7bSTyler Baicar }
98bbcc2e7bSTyler Baicar
acpi_hest_get_error_length(struct acpi_hest_generic_data * gdata)99bbcc2e7bSTyler Baicar static inline int acpi_hest_get_error_length(struct acpi_hest_generic_data *gdata)
100bbcc2e7bSTyler Baicar {
101bbcc2e7bSTyler Baicar return ((struct acpi_hest_generic_data *)(gdata))->error_data_length;
102bbcc2e7bSTyler Baicar }
103bbcc2e7bSTyler Baicar
acpi_hest_get_size(struct acpi_hest_generic_data * gdata)104bbcc2e7bSTyler Baicar static inline int acpi_hest_get_size(struct acpi_hest_generic_data *gdata)
105bbcc2e7bSTyler Baicar {
106bbcc2e7bSTyler Baicar if (acpi_hest_get_version(gdata) >= 3)
107bbcc2e7bSTyler Baicar return sizeof(struct acpi_hest_generic_data_v300);
108bbcc2e7bSTyler Baicar
109bbcc2e7bSTyler Baicar return sizeof(struct acpi_hest_generic_data);
110bbcc2e7bSTyler Baicar }
111bbcc2e7bSTyler Baicar
acpi_hest_get_record_size(struct acpi_hest_generic_data * gdata)112bbcc2e7bSTyler Baicar static inline int acpi_hest_get_record_size(struct acpi_hest_generic_data *gdata)
113bbcc2e7bSTyler Baicar {
114bbcc2e7bSTyler Baicar return (acpi_hest_get_size(gdata) + acpi_hest_get_error_length(gdata));
115bbcc2e7bSTyler Baicar }
116bbcc2e7bSTyler Baicar
acpi_hest_get_next(struct acpi_hest_generic_data * gdata)117bbcc2e7bSTyler Baicar static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata)
118bbcc2e7bSTyler Baicar {
119bbcc2e7bSTyler Baicar return (void *)(gdata) + acpi_hest_get_record_size(gdata);
120bbcc2e7bSTyler Baicar }
1217edda088STyler Baicar
122c4335fddSgengdongjiu #define apei_estatus_for_each_section(estatus, section) \
123c4335fddSgengdongjiu for (section = (struct acpi_hest_generic_data *)(estatus + 1); \
124c4335fddSgengdongjiu (void *)section - (void *)(estatus + 1) < estatus->data_length; \
125c4335fddSgengdongjiu section = acpi_hest_get_next(section))
126c4335fddSgengdongjiu
1271035a078SDongjiu Geng #ifdef CONFIG_ACPI_APEI_SEA
128621f48e4STyler Baicar int ghes_notify_sea(void);
1291035a078SDongjiu Geng #else
ghes_notify_sea(void)1301035a078SDongjiu Geng static inline int ghes_notify_sea(void) { return -ENOENT; }
1311035a078SDongjiu Geng #endif
1327edda088STyler Baicar
1338e40612fSJia He struct notifier_block;
1348e40612fSJia He extern void ghes_register_report_chain(struct notifier_block *nb);
1358e40612fSJia He extern void ghes_unregister_report_chain(struct notifier_block *nb);
1367edda088STyler Baicar #endif /* GHES_H */
137