Rev 1628 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1628 | Rev 1633 | ||
---|---|---|---|
1 | #include |
1 | #include |
2 | #include |
2 | #include |
3 | #include |
3 | #include |
4 | #include |
4 | #include |
5 | #include |
5 | #include |
6 | 6 | ||
7 | #include "acpi.h" |
7 | #include "acpi.h" |
8 | #include "acpi_bus.h" |
8 | #include "acpi_bus.h" |
9 | 9 | ||
10 | 10 | ||
11 | #define PREFIX "ACPI: " |
11 | #define PREFIX "ACPI: " |
12 | 12 | ||
13 | 13 | ||
14 | struct acpi_handle_node { |
14 | struct acpi_handle_node { |
15 | struct list_head node; |
15 | struct list_head node; |
16 | ACPI_HANDLE handle; |
16 | ACPI_HANDLE handle; |
17 | }; |
17 | }; |
18 | 18 | ||
19 | static const struct acpi_device_ids root_device_ids[] = { |
19 | static const struct acpi_device_ids root_device_ids[] = { |
20 | {"PNP0A03", 0}, |
20 | {"PNP0A03", 0}, |
21 | {"", 0}, |
21 | {"", 0}, |
22 | }; |
22 | }; |
23 | 23 | ||
24 | static LIST_HEAD(acpi_pci_roots); |
24 | LIST_HEAD(acpi_pci_roots); |
25 | 25 | ||
26 | 26 | ||
27 | /** |
27 | /** |
28 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge |
28 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge |
29 | * @handle - the ACPI CA node in question. |
29 | * @handle - the ACPI CA node in question. |
30 | * |
30 | * |
31 | * Note: we could make this API take a struct acpi_device * instead, but |
31 | * Note: we could make this API take a struct acpi_device * instead, but |
32 | * for now, it's more convenient to operate on an acpi_handle. |
32 | * for now, it's more convenient to operate on an acpi_handle. |
33 | */ |
33 | */ |
34 | int acpi_is_root_bridge(ACPI_HANDLE handle) |
34 | int acpi_is_root_bridge(ACPI_HANDLE handle) |
35 | { |
35 | { |
36 | int ret; |
36 | int ret; |
37 | struct acpi_device *device; |
37 | struct acpi_device *device; |
38 | 38 | ||
39 | ret = acpi_bus_get_device(handle, &device); |
39 | ret = acpi_bus_get_device(handle, &device); |
40 | if (ret) |
40 | if (ret) |
41 | return 0; |
41 | return 0; |
42 | 42 | ||
43 | ret = acpi_match_device_ids(device, root_device_ids); |
43 | ret = acpi_match_device_ids(device, root_device_ids); |
44 | if (ret) |
44 | if (ret) |
45 | return 0; |
45 | return 0; |
46 | else |
46 | else |
47 | return 1; |
47 | return 1; |
48 | } |
48 | } |
49 | 49 | ||
50 | 50 | ||
51 | struct acpi_pci_root *acpi_pci_find_root(ACPI_HANDLE handle) |
51 | struct acpi_pci_root *acpi_pci_find_root(ACPI_HANDLE handle) |
52 | { |
52 | { |
53 | struct acpi_pci_root *root; |
53 | struct acpi_pci_root *root; |
54 | 54 | ||
55 | list_for_each_entry(root, &acpi_pci_roots, node) { |
55 | list_for_each_entry(root, &acpi_pci_roots, node) { |
56 | if (root->device->handle == handle) |
56 | if (root->device->handle == handle) |
57 | return root; |
57 | return root; |
58 | } |
58 | } |
59 | return NULL; |
59 | return NULL; |
60 | } |
60 | } |
61 | 61 | ||
62 | 62 | ||
63 | /** |
63 | /** |
64 | * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev |
64 | * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev |
65 | * @handle: the handle in question |
65 | * @handle: the handle in question |
66 | * |
66 | * |
67 | * Given an ACPI CA handle, the desired PCI device is located in the |
67 | * Given an ACPI CA handle, the desired PCI device is located in the |
68 | * list of PCI devices. |
68 | * list of PCI devices. |
69 | * |
69 | * |
70 | * If the device is found, its reference count is increased and this |
70 | * If the device is found, its reference count is increased and this |
71 | * function returns a pointer to its data structure. The caller must |
71 | * function returns a pointer to its data structure. The caller must |
72 | * decrement the reference count by calling pci_dev_put(). |
72 | * decrement the reference count by calling pci_dev_put(). |
73 | * If no device is found, %NULL is returned. |
73 | * If no device is found, %NULL is returned. |
74 | */ |
74 | */ |
75 | struct pci_dev *acpi_get_pci_dev(ACPI_HANDLE handle) |
75 | struct pci_dev *acpi_get_pci_dev(ACPI_HANDLE handle) |
76 | { |
76 | { |
77 | int dev, fn; |
77 | int dev, fn; |
78 | unsigned long long adr; |
78 | unsigned long long adr; |
79 | ACPI_STATUS status; |
79 | ACPI_STATUS status; |
80 | ACPI_HANDLE phandle; |
80 | ACPI_HANDLE phandle; |
81 | struct pci_bus *pbus; |
81 | struct pci_bus *pbus; |
82 | struct pci_dev *pdev = NULL; |
82 | struct pci_dev *pdev = NULL; |
83 | struct acpi_handle_node *node, *tmp; |
83 | struct acpi_handle_node *node, *tmp; |
84 | struct acpi_pci_root *root; |
84 | struct acpi_pci_root *root; |
85 | LIST_HEAD(device_list); |
85 | LIST_HEAD(device_list); |
86 | 86 | ||
87 | /* |
87 | /* |
88 | * Walk up the ACPI CA namespace until we reach a PCI root bridge. |
88 | * Walk up the ACPI CA namespace until we reach a PCI root bridge. |
89 | */ |
89 | */ |
90 | phandle = handle; |
90 | phandle = handle; |
91 | while (!acpi_is_root_bridge(phandle)) { |
91 | while (!acpi_is_root_bridge(phandle)) { |
92 | node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL); |
92 | node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL); |
93 | if (!node) |
93 | if (!node) |
94 | goto out; |
94 | goto out; |
95 | 95 | ||
96 | INIT_LIST_HEAD(&node->node); |
96 | INIT_LIST_HEAD(&node->node); |
97 | node->handle = phandle; |
97 | node->handle = phandle; |
98 | list_add(&node->node, &device_list); |
98 | list_add(&node->node, &device_list); |
99 | 99 | ||
100 | status = AcpiGetParent(phandle, &phandle); |
100 | status = AcpiGetParent(phandle, &phandle); |
101 | if (ACPI_FAILURE(status)) |
101 | if (ACPI_FAILURE(status)) |
102 | goto out; |
102 | goto out; |
103 | } |
103 | } |
104 | 104 | ||
105 | root = acpi_pci_find_root(phandle); |
105 | root = acpi_pci_find_root(phandle); |
106 | if (!root) |
106 | if (!root) |
107 | goto out; |
107 | goto out; |
108 | 108 | ||
109 | pbus = root->bus; |
109 | pbus = root->bus; |
110 | 110 | ||
111 | /* |
111 | /* |
112 | * Now, walk back down the PCI device tree until we return to our |
112 | * Now, walk back down the PCI device tree until we return to our |
113 | * original handle. Assumes that everything between the PCI root |
113 | * original handle. Assumes that everything between the PCI root |
114 | * bridge and the device we're looking for must be a P2P bridge. |
114 | * bridge and the device we're looking for must be a P2P bridge. |
115 | */ |
115 | */ |
116 | list_for_each_entry(node, &device_list, node) { |
116 | list_for_each_entry(node, &device_list, node) { |
117 | ACPI_HANDLE hnd = node->handle; |
117 | ACPI_HANDLE hnd = node->handle; |
118 | status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr); |
118 | status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr); |
119 | if (ACPI_FAILURE(status)) |
119 | if (ACPI_FAILURE(status)) |
120 | goto out; |
120 | goto out; |
121 | dev = (adr >> 16) & 0xffff; |
121 | dev = (adr >> 16) & 0xffff; |
122 | fn = adr & 0xffff; |
122 | fn = adr & 0xffff; |
123 | 123 | ||
124 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); |
124 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); |
125 | if (!pdev || hnd == handle) |
125 | if (!pdev || hnd == handle) |
126 | break; |
126 | break; |
127 | 127 | ||
128 | pbus = pdev->subordinate; |
128 | pbus = pdev->subordinate; |
129 | // pci_dev_put(pdev); |
129 | // pci_dev_put(pdev); |
130 | 130 | ||
131 | /* |
131 | /* |
132 | * This function may be called for a non-PCI device that has a |
132 | * This function may be called for a non-PCI device that has a |
133 | * PCI parent (eg. a disk under a PCI SATA controller). In that |
133 | * PCI parent (eg. a disk under a PCI SATA controller). In that |
134 | * case pdev->subordinate will be NULL for the parent. |
134 | * case pdev->subordinate will be NULL for the parent. |
135 | */ |
135 | */ |
136 | if (!pbus) { |
136 | if (!pbus) { |
137 | dbgprintf("Not a PCI-to-PCI bridge\n"); |
137 | dbgprintf("Not a PCI-to-PCI bridge\n"); |
138 | pdev = NULL; |
138 | pdev = NULL; |
139 | break; |
139 | break; |
140 | } |
140 | } |
141 | } |
141 | } |
142 | out: |
142 | out: |
143 | list_for_each_entry_safe(node, tmp, &device_list, node) |
143 | list_for_each_entry_safe(node, tmp, &device_list, node) |
144 | kfree(node); |
144 | kfree(node); |
145 | 145 | ||
146 | return pdev; |
146 | return pdev; |
147 | } |
147 | } |
148 | 148 | ||
- | 149 | ||
- | 150 | static void print_bus_irqs(struct pci_bus *bus) |
|
- | 151 | { |
|
- | 152 | struct pci_dev *dev; |
|
- | 153 | ||
- | 154 | list_for_each_entry(dev, &bus->devices, bus_list) |
|
- | 155 | { |
|
- | 156 | dbgprintf("PCI_%x_%x bus:%d devfn: %x bios irq %d acpi irq %d\n", |
|
- | 157 | dev->vendor, dev->device, dev->busnr, dev->devfn, |
|
- | 158 | dev->irq, acpi_get_irq(dev)); |
|
- | 159 | }; |
|
- | 160 | } |
|
- | 161 | ||
- | 162 | void print_pci_irqs() |
|
- | 163 | { |
|
- | 164 | struct acpi_pci_root *root; |
|
- | 165 | ||
- | 166 | ENTER(); |
|
- | 167 | list_for_each_entry(root, &acpi_pci_roots, node) |
|
- | 168 | { |
|
- | 169 | struct pci_bus *pbus, *tbus; |
|
- | 170 | struct pci_dev *dev; |
|
- | 171 | ||
- | 172 | pbus = root->bus; |
|
- | 173 | ||
- | 174 | list_for_each_entry(dev, &pbus->devices, bus_list) |
|
- | 175 | { |
|
- | 176 | dbgprintf("PCI_%x_%x bus:%d devfn: %x bios irq %d acpi irq %d\n", |
|
- | 177 | dev->vendor, dev->device, dev->busnr, dev->devfn, |
|
- | 178 | dev->irq, acpi_get_irq(dev)); |
|
- | 179 | }; |
|
- | 180 | ||
- | 181 | list_for_each_entry(tbus, &pbus->children, node) |
|
- | 182 | { |
|
- | 183 | print_bus_irqs(tbus); |
|
- | 184 | }; |
|
- | 185 | } |
|
- | 186 | LEAVE(); |
|
- | 187 | }; |
|
- | 188 | ||
- | 189 |