]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
PCI: Setup disabled bridges even if buses are added
authorYuji Shimada <shimada-yxb@necst.nec.co.jp>
Fri, 3 Apr 2009 07:41:46 +0000 (16:41 +0900)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Mon, 6 Apr 2009 18:25:06 +0000 (11:25 -0700)
This patch sets up disabled bridges even if buses have already been
added.

pci_assign_unassigned_resources is called after buses are added.
pci_assign_unassigned_resources calls pci_bus_assign_resources.
pci_bus_assign_resources calls pci_setup_bridge to configure BARs of
bridges.

Currently pci_setup_bridge returns immediately if the bus have already
been added. So pci_assign_unassigned_resources can't configure BARs of
bridges that were added in a disabled state; this patch fixes the issue.

On logical hot-add, we need to prevent the kernel from re-initializing
bridges that have already been initialized. To achieve this,
pci_setup_bridge returns immediately if the bridge have already been
enabled.

We don't need to check whether the specified bus is a root bus or not.
pci_setup_bridge is not called on a root bus, because a root bus does
not have a bridge.

The patch adds a new helper function, pci_is_enabled. I made the
function name similar to pci_is_managed. The codes which use
enable_cnt directly are changed to use pci_is_enabled.

Acked-by: Alex Chiang <achiang@hp.com>
Signed-off-by: Yuji Shimada <shimada-yxb@necst.nec.co.jp>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/pci/bus.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/setup-bus.c
include/linux/pci.h

index 68f91a25259563c6bb7250d8ea3acfd636ad0b29..97a8194063b5d66fd754680a5c94323bec456c8c 100644 (file)
@@ -184,7 +184,7 @@ void pci_enable_bridges(struct pci_bus *bus)
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                if (dev->subordinate) {
-                       if (atomic_read(&dev->enable_cnt) == 0) {
+                       if (!pci_is_enabled(dev)) {
                                retval = pci_enable_device(dev);
                                pci_set_master(dev);
                        }
index e9a8706a640182de0da0257cf2d82b590245eaf5..cd8e682c04aa0636c47c2b08b821a445a1d09994 100644 (file)
@@ -148,7 +148,7 @@ static ssize_t is_enabled_store(struct device *dev,
                return -EPERM;
 
        if (!val) {
-               if (atomic_read(&pdev->enable_cnt) != 0)
+               if (pci_is_enabled(pdev))
                        pci_disable_device(pdev);
                else
                        result = -EIO;
index 445fb6f7ea3fa01dc79beabc6d5685c48fa064fe..16fd0d4c316655dbcfb8729f82a9aef5cabb7e8c 100644 (file)
@@ -844,7 +844,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
  */
 int pci_reenable_device(struct pci_dev *dev)
 {
-       if (atomic_read(&dev->enable_cnt))
+       if (pci_is_enabled(dev))
                return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
        return 0;
 }
@@ -1042,7 +1042,7 @@ static void do_pci_disable_device(struct pci_dev *dev)
  */
 void pci_disable_enabled_device(struct pci_dev *dev)
 {
-       if (atomic_read(&dev->enable_cnt))
+       if (pci_is_enabled(dev))
                do_pci_disable_device(dev);
 }
 
index 334285a8e23760f7b36eda595e9ef7aa0da0ecf4..8d9da9d30a61ffcd058c352f22cc6baab8f9e9a4 100644 (file)
@@ -144,7 +144,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
        struct pci_bus_region region;
        u32 l, bu, lu, io_upper16;
 
-       if (!pci_is_root_bus(bus) && bus->is_added)
+       if (pci_is_enabled(bridge))
                return;
 
        dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
index a7fe4bbd7ff1f7be9eb28952bffd8802c55e6ff8..72698d89e767c76909fb0b4cdb65f292c93e0b76 100644 (file)
@@ -674,6 +674,11 @@ int __must_check pci_reenable_device(struct pci_dev *);
 int __must_check pcim_enable_device(struct pci_dev *pdev);
 void pcim_pin_device(struct pci_dev *pdev);
 
+static inline int pci_is_enabled(struct pci_dev *pdev)
+{
+       return (atomic_read(&pdev->enable_cnt) > 0);
+}
+
 static inline int pci_is_managed(struct pci_dev *pdev)
 {
        return pdev->is_managed;