]> xenbits.xensource.com Git - people/ssmith/nc2-2.6.27.git/commitdiff
patch pci-ignore
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Tue, 30 Jun 2009 11:55:48 +0000 (12:55 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Tue, 30 Jun 2009 11:55:48 +0000 (12:55 +0100)
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c

index 1964c670cf7c98d666d46b8f7d58a35a10d30b85..cf0a00cbd55a4736432114243d4edcd0570ac073 100644 (file)
@@ -23,6 +23,9 @@
 
 unsigned int pci_pm_d3_delay = 10;
 
+struct pci_ignore pci_ignore_list[512] __devinitdata = {{-1,-1,-1},};
+int pci_ignore_count __devinitdata = 0;
+
 #ifdef CONFIG_PCI_DOMAINS
 int pci_domains_supported = 1;
 #endif
@@ -1927,6 +1930,33 @@ static int __devinit pci_init(void)
        return 0;
 }
 
+static int __devinit pci_ignore(char *str)
+{
+       unsigned int bus = -1u, dev = -1u, fn = -1u;
+       int fields;
+
+       fields = sscanf(str, "ignore-%x-%x-%x", &bus, &dev, &fn);
+       if (fields < 1 || fields > 3) 
+               return 0;
+
+       if (pci_ignore_count >= 512) 
+               return 0;
+
+       printk(KERN_INFO "PCI: Ignoring %2.2x", bus);
+       if (dev != -1u)
+               printk(".%2.2x", dev);
+       if (fn != -1u)
+               printk(".%2.2x", dev);
+       printk("\n");
+
+       pci_ignore_list[pci_ignore_count].bus = bus;
+       pci_ignore_list[pci_ignore_count].dev = dev;
+       pci_ignore_list[pci_ignore_count].fn = fn;
+       pci_ignore_count++;
+
+       return 1;
+}
+
 static int __devinit pci_setup(char *str)
 {
        while (str) {
@@ -1944,7 +1974,7 @@ static int __devinit pci_setup(char *str)
                                pci_cardbus_io_size = memparse(str + 9, &str);
                        } else if (!strncmp(str, "cbmemsize=", 10)) {
                                pci_cardbus_mem_size = memparse(str + 10, &str);
-                       } else {
+                       } else if (!pci_ignore(str)) {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);
                        }
index 9b7f9cc3fa9f1d58695f90b9d85b24e44fdef98b..b7a59d7afc5286cbfdd88484fbc678c577c22f9d 100644 (file)
@@ -131,6 +131,31 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
        return NULL;
 }
 
+/* Linked list of pci bus/dev/fn combinations not to touch */
+struct pci_ignore {
+       unsigned int bus, dev, fn; /* what to ignore; -1u means wildcard */
+};
+
+extern struct pci_ignore pci_ignore_list[];
+extern int pci_ignore_count;
+
+static inline int __devinit pci_ignore_chk(unsigned int bus, 
+                                          unsigned int dev, 
+                                          unsigned int fn)
+{
+       int i;
+       struct pci_ignore *ig = pci_ignore_list;
+       for (i = 0; i < pci_ignore_count; i++)
+               if (ig[i].bus == bus 
+                   && (ig[i].dev == dev || ig[i].dev == -1u)
+                   && (ig[i].fn == fn || ig[i].fn == -1u))
+                       return 1;
+       return 0;
+}
+
+#define pci_ignore_bus(_b)     pci_ignore_chk((_b), -1u, -1u)
+#define pci_ignore_dev(_b, _d) pci_ignore_chk((_b), (_d), -1u)
+#define pci_ignore_fn(_b, _f)  pci_ignore_chk((_b), PCI_SLOT(_f), PCI_FUNC(_f))
 struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev);
 
 /* PCI slot sysfs helper code */
index eb6c8d159e54dc7244dd621f990daa0addfcb79a..f12de80e7ce6506dc6c1f4fdb38622de3b85e7a5 100644 (file)
@@ -955,6 +955,13 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
        u8 hdr_type;
        int delay = 1;
 
+       if (pci_ignore_fn(bus->number, devfn)) {
+               pr_debug("PCI: skipping dev/fn %04x:%02x:%02x:%02x\n",
+                        pci_domain_nr(bus), bus->number,
+                        PCI_SLOT(devfn), PCI_SLOT(devfn));
+               return NULL;
+       }
+
        if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
                return NULL;
 
@@ -1071,6 +1078,12 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
        int func, nr = 0;
        int scan_all_fns;
 
+       if (pci_ignore_dev(bus->number, PCI_SLOT(devfn))) {
+               pr_debug("PCI: skipping dev %04x:%02x:%02x\n",
+                        pci_domain_nr(bus), bus->number, PCI_SLOT(devfn));
+               return nr;
+       }
+
        scan_all_fns = pcibios_scan_all_fns(bus, devfn);
 
        for (func = 0; func < 8; func++, devfn++) {
@@ -1109,6 +1122,12 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
        unsigned int devfn, pass, max = bus->secondary;
        struct pci_dev *dev;
 
+       if (pci_ignore_bus(bus->number)) {
+               pr_debug("PCI: skipping bus %04x:%02x\n",
+                        pci_domain_nr(bus), bus->number);
+               return max;
+       }
+
        pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(bus), bus->number);
 
        /* Go find them, Rover! */