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>
This commit is contained in:
Родитель
7eb93b175d
Коммит
296ccb086d
|
@ -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,
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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 *);
|
||||||
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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче