diff options
Diffstat (limited to 'drivers/pci/pcie/aer/aerdrv_acpi.c')
| -rw-r--r-- | drivers/pci/pcie/aer/aerdrv_acpi.c | 56 | 
1 files changed, 33 insertions, 23 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index cf611ab2193..01906576ab9 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -23,10 +23,10 @@  static inline int hest_match_pci(struct acpi_hest_aer_common *p,  				 struct pci_dev *pci)  { -	return	(0           == pci_domain_nr(pci->bus) && -		 p->bus      == pci->bus->number && -		 p->device   == PCI_SLOT(pci->devfn) && -		 p->function == PCI_FUNC(pci->devfn)); +	return   ACPI_HEST_SEGMENT(p->bus) == pci_domain_nr(pci->bus) && +		 ACPI_HEST_BUS(p->bus)     == pci->bus->number && +		 p->device                 == PCI_SLOT(pci->devfn) && +		 p->function               == PCI_FUNC(pci->devfn);  }  static inline bool hest_match_type(struct acpi_hest_header *hest_hdr, @@ -50,14 +50,37 @@ struct aer_hest_parse_info {  	int firmware_first;  }; +static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr) +{ +	if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT || +	    hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT || +	    hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE) +		return 1; +	return 0; +} +  static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)  {  	struct aer_hest_parse_info *info = data;  	struct acpi_hest_aer_common *p;  	int ff; +	if (!hest_source_is_pcie_aer(hest_hdr)) +		return 0; +  	p = (struct acpi_hest_aer_common *)(hest_hdr + 1);  	ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); + +	/* +	 * If no specific device is supplied, determine whether +	 * FIRMWARE_FIRST is set for *any* PCIe device. +	 */ +	if (!info->pci_dev) { +		info->firmware_first |= ff; +		return 0; +	} + +	/* Otherwise, check the specific device */  	if (p->flags & ACPI_HEST_GLOBAL) {  		if (hest_match_type(hest_hdr, info->pci_dev))  			info->firmware_first = ff; @@ -97,33 +120,20 @@ int pcie_aer_get_firmware_first(struct pci_dev *dev)  static bool aer_firmware_first; -static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data) -{ -	struct acpi_hest_aer_common *p; - -	if (aer_firmware_first) -		return 0; - -	switch (hest_hdr->type) { -	case ACPI_HEST_TYPE_AER_ROOT_PORT: -	case ACPI_HEST_TYPE_AER_ENDPOINT: -	case ACPI_HEST_TYPE_AER_BRIDGE: -		p = (struct acpi_hest_aer_common *)(hest_hdr + 1); -		aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); -	default: -		return 0; -	} -} -  /**   * aer_acpi_firmware_first - Check if APEI should control AER.   */  bool aer_acpi_firmware_first(void)  {  	static bool parsed = false; +	struct aer_hest_parse_info info = { +		.pci_dev	= NULL,	/* Check all PCIe devices */ +		.firmware_first	= 0, +	};  	if (!parsed) { -		apei_hest_parse(aer_hest_parse_aff, NULL); +		apei_hest_parse(aer_hest_parse, &info); +		aer_firmware_first = info.firmware_first;  		parsed = true;  	}  	return aer_firmware_first;  | 
