aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuji Shimada <shimada-yxb@necst.nec.co.jp>2009-04-03 03:41:46 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-04-06 14:25:06 -0400
commit296ccb086dfb89b5b8d73ef08c795ffdff12a597 (patch)
tree8c4ef0f0271e448b6843811a1bcded8c47c005a1
parent7eb93b175d4de9438a4b0af3a94a112cb5266944 (diff)
PCI: Setup disabled bridges even if buses are added
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>
-rw-r--r--drivers/pci/bus.c2
-rw-r--r--drivers/pci/pci-sysfs.c2
-rw-r--r--drivers/pci/pci.c4
-rw-r--r--drivers/pci/setup-bus.c2
-rw-r--r--include/linux/pci.h5
5 files changed, 10 insertions, 5 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 68f91a252595..97a8194063b5 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -184,7 +184,7 @@ void pci_enable_bridges(struct pci_bus *bus)
184 184
185 list_for_each_entry(dev, &bus->devices, bus_list) { 185 list_for_each_entry(dev, &bus->devices, bus_list) {
186 if (dev->subordinate) { 186 if (dev->subordinate) {
187 if (atomic_read(&dev->enable_cnt) == 0) { 187 if (!pci_is_enabled(dev)) {
188 retval = pci_enable_device(dev); 188 retval = pci_enable_device(dev);
189 pci_set_master(dev); 189 pci_set_master(dev);
190 } 190 }
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index e9a8706a6401..cd8e682c04aa 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -148,7 +148,7 @@ static ssize_t is_enabled_store(struct device *dev,
148 return -EPERM; 148 return -EPERM;
149 149
150 if (!val) { 150 if (!val) {
151 if (atomic_read(&pdev->enable_cnt) != 0) 151 if (pci_is_enabled(pdev))
152 pci_disable_device(pdev); 152 pci_disable_device(pdev);
153 else 153 else
154 result = -EIO; 154 result = -EIO;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 445fb6f7ea3f..16fd0d4c3166 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -844,7 +844,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
844 */ 844 */
845int pci_reenable_device(struct pci_dev *dev) 845int pci_reenable_device(struct pci_dev *dev)
846{ 846{
847 if (atomic_read(&dev->enable_cnt)) 847 if (pci_is_enabled(dev))
848 return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1); 848 return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
849 return 0; 849 return 0;
850} 850}
@@ -1042,7 +1042,7 @@ static void do_pci_disable_device(struct pci_dev *dev)
1042 */ 1042 */
1043void pci_disable_enabled_device(struct pci_dev *dev) 1043void pci_disable_enabled_device(struct pci_dev *dev)
1044{ 1044{
1045 if (atomic_read(&dev->enable_cnt)) 1045 if (pci_is_enabled(dev))
1046 do_pci_disable_device(dev); 1046 do_pci_disable_device(dev);
1047} 1047}
1048 1048
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 334285a8e237..8d9da9d30a61 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -144,7 +144,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
144 struct pci_bus_region region; 144 struct pci_bus_region region;
145 u32 l, bu, lu, io_upper16; 145 u32 l, bu, lu, io_upper16;
146 146
147 if (!pci_is_root_bus(bus) && bus->is_added) 147 if (pci_is_enabled(bridge))
148 return; 148 return;
149 149
150 dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n", 150 dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a7fe4bbd7ff1..72698d89e767 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -674,6 +674,11 @@ int __must_check pci_reenable_device(struct pci_dev *);
674int __must_check pcim_enable_device(struct pci_dev *pdev); 674int __must_check pcim_enable_device(struct pci_dev *pdev);
675void pcim_pin_device(struct pci_dev *pdev); 675void pcim_pin_device(struct pci_dev *pdev);
676 676
677static inline int pci_is_enabled(struct pci_dev *pdev)
678{
679 return (atomic_read(&pdev->enable_cnt) > 0);
680}
681
677static inline int pci_is_managed(struct pci_dev *pdev) 682static inline int pci_is_managed(struct pci_dev *pdev)
678{ 683{
679 return pdev->is_managed; 684 return pdev->is_managed;