Commit 296ccb08 authored by Yuji Shimada's avatar Yuji Shimada Committed by Jesse Barnes

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: default avatarAlex Chiang <achiang@hp.com>
Signed-off-by: default avatarYuji Shimada <shimada-yxb@necst.nec.co.jp>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 7eb93b17
...@@ -184,7 +184,7 @@ void pci_enable_bridges(struct pci_bus *bus) ...@@ -184,7 +184,7 @@ void pci_enable_bridges(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->subordinate) { if (dev->subordinate) {
if (atomic_read(&dev->enable_cnt) == 0) { if (!pci_is_enabled(dev)) {
retval = pci_enable_device(dev); retval = pci_enable_device(dev);
pci_set_master(dev); pci_set_master(dev);
} }
......
...@@ -148,7 +148,7 @@ static ssize_t is_enabled_store(struct device *dev, ...@@ -148,7 +148,7 @@ static ssize_t is_enabled_store(struct device *dev,
return -EPERM; return -EPERM;
if (!val) { if (!val) {
if (atomic_read(&pdev->enable_cnt) != 0) if (pci_is_enabled(pdev))
pci_disable_device(pdev); pci_disable_device(pdev);
else else
result = -EIO; result = -EIO;
......
...@@ -844,7 +844,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars) ...@@ -844,7 +844,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
*/ */
int pci_reenable_device(struct pci_dev *dev) 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 do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
return 0; return 0;
} }
...@@ -1042,7 +1042,7 @@ static void do_pci_disable_device(struct pci_dev *dev) ...@@ -1042,7 +1042,7 @@ static void do_pci_disable_device(struct pci_dev *dev)
*/ */
void pci_disable_enabled_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); do_pci_disable_device(dev);
} }
......
...@@ -144,7 +144,7 @@ static void pci_setup_bridge(struct pci_bus *bus) ...@@ -144,7 +144,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
struct pci_bus_region region; struct pci_bus_region region;
u32 l, bu, lu, io_upper16; u32 l, bu, lu, io_upper16;
if (!pci_is_root_bus(bus) && bus->is_added) if (pci_is_enabled(bridge))
return; return;
dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n", dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
......
...@@ -674,6 +674,11 @@ int __must_check pci_reenable_device(struct pci_dev *); ...@@ -674,6 +674,11 @@ int __must_check pci_reenable_device(struct pci_dev *);
int __must_check pcim_enable_device(struct pci_dev *pdev); int __must_check pcim_enable_device(struct pci_dev *pdev);
void pcim_pin_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) static inline int pci_is_managed(struct pci_dev *pdev)
{ {
return pdev->is_managed; return pdev->is_managed;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment