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