ghes.h 3.6 KB

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