PCI: add busn_res operation functions
authorYinghai Lu <yinghai@kernel.org>
Fri, 18 May 2012 17:35:50 +0000 (11:35 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 13 Jun 2012 21:42:22 +0000 (15:42 -0600)
Will use them insert/update busn res in pci_bus struct.

[bhelgaas: print conflicting entry if insertion fails]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/probe.c
include/linux/pci.h

index 674a477a64864cc9b28e2f0089ece04fe718d169..7662ab7b2640a5167ecc89bded0ef2adbb35ccd5 100644 (file)
@@ -1714,6 +1714,74 @@ err_out:
        return NULL;
 }
 
+int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
+{
+       struct resource *res = &b->busn_res;
+       struct resource *parent_res, *conflict;
+
+       res->start = bus;
+       res->end = bus_max;
+       res->flags = IORESOURCE_BUS;
+
+       if (!pci_is_root_bus(b))
+               parent_res = &b->parent->busn_res;
+       else {
+               parent_res = get_pci_domain_busn_res(pci_domain_nr(b));
+               res->flags |= IORESOURCE_PCI_FIXED;
+       }
+
+       conflict = insert_resource_conflict(parent_res, res);
+
+       if (conflict)
+               dev_printk(KERN_DEBUG, &b->dev,
+                          "busn_res: can not insert %pR under %s%pR (conflicts with %s %pR)\n",
+                           res, pci_is_root_bus(b) ? "domain " : "",
+                           parent_res, conflict->name, conflict);
+       else
+               dev_printk(KERN_DEBUG, &b->dev,
+                          "busn_res: %pR is inserted under %s%pR\n",
+                          res, pci_is_root_bus(b) ? "domain " : "",
+                          parent_res);
+
+       return conflict == NULL;
+}
+
+int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
+{
+       struct resource *res = &b->busn_res;
+       struct resource old_res = *res;
+       resource_size_t size;
+       int ret;
+
+       if (res->start > bus_max)
+               return -EINVAL;
+
+       size = bus_max - res->start + 1;
+       ret = adjust_resource(res, res->start, size);
+       dev_printk(KERN_DEBUG, &b->dev,
+                       "busn_res: %pR end %s updated to %02x\n",
+                       &old_res, ret ? "can not be" : "is", bus_max);
+
+       if (!ret && !res->parent)
+               pci_bus_insert_busn_res(b, res->start, res->end);
+
+       return ret;
+}
+
+void pci_bus_release_busn_res(struct pci_bus *b)
+{
+       struct resource *res = &b->busn_res;
+       int ret;
+
+       if (!res->flags || !res->parent)
+               return;
+
+       ret = release_resource(res);
+       dev_printk(KERN_DEBUG, &b->dev,
+                       "busn_res: %pR %s released\n",
+                       res, ret ? "can not be" : "is");
+}
+
 struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
                struct pci_ops *ops, void *sysdata, struct list_head *resources)
 {
index 6b10966cd1b914733f34214cb6fc6a3a82b8ae1f..c4df570f3bbb9392a7d5a085cf88c484cc0b9a3a 100644 (file)
@@ -667,6 +667,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
 struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
                                    struct pci_ops *ops, void *sysdata,
                                    struct list_head *resources);
+int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
+int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
+void pci_bus_release_busn_res(struct pci_bus *b);
 struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
                                             struct pci_ops *ops, void *sysdata,
                                             struct list_head *resources);