Blame view

drivers/acpi/pci_root.c 23.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   *  pci_root.c - ACPI PCI Root Bridge Driver ($Revision: 40 $)
   *
   *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
   *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or (at
   *  your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful, but
   *  WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  General Public License for more details.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
24
25
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/types.h>
d0020f652   Taku Izumi   PCI/ACPI: Protect...
26
  #include <linux/mutex.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include <linux/pm.h>
b67ea7617   Rafael J. Wysocki   PCI / ACPI / PM: ...
28
  #include <linux/pm_runtime.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include <linux/pci.h>
990a7ac56   Andrew Patterson   ACPI/PCI: call _O...
30
  #include <linux/pci-acpi.h>
eca67315e   Naga Chumbalkar   PCI: Disable ASPM...
31
  #include <linux/pci-aspm.h>
864b94adf   Jiang Liu   pci, ACPI, iommu:...
32
  #include <linux/dmar.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  #include <linux/acpi.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
34
  #include <linux/slab.h>
7bc5a2bad   Matthew Garrett   ACPI: Support _OS...
35
  #include <linux/dmi.h>
8b48463f8   Lv Zheng   ACPI: Clean up in...
36
  #include <acpi/apei.h>	/* for acpi_hest_init() */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

ace8238b0   Rafael J. Wysocki   ACPI / hotplug: M...
38
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  #define _COMPONENT		ACPI_PCI_COMPONENT
f52fd66d2   Len Brown   ACPI: clean up AC...
40
  ACPI_MODULE_NAME("pci_root");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  #define ACPI_PCI_ROOT_CLASS		"pci_bridge"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  #define ACPI_PCI_ROOT_DEVICE_NAME	"PCI Root Bridge"
00c43b968   Rafael J. Wysocki   ACPI / PCI: Make ...
43
44
45
  static int acpi_pci_root_add(struct acpi_device *device,
  			     const struct acpi_device_id *not_used);
  static void acpi_pci_root_remove(struct acpi_device *device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

3338db005   Rafael J. Wysocki   ACPI / hotplug: M...
47
48
  static int acpi_pci_root_scan_dependent(struct acpi_device *adev)
  {
1f7c164b6   Rafael J. Wysocki   ACPI / hotplug / ...
49
  	acpiphp_check_host_bridge(adev);
3338db005   Rafael J. Wysocki   ACPI / hotplug: M...
50
51
  	return 0;
  }
7dab9ef4f   Bjorn Helgaas   PCI/ACPI: Name _O...
52
53
54
55
  #define ACPI_PCIE_REQ_SUPPORT (OSC_PCI_EXT_CONFIG_SUPPORT \
  				| OSC_PCI_ASPM_SUPPORT \
  				| OSC_PCI_CLOCK_PM_SUPPORT \
  				| OSC_PCI_MSI_SUPPORT)
415e12b23   Rafael J. Wysocki   PCI/ACPI: Request...
56

c97adf9e7   Márton Németh   acpi: make ACPI d...
57
  static const struct acpi_device_id root_device_ids[] = {
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
58
59
60
  	{"PNP0A03", 0},
  	{"", 0},
  };
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
61

00c43b968   Rafael J. Wysocki   ACPI / PCI: Make ...
62
  static struct acpi_scan_handler pci_root_handler = {
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
63
  	.ids = root_device_ids,
00c43b968   Rafael J. Wysocki   ACPI / PCI: Make ...
64
65
  	.attach = acpi_pci_root_add,
  	.detach = acpi_pci_root_remove,
ca499fc87   Toshi Kani   ACPI / hotplug: F...
66
  	.hotplug = {
3338db005   Rafael J. Wysocki   ACPI / hotplug: M...
67
68
  		.enabled = true,
  		.scan_dependent = acpi_pci_root_scan_dependent,
ca499fc87   Toshi Kani   ACPI / hotplug: F...
69
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  };
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
71
  static DEFINE_MUTEX(osc_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

275582031   Alexander Chiang   ACPI: Introduce a...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  /**
   * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
   * @handle - the ACPI CA node in question.
   *
   * Note: we could make this API take a struct acpi_device * instead, but
   * for now, it's more convenient to operate on an acpi_handle.
   */
  int acpi_is_root_bridge(acpi_handle handle)
  {
  	int ret;
  	struct acpi_device *device;
  
  	ret = acpi_bus_get_device(handle, &device);
  	if (ret)
  		return 0;
  
  	ret = acpi_match_device_ids(device, root_device_ids);
  	if (ret)
  		return 0;
  	else
  		return 1;
  }
  EXPORT_SYMBOL_GPL(acpi_is_root_bridge);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  static acpi_status
4be44fcd3   Len Brown   [ACPI] Lindent al...
97
  get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  {
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
99
  	struct resource *res = data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  	struct acpi_resource_address64 address;
f6c1c8ff4   Bjorn Helgaas   PCI/ACPI: Check a...
101
  	acpi_status status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102

f6c1c8ff4   Bjorn Helgaas   PCI/ACPI: Check a...
103
104
  	status = acpi_resource_to_address64(resource, &address);
  	if (ACPI_FAILURE(status))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  		return AE_OK;
a45de93eb   Lv Zheng   ACPICA: Resources...
106
  	if ((address.address.address_length > 0) &&
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
107
  	    (address.resource_type == ACPI_BUS_NUMBER_RANGE)) {
a45de93eb   Lv Zheng   ACPICA: Resources...
108
109
  		res->start = address.address.minimum;
  		res->end = address.address.minimum + address.address.address_length - 1;
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
110
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
113
  
  	return AE_OK;
  }
f5eebbe11   Bjorn Helgaas   ACPI: pci_root: s...
114
  static acpi_status try_get_root_bridge_busnr(acpi_handle handle,
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
115
  					     struct resource *res)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
  {
  	acpi_status status;
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
118
  	res->start = -1;
4be44fcd3   Len Brown   [ACPI] Lindent al...
119
120
  	status =
  	    acpi_walk_resources(handle, METHOD_NAME__CRS,
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
121
  				get_root_bridge_busnr_callback, res);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
  	if (ACPI_FAILURE(status))
  		return status;
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
124
  	if (res->start == -1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
  		return AE_ERROR;
  	return AE_OK;
  }
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  struct pci_osc_bit_struct {
  	u32 bit;
  	char *desc;
  };
  
  static struct pci_osc_bit_struct pci_osc_support_bit[] = {
  	{ OSC_PCI_EXT_CONFIG_SUPPORT, "ExtendedConfig" },
  	{ OSC_PCI_ASPM_SUPPORT, "ASPM" },
  	{ OSC_PCI_CLOCK_PM_SUPPORT, "ClockPM" },
  	{ OSC_PCI_SEGMENT_GROUPS_SUPPORT, "Segments" },
  	{ OSC_PCI_MSI_SUPPORT, "MSI" },
  };
  
  static struct pci_osc_bit_struct pci_osc_control_bit[] = {
  	{ OSC_PCI_EXPRESS_NATIVE_HP_CONTROL, "PCIeHotplug" },
  	{ OSC_PCI_SHPC_NATIVE_HP_CONTROL, "SHPCHotplug" },
  	{ OSC_PCI_EXPRESS_PME_CONTROL, "PME" },
  	{ OSC_PCI_EXPRESS_AER_CONTROL, "AER" },
  	{ OSC_PCI_EXPRESS_CAPABILITY_CONTROL, "PCIeCapability" },
  };
  
  static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word,
  			    struct pci_osc_bit_struct *table, int size)
  {
  	char buf[80];
  	int i, len = 0;
  	struct pci_osc_bit_struct *entry;
  
  	buf[0] = '\0';
  	for (i = 0, entry = table; i < size; i++, entry++)
  		if (word & entry->bit)
  			len += snprintf(buf + len, sizeof(buf) - len, "%s%s",
  					len ? " " : "", entry->desc);
  
  	dev_info(&root->device->dev, "_OSC: %s [%s]
  ", msg, buf);
  }
  
  static void decode_osc_support(struct acpi_pci_root *root, char *msg, u32 word)
  {
  	decode_osc_bits(root, msg, word, pci_osc_support_bit,
  			ARRAY_SIZE(pci_osc_support_bit));
  }
  
  static void decode_osc_control(struct acpi_pci_root *root, char *msg, u32 word)
  {
  	decode_osc_bits(root, msg, word, pci_osc_control_bit,
  			ARRAY_SIZE(pci_osc_control_bit));
  }
3a9622dc4   Shaohua Li   ACPI: cleanup pci...
177
  static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
178
179
180
181
  
  static acpi_status acpi_pci_run_osc(acpi_handle handle,
  				    const u32 *capbuf, u32 *retval)
  {
3a9622dc4   Shaohua Li   ACPI: cleanup pci...
182
183
184
185
186
187
  	struct acpi_osc_context context = {
  		.uuid_str = pci_osc_uuid_str,
  		.rev = 1,
  		.cap.length = 12,
  		.cap.pointer = (void *)capbuf,
  	};
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
188
  	acpi_status status;
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
189

3a9622dc4   Shaohua Li   ACPI: cleanup pci...
190
191
192
193
  	status = acpi_run_osc(handle, &context);
  	if (ACPI_SUCCESS(status)) {
  		*retval = *((u32 *)(context.ret.pointer + 8));
  		kfree(context.ret.pointer);
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
194
  	}
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
195
196
  	return status;
  }
ab8e8957a   Rafael J. Wysocki   ACPI/PCI: Make ac...
197
198
199
  static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root,
  					u32 support,
  					u32 *control)
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
200
201
  {
  	acpi_status status;
ab8e8957a   Rafael J. Wysocki   ACPI/PCI: Make ac...
202
203
204
205
  	u32 result, capbuf[3];
  
  	support &= OSC_PCI_SUPPORT_MASKS;
  	support |= root->osc_support_set;
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
206

b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
207
208
  	capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
  	capbuf[OSC_SUPPORT_DWORD] = support;
ab8e8957a   Rafael J. Wysocki   ACPI/PCI: Make ac...
209
210
  	if (control) {
  		*control &= OSC_PCI_CONTROL_MASKS;
b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
211
  		capbuf[OSC_CONTROL_DWORD] = *control | root->osc_control_set;
ab8e8957a   Rafael J. Wysocki   ACPI/PCI: Make ac...
212
  	} else {
545d6e189   Yinghai Lu   PCI / ACPI: Don't...
213
  		/* Run _OSC query only with existing controls. */
b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
214
  		capbuf[OSC_CONTROL_DWORD] = root->osc_control_set;
ab8e8957a   Rafael J. Wysocki   ACPI/PCI: Make ac...
215
  	}
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
216
217
218
  
  	status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
  	if (ACPI_SUCCESS(status)) {
ab8e8957a   Rafael J. Wysocki   ACPI/PCI: Make ac...
219
  		root->osc_support_set = support;
2b8fd9186   Rafael J. Wysocki   ACPI/PCI: Do not ...
220
  		if (control)
ab8e8957a   Rafael J. Wysocki   ACPI/PCI: Make ac...
221
  			*control = result;
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
222
223
224
225
226
227
228
  	}
  	return status;
  }
  
  static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
  {
  	acpi_status status;
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
229

63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
230
  	mutex_lock(&osc_lock);
ab8e8957a   Rafael J. Wysocki   ACPI/PCI: Make ac...
231
  	status = acpi_pci_query_osc(root, flags, NULL);
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
232
233
234
  	mutex_unlock(&osc_lock);
  	return status;
  }
76d56de57   Alex Chiang   ACPI: export acpi...
235
  struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
236
237
  {
  	struct acpi_pci_root *root;
cd4faf9c3   Taku Izumi   PCI/ACPI: Use acp...
238
  	struct acpi_device *device;
c1aec8341   Bjorn Helgaas   ACPI: pci_root: s...
239

cd4faf9c3   Taku Izumi   PCI/ACPI: Use acp...
240
241
242
243
244
245
246
  	if (acpi_bus_get_device(handle, &device) ||
  	    acpi_match_device_ids(device, root_device_ids))
  		return NULL;
  
  	root = acpi_driver_data(device);
  
  	return root;
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
247
  }
76d56de57   Alex Chiang   ACPI: export acpi...
248
  EXPORT_SYMBOL_GPL(acpi_pci_find_root);
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
249

2f7bbceb5   Alexander Chiang   ACPI: Introduce a...
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  struct acpi_handle_node {
  	struct list_head node;
  	acpi_handle handle;
  };
  
  /**
   * acpi_get_pci_dev - convert ACPI CA handle to struct pci_dev
   * @handle: the handle in question
   *
   * Given an ACPI CA handle, the desired PCI device is located in the
   * list of PCI devices.
   *
   * If the device is found, its reference count is increased and this
   * function returns a pointer to its data structure.  The caller must
   * decrement the reference count by calling pci_dev_put().
   * If no device is found, %NULL is returned.
   */
  struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
  {
  	int dev, fn;
  	unsigned long long adr;
  	acpi_status status;
  	acpi_handle phandle;
  	struct pci_bus *pbus;
  	struct pci_dev *pdev = NULL;
  	struct acpi_handle_node *node, *tmp;
  	struct acpi_pci_root *root;
  	LIST_HEAD(device_list);
  
  	/*
  	 * Walk up the ACPI CA namespace until we reach a PCI root bridge.
  	 */
  	phandle = handle;
  	while (!acpi_is_root_bridge(phandle)) {
  		node = kzalloc(sizeof(struct acpi_handle_node), GFP_KERNEL);
  		if (!node)
  			goto out;
  
  		INIT_LIST_HEAD(&node->node);
  		node->handle = phandle;
  		list_add(&node->node, &device_list);
  
  		status = acpi_get_parent(phandle, &phandle);
  		if (ACPI_FAILURE(status))
  			goto out;
  	}
  
  	root = acpi_pci_find_root(phandle);
  	if (!root)
  		goto out;
  
  	pbus = root->bus;
  
  	/*
  	 * Now, walk back down the PCI device tree until we return to our
  	 * original handle. Assumes that everything between the PCI root
  	 * bridge and the device we're looking for must be a P2P bridge.
  	 */
  	list_for_each_entry(node, &device_list, node) {
  		acpi_handle hnd = node->handle;
  		status = acpi_evaluate_integer(hnd, "_ADR", NULL, &adr);
  		if (ACPI_FAILURE(status))
  			goto out;
  		dev = (adr >> 16) & 0xffff;
  		fn  = adr & 0xffff;
  
  		pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
412af9783   Troy Moure   ACPI: video: prev...
317
  		if (!pdev || hnd == handle)
2f7bbceb5   Alexander Chiang   ACPI: Introduce a...
318
319
320
321
  			break;
  
  		pbus = pdev->subordinate;
  		pci_dev_put(pdev);
497fb54f5   Rafael J. Wysocki   ACPI / PCI: Fix N...
322
323
324
325
326
327
328
329
330
331
332
333
  
  		/*
  		 * This function may be called for a non-PCI device that has a
  		 * PCI parent (eg. a disk under a PCI SATA controller).  In that
  		 * case pdev->subordinate will be NULL for the parent.
  		 */
  		if (!pbus) {
  			dev_dbg(&pdev->dev, "Not a PCI-to-PCI bridge
  ");
  			pdev = NULL;
  			break;
  		}
2f7bbceb5   Alexander Chiang   ACPI: Introduce a...
334
335
336
337
338
339
340
341
  	}
  out:
  	list_for_each_entry_safe(node, tmp, &device_list, node)
  		kfree(node);
  
  	return pdev;
  }
  EXPORT_SYMBOL_GPL(acpi_get_pci_dev);
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
342
  /**
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
343
344
345
346
   * acpi_pci_osc_control_set - Request control of PCI root _OSC features.
   * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex).
   * @mask: Mask of _OSC bits to request control of, place to store control mask.
   * @req: Mask of _OSC bits the control of is essential to the caller.
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
347
   *
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
348
349
350
351
352
353
354
355
   * Run _OSC query for @mask and if that is successful, compare the returned
   * mask of control bits with @req.  If all of the @req bits are set in the
   * returned mask, run _OSC request for it.
   *
   * The variable at the @mask address may be modified regardless of whether or
   * not the function returns success.  On success it will contain the mask of
   * _OSC bits the BIOS has granted control of, but its contents are meaningless
   * on failure.
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
356
   **/
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
357
  acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req)
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
358
  {
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
359
  	struct acpi_pci_root *root;
4ffe6e54b   Bjorn Helgaas   PCI/ACPI: Drop un...
360
  	acpi_status status = AE_OK;
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
361
  	u32 ctrl, capbuf[3];
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
362

75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
363
364
365
366
367
  	if (!mask)
  		return AE_BAD_PARAMETER;
  
  	ctrl = *mask & OSC_PCI_CONTROL_MASKS;
  	if ((ctrl & req) != req)
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
368
369
370
371
372
373
374
  		return AE_TYPE;
  
  	root = acpi_pci_find_root(handle);
  	if (!root)
  		return AE_NOT_EXIST;
  
  	mutex_lock(&osc_lock);
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
375
376
  
  	*mask = ctrl | root->osc_control_set;
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
377
  	/* No need to evaluate _OSC if the control was already granted. */
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
378
  	if ((root->osc_control_set & ctrl) == ctrl)
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
379
  		goto out;
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
380
381
382
383
384
385
386
  	/* Need to check the available controls bits before requesting them. */
  	while (*mask) {
  		status = acpi_pci_query_osc(root, root->osc_support_set, mask);
  		if (ACPI_FAILURE(status))
  			goto out;
  		if (ctrl == *mask)
  			break;
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
387
388
  		decode_osc_control(root, "platform does not support",
  				   ctrl & ~(*mask));
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
389
390
  		ctrl = *mask;
  	}
2b8fd9186   Rafael J. Wysocki   ACPI/PCI: Do not ...
391

75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
392
  	if ((ctrl & req) != req) {
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
393
394
  		decode_osc_control(root, "not requesting control; platform does not support",
  				   req & ~(ctrl));
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
395
396
397
  		status = AE_SUPPORT;
  		goto out;
  	}
b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
398
399
400
  	capbuf[OSC_QUERY_DWORD] = 0;
  	capbuf[OSC_SUPPORT_DWORD] = root->osc_support_set;
  	capbuf[OSC_CONTROL_DWORD] = ctrl;
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
401
  	status = acpi_pci_run_osc(handle, capbuf, mask);
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
402
  	if (ACPI_SUCCESS(status))
75fb60f26   Rafael J. Wysocki   ACPI/PCI: Negotia...
403
  		root->osc_control_set = *mask;
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
404
405
406
407
  out:
  	mutex_unlock(&osc_lock);
  	return status;
  }
9f5404d8e   Kenji Kaneshige   PCI/ACPI: rename ...
408
  EXPORT_SYMBOL(acpi_pci_osc_control_set);
63f10f0f6   Kenji Kaneshige   PCI/ACPI: move _O...
409

387d37577   Matthew Garrett   PCI: Don't clear ...
410
  static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  {
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
412
  	u32 support, control, requested;
3e43abb01   Bjorn Helgaas   PCI/ACPI: Move _O...
413
414
  	acpi_status status;
  	struct acpi_device *device = root->device;
bfe2414ae   Jiang Liu   PCI/ACPI: Introdu...
415
  	acpi_handle handle = device->handle;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416

2786f6e38   Rui Zhang   ACPI: fix Supermi...
417
  	/*
7bc5a2bad   Matthew Garrett   ACPI: Support _OS...
418
419
420
421
422
423
424
425
426
427
428
429
430
  	 * Apple always return failure on _OSC calls when _OSI("Darwin") has
  	 * been called successfully. We know the feature set supported by the
  	 * platform, so avoid calling _OSC at all
  	 */
  
  	if (dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) {
  		root->osc_control_set = ~OSC_PCI_EXPRESS_PME_CONTROL;
  		decode_osc_control(root, "OS assumes control of",
  				   root->osc_control_set);
  		return;
  	}
  
  	/*
990a7ac56   Andrew Patterson   ACPI/PCI: call _O...
431
432
  	 * All supported architectures that use ACPI have support for
  	 * PCI domains, so we indicate this in _OSC support capabilities.
2786f6e38   Rui Zhang   ACPI: fix Supermi...
433
  	 */
65afe9162   Bjorn Helgaas   PCI/ACPI: Skip _O...
434
  	support = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
8c33f51df   Taku Izumi   PCI/ACPI: Request...
435
  	if (pci_ext_cfg_avail())
b8eb67fcc   Bjorn Helgaas   PCI/ACPI: Split _...
436
  		support |= OSC_PCI_EXT_CONFIG_SUPPORT;
1b2a7be60   Bjorn Helgaas   PCI/ACPI: Run _OS...
437
  	if (pcie_aspm_support_enabled())
b8eb67fcc   Bjorn Helgaas   PCI/ACPI: Split _...
438
  		support |= OSC_PCI_ASPM_SUPPORT | OSC_PCI_CLOCK_PM_SUPPORT;
07ae95f98   Andrew Patterson   ACPI/PCI: PCI MSI...
439
  	if (pci_msi_enabled())
b8eb67fcc   Bjorn Helgaas   PCI/ACPI: Split _...
440
  		support |= OSC_PCI_MSI_SUPPORT;
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
441
442
  
  	decode_osc_support(root, "OS supports", support);
1b2a7be60   Bjorn Helgaas   PCI/ACPI: Run _OS...
443
444
  	status = acpi_pci_osc_support(root, support);
  	if (ACPI_FAILURE(status)) {
65afe9162   Bjorn Helgaas   PCI/ACPI: Skip _O...
445
446
447
  		dev_info(&device->dev, "_OSC failed (%s); disabling ASPM
  ",
  			 acpi_format_exception(status));
1b2a7be60   Bjorn Helgaas   PCI/ACPI: Run _OS...
448
  		*no_aspm = 1;
65afe9162   Bjorn Helgaas   PCI/ACPI: Skip _O...
449
  		return;
2d9c86774   Rafael J. Wysocki   ACPI / PCI: Do no...
450
  	}
b8178f130   Bjorn Helgaas   Revert "PCI/ACPI:...
451

43613a1fa   Bjorn Helgaas   PCI/ACPI: Separat...
452
453
454
455
456
  	if (pcie_ports_disabled) {
  		dev_info(&device->dev, "PCIe port services disabled; not requesting _OSC control
  ");
  		return;
  	}
de1896622   Bjorn Helgaas   PCI/ACPI: Separat...
457
  	if ((support & ACPI_PCIE_REQ_SUPPORT) != ACPI_PCIE_REQ_SUPPORT) {
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
458
459
  		decode_osc_support(root, "not requesting OS control; OS requires",
  				   ACPI_PCIE_REQ_SUPPORT);
de1896622   Bjorn Helgaas   PCI/ACPI: Separat...
460
461
462
463
464
465
466
467
468
  		return;
  	}
  
  	control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL
  		| OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
  		| OSC_PCI_EXPRESS_PME_CONTROL;
  
  	if (pci_aer_available()) {
  		if (aer_acpi_firmware_first())
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
469
470
471
  			dev_info(&device->dev,
  				 "PCIe AER handled by firmware
  ");
de1896622   Bjorn Helgaas   PCI/ACPI: Separat...
472
473
474
  		else
  			control |= OSC_PCI_EXPRESS_AER_CONTROL;
  	}
415e12b23   Rafael J. Wysocki   PCI/ACPI: Request...
475

955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
476
  	requested = control;
de1896622   Bjorn Helgaas   PCI/ACPI: Separat...
477
478
479
  	status = acpi_pci_osc_control_set(handle, &control,
  					  OSC_PCI_EXPRESS_CAPABILITY_CONTROL);
  	if (ACPI_SUCCESS(status)) {
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
480
  		decode_osc_control(root, "OS now controls", control);
de1896622   Bjorn Helgaas   PCI/ACPI: Separat...
481
  		if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
3dc48af31   Neil Horman   PCI/ACPI: Fix _OS...
482
  			/*
387d37577   Matthew Garrett   PCI: Don't clear ...
483
484
485
  			 * We have ASPM control, but the FADT indicates that
  			 * it's unsupported. Leave existing configuration
  			 * intact and prevent the OS from touching it.
3dc48af31   Neil Horman   PCI/ACPI: Fix _OS...
486
  			 */
387d37577   Matthew Garrett   PCI: Don't clear ...
487
488
489
  			dev_info(&device->dev, "FADT indicates ASPM is unsupported, using BIOS configuration
  ");
  			*no_aspm = 1;
eca67315e   Naga Chumbalkar   PCI: Disable ASPM...
490
  		}
a246670dd   Rafael J. Wysocki   PCI/ACPI: Report ...
491
  	} else {
955f14b4e   Bjorn Helgaas   PCI/ACPI: Decode ...
492
493
494
495
496
  		decode_osc_control(root, "OS requested", requested);
  		decode_osc_control(root, "platform willing to grant", control);
  		dev_info(&device->dev, "_OSC failed (%s); disabling ASPM
  ",
  			acpi_format_exception(status));
de1896622   Bjorn Helgaas   PCI/ACPI: Separat...
497
498
499
500
501
502
503
504
  		/*
  		 * We want to disable ASPM here, but aspm_disabled
  		 * needs to remain in its state from boot so that we
  		 * properly handle PCIe 1.1 devices.  So we set this
  		 * flag here, to defer the action until after the ACPI
  		 * root scan.
  		 */
  		*no_aspm = 1;
415e12b23   Rafael J. Wysocki   PCI/ACPI: Request...
505
  	}
3e43abb01   Bjorn Helgaas   PCI/ACPI: Move _O...
506
  }
00c43b968   Rafael J. Wysocki   ACPI / PCI: Make ...
507
508
  static int acpi_pci_root_add(struct acpi_device *device,
  			     const struct acpi_device_id *not_used)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
  {
f5eebbe11   Bjorn Helgaas   ACPI: pci_root: s...
510
511
512
513
  	unsigned long long segment, bus;
  	acpi_status status;
  	int result;
  	struct acpi_pci_root *root;
bfe2414ae   Jiang Liu   PCI/ACPI: Introdu...
514
  	acpi_handle handle = device->handle;
387d37577   Matthew Garrett   PCI: Don't clear ...
515
  	int no_aspm = 0;
864b94adf   Jiang Liu   pci, ACPI, iommu:...
516
  	bool hotadd = system_state != SYSTEM_BOOTING;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517

6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
518
519
520
  	root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
  	if (!root)
  		return -ENOMEM;
f5eebbe11   Bjorn Helgaas   ACPI: pci_root: s...
521
  	segment = 0;
bfe2414ae   Jiang Liu   PCI/ACPI: Introdu...
522
  	status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL,
f5eebbe11   Bjorn Helgaas   ACPI: pci_root: s...
523
524
  				       &segment);
  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
6dc7d22c6   Jiang Liu   PCI/ACPI: Use dev...
525
526
  		dev_err(&device->dev,  "can't evaluate _SEG
  ");
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
527
528
  		result = -ENODEV;
  		goto end;
f5eebbe11   Bjorn Helgaas   ACPI: pci_root: s...
529
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530

f5eebbe11   Bjorn Helgaas   ACPI: pci_root: s...
531
  	/* Check _CRS first, then _BBN.  If no _BBN, default to zero. */
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
532
  	root->secondary.flags = IORESOURCE_BUS;
bfe2414ae   Jiang Liu   PCI/ACPI: Introdu...
533
  	status = try_get_root_bridge_busnr(handle, &root->secondary);
f5eebbe11   Bjorn Helgaas   ACPI: pci_root: s...
534
  	if (ACPI_FAILURE(status)) {
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
535
536
537
538
539
540
541
  		/*
  		 * We need both the start and end of the downstream bus range
  		 * to interpret _CBA (MMCONFIG base address), so it really is
  		 * supposed to be in _CRS.  If we don't find it there, all we
  		 * can do is assume [_BBN-0xFF] or [0-0xFF].
  		 */
  		root->secondary.end = 0xFF;
6dc7d22c6   Jiang Liu   PCI/ACPI: Use dev...
542
543
544
  		dev_warn(&device->dev,
  			 FW_BUG "no secondary bus range in _CRS
  ");
bfe2414ae   Jiang Liu   PCI/ACPI: Introdu...
545
  		status = acpi_evaluate_integer(handle, METHOD_NAME__BBN,
e545b55a1   Jon Mason   ACPI: fix 80 char...
546
  					       NULL, &bus);
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
547
548
549
550
551
  		if (ACPI_SUCCESS(status))
  			root->secondary.start = bus;
  		else if (status == AE_NOT_FOUND)
  			root->secondary.start = 0;
  		else {
6dc7d22c6   Jiang Liu   PCI/ACPI: Use dev...
552
553
  			dev_err(&device->dev, "can't evaluate _BBN
  ");
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
554
555
  			result = -ENODEV;
  			goto end;
f5eebbe11   Bjorn Helgaas   ACPI: pci_root: s...
556
557
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558

32917e5b5   Patrick Mochel   ACPI: pci root: a...
559
  	root->device = device;
0705495d9   Bjorn Helgaas   ACPI: pci_root: r...
560
  	root->segment = segment & 0xFFFF;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
562
  	strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
  	strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
db89b4f0d   Pavel Machek   ACPI: catch calls...
563
  	device->driver_data = root;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564

864b94adf   Jiang Liu   pci, ACPI, iommu:...
565
566
567
568
  	if (hotadd && dmar_device_add(handle)) {
  		result = -ENXIO;
  		goto end;
  	}
6dc7d22c6   Jiang Liu   PCI/ACPI: Use dev...
569
570
  	pr_info(PREFIX "%s [%s] (domain %04x %pR)
  ",
4be44fcd3   Len Brown   [ACPI] Lindent al...
571
  	       acpi_device_name(device), acpi_device_bid(device),
6ad95513d   Bjorn Helgaas   ACPI: pci_root: s...
572
  	       root->segment, &root->secondary);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573

bfe2414ae   Jiang Liu   PCI/ACPI: Introdu...
574
  	root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575

387d37577   Matthew Garrett   PCI: Don't clear ...
576
  	negotiate_os_control(root, &no_aspm);
415e12b23   Rafael J. Wysocki   PCI/ACPI: Request...
577

3dc48af31   Neil Horman   PCI/ACPI: Fix _OS...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  	/*
  	 * TBD: Need PCI interface for enumeration/configuration of roots.
  	 */
  
  	/*
  	 * Scan the Root Bridge
  	 * --------------------
  	 * Must do this prior to any attempt to bind the root device, as the
  	 * PCI namespace does not get created until this call is made (and
  	 * thus the root bridge's pci_dev does not exist).
  	 */
  	root->bus = pci_acpi_scan_root(root);
  	if (!root->bus) {
  		dev_err(&device->dev,
  			"Bus %04x:%02x not present in PCI namespace
  ",
  			root->segment, (unsigned int)root->secondary.start);
f516bde51   Rafael J. Wysocki   ACPI / PCI root: ...
595
  		device->driver_data = NULL;
3dc48af31   Neil Horman   PCI/ACPI: Fix _OS...
596
  		result = -ENODEV;
864b94adf   Jiang Liu   pci, ACPI, iommu:...
597
  		goto remove_dmar;
3dc48af31   Neil Horman   PCI/ACPI: Fix _OS...
598
  	}
3dc48af31   Neil Horman   PCI/ACPI: Fix _OS...
599
600
  	if (no_aspm)
  		pcie_no_aspm();
c072530f3   Rafael J. Wysocki   ACPI / PM: Revork...
601
  	pci_acpi_add_bus_pm_notifier(device);
b67ea7617   Rafael J. Wysocki   PCI / ACPI / PM: ...
602
603
  	if (device->wakeup.flags.run_wake)
  		device_set_run_wake(root->bus->bridge, true);
864b94adf   Jiang Liu   pci, ACPI, iommu:...
604
  	if (hotadd) {
3c449ed00   Yinghai Lu   PCI/ACPI: Reserve...
605
  		pcibios_resource_survey_bus(root->bus);
39772038e   Yinghai Lu   PCI: Assign resou...
606
  		pci_assign_unassigned_root_bus_resources(root->bus);
c183619b6   Jiang Liu   x86/irq, ACPI: Im...
607
  		acpi_ioapic_add(root);
516ca2230   Jiang Liu   PCI/ACPI: Combine...
608
  	}
62a08c5a3   Yinghai Lu   PCI/ACPI: Assign ...
609

7a3bb55eb   Rafael J. Wysocki   ACPI / PCI: Use g...
610
  	pci_lock_rescan_remove();
caf420c68   Bjorn Helgaas   ACPI: pci_root: u...
611
  	pci_bus_add_devices(root->bus);
7a3bb55eb   Rafael J. Wysocki   ACPI / PCI: Use g...
612
  	pci_unlock_rescan_remove();
00c43b968   Rafael J. Wysocki   ACPI / PCI: Make ...
613
  	return 1;
47525cda8   Rafael J. Wysocki   ACPI / PCI: Fold ...
614

864b94adf   Jiang Liu   pci, ACPI, iommu:...
615
616
617
  remove_dmar:
  	if (hotadd)
  		dmar_device_remove(handle);
47525cda8   Rafael J. Wysocki   ACPI / PCI: Fold ...
618
619
620
  end:
  	kfree(root);
  	return result;
c431ada45   Rajesh Shah   [PATCH] acpi brid...
621
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622

00c43b968   Rafael J. Wysocki   ACPI / PCI: Make ...
623
  static void acpi_pci_root_remove(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  {
caf420c68   Bjorn Helgaas   ACPI: pci_root: u...
625
  	struct acpi_pci_root *root = acpi_driver_data(device);
c8e9afb12   Jiang Liu   PCI/ACPI: Notify ...
626

7a3bb55eb   Rafael J. Wysocki   ACPI / PCI: Use g...
627
  	pci_lock_rescan_remove();
9738a1fd2   Yinghai Lu   PCI/ACPI: Make ac...
628
  	pci_stop_root_bus(root->bus);
c183619b6   Jiang Liu   x86/irq, ACPI: Im...
629
  	WARN_ON(acpi_ioapic_remove(root));
b67ea7617   Rafael J. Wysocki   PCI / ACPI / PM: ...
630
631
  	device_set_run_wake(root->bus->bridge, false);
  	pci_acpi_remove_bus_pm_notifier(device);
9738a1fd2   Yinghai Lu   PCI/ACPI: Make ac...
632
  	pci_remove_root_bus(root->bus);
864b94adf   Jiang Liu   pci, ACPI, iommu:...
633
  	dmar_device_remove(device->handle);
7a3bb55eb   Rafael J. Wysocki   ACPI / PCI: Use g...
634
  	pci_unlock_rescan_remove();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  	kfree(root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
636
  }
2c204383a   Jiang Liu   PCI/ACPI: Add int...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
  /*
   * Following code to support acpi_pci_root_create() is copied from
   * arch/x86/pci/acpi.c and modified so it could be reused by x86, IA64
   * and ARM64.
   */
  static void acpi_pci_root_validate_resources(struct device *dev,
  					     struct list_head *resources,
  					     unsigned long type)
  {
  	LIST_HEAD(list);
  	struct resource *res1, *res2, *root = NULL;
  	struct resource_entry *tmp, *entry, *entry2;
  
  	BUG_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
  	root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
  
  	list_splice_init(resources, &list);
  	resource_list_for_each_entry_safe(entry, tmp, &list) {
  		bool free = false;
  		resource_size_t end;
  
  		res1 = entry->res;
  		if (!(res1->flags & type))
  			goto next;
  
  		/* Exclude non-addressable range or non-addressable portion */
  		end = min(res1->end, root->end);
  		if (end <= res1->start) {
  			dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)
  ",
  				 res1);
  			free = true;
  			goto next;
  		} else if (res1->end != end) {
  			dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)
  ",
  				 res1, (unsigned long long)end + 1,
  				 (unsigned long long)res1->end);
  			res1->end = end;
  		}
  
  		resource_list_for_each_entry(entry2, resources) {
  			res2 = entry2->res;
  			if (!(res2->flags & type))
  				continue;
  
  			/*
  			 * I don't like throwing away windows because then
  			 * our resources no longer match the ACPI _CRS, but
  			 * the kernel resource tree doesn't allow overlaps.
  			 */
  			if (resource_overlaps(res1, res2)) {
  				res2->start = min(res1->start, res2->start);
  				res2->end = max(res1->end, res2->end);
  				dev_info(dev, "host bridge window expanded to %pR; %pR ignored
  ",
  					 res2, res1);
  				free = true;
  				goto next;
  			}
  		}
  
  next:
  		resource_list_del(entry);
  		if (free)
  			resource_list_free_entry(entry);
  		else
  			resource_list_add_tail(entry, resources);
  	}
  }
  
  int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info)
  {
  	int ret;
  	struct list_head *list = &info->resources;
  	struct acpi_device *device = info->bridge;
  	struct resource_entry *entry, *tmp;
  	unsigned long flags;
  
  	flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT;
  	ret = acpi_dev_get_resources(device, list,
  				     acpi_dev_filter_resource_type_cb,
  				     (void *)flags);
  	if (ret < 0)
  		dev_warn(&device->dev,
  			 "failed to parse _CRS method, error code %d
  ", ret);
  	else if (ret == 0)
  		dev_dbg(&device->dev,
  			"no IO and memory resources present in _CRS
  ");
  	else {
  		resource_list_for_each_entry_safe(entry, tmp, list) {
  			if (entry->res->flags & IORESOURCE_DISABLED)
  				resource_list_destroy_entry(entry);
  			else
  				entry->res->name = info->name;
  		}
  		acpi_pci_root_validate_resources(&device->dev, list,
  						 IORESOURCE_MEM);
  		acpi_pci_root_validate_resources(&device->dev, list,
  						 IORESOURCE_IO);
  	}
  
  	return ret;
  }
  
  static void pci_acpi_root_add_resources(struct acpi_pci_root_info *info)
  {
  	struct resource_entry *entry, *tmp;
  	struct resource *res, *conflict, *root = NULL;
  
  	resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
  		res = entry->res;
  		if (res->flags & IORESOURCE_MEM)
  			root = &iomem_resource;
  		else if (res->flags & IORESOURCE_IO)
  			root = &ioport_resource;
  		else
  			continue;
727ae8be3   Liu Jiang   x86/PCI/ACPI: Fix...
757
758
759
760
761
762
  		/*
  		 * Some legacy x86 host bridge drivers use iomem_resource and
  		 * ioport_resource as default resource pool, skip it.
  		 */
  		if (res == root)
  			continue;
2c204383a   Jiang Liu   PCI/ACPI: Add int...
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
  		conflict = insert_resource_conflict(root, res);
  		if (conflict) {
  			dev_info(&info->bridge->dev,
  				 "ignoring host bridge window %pR (conflicts with %s %pR)
  ",
  				 res, conflict->name, conflict);
  			resource_list_destroy_entry(entry);
  		}
  	}
  }
  
  static void __acpi_pci_root_release_info(struct acpi_pci_root_info *info)
  {
  	struct resource *res;
  	struct resource_entry *entry, *tmp;
  
  	if (!info)
  		return;
  
  	resource_list_for_each_entry_safe(entry, tmp, &info->resources) {
  		res = entry->res;
  		if (res->parent &&
  		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
  			release_resource(res);
  		resource_list_destroy_entry(entry);
  	}
  
  	info->ops->release_info(info);
  }
  
  static void acpi_pci_root_release_info(struct pci_host_bridge *bridge)
  {
  	struct resource *res;
  	struct resource_entry *entry;
  
  	resource_list_for_each_entry(entry, &bridge->windows) {
  		res = entry->res;
  		if (res->parent &&
  		    (res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
  			release_resource(res);
  	}
  	__acpi_pci_root_release_info(bridge->release_data);
  }
  
  struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
  				     struct acpi_pci_root_ops *ops,
  				     struct acpi_pci_root_info *info,
  				     void *sysdata)
  {
  	int ret, busnum = root->secondary.start;
  	struct acpi_device *device = root->device;
  	int node = acpi_get_node(device->handle);
  	struct pci_bus *bus;
  
  	info->root = root;
  	info->bridge = device;
  	info->ops = ops;
  	INIT_LIST_HEAD(&info->resources);
  	snprintf(info->name, sizeof(info->name), "PCI Bus %04x:%02x",
  		 root->segment, busnum);
  
  	if (ops->init_info && ops->init_info(info))
  		goto out_release_info;
  	if (ops->prepare_resources)
  		ret = ops->prepare_resources(info);
  	else
  		ret = acpi_pci_probe_root_resources(info);
  	if (ret < 0)
  		goto out_release_info;
  
  	pci_acpi_root_add_resources(info);
  	pci_add_resource(&info->resources, &root->secondary);
  	bus = pci_create_root_bus(NULL, busnum, ops->pci_ops,
  				  sysdata, &info->resources);
  	if (!bus)
  		goto out_release_info;
  
  	pci_scan_child_bus(bus);
  	pci_set_host_bridge_release(to_pci_host_bridge(bus->bridge),
  				    acpi_pci_root_release_info, info);
  	if (node != NUMA_NO_NODE)
  		dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d
  ", node);
  	return bus;
  
  out_release_info:
  	__acpi_pci_root_release_info(info);
  	return NULL;
  }
00c43b968   Rafael J. Wysocki   ACPI / PCI: Make ...
852
  void __init acpi_pci_root_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
  {
d3072e6a7   Rafael J. Wysocki   ACPI: Fix boot pr...
854
  	acpi_hest_init();
3338db005   Rafael J. Wysocki   ACPI / hotplug: M...
855
  	if (acpi_pci_disabled)
668192b67   Yinghai Lu   PCI: acpiphp: Mov...
856
  		return;
668192b67   Yinghai Lu   PCI: acpiphp: Mov...
857

3338db005   Rafael J. Wysocki   ACPI / hotplug: M...
858
859
  	pci_acpi_crs_quirks();
  	acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root");
668192b67   Yinghai Lu   PCI: acpiphp: Mov...
860
  }