Commit | Line | Data |
---|---|---|
c942fddf | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 LT |
2 | /* |
3 | * pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 40 $) | |
4 | * | |
5 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | |
6 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | |
1da177e4 LT |
7 | */ |
8 | ||
ccde83e3 HG |
9 | #define pr_fmt(fmt) "ACPI: " fmt |
10 | ||
1da177e4 LT |
11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> | |
13 | #include <linux/init.h> | |
14 | #include <linux/types.h> | |
d0020f65 | 15 | #include <linux/mutex.h> |
1da177e4 | 16 | #include <linux/pm.h> |
b67ea761 | 17 | #include <linux/pm_runtime.h> |
1da177e4 | 18 | #include <linux/pci.h> |
990a7ac5 | 19 | #include <linux/pci-acpi.h> |
864b94ad | 20 | #include <linux/dmar.h> |
1da177e4 | 21 | #include <linux/acpi.h> |
5a0e3ad6 | 22 | #include <linux/slab.h> |
7bc5a2ba | 23 | #include <linux/dmi.h> |
630b3aff | 24 | #include <linux/platform_data/x86/apple.h> |
ace8238b RW |
25 | #include "internal.h" |
26 | ||
1da177e4 | 27 | #define ACPI_PCI_ROOT_CLASS "pci_bridge" |
1da177e4 | 28 | #define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge" |
00c43b96 RW |
29 | static int acpi_pci_root_add(struct acpi_device *device, |
30 | const struct acpi_device_id *not_used); | |
31 | static void acpi_pci_root_remove(struct acpi_device *device); | |
1da177e4 | 32 | |
3338db00 RW |
33 | static int acpi_pci_root_scan_dependent(struct acpi_device *adev) |
34 | { | |
1f7c164b | 35 | acpiphp_check_host_bridge(adev); |
3338db00 RW |
36 | return 0; |
37 | } | |
38 | ||
7dab9ef4 BH |
39 | #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \ |
40 | | OSC_PCI_ASPM_SUPPORT \ | |
41 | | OSC_PCI_CLOCK_PM_SUPPORT \ | |
42 | | OSC_PCI_MSI_SUPPORT) | |
415e12b2 | 43 | |
c97adf9e | 44 | static const struct acpi_device_id root_device_ids[] = { |
1ba90e3a TR |
45 | {"PNP0A03", 0}, |
46 | {"", 0}, | |
47 | }; | |
1ba90e3a | 48 | |
00c43b96 | 49 | static struct acpi_scan_handler pci_root_handler = { |
1ba90e3a | 50 | .ids = root_device_ids, |
00c43b96 RW |
51 | .attach = acpi_pci_root_add, |
52 | .detach = acpi_pci_root_remove, | |
ca499fc8 | 53 | .hotplug = { |
3338db00 RW |
54 | .enabled = true, |
55 | .scan_dependent = acpi_pci_root_scan_dependent, | |
ca499fc8 | 56 | }, |
1da177e4 LT |
57 | }; |
58 | ||
27558203 AC |
59 | /** |
60 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge | |
8e8883ce | 61 | * @handle: the ACPI CA node in question. |
27558203 AC |
62 | * |
63 | * Note: we could make this API take a struct acpi_device * instead, but | |
64 | * for now, it's more convenient to operate on an acpi_handle. | |
65 | */ | |
66 | int acpi_is_root_bridge(acpi_handle handle) | |
67 | { | |
99ece713 | 68 | struct acpi_device *device = acpi_fetch_acpi_dev(handle); |
27558203 | 69 | int ret; |
27558203 | 70 | |
99ece713 | 71 | if (!device) |
27558203 AC |
72 | return 0; |
73 | ||
74 | ret = acpi_match_device_ids(device, root_device_ids); | |
75 | if (ret) | |
76 | return 0; | |
77 | else | |
78 | return 1; | |
79 | } | |
80 | EXPORT_SYMBOL_GPL(acpi_is_root_bridge); | |
81 | ||
1da177e4 | 82 | static acpi_status |
4be44fcd | 83 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) |
1da177e4 | 84 | { |
6ad95513 | 85 | struct resource *res = data; |
1da177e4 | 86 | struct acpi_resource_address64 address; |
f6c1c8ff | 87 | acpi_status status; |
1da177e4 | 88 | |
f6c1c8ff BH |
89 | status = acpi_resource_to_address64(resource, &address); |
90 | if (ACPI_FAILURE(status)) | |
1da177e4 LT |
91 | return AE_OK; |
92 | ||
a45de93e | 93 | if ((address.address.address_length > 0) && |
6ad95513 | 94 | (address.resource_type == ACPI_BUS_NUMBER_RANGE)) { |
a45de93e LZ |
95 | res->start = address.address.minimum; |
96 | res->end = address.address.minimum + address.address.address_length - 1; | |
6ad95513 | 97 | } |
1da177e4 LT |
98 | |
99 | return AE_OK; | |
100 | } | |
101 | ||
f5eebbe1 | 102 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, |
6ad95513 | 103 | struct resource *res) |
1da177e4 LT |
104 | { |
105 | acpi_status status; | |
106 | ||
6ad95513 | 107 | res->start = -1; |
4be44fcd LB |
108 | status = |
109 | acpi_walk_resources(handle, METHOD_NAME__CRS, | |
6ad95513 | 110 | get_root_bridge_busnr_callback, res); |
1da177e4 LT |
111 | if (ACPI_FAILURE(status)) |
112 | return status; | |
6ad95513 | 113 | if (res->start == -1) |
1da177e4 LT |
114 | return AE_ERROR; |
115 | return AE_OK; | |
116 | } | |
117 | ||
955f14b4 BH |
118 | struct pci_osc_bit_struct { |
119 | u32 bit; | |
120 | char *desc; | |
121 | }; | |
122 | ||
123 | static struct pci_osc_bit_struct pci_osc_support_bit[] = { | |
124 | { OSC_PCI_EXT_CONFIG_SUPPORT, "ExtendedConfig" }, | |
125 | { OSC_PCI_ASPM_SUPPORT, "ASPM" }, | |
126 | { OSC_PCI_CLOCK_PM_SUPPORT, "ClockPM" }, | |
127 | { OSC_PCI_SEGMENT_GROUPS_SUPPORT, "Segments" }, | |
128 | { OSC_PCI_MSI_SUPPORT, "MSI" }, | |
ac1c8e35 | 129 | { OSC_PCI_EDR_SUPPORT, "EDR" }, |
ba11edc6 | 130 | { OSC_PCI_HPX_TYPE_3_SUPPORT, "HPX-Type3" }, |
955f14b4 BH |
131 | }; |
132 | ||
133 | static struct pci_osc_bit_struct pci_osc_control_bit[] = { | |
134 | { OSC_PCI_EXPRESS_NATIVE_HP_CONTROL, "PCIeHotplug" }, | |
135 | { OSC_PCI_SHPC_NATIVE_HP_CONTROL, "SHPCHotplug" }, | |
136 | { OSC_PCI_EXPRESS_PME_CONTROL, "PME" }, | |
137 | { OSC_PCI_EXPRESS_AER_CONTROL, "AER" }, | |
138 | { OSC_PCI_EXPRESS_CAPABILITY_CONTROL, "PCIeCapability" }, | |
af8bb9f8 | 139 | { OSC_PCI_EXPRESS_LTR_CONTROL, "LTR" }, |
ac1c8e35 | 140 | { OSC_PCI_EXPRESS_DPC_CONTROL, "DPC" }, |
955f14b4 BH |
141 | }; |
142 | ||
56368029 VV |
143 | static struct pci_osc_bit_struct cxl_osc_support_bit[] = { |
144 | { OSC_CXL_1_1_PORT_REG_ACCESS_SUPPORT, "CXL11PortRegAccess" }, | |
145 | { OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT, "CXL20PortDevRegAccess" }, | |
146 | { OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT, "CXLProtocolErrorReporting" }, | |
147 | { OSC_CXL_NATIVE_HP_SUPPORT, "CXLNativeHotPlug" }, | |
148 | }; | |
149 | ||
150 | static struct pci_osc_bit_struct cxl_osc_control_bit[] = { | |
151 | { OSC_CXL_ERROR_REPORTING_CONTROL, "CXLMemErrorReporting" }, | |
152 | }; | |
153 | ||
955f14b4 BH |
154 | static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word, |
155 | struct pci_osc_bit_struct *table, int size) | |
156 | { | |
157 | char buf[80]; | |
158 | int i, len = 0; | |
159 | struct pci_osc_bit_struct *entry; | |
160 | ||
161 | buf[0] = '\0'; | |
162 | for (i = 0, entry = table; i < size; i++, entry++) | |
163 | if (word & entry->bit) | |
edd66086 | 164 | len += scnprintf(buf + len, sizeof(buf) - len, "%s%s", |
955f14b4 BH |
165 | len ? " " : "", entry->desc); |
166 | ||
167 | dev_info(&root->device->dev, "_OSC: %s [%s]\n", msg, buf); | |
168 | } | |
169 | ||
170 | static void decode_osc_support(struct acpi_pci_root *root, char *msg, u32 word) | |
171 | { | |
172 | decode_osc_bits(root, msg, word, pci_osc_support_bit, | |
173 | ARRAY_SIZE(pci_osc_support_bit)); | |
174 | } | |
175 | ||
176 | static void decode_osc_control(struct acpi_pci_root *root, char *msg, u32 word) | |
177 | { | |
178 | decode_osc_bits(root, msg, word, pci_osc_control_bit, | |
179 | ARRAY_SIZE(pci_osc_control_bit)); | |
180 | } | |
181 | ||
56368029 VV |
182 | static void decode_cxl_osc_support(struct acpi_pci_root *root, char *msg, u32 word) |
183 | { | |
184 | decode_osc_bits(root, msg, word, cxl_osc_support_bit, | |
185 | ARRAY_SIZE(cxl_osc_support_bit)); | |
186 | } | |
187 | ||
188 | static void decode_cxl_osc_control(struct acpi_pci_root *root, char *msg, u32 word) | |
189 | { | |
190 | decode_osc_bits(root, msg, word, cxl_osc_control_bit, | |
191 | ARRAY_SIZE(cxl_osc_control_bit)); | |
192 | } | |
193 | ||
241d26bc DW |
194 | static inline bool is_pcie(struct acpi_pci_root *root) |
195 | { | |
196 | return root->bridge_type == ACPI_BRIDGE_TYPE_PCIE; | |
197 | } | |
198 | ||
199 | static inline bool is_cxl(struct acpi_pci_root *root) | |
200 | { | |
201 | return root->bridge_type == ACPI_BRIDGE_TYPE_CXL; | |
202 | } | |
203 | ||
3a9622dc | 204 | static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; |
241d26bc | 205 | static u8 cxl_osc_uuid_str[] = "68F2D50B-C469-4d8A-BD3D-941A103FD3FC"; |
63f10f0f | 206 | |
241d26bc DW |
207 | static char *to_uuid(struct acpi_pci_root *root) |
208 | { | |
209 | if (is_cxl(root)) | |
210 | return cxl_osc_uuid_str; | |
211 | return pci_osc_uuid_str; | |
212 | } | |
213 | ||
214 | static int cap_length(struct acpi_pci_root *root) | |
215 | { | |
216 | if (is_cxl(root)) | |
217 | return sizeof(u32) * OSC_CXL_CAPABILITY_DWORDS; | |
218 | return sizeof(u32) * OSC_PCI_CAPABILITY_DWORDS; | |
219 | } | |
63f10f0f | 220 | |
241d26bc | 221 | static acpi_status acpi_pci_run_osc(struct acpi_pci_root *root, |
56368029 VV |
222 | const u32 *capbuf, u32 *pci_control, |
223 | u32 *cxl_control) | |
63f10f0f | 224 | { |
3a9622dc | 225 | struct acpi_osc_context context = { |
241d26bc | 226 | .uuid_str = to_uuid(root), |
3a9622dc | 227 | .rev = 1, |
241d26bc | 228 | .cap.length = cap_length(root), |
3a9622dc SL |
229 | .cap.pointer = (void *)capbuf, |
230 | }; | |
63f10f0f | 231 | acpi_status status; |
63f10f0f | 232 | |
241d26bc | 233 | status = acpi_run_osc(root->device->handle, &context); |
3a9622dc | 234 | if (ACPI_SUCCESS(status)) { |
56368029 VV |
235 | *pci_control = acpi_osc_ctx_get_pci_control(&context); |
236 | if (is_cxl(root)) | |
237 | *cxl_control = acpi_osc_ctx_get_cxl_control(&context); | |
3a9622dc | 238 | kfree(context.ret.pointer); |
63f10f0f | 239 | } |
63f10f0f KK |
240 | return status; |
241 | } | |
242 | ||
56368029 VV |
243 | static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 support, |
244 | u32 *control, u32 cxl_support, | |
245 | u32 *cxl_control) | |
63f10f0f KK |
246 | { |
247 | acpi_status status; | |
56368029 | 248 | u32 pci_result, cxl_result, capbuf[OSC_CXL_CAPABILITY_DWORDS]; |
ab8e8957 | 249 | |
ab8e8957 | 250 | support |= root->osc_support_set; |
63f10f0f | 251 | |
b938a229 BH |
252 | capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE; |
253 | capbuf[OSC_SUPPORT_DWORD] = support; | |
6bc779ee | 254 | capbuf[OSC_CONTROL_DWORD] = *control | root->osc_control_set; |
63f10f0f | 255 | |
56368029 VV |
256 | if (is_cxl(root)) { |
257 | cxl_support |= root->osc_ext_support_set; | |
258 | capbuf[OSC_EXT_SUPPORT_DWORD] = cxl_support; | |
259 | capbuf[OSC_EXT_CONTROL_DWORD] = *cxl_control | root->osc_ext_control_set; | |
260 | } | |
261 | ||
241d26bc | 262 | retry: |
56368029 | 263 | status = acpi_pci_run_osc(root, capbuf, &pci_result, &cxl_result); |
63f10f0f | 264 | if (ACPI_SUCCESS(status)) { |
ab8e8957 | 265 | root->osc_support_set = support; |
56368029 VV |
266 | *control = pci_result; |
267 | if (is_cxl(root)) { | |
268 | root->osc_ext_support_set = cxl_support; | |
269 | *cxl_control = cxl_result; | |
270 | } | |
241d26bc DW |
271 | } else if (is_cxl(root)) { |
272 | /* | |
273 | * CXL _OSC is optional on CXL 1.1 hosts. Fall back to PCIe _OSC | |
274 | * upon any failure using CXL _OSC. | |
275 | */ | |
276 | root->bridge_type = ACPI_BRIDGE_TYPE_PCIE; | |
277 | goto retry; | |
63f10f0f KK |
278 | } |
279 | return status; | |
280 | } | |
281 | ||
76d56de5 | 282 | struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) |
63f10f0f | 283 | { |
99ece713 | 284 | struct acpi_device *device = acpi_fetch_acpi_dev(handle); |
63f10f0f | 285 | struct acpi_pci_root *root; |
c1aec834 | 286 | |
99ece713 | 287 | if (!device || acpi_match_device_ids(device, root_device_ids)) |
cd4faf9c TI |
288 | return NULL; |
289 | ||
290 | root = acpi_driver_data(device); | |
291 | ||
292 | return root; | |
63f10f0f | 293 | } |
76d56de5 | 294 | EXPORT_SYMBOL_GPL(acpi_pci_find_root); |
63f10f0f | 295 | |
2f7bbceb AC |
296 | /** |
297 | * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev | |
298 | * @handle: the handle in question | |
299 | * | |
300 | * Given an ACPI CA handle, the desired PCI device is located in the | |
301 | * list of PCI devices. | |
302 | * | |
303 | * If the device is found, its reference count is increased and this | |
304 | * function returns a pointer to its data structure. The caller must | |
305 | * decrement the reference count by calling pci_dev_put(). | |
306 | * If no device is found, %NULL is returned. | |
307 | */ | |
308 | struct pci_dev *acpi_get_pci_dev(acpi_handle handle) | |
309 | { | |
63f534b8 RW |
310 | struct acpi_device *adev = acpi_fetch_acpi_dev(handle); |
311 | struct acpi_device_physical_node *pn; | |
312 | struct pci_dev *pci_dev = NULL; | |
2f7bbceb | 313 | |
63f534b8 RW |
314 | if (!adev) |
315 | return NULL; | |
2f7bbceb | 316 | |
63f534b8 | 317 | mutex_lock(&adev->physical_node_lock); |
497fb54f | 318 | |
63f534b8 RW |
319 | list_for_each_entry(pn, &adev->physical_node_list, node) { |
320 | if (dev_is_pci(pn->dev)) { | |
eb1d3926 | 321 | get_device(pn->dev); |
63f534b8 | 322 | pci_dev = to_pci_dev(pn->dev); |
497fb54f RW |
323 | break; |
324 | } | |
2f7bbceb | 325 | } |
2f7bbceb | 326 | |
63f534b8 RW |
327 | mutex_unlock(&adev->physical_node_lock); |
328 | ||
329 | return pci_dev; | |
2f7bbceb AC |
330 | } |
331 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); | |
332 | ||
63f10f0f | 333 | /** |
75fb60f2 RW |
334 | * acpi_pci_osc_control_set - Request control of PCI root _OSC features. |
335 | * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). | |
336 | * @mask: Mask of _OSC bits to request control of, place to store control mask. | |
843438de | 337 | * @support: _OSC supported capability. |
56368029 VV |
338 | * @cxl_mask: Mask of CXL _OSC control bits, place to store control mask. |
339 | * @cxl_support: CXL _OSC supported capability. | |
63f10f0f | 340 | * |
75fb60f2 RW |
341 | * Run _OSC query for @mask and if that is successful, compare the returned |
342 | * mask of control bits with @req. If all of the @req bits are set in the | |
343 | * returned mask, run _OSC request for it. | |
344 | * | |
345 | * The variable at the @mask address may be modified regardless of whether or | |
346 | * not the function returns success. On success it will contain the mask of | |
347 | * _OSC bits the BIOS has granted control of, but its contents are meaningless | |
348 | * on failure. | |
63f10f0f | 349 | **/ |
56368029 VV |
350 | static acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, |
351 | u32 support, u32 *cxl_mask, | |
352 | u32 cxl_support) | |
63f10f0f | 353 | { |
6bc779ee | 354 | u32 req = OSC_PCI_EXPRESS_CAPABILITY_CONTROL; |
75fb60f2 | 355 | struct acpi_pci_root *root; |
866e61fc | 356 | acpi_status status; |
56368029 | 357 | u32 ctrl, cxl_ctrl = 0, capbuf[OSC_CXL_CAPABILITY_DWORDS]; |
63f10f0f | 358 | |
75fb60f2 RW |
359 | if (!mask) |
360 | return AE_BAD_PARAMETER; | |
361 | ||
63f10f0f KK |
362 | root = acpi_pci_find_root(handle); |
363 | if (!root) | |
364 | return AE_NOT_EXIST; | |
365 | ||
6bc779ee JR |
366 | ctrl = *mask; |
367 | *mask |= root->osc_control_set; | |
63f10f0f | 368 | |
56368029 VV |
369 | if (is_cxl(root)) { |
370 | cxl_ctrl = *cxl_mask; | |
371 | *cxl_mask |= root->osc_ext_control_set; | |
372 | } | |
373 | ||
75fb60f2 | 374 | /* Need to check the available controls bits before requesting them. */ |
6bc779ee | 375 | do { |
56368029 VV |
376 | u32 pci_missing = 0, cxl_missing = 0; |
377 | ||
378 | status = acpi_pci_query_osc(root, support, mask, cxl_support, | |
379 | cxl_mask); | |
75fb60f2 | 380 | if (ACPI_FAILURE(status)) |
866e61fc | 381 | return status; |
56368029 VV |
382 | if (is_cxl(root)) { |
383 | if (ctrl == *mask && cxl_ctrl == *cxl_mask) | |
384 | break; | |
385 | pci_missing = ctrl & ~(*mask); | |
386 | cxl_missing = cxl_ctrl & ~(*cxl_mask); | |
387 | } else { | |
388 | if (ctrl == *mask) | |
389 | break; | |
390 | pci_missing = ctrl & ~(*mask); | |
391 | } | |
392 | if (pci_missing) | |
393 | decode_osc_control(root, "platform does not support", | |
394 | pci_missing); | |
395 | if (cxl_missing) | |
396 | decode_cxl_osc_control(root, "CXL platform does not support", | |
397 | cxl_missing); | |
75fb60f2 | 398 | ctrl = *mask; |
56368029 VV |
399 | cxl_ctrl = *cxl_mask; |
400 | } while (*mask || *cxl_mask); | |
6bc779ee JR |
401 | |
402 | /* No need to request _OSC if the control was already granted. */ | |
56368029 VV |
403 | if ((root->osc_control_set & ctrl) == ctrl && |
404 | (root->osc_ext_control_set & cxl_ctrl) == cxl_ctrl) | |
6bc779ee | 405 | return AE_OK; |
2b8fd918 | 406 | |
75fb60f2 | 407 | if ((ctrl & req) != req) { |
955f14b4 BH |
408 | decode_osc_control(root, "not requesting control; platform does not support", |
409 | req & ~(ctrl)); | |
866e61fc | 410 | return AE_SUPPORT; |
63f10f0f KK |
411 | } |
412 | ||
b938a229 BH |
413 | capbuf[OSC_QUERY_DWORD] = 0; |
414 | capbuf[OSC_SUPPORT_DWORD] = root->osc_support_set; | |
415 | capbuf[OSC_CONTROL_DWORD] = ctrl; | |
56368029 VV |
416 | if (is_cxl(root)) { |
417 | capbuf[OSC_EXT_SUPPORT_DWORD] = root->osc_ext_support_set; | |
418 | capbuf[OSC_EXT_CONTROL_DWORD] = cxl_ctrl; | |
419 | } | |
420 | ||
421 | status = acpi_pci_run_osc(root, capbuf, mask, cxl_mask); | |
866e61fc BH |
422 | if (ACPI_FAILURE(status)) |
423 | return status; | |
424 | ||
425 | root->osc_control_set = *mask; | |
56368029 | 426 | root->osc_ext_control_set = *cxl_mask; |
866e61fc | 427 | return AE_OK; |
63f10f0f | 428 | } |
63f10f0f | 429 | |
4c6f6060 JR |
430 | static u32 calculate_support(void) |
431 | { | |
432 | u32 support; | |
433 | ||
434 | /* | |
435 | * All supported architectures that use ACPI have support for | |
436 | * PCI domains, so we indicate this in _OSC support capabilities. | |
437 | */ | |
438 | support = OSC_PCI_SEGMENT_GROUPS_SUPPORT; | |
439 | support |= OSC_PCI_HPX_TYPE_3_SUPPORT; | |
440 | if (pci_ext_cfg_avail()) | |
441 | support |= OSC_PCI_EXT_CONFIG_SUPPORT; | |
442 | if (pcie_aspm_support_enabled()) | |
443 | support |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT; | |
444 | if (pci_msi_enabled()) | |
445 | support |= OSC_PCI_MSI_SUPPORT; | |
446 | if (IS_ENABLED(CONFIG_PCIE_EDR)) | |
447 | support |= OSC_PCI_EDR_SUPPORT; | |
448 | ||
449 | return support; | |
450 | } | |
451 | ||
56368029 VV |
452 | /* |
453 | * Background on hotplug support, and making it depend on only | |
454 | * CONFIG_HOTPLUG_PCI_PCIE vs. also considering CONFIG_MEMORY_HOTPLUG: | |
455 | * | |
456 | * CONFIG_ACPI_HOTPLUG_MEMORY does depend on CONFIG_MEMORY_HOTPLUG, but | |
457 | * there is no existing _OSC for memory hotplug support. The reason is that | |
458 | * ACPI memory hotplug requires the OS to acknowledge / coordinate with | |
459 | * memory plug events via a scan handler. On the CXL side the equivalent | |
460 | * would be if Linux supported the Mechanical Retention Lock [1], or | |
461 | * otherwise had some coordination for the driver of a PCI device | |
462 | * undergoing hotplug to be consulted on whether the hotplug should | |
463 | * proceed or not. | |
464 | * | |
465 | * The concern is that if Linux says no to supporting CXL hotplug then | |
466 | * the BIOS may say no to giving the OS hotplug control of any other PCIe | |
467 | * device. So the question here is not whether hotplug is enabled, it's | |
468 | * whether it is handled natively by the at all OS, and if | |
469 | * CONFIG_HOTPLUG_PCI_PCIE is enabled then the answer is "yes". | |
470 | * | |
471 | * Otherwise, the plan for CXL coordinated remove, since the kernel does | |
472 | * not support blocking hotplug, is to require the memory device to be | |
473 | * disabled before hotplug is attempted. When CONFIG_MEMORY_HOTPLUG is | |
474 | * disabled that step will fail and the remove attempt cancelled by the | |
475 | * user. If that is not honored and the card is removed anyway then it | |
476 | * does not matter if CONFIG_MEMORY_HOTPLUG is enabled or not, it will | |
477 | * cause a crash and other badness. | |
478 | * | |
479 | * Therefore, just say yes to CXL hotplug and require removal to | |
480 | * be coordinated by userspace unless and until the kernel grows better | |
481 | * mechanisms for doing "managed" removal of devices in consultation with | |
482 | * the driver. | |
483 | * | |
484 | * [1]: https://lore.kernel.org/all/20201122014203.4706-1-ashok.raj@intel.com/ | |
485 | */ | |
486 | static u32 calculate_cxl_support(void) | |
487 | { | |
488 | u32 support; | |
489 | ||
490 | support = OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT; | |
da8380bb | 491 | support |= OSC_CXL_1_1_PORT_REG_ACCESS_SUPPORT; |
56368029 VV |
492 | if (pci_aer_available()) |
493 | support |= OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT; | |
494 | if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) | |
495 | support |= OSC_CXL_NATIVE_HP_SUPPORT; | |
496 | ||
497 | return support; | |
498 | } | |
499 | ||
4c6f6060 JR |
500 | static u32 calculate_control(void) |
501 | { | |
502 | u32 control; | |
503 | ||
504 | control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL | |
505 | | OSC_PCI_EXPRESS_PME_CONTROL; | |
506 | ||
507 | if (IS_ENABLED(CONFIG_PCIEASPM)) | |
508 | control |= OSC_PCI_EXPRESS_LTR_CONTROL; | |
509 | ||
510 | if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) | |
511 | control |= OSC_PCI_EXPRESS_NATIVE_HP_CONTROL; | |
512 | ||
513 | if (IS_ENABLED(CONFIG_HOTPLUG_PCI_SHPC)) | |
514 | control |= OSC_PCI_SHPC_NATIVE_HP_CONTROL; | |
515 | ||
516 | if (pci_aer_available()) | |
517 | control |= OSC_PCI_EXPRESS_AER_CONTROL; | |
518 | ||
519 | /* | |
520 | * Per the Downstream Port Containment Related Enhancements ECN to | |
521 | * the PCI Firmware Spec, r3.2, sec 4.5.1, table 4-5, | |
522 | * OSC_PCI_EXPRESS_DPC_CONTROL indicates the OS supports both DPC | |
523 | * and EDR. | |
524 | */ | |
525 | if (IS_ENABLED(CONFIG_PCIE_DPC) && IS_ENABLED(CONFIG_PCIE_EDR)) | |
526 | control |= OSC_PCI_EXPRESS_DPC_CONTROL; | |
527 | ||
528 | return control; | |
529 | } | |
530 | ||
56368029 VV |
531 | static u32 calculate_cxl_control(void) |
532 | { | |
533 | u32 control = 0; | |
534 | ||
535 | if (IS_ENABLED(CONFIG_MEMORY_FAILURE)) | |
536 | control |= OSC_CXL_ERROR_REPORTING_CONTROL; | |
537 | ||
538 | return control; | |
539 | } | |
540 | ||
87f1f87a JR |
541 | static bool os_control_query_checks(struct acpi_pci_root *root, u32 support) |
542 | { | |
543 | struct acpi_device *device = root->device; | |
544 | ||
545 | if (pcie_ports_disabled) { | |
546 | dev_info(&device->dev, "PCIe port services disabled; not requesting _OSC control\n"); | |
547 | return false; | |
548 | } | |
549 | ||
550 | if ((support & ACPI_PCIE_REQ_SUPPORT) != ACPI_PCIE_REQ_SUPPORT) { | |
551 | decode_osc_support(root, "not requesting OS control; OS requires", | |
552 | ACPI_PCIE_REQ_SUPPORT); | |
553 | return false; | |
554 | } | |
555 | ||
556 | return true; | |
557 | } | |
558 | ||
241d26bc | 559 | static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm) |
1da177e4 | 560 | { |
6bc779ee | 561 | u32 support, control = 0, requested = 0; |
56368029 | 562 | u32 cxl_support = 0, cxl_control = 0, cxl_requested = 0; |
3e43abb0 BH |
563 | acpi_status status; |
564 | struct acpi_device *device = root->device; | |
bfe2414a | 565 | acpi_handle handle = device->handle; |
1da177e4 | 566 | |
7bc5a2ba MG |
567 | /* |
568 | * Apple always return failure on _OSC calls when _OSI("Darwin") has | |
569 | * been called successfully. We know the feature set supported by the | |
570 | * platform, so avoid calling _OSC at all | |
571 | */ | |
630b3aff | 572 | if (x86_apple_machine) { |
7bc5a2ba MG |
573 | root->osc_control_set = ~OSC_PCI_EXPRESS_PME_CONTROL; |
574 | decode_osc_control(root, "OS assumes control of", | |
575 | root->osc_control_set); | |
576 | return; | |
577 | } | |
578 | ||
4c6f6060 | 579 | support = calculate_support(); |
955f14b4 BH |
580 | |
581 | decode_osc_support(root, "OS supports", support); | |
c238252f | 582 | |
6bc779ee JR |
583 | if (os_control_query_checks(root, support)) |
584 | requested = control = calculate_control(); | |
c238252f | 585 | |
56368029 VV |
586 | if (is_cxl(root)) { |
587 | cxl_support = calculate_cxl_support(); | |
588 | decode_cxl_osc_support(root, "OS supports", cxl_support); | |
589 | cxl_requested = cxl_control = calculate_cxl_control(); | |
590 | } | |
591 | ||
592 | status = acpi_pci_osc_control_set(handle, &control, support, | |
593 | &cxl_control, cxl_support); | |
de189662 | 594 | if (ACPI_SUCCESS(status)) { |
6bc779ee JR |
595 | if (control) |
596 | decode_osc_control(root, "OS now controls", control); | |
56368029 VV |
597 | if (cxl_control) |
598 | decode_cxl_osc_control(root, "OS now controls", | |
599 | cxl_control); | |
6bc779ee | 600 | |
de189662 | 601 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { |
3dc48af3 | 602 | /* |
387d3757 MG |
603 | * We have ASPM control, but the FADT indicates that |
604 | * it's unsupported. Leave existing configuration | |
605 | * intact and prevent the OS from touching it. | |
3dc48af3 | 606 | */ |
387d3757 MG |
607 | dev_info(&device->dev, "FADT indicates ASPM is unsupported, using BIOS configuration\n"); |
608 | *no_aspm = 1; | |
eca67315 | 609 | } |
a246670d | 610 | } else { |
de189662 BH |
611 | /* |
612 | * We want to disable ASPM here, but aspm_disabled | |
613 | * needs to remain in its state from boot so that we | |
614 | * properly handle PCIe 1.1 devices. So we set this | |
615 | * flag here, to defer the action until after the ACPI | |
616 | * root scan. | |
617 | */ | |
618 | *no_aspm = 1; | |
6bc779ee JR |
619 | |
620 | /* _OSC is optional for PCI host bridges */ | |
241d26bc | 621 | if (status == AE_NOT_FOUND && !is_pcie(root)) |
6bc779ee JR |
622 | return; |
623 | ||
624 | if (control) { | |
625 | decode_osc_control(root, "OS requested", requested); | |
626 | decode_osc_control(root, "platform willing to grant", control); | |
627 | } | |
56368029 VV |
628 | if (cxl_control) { |
629 | decode_cxl_osc_control(root, "OS requested", cxl_requested); | |
630 | decode_cxl_osc_control(root, "platform willing to grant", | |
631 | cxl_control); | |
632 | } | |
6bc779ee JR |
633 | |
634 | dev_info(&device->dev, "_OSC: platform retains control of PCIe features (%s)\n", | |
635 | acpi_format_exception(status)); | |
415e12b2 | 636 | } |
3e43abb0 BH |
637 | } |
638 | ||
00c43b96 RW |
639 | static int acpi_pci_root_add(struct acpi_device *device, |
640 | const struct acpi_device_id *not_used) | |
1da177e4 | 641 | { |
f5eebbe1 BH |
642 | unsigned long long segment, bus; |
643 | acpi_status status; | |
644 | int result; | |
645 | struct acpi_pci_root *root; | |
bfe2414a | 646 | acpi_handle handle = device->handle; |
387d3757 | 647 | int no_aspm = 0; |
9762b33d | 648 | bool hotadd = system_state == SYSTEM_RUNNING; |
241d26bc | 649 | const char *acpi_hid; |
1da177e4 | 650 | |
6ad95513 BH |
651 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); |
652 | if (!root) | |
653 | return -ENOMEM; | |
654 | ||
f5eebbe1 | 655 | segment = 0; |
bfe2414a | 656 | status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, |
f5eebbe1 BH |
657 | &segment); |
658 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | |
6dc7d22c | 659 | dev_err(&device->dev, "can't evaluate _SEG\n"); |
6ad95513 BH |
660 | result = -ENODEV; |
661 | goto end; | |
f5eebbe1 | 662 | } |
1da177e4 | 663 | |
f5eebbe1 | 664 | /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ |
6ad95513 | 665 | root->secondary.flags = IORESOURCE_BUS; |
bfe2414a | 666 | status = try_get_root_bridge_busnr(handle, &root->secondary); |
f5eebbe1 | 667 | if (ACPI_FAILURE(status)) { |
6ad95513 BH |
668 | /* |
669 | * We need both the start and end of the downstream bus range | |
670 | * to interpret _CBA (MMCONFIG base address), so it really is | |
671 | * supposed to be in _CRS. If we don't find it there, all we | |
672 | * can do is assume [_BBN-0xFF] or [0-0xFF]. | |
673 | */ | |
674 | root->secondary.end = 0xFF; | |
6dc7d22c JL |
675 | dev_warn(&device->dev, |
676 | FW_BUG "no secondary bus range in _CRS\n"); | |
bfe2414a | 677 | status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, |
e545b55a | 678 | NULL, &bus); |
6ad95513 BH |
679 | if (ACPI_SUCCESS(status)) |
680 | root->secondary.start = bus; | |
681 | else if (status == AE_NOT_FOUND) | |
682 | root->secondary.start = 0; | |
683 | else { | |
6dc7d22c | 684 | dev_err(&device->dev, "can't evaluate _BBN\n"); |
6ad95513 BH |
685 | result = -ENODEV; |
686 | goto end; | |
f5eebbe1 BH |
687 | } |
688 | } | |
1da177e4 | 689 | |
32917e5b | 690 | root->device = device; |
0705495d | 691 | root->segment = segment & 0xFFFF; |
9ff23678 MQAM |
692 | strscpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); |
693 | strscpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); | |
db89b4f0 | 694 | device->driver_data = root; |
1da177e4 | 695 | |
864b94ad JL |
696 | if (hotadd && dmar_device_add(handle)) { |
697 | result = -ENXIO; | |
698 | goto end; | |
699 | } | |
700 | ||
ccde83e3 | 701 | pr_info("%s [%s] (domain %04x %pR)\n", |
4be44fcd | 702 | acpi_device_name(device), acpi_device_bid(device), |
6ad95513 | 703 | root->segment, &root->secondary); |
1da177e4 | 704 | |
bfe2414a | 705 | root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle); |
1da177e4 | 706 | |
241d26bc DW |
707 | acpi_hid = acpi_device_hid(root->device); |
708 | if (strcmp(acpi_hid, "PNP0A08") == 0) | |
709 | root->bridge_type = ACPI_BRIDGE_TYPE_PCIE; | |
710 | else if (strcmp(acpi_hid, "ACPI0016") == 0) | |
711 | root->bridge_type = ACPI_BRIDGE_TYPE_CXL; | |
712 | else | |
713 | dev_dbg(&device->dev, "Assuming non-PCIe host bridge\n"); | |
714 | ||
715 | negotiate_os_control(root, &no_aspm); | |
415e12b2 | 716 | |
3dc48af3 NH |
717 | /* |
718 | * TBD: Need PCI interface for enumeration/configuration of roots. | |
719 | */ | |
720 | ||
721 | /* | |
722 | * Scan the Root Bridge | |
723 | * -------------------- | |
724 | * Must do this prior to any attempt to bind the root device, as the | |
725 | * PCI namespace does not get created until this call is made (and | |
726 | * thus the root bridge's pci_dev does not exist). | |
727 | */ | |
728 | root->bus = pci_acpi_scan_root(root); | |
729 | if (!root->bus) { | |
730 | dev_err(&device->dev, | |
731 | "Bus %04x:%02x not present in PCI namespace\n", | |
732 | root->segment, (unsigned int)root->secondary.start); | |
f516bde5 | 733 | device->driver_data = NULL; |
3dc48af3 | 734 | result = -ENODEV; |
864b94ad | 735 | goto remove_dmar; |
3dc48af3 NH |
736 | } |
737 | ||
3dc48af3 NH |
738 | if (no_aspm) |
739 | pcie_no_aspm(); | |
740 | ||
c072530f | 741 | pci_acpi_add_bus_pm_notifier(device); |
de3ef1eb | 742 | device_set_wakeup_capable(root->bus->bridge, device->wakeup.flags.valid); |
b67ea761 | 743 | |
864b94ad | 744 | if (hotadd) { |
3c449ed0 | 745 | pcibios_resource_survey_bus(root->bus); |
39772038 | 746 | pci_assign_unassigned_root_bus_resources(root->bus); |
584c5c42 RW |
747 | /* |
748 | * This is only called for the hotadd case. For the boot-time | |
749 | * case, we need to wait until after PCI initialization in | |
750 | * order to deal with IOAPICs mapped in on a PCI BAR. | |
751 | * | |
752 | * This is currently x86-specific, because acpi_ioapic_add() | |
753 | * is an empty function without CONFIG_ACPI_HOTPLUG_IOAPIC. | |
754 | * And CONFIG_ACPI_HOTPLUG_IOAPIC depends on CONFIG_X86_IO_APIC | |
755 | * (see drivers/acpi/Kconfig). | |
756 | */ | |
fe7bd58f | 757 | acpi_ioapic_add(root->device->handle); |
516ca223 | 758 | } |
62a08c5a | 759 | |
7a3bb55e | 760 | pci_lock_rescan_remove(); |
caf420c6 | 761 | pci_bus_add_devices(root->bus); |
7a3bb55e | 762 | pci_unlock_rescan_remove(); |
00c43b96 | 763 | return 1; |
47525cda | 764 | |
864b94ad JL |
765 | remove_dmar: |
766 | if (hotadd) | |
767 | dmar_device_remove(handle); | |
47525cda RW |
768 | end: |
769 | kfree(root); | |
770 | return result; | |
c431ada4 | 771 | } |
1da177e4 | 772 | |
00c43b96 | 773 | static void acpi_pci_root_remove(struct acpi_device *device) |
1da177e4 | 774 | { |
caf420c6 | 775 | struct acpi_pci_root *root = acpi_driver_data(device); |
c8e9afb1 | 776 | |
7a3bb55e RW |
777 | pci_lock_rescan_remove(); |
778 | ||
9738a1fd YL |
779 | pci_stop_root_bus(root->bus); |
780 | ||
f2ae5da7 | 781 | pci_ioapic_remove(root); |
de3ef1eb | 782 | device_set_wakeup_capable(root->bus->bridge, false); |
b67ea761 RW |
783 | pci_acpi_remove_bus_pm_notifier(device); |
784 | ||
9738a1fd | 785 | pci_remove_root_bus(root->bus); |
f2ae5da7 | 786 | WARN_ON(acpi_ioapic_remove(root)); |
9738a1fd | 787 | |
864b94ad JL |
788 | dmar_device_remove(device->handle); |
789 | ||
7a3bb55e RW |
790 | pci_unlock_rescan_remove(); |
791 | ||
1da177e4 | 792 | kfree(root); |
1da177e4 LT |
793 | } |
794 | ||
2c204383 JL |
795 | /* |
796 | * Following code to support acpi_pci_root_create() is copied from | |
797 | * arch/x86/pci/acpi.c and modified so it could be reused by x86, IA64 | |
798 | * and ARM64. | |
799 | */ | |
800 | static void acpi_pci_root_validate_resources(struct device *dev, | |
801 | struct list_head *resources, | |
802 | unsigned long type) | |
803 | { | |
804 | LIST_HEAD(list); | |
805 | struct resource *res1, *res2, *root = NULL; | |
806 | struct resource_entry *tmp, *entry, *entry2; | |
807 | ||
808 | BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0); | |
809 | root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource; | |
810 | ||
811 | list_splice_init(resources, &list); | |
812 | resource_list_for_each_entry_safe(entry, tmp, &list) { | |
813 | bool free = false; | |
814 | resource_size_t end; | |
815 | ||
816 | res1 = entry->res; | |
817 | if (!(res1->flags & type)) | |
818 | goto next; | |
819 | ||
820 | /* Exclude non-addressable range or non-addressable portion */ | |
821 | end = min(res1->end, root->end); | |
822 | if (end <= res1->start) { | |
823 | dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n", | |
824 | res1); | |
825 | free = true; | |
826 | goto next; | |
827 | } else if (res1->end != end) { | |
828 | dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n", | |
829 | res1, (unsigned long long)end + 1, | |
830 | (unsigned long long)res1->end); | |
831 | res1->end = end; | |
832 | } | |
833 | ||
834 | resource_list_for_each_entry(entry2, resources) { | |
835 | res2 = entry2->res; | |
836 | if (!(res2->flags & type)) | |
837 | continue; | |
838 | ||
839 | /* | |
840 | * I don't like throwing away windows because then | |
841 | * our resources no longer match the ACPI _CRS, but | |
842 | * the kernel resource tree doesn't allow overlaps. | |
843 | */ | |
07aec68e | 844 | if (resource_union(res1, res2, res2)) { |
2c204383 JL |
845 | dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n", |
846 | res2, res1); | |
847 | free = true; | |
848 | goto next; | |
849 | } | |
850 | } | |
851 | ||
852 | next: | |
853 | resource_list_del(entry); | |
854 | if (free) | |
855 | resource_list_free_entry(entry); | |
856 | else | |
857 | resource_list_add_tail(entry, resources); | |
858 | } | |
859 | } | |
860 | ||
eba614b8 | 861 | static void acpi_pci_root_remap_iospace(const struct fwnode_handle *fwnode, |
fcfaab30 | 862 | struct resource_entry *entry) |
0a70abb3 J |
863 | { |
864 | #ifdef PCI_IOBASE | |
865 | struct resource *res = entry->res; | |
866 | resource_size_t cpu_addr = res->start; | |
867 | resource_size_t pci_addr = cpu_addr - entry->offset; | |
868 | resource_size_t length = resource_size(res); | |
869 | unsigned long port; | |
870 | ||
fcfaab30 | 871 | if (pci_register_io_range(fwnode, cpu_addr, length)) |
0a70abb3 J |
872 | goto err; |
873 | ||
874 | port = pci_address_to_pio(cpu_addr); | |
875 | if (port == (unsigned long)-1) | |
876 | goto err; | |
877 | ||
878 | res->start = port; | |
879 | res->end = port + length - 1; | |
880 | entry->offset = port - pci_addr; | |
881 | ||
882 | if (pci_remap_iospace(res, cpu_addr) < 0) | |
883 | goto err; | |
884 | ||
885 | pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res); | |
886 | return; | |
887 | err: | |
888 | res->flags |= IORESOURCE_DISABLED; | |
889 | #endif | |
890 | } | |
891 | ||
2c204383 JL |
892 | int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info) |
893 | { | |
894 | int ret; | |
895 | struct list_head *list = &info->resources; | |
896 | struct acpi_device *device = info->bridge; | |
897 | struct resource_entry *entry, *tmp; | |
898 | unsigned long flags; | |
899 | ||
900 | flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT; | |
901 | ret = acpi_dev_get_resources(device, list, | |
902 | acpi_dev_filter_resource_type_cb, | |
903 | (void *)flags); | |
904 | if (ret < 0) | |
905 | dev_warn(&device->dev, | |
906 | "failed to parse _CRS method, error code %d\n", ret); | |
907 | else if (ret == 0) | |
908 | dev_dbg(&device->dev, | |
909 | "no IO and memory resources present in _CRS\n"); | |
910 | else { | |
911 | resource_list_for_each_entry_safe(entry, tmp, list) { | |
0a70abb3 | 912 | if (entry->res->flags & IORESOURCE_IO) |
fcfaab30 GP |
913 | acpi_pci_root_remap_iospace(&device->fwnode, |
914 | entry); | |
0a70abb3 | 915 | |
2c204383 JL |
916 | if (entry->res->flags & IORESOURCE_DISABLED) |
917 | resource_list_destroy_entry(entry); | |
918 | else | |
919 | entry->res->name = info->name; | |
920 | } | |
921 | acpi_pci_root_validate_resources(&device->dev, list, | |
922 | IORESOURCE_MEM); | |
923 | acpi_pci_root_validate_resources(&device->dev, list, | |
924 | IORESOURCE_IO); | |
925 | } | |
926 | ||
927 | return ret; | |
928 | } | |
929 | ||
930 | static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info) | |
931 | { | |
932 | struct resource_entry *entry, *tmp; | |
933 | struct resource *res, *conflict, *root = NULL; | |
934 | ||
935 | resource_list_for_each_entry_safe(entry, tmp, &info->resources) { | |
936 | res = entry->res; | |
937 | if (res->flags & IORESOURCE_MEM) | |
938 | root = &iomem_resource; | |
939 | else if (res->flags & IORESOURCE_IO) | |
940 | root = &ioport_resource; | |
941 | else | |
942 | continue; | |
943 | ||
727ae8be LJ |
944 | /* |
945 | * Some legacy x86 host bridge drivers use iomem_resource and | |
946 | * ioport_resource as default resource pool, skip it. | |
947 | */ | |
948 | if (res == root) | |
949 | continue; | |
950 | ||
2c204383 JL |
951 | conflict = insert_resource_conflict(root, res); |
952 | if (conflict) { | |
953 | dev_info(&info->bridge->dev, | |
954 | "ignoring host bridge window %pR (conflicts with %s %pR)\n", | |
955 | res, conflict->name, conflict); | |
956 | resource_list_destroy_entry(entry); | |
957 | } | |
958 | } | |
959 | } | |
960 | ||
961 | static void __acpi_pci_root_release_info(struct acpi_pci_root_info *info) | |
962 | { | |
963 | struct resource *res; | |
964 | struct resource_entry *entry, *tmp; | |
965 | ||
966 | if (!info) | |
967 | return; | |
968 | ||
969 | resource_list_for_each_entry_safe(entry, tmp, &info->resources) { | |
970 | res = entry->res; | |
971 | if (res->parent && | |
972 | (res->flags & (IORESOURCE_MEM | IORESOURCE_IO))) | |
973 | release_resource(res); | |
974 | resource_list_destroy_entry(entry); | |
975 | } | |
976 | ||
977 | info->ops->release_info(info); | |
978 | } | |
979 | ||
980 | static void acpi_pci_root_release_info(struct pci_host_bridge *bridge) | |
981 | { | |
982 | struct resource *res; | |
983 | struct resource_entry *entry; | |
984 | ||
985 | resource_list_for_each_entry(entry, &bridge->windows) { | |
986 | res = entry->res; | |
0a70abb3 J |
987 | if (res->flags & IORESOURCE_IO) |
988 | pci_unmap_iospace(res); | |
2c204383 JL |
989 | if (res->parent && |
990 | (res->flags & (IORESOURCE_MEM | IORESOURCE_IO))) | |
991 | release_resource(res); | |
992 | } | |
993 | __acpi_pci_root_release_info(bridge->release_data); | |
994 | } | |
995 | ||
996 | struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, | |
997 | struct acpi_pci_root_ops *ops, | |
998 | struct acpi_pci_root_info *info, | |
999 | void *sysdata) | |
1000 | { | |
1001 | int ret, busnum = root->secondary.start; | |
1002 | struct acpi_device *device = root->device; | |
1003 | int node = acpi_get_node(device->handle); | |
1004 | struct pci_bus *bus; | |
02bfeb48 | 1005 | struct pci_host_bridge *host_bridge; |
2c204383 JL |
1006 | |
1007 | info->root = root; | |
1008 | info->bridge = device; | |
1009 | info->ops = ops; | |
1010 | INIT_LIST_HEAD(&info->resources); | |
1011 | snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x", | |
1012 | root->segment, busnum); | |
1013 | ||
1014 | if (ops->init_info && ops->init_info(info)) | |
1015 | goto out_release_info; | |
1016 | if (ops->prepare_resources) | |
1017 | ret = ops->prepare_resources(info); | |
1018 | else | |
1019 | ret = acpi_pci_probe_root_resources(info); | |
1020 | if (ret < 0) | |
1021 | goto out_release_info; | |
1022 | ||
1023 | pci_acpi_root_add_resources(info); | |
1024 | pci_add_resource(&info->resources, &root->secondary); | |
1025 | bus = pci_create_root_bus(NULL, busnum, ops->pci_ops, | |
1026 | sysdata, &info->resources); | |
1027 | if (!bus) | |
1028 | goto out_release_info; | |
1029 | ||
02bfeb48 BH |
1030 | host_bridge = to_pci_host_bridge(bus->bridge); |
1031 | if (!(root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) | |
9310f0dc | 1032 | host_bridge->native_pcie_hotplug = 0; |
1df81a6d MW |
1033 | if (!(root->osc_control_set & OSC_PCI_SHPC_NATIVE_HP_CONTROL)) |
1034 | host_bridge->native_shpc_hotplug = 0; | |
02bfeb48 BH |
1035 | if (!(root->osc_control_set & OSC_PCI_EXPRESS_AER_CONTROL)) |
1036 | host_bridge->native_aer = 0; | |
1037 | if (!(root->osc_control_set & OSC_PCI_EXPRESS_PME_CONTROL)) | |
1038 | host_bridge->native_pme = 0; | |
af8bb9f8 BH |
1039 | if (!(root->osc_control_set & OSC_PCI_EXPRESS_LTR_CONTROL)) |
1040 | host_bridge->native_ltr = 0; | |
ac1c8e35 KS |
1041 | if (!(root->osc_control_set & OSC_PCI_EXPRESS_DPC_CONTROL)) |
1042 | host_bridge->native_dpc = 0; | |
02bfeb48 | 1043 | |
589c3357 IW |
1044 | if (!(root->osc_ext_control_set & OSC_CXL_ERROR_REPORTING_CONTROL)) |
1045 | host_bridge->native_cxl_error = 0; | |
1046 | ||
62d52871 RW |
1047 | acpi_dev_power_up_children_with_adr(device); |
1048 | ||
2c204383 | 1049 | pci_scan_child_bus(bus); |
02bfeb48 BH |
1050 | pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info, |
1051 | info); | |
2c204383 JL |
1052 | if (node != NUMA_NO_NODE) |
1053 | dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node); | |
1054 | return bus; | |
1055 | ||
1056 | out_release_info: | |
1057 | __acpi_pci_root_release_info(info); | |
1058 | return NULL; | |
1059 | } | |
1060 | ||
00c43b96 | 1061 | void __init acpi_pci_root_init(void) |
1da177e4 | 1062 | { |
3338db00 | 1063 | if (acpi_pci_disabled) |
668192b6 | 1064 | return; |
668192b6 | 1065 | |
3338db00 RW |
1066 | pci_acpi_crs_quirks(); |
1067 | acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root"); | |
668192b6 | 1068 | } |