hest.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include <linux/acpi.h>
  2. #include <linux/pci.h>
  3. #define PREFIX "ACPI: "
  4. static inline unsigned long parse_acpi_hest_ia_machine_check(struct acpi_hest_ia_machine_check *p)
  5. {
  6. return sizeof(*p) +
  7. (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
  8. }
  9. static inline unsigned long parse_acpi_hest_ia_corrected(struct acpi_hest_ia_corrected *p)
  10. {
  11. return sizeof(*p) +
  12. (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks);
  13. }
  14. static inline unsigned long parse_acpi_hest_ia_nmi(struct acpi_hest_ia_nmi *p)
  15. {
  16. return sizeof(*p);
  17. }
  18. static inline unsigned long parse_acpi_hest_generic(struct acpi_hest_generic *p)
  19. {
  20. return sizeof(*p);
  21. }
  22. static inline unsigned int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci)
  23. {
  24. return (0 == pci_domain_nr(pci->bus) &&
  25. p->bus == pci->bus->number &&
  26. p->device == PCI_SLOT(pci->devfn) &&
  27. p->function == PCI_FUNC(pci->devfn));
  28. }
  29. static unsigned long parse_acpi_hest_aer(void *hdr, int type, struct pci_dev *pci, int *firmware_first)
  30. {
  31. struct acpi_hest_aer_common *p = hdr + sizeof(struct acpi_hest_header);
  32. unsigned long rc=0;
  33. u8 pcie_type = 0;
  34. u8 bridge = 0;
  35. switch (type) {
  36. case ACPI_HEST_TYPE_AER_ROOT_PORT:
  37. rc = sizeof(struct acpi_hest_aer_root);
  38. pcie_type = PCI_EXP_TYPE_ROOT_PORT;
  39. break;
  40. case ACPI_HEST_TYPE_AER_ENDPOINT:
  41. rc = sizeof(struct acpi_hest_aer);
  42. pcie_type = PCI_EXP_TYPE_ENDPOINT;
  43. break;
  44. case ACPI_HEST_TYPE_AER_BRIDGE:
  45. rc = sizeof(struct acpi_hest_aer_bridge);
  46. if ((pci->class >> 16) == PCI_BASE_CLASS_BRIDGE)
  47. bridge = 1;
  48. break;
  49. }
  50. if (p->flags & ACPI_HEST_GLOBAL) {
  51. if ((pci->is_pcie && (pci->pcie_type == pcie_type)) || bridge)
  52. *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
  53. }
  54. else
  55. if (hest_match_pci(p, pci))
  56. *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
  57. return rc;
  58. }
  59. static int acpi_hest_firmware_first(struct acpi_table_header *stdheader, struct pci_dev *pci)
  60. {
  61. struct acpi_table_hest *hest = (struct acpi_table_hest *)stdheader;
  62. void *p = (void *)hest + sizeof(*hest); /* defined by the ACPI 4.0 spec */
  63. struct acpi_hest_header *hdr = p;
  64. int i;
  65. int firmware_first = 0;
  66. static unsigned char printed_unused = 0;
  67. static unsigned char printed_reserved = 0;
  68. for (i=0, hdr=p; p < (((void *)hest) + hest->header.length) && i < hest->error_source_count; i++) {
  69. switch (hdr->type) {
  70. case ACPI_HEST_TYPE_IA32_CHECK:
  71. p += parse_acpi_hest_ia_machine_check(p);
  72. break;
  73. case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK:
  74. p += parse_acpi_hest_ia_corrected(p);
  75. break;
  76. case ACPI_HEST_TYPE_IA32_NMI:
  77. p += parse_acpi_hest_ia_nmi(p);
  78. break;
  79. /* These three should never appear */
  80. case ACPI_HEST_TYPE_NOT_USED3:
  81. case ACPI_HEST_TYPE_NOT_USED4:
  82. case ACPI_HEST_TYPE_NOT_USED5:
  83. if (!printed_unused) {
  84. printk(KERN_DEBUG PREFIX
  85. "HEST Error Source list contains an obsolete type (%d).\n", hdr->type);
  86. printed_unused = 1;
  87. }
  88. break;
  89. case ACPI_HEST_TYPE_AER_ROOT_PORT:
  90. case ACPI_HEST_TYPE_AER_ENDPOINT:
  91. case ACPI_HEST_TYPE_AER_BRIDGE:
  92. p += parse_acpi_hest_aer(p, hdr->type, pci, &firmware_first);
  93. break;
  94. case ACPI_HEST_TYPE_GENERIC_ERROR:
  95. p += parse_acpi_hest_generic(p);
  96. break;
  97. /* These should never appear either */
  98. case ACPI_HEST_TYPE_RESERVED:
  99. default:
  100. if (!printed_reserved) {
  101. printk(KERN_DEBUG PREFIX
  102. "HEST Error Source list contains a reserved type (%d).\n", hdr->type);
  103. printed_reserved = 1;
  104. }
  105. break;
  106. }
  107. }
  108. return firmware_first;
  109. }
  110. int acpi_hest_firmware_first_pci(struct pci_dev *pci)
  111. {
  112. acpi_status status = AE_NOT_FOUND;
  113. struct acpi_table_header *hest = NULL;
  114. status = acpi_get_table(ACPI_SIG_HEST, 1, &hest);
  115. if (ACPI_SUCCESS(status)) {
  116. if (acpi_hest_firmware_first(hest, pci)) {
  117. return 1;
  118. }
  119. }
  120. return 0;
  121. }
  122. EXPORT_SYMBOL_GPL(acpi_hest_firmware_first_pci);