diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2008-03-04 11:56:47 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-04-20 21:47:04 -0700 |
commit | 842de40d93e00a5c40a1a7f520a6fbe422994e99 (patch) | |
tree | ec59fd64804a4f5cde40f5edf43fabd5ddb3c413 /drivers/pci/setup-res.c | |
parent | 7d715a6c1ae5785d00fb9a876b5abdfc43abc44b (diff) | |
download | op-kernel-dev-842de40d93e00a5c40a1a7f520a6fbe422994e99.zip op-kernel-dev-842de40d93e00a5c40a1a7f520a6fbe422994e99.tar.gz |
PCI: add generic pci_enable_resources()
Each architecture has its own pcibios_enable_resources() implementation.
These differ in many minor ways that have nothing to do with actual
architectural differences. Follow-on patches will make most arches
use this generic version instead.
This version is based on powerpc, which seemed most up-to-date. The only
functional difference from the x86 version is that this uses "!r->parent"
to check for resource collisions instead of "!r->start && r->end".
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/setup-res.c')
-rw-r--r-- | drivers/pci/setup-res.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 9e4d485..bad509e 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -263,3 +263,46 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) } } } + +int pci_enable_resources(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int i; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + if (!(mask & (1 << i))) + continue; + + r = &dev->resource[i]; + + if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) + continue; + if ((i == PCI_ROM_RESOURCE) && + (!(r->flags & IORESOURCE_ROM_ENABLE))) + continue; + + if (!r->parent) { + dev_err(&dev->dev, "device not available because of " + "BAR %d [%llx:%llx] collisions\n", i, + (unsigned long long) r->start, + (unsigned long long) r->end); + return -EINVAL; + } + + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + + if (cmd != old_cmd) { + dev_info(&dev->dev, "enabling device (%04x -> %04x)\n", + old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} |