diff options
Diffstat (limited to 'arch/ia64/pci/pci.c')
| -rw-r--r-- | arch/ia64/pci/pci.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index e3fc4edea113..720a861f88be 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
| @@ -312,7 +312,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) | |||
| 312 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, | 312 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, |
| 313 | &info); | 313 | &info); |
| 314 | 314 | ||
| 315 | pbus = pci_scan_bus(bus, &pci_root_ops, controller); | 315 | pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller); |
| 316 | if (pbus) | 316 | if (pbus) |
| 317 | pcibios_setup_root_windows(pbus, controller); | 317 | pcibios_setup_root_windows(pbus, controller); |
| 318 | 318 | ||
| @@ -373,6 +373,25 @@ void pcibios_bus_to_resource(struct pci_dev *dev, | |||
| 373 | res->end = region->end + offset; | 373 | res->end = region->end + offset; |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | static int __devinit is_valid_resource(struct pci_dev *dev, int idx) | ||
| 377 | { | ||
| 378 | unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; | ||
| 379 | struct resource *devr = &dev->resource[idx]; | ||
| 380 | |||
| 381 | if (!dev->bus) | ||
| 382 | return 0; | ||
| 383 | for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) { | ||
| 384 | struct resource *busr = dev->bus->resource[i]; | ||
| 385 | |||
| 386 | if (!busr || ((busr->flags ^ devr->flags) & type_mask)) | ||
| 387 | continue; | ||
| 388 | if ((devr->start) && (devr->start >= busr->start) && | ||
| 389 | (devr->end <= busr->end)) | ||
| 390 | return 1; | ||
| 391 | } | ||
| 392 | return 0; | ||
| 393 | } | ||
| 394 | |||
| 376 | static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) | 395 | static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) |
| 377 | { | 396 | { |
| 378 | struct pci_bus_region region; | 397 | struct pci_bus_region region; |
| @@ -386,7 +405,8 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) | |||
| 386 | region.start = dev->resource[i].start; | 405 | region.start = dev->resource[i].start; |
| 387 | region.end = dev->resource[i].end; | 406 | region.end = dev->resource[i].end; |
| 388 | pcibios_bus_to_resource(dev, &dev->resource[i], ®ion); | 407 | pcibios_bus_to_resource(dev, &dev->resource[i], ®ion); |
| 389 | pci_claim_resource(dev, i); | 408 | if ((is_valid_resource(dev, i))) |
| 409 | pci_claim_resource(dev, i); | ||
| 390 | } | 410 | } |
| 391 | } | 411 | } |
| 392 | 412 | ||
| @@ -398,6 +418,10 @@ pcibios_fixup_bus (struct pci_bus *b) | |||
| 398 | { | 418 | { |
| 399 | struct pci_dev *dev; | 419 | struct pci_dev *dev; |
| 400 | 420 | ||
| 421 | if (b->self) { | ||
| 422 | pci_read_bridge_bases(b); | ||
| 423 | pcibios_fixup_device_resources(b->self); | ||
| 424 | } | ||
| 401 | list_for_each_entry(dev, &b->devices, bus_list) | 425 | list_for_each_entry(dev, &b->devices, bus_list) |
| 402 | pcibios_fixup_device_resources(dev); | 426 | pcibios_fixup_device_resources(dev); |
| 403 | 427 | ||
| @@ -418,18 +442,24 @@ pcibios_enable_resources (struct pci_dev *dev, int mask) | |||
| 418 | u16 cmd, old_cmd; | 442 | u16 cmd, old_cmd; |
| 419 | int idx; | 443 | int idx; |
| 420 | struct resource *r; | 444 | struct resource *r; |
| 445 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; | ||
| 421 | 446 | ||
| 422 | if (!dev) | 447 | if (!dev) |
| 423 | return -EINVAL; | 448 | return -EINVAL; |
| 424 | 449 | ||
| 425 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | 450 | pci_read_config_word(dev, PCI_COMMAND, &cmd); |
| 426 | old_cmd = cmd; | 451 | old_cmd = cmd; |
| 427 | for (idx=0; idx<6; idx++) { | 452 | for (idx=0; idx<PCI_NUM_RESOURCES; idx++) { |
| 428 | /* Only set up the desired resources. */ | 453 | /* Only set up the desired resources. */ |
| 429 | if (!(mask & (1 << idx))) | 454 | if (!(mask & (1 << idx))) |
| 430 | continue; | 455 | continue; |
| 431 | 456 | ||
| 432 | r = &dev->resource[idx]; | 457 | r = &dev->resource[idx]; |
| 458 | if (!(r->flags & type_mask)) | ||
| 459 | continue; | ||
| 460 | if ((idx == PCI_ROM_RESOURCE) && | ||
| 461 | (!(r->flags & IORESOURCE_ROM_ENABLE))) | ||
| 462 | continue; | ||
| 433 | if (!r->start && r->end) { | 463 | if (!r->start && r->end) { |
| 434 | printk(KERN_ERR | 464 | printk(KERN_ERR |
| 435 | "PCI: Device %s not available because of resource collisions\n", | 465 | "PCI: Device %s not available because of resource collisions\n", |
| @@ -441,8 +471,6 @@ pcibios_enable_resources (struct pci_dev *dev, int mask) | |||
| 441 | if (r->flags & IORESOURCE_MEM) | 471 | if (r->flags & IORESOURCE_MEM) |
| 442 | cmd |= PCI_COMMAND_MEMORY; | 472 | cmd |= PCI_COMMAND_MEMORY; |
| 443 | } | 473 | } |
| 444 | if (dev->resource[PCI_ROM_RESOURCE].start) | ||
| 445 | cmd |= PCI_COMMAND_MEMORY; | ||
| 446 | if (cmd != old_cmd) { | 474 | if (cmd != old_cmd) { |
| 447 | printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); | 475 | printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); |
| 448 | pci_write_config_word(dev, PCI_COMMAND, cmd); | 476 | pci_write_config_word(dev, PCI_COMMAND, cmd); |
