PCI: add generic pci_enable_resources()
authorBjorn Helgaas <bjorn.helgaas@hp.com>
Tue, 4 Mar 2008 18:56:47 +0000 (11:56 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 21 Apr 2008 04:47:04 +0000 (21:47 -0700)
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>
drivers/pci/setup-res.c
include/linux/pci.h

index 9e4d485ba9cd1ee28a769dd10da934fc26408569..bad509e40fbc7f8f01920025cd5f8528aad2b59f 100644 (file)
@@ -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;
+}
index 14bf3d236d1943e7afd9a34ae6783a1af09b047b..e2f46b05cf8be4ff5eddbb5a76f28272d54520ea 100644 (file)
@@ -624,6 +624,7 @@ int pci_claim_resource(struct pci_dev *, int);
 void pci_assign_unassigned_resources(void);
 void pdev_enable_device(struct pci_dev *);
 void pdev_sort_resources(struct pci_dev *, struct resource_list *);
+int pci_enable_resources(struct pci_dev *, int mask);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
                    int (*)(struct pci_dev *, u8, u8));
 #define HAVE_PCI_REQ_REGIONS   2