diff options
author | Yijing Wang <wangyijing@huawei.com> | 2013-06-06 03:34:48 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2013-06-18 12:44:10 -0400 |
commit | 5cd7595dea8d54d93124cfc4faec103ce56ab03d (patch) | |
tree | 2c0fb4985707e51283f4fac48c7079dbed0be6df /arch/ia64/pci | |
parent | 2ead66b5472542d82f31c3b6418b23ace3dac87d (diff) |
PCI/IA64: embed pci hostbridge resources into pci_root_info
Currently, pcibios_resource_to_bus() and pcibios_bus_to_resource()
functions use pci_host_bridge to translate bus side address from/to
cpu side address. The pci_window in pci_controller never be used again.
So we remove pci_window in pci_controller and embed hostbridge resource
into pci_root_info. Bjorn suggested to implement hostbridge resources
release in IA64 like in X86, this patch is to prepare for that.
Signed-off-by: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Jiang Liu <jiang.liu@huawei.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Thierry Reding <thierry.reding@avionic-design.de>
Cc: linux-ia64@vger.kernel.org
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/pci')
-rw-r--r-- | arch/ia64/pci/pci.c | 65 |
1 files changed, 37 insertions, 28 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index de1474ff0bc5..82eb8b2a4f1d 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -134,6 +134,9 @@ struct pci_root_info { | |||
134 | struct acpi_device *bridge; | 134 | struct acpi_device *bridge; |
135 | struct pci_controller *controller; | 135 | struct pci_controller *controller; |
136 | struct list_head resources; | 136 | struct list_head resources; |
137 | struct resource *res; | ||
138 | resource_size_t *res_offset; | ||
139 | unsigned int res_num; | ||
137 | char *name; | 140 | char *name; |
138 | }; | 141 | }; |
139 | 142 | ||
@@ -265,7 +268,7 @@ static acpi_status count_window(struct acpi_resource *resource, void *data) | |||
265 | static acpi_status add_window(struct acpi_resource *res, void *data) | 268 | static acpi_status add_window(struct acpi_resource *res, void *data) |
266 | { | 269 | { |
267 | struct pci_root_info *info = data; | 270 | struct pci_root_info *info = data; |
268 | struct pci_window *window; | 271 | struct resource *resource; |
269 | struct acpi_resource_address64 addr; | 272 | struct acpi_resource_address64 addr; |
270 | acpi_status status; | 273 | acpi_status status; |
271 | unsigned long flags, offset = 0; | 274 | unsigned long flags, offset = 0; |
@@ -289,37 +292,36 @@ static acpi_status add_window(struct acpi_resource *res, void *data) | |||
289 | } else | 292 | } else |
290 | return AE_OK; | 293 | return AE_OK; |
291 | 294 | ||
292 | window = &info->controller->window[info->controller->windows++]; | 295 | resource = &info->res[info->res_num]; |
293 | window->resource.name = info->name; | 296 | resource->name = info->name; |
294 | window->resource.flags = flags; | 297 | resource->flags = flags; |
295 | window->resource.start = addr.minimum + offset; | 298 | resource->start = addr.minimum + offset; |
296 | window->resource.end = window->resource.start + addr.address_length - 1; | 299 | resource->end = resource->start + addr.address_length - 1; |
297 | window->offset = offset; | 300 | info->res_offset[info->res_num] = offset; |
298 | 301 | ||
299 | if (insert_resource(root, &window->resource)) { | 302 | if (insert_resource(root, resource)) { |
300 | dev_err(&info->bridge->dev, | 303 | dev_err(&info->bridge->dev, |
301 | "can't allocate host bridge window %pR\n", | 304 | "can't allocate host bridge window %pR\n", |
302 | &window->resource); | 305 | resource); |
303 | } else { | 306 | } else { |
304 | if (offset) | 307 | if (offset) |
305 | dev_info(&info->bridge->dev, "host bridge window %pR " | 308 | dev_info(&info->bridge->dev, "host bridge window %pR " |
306 | "(PCI address [%#llx-%#llx])\n", | 309 | "(PCI address [%#llx-%#llx])\n", |
307 | &window->resource, | 310 | resource, |
308 | window->resource.start - offset, | 311 | resource->start - offset, |
309 | window->resource.end - offset); | 312 | resource->end - offset); |
310 | else | 313 | else |
311 | dev_info(&info->bridge->dev, | 314 | dev_info(&info->bridge->dev, |
312 | "host bridge window %pR\n", | 315 | "host bridge window %pR\n", resource); |
313 | &window->resource); | ||
314 | } | 316 | } |
315 | |||
316 | /* HP's firmware has a hack to work around a Windows bug. | 317 | /* HP's firmware has a hack to work around a Windows bug. |
317 | * Ignore these tiny memory ranges */ | 318 | * Ignore these tiny memory ranges */ |
318 | if (!((window->resource.flags & IORESOURCE_MEM) && | 319 | if (!((resource->flags & IORESOURCE_MEM) && |
319 | (window->resource.end - window->resource.start < 16))) | 320 | (resource->end - resource->start < 16))) |
320 | pci_add_resource_offset(&info->resources, &window->resource, | 321 | pci_add_resource_offset(&info->resources, resource, |
321 | window->offset); | 322 | info->res_offset[info->res_num]); |
322 | 323 | ||
324 | info->res_num++; | ||
323 | return AE_OK; | 325 | return AE_OK; |
324 | } | 326 | } |
325 | 327 | ||
@@ -329,7 +331,6 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
329 | int domain = root->segment; | 331 | int domain = root->segment; |
330 | int bus = root->secondary.start; | 332 | int bus = root->secondary.start; |
331 | struct pci_controller *controller; | 333 | struct pci_controller *controller; |
332 | unsigned int windows = 0; | ||
333 | struct pci_root_info info; | 334 | struct pci_root_info info; |
334 | struct pci_bus *pbus; | 335 | struct pci_bus *pbus; |
335 | char *name; | 336 | char *name; |
@@ -351,22 +352,29 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
351 | /* insert busn resource at first */ | 352 | /* insert busn resource at first */ |
352 | pci_add_resource(&info.resources, &root->secondary); | 353 | pci_add_resource(&info.resources, &root->secondary); |
353 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, | 354 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, |
354 | &windows); | 355 | &info.res_num); |
355 | if (windows) { | 356 | if (info.res_num) { |
356 | controller->window = | 357 | info.res = |
357 | kzalloc_node(sizeof(*controller->window) * windows, | 358 | kzalloc_node(sizeof(*info.res) * info.res_num, |
358 | GFP_KERNEL, controller->node); | 359 | GFP_KERNEL, controller->node); |
359 | if (!controller->window) | 360 | if (!info.res) |
360 | goto out2; | 361 | goto out2; |
361 | 362 | ||
363 | info.res_offset = | ||
364 | kzalloc_node(sizeof(*info.res_offset) * info.res_num, | ||
365 | GFP_KERNEL, controller->node); | ||
366 | if (!info.res_offset) | ||
367 | goto out3; | ||
368 | |||
362 | name = kmalloc(16, GFP_KERNEL); | 369 | name = kmalloc(16, GFP_KERNEL); |
363 | if (!name) | 370 | if (!name) |
364 | goto out3; | 371 | goto out4; |
365 | 372 | ||
366 | sprintf(name, "PCI Bus %04x:%02x", domain, bus); | 373 | sprintf(name, "PCI Bus %04x:%02x", domain, bus); |
367 | info.bridge = device; | 374 | info.bridge = device; |
368 | info.controller = controller; | 375 | info.controller = controller; |
369 | info.name = name; | 376 | info.name = name; |
377 | info.res_num = 0; | ||
370 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, | 378 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, |
371 | add_window, &info); | 379 | add_window, &info); |
372 | } | 380 | } |
@@ -385,9 +393,10 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) | |||
385 | 393 | ||
386 | pci_scan_child_bus(pbus); | 394 | pci_scan_child_bus(pbus); |
387 | return pbus; | 395 | return pbus; |
388 | 396 | out4: | |
397 | kfree(info.res_offset); | ||
389 | out3: | 398 | out3: |
390 | kfree(controller->window); | 399 | kfree(info.res); |
391 | out2: | 400 | out2: |
392 | kfree(controller); | 401 | kfree(controller); |
393 | out1: | 402 | out1: |