PCI: Introduce pci_pcie_type(dev) to replace pci_dev->pcie_type
[deliverable/linux.git] / drivers / pci / pcie / aer / aerdrv_acpi.c
CommitLineData
6c2b374d
ZY
1/*
2 * Access ACPI _OSC method
3 *
4 * Copyright (C) 2006 Intel Corp.
5 * Tom Long Nguyen (tom.l.nguyen@intel.com)
6 * Zhang Yanmin (yanmin.zhang@intel.com)
7 *
8 */
9
10#include <linux/module.h>
11#include <linux/pci.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/pm.h>
15#include <linux/suspend.h>
16#include <linux/acpi.h>
17#include <linux/pci-acpi.h>
18#include <linux/delay.h>
affb72c3 19#include <acpi/apei.h>
6c2b374d
ZY
20#include "aerdrv.h"
21
affb72c3
HY
22#ifdef CONFIG_ACPI_APEI
23static inline int hest_match_pci(struct acpi_hest_aer_common *p,
24 struct pci_dev *pci)
25{
26 return (0 == pci_domain_nr(pci->bus) &&
27 p->bus == pci->bus->number &&
28 p->device == PCI_SLOT(pci->devfn) &&
29 p->function == PCI_FUNC(pci->devfn));
30}
31
32struct aer_hest_parse_info {
33 struct pci_dev *pci_dev;
34 int firmware_first;
35};
36
37static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
38{
39 struct aer_hest_parse_info *info = data;
40 struct acpi_hest_aer_common *p;
41 u8 pcie_type = 0;
42 u8 bridge = 0;
43 int ff = 0;
44
45 switch (hest_hdr->type) {
46 case ACPI_HEST_TYPE_AER_ROOT_PORT:
47 pcie_type = PCI_EXP_TYPE_ROOT_PORT;
48 break;
49 case ACPI_HEST_TYPE_AER_ENDPOINT:
50 pcie_type = PCI_EXP_TYPE_ENDPOINT;
51 break;
52 case ACPI_HEST_TYPE_AER_BRIDGE:
53 if ((info->pci_dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
54 bridge = 1;
55 break;
56 default:
57 return 0;
58 }
59
60 p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
61 if (p->flags & ACPI_HEST_GLOBAL) {
505cf30b 62 if ((pci_is_pcie(info->pci_dev) &&
62f87c0e 63 pci_pcie_type(info->pci_dev) == pcie_type) || bridge)
affb72c3
HY
64 ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
65 } else
66 if (hest_match_pci(p, info->pci_dev))
67 ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
68 info->firmware_first = ff;
69
70 return 0;
71}
72
73static void aer_set_firmware_first(struct pci_dev *pci_dev)
74{
75 int rc;
76 struct aer_hest_parse_info info = {
77 .pci_dev = pci_dev,
78 .firmware_first = 0,
79 };
80
81 rc = apei_hest_parse(aer_hest_parse, &info);
82
83 if (rc)
84 pci_dev->__aer_firmware_first = 0;
85 else
86 pci_dev->__aer_firmware_first = info.firmware_first;
87 pci_dev->__aer_firmware_first_valid = 1;
88}
89
90int pcie_aer_get_firmware_first(struct pci_dev *dev)
91{
92 if (!dev->__aer_firmware_first_valid)
93 aer_set_firmware_first(dev);
94 return dev->__aer_firmware_first;
95}
b22c3d82
RW
96
97static bool aer_firmware_first;
98
99static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data)
100{
101 struct acpi_hest_aer_common *p;
102
103 if (aer_firmware_first)
104 return 0;
105
106 switch (hest_hdr->type) {
107 case ACPI_HEST_TYPE_AER_ROOT_PORT:
108 case ACPI_HEST_TYPE_AER_ENDPOINT:
109 case ACPI_HEST_TYPE_AER_BRIDGE:
110 p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
111 aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
112 default:
113 return 0;
114 }
115}
116
117/**
118 * aer_acpi_firmware_first - Check if APEI should control AER.
119 */
120bool aer_acpi_firmware_first(void)
121{
122 static bool parsed = false;
123
124 if (!parsed) {
125 apei_hest_parse(aer_hest_parse_aff, NULL);
126 parsed = true;
127 }
128 return aer_firmware_first;
129}
affb72c3 130#endif
This page took 0.504283 seconds and 5 git commands to generate.