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