Skip to content

Commit 6228133

Browse files
committed
Merge branch 'pci/reset'
- Warn about doing a Secondary Bus Reset without holding the device lock (Dan Williams) - Lock bridge in addition to downstream hierarchy before doing a Secondary Bus Reset (Dan Williams) * pci/reset: PCI: Add missing bridge lock to pci_bus_lock() PCI: Warn on missing cfg_access_lock during secondary bus reset
2 parents 675ba77 + a4e7728 commit 6228133

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

drivers/pci/pci.c

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4954,6 +4954,9 @@ void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
49544954
int pci_bridge_secondary_bus_reset(struct pci_dev *dev)
49554955
{
49564956
lock_map_assert_held(&dev->cfg_access_lock);
4957+
if (!dev->block_cfg_access)
4958+
pci_warn_once(dev, "unlocked secondary bus reset via: %pS\n",
4959+
__builtin_return_address(0));
49574960
pcibios_reset_secondary_bus(dev);
49584961

49594962
return pci_bridge_wait_for_secondary_bus(dev, "bus reset");
@@ -5512,10 +5515,12 @@ static void pci_bus_lock(struct pci_bus *bus)
55125515
{
55135516
struct pci_dev *dev;
55145517

5518+
pci_dev_lock(bus->self);
55155519
list_for_each_entry(dev, &bus->devices, bus_list) {
5516-
pci_dev_lock(dev);
55175520
if (dev->subordinate)
55185521
pci_bus_lock(dev->subordinate);
5522+
else
5523+
pci_dev_lock(dev);
55195524
}
55205525
}
55215526

@@ -5527,33 +5532,37 @@ static void pci_bus_unlock(struct pci_bus *bus)
55275532
list_for_each_entry(dev, &bus->devices, bus_list) {
55285533
if (dev->subordinate)
55295534
pci_bus_unlock(dev->subordinate);
5530-
pci_dev_unlock(dev);
5535+
else
5536+
pci_dev_unlock(dev);
55315537
}
5538+
pci_dev_unlock(bus->self);
55325539
}
55335540

55345541
/* Return 1 on successful lock, 0 on contention */
55355542
static int pci_bus_trylock(struct pci_bus *bus)
55365543
{
55375544
struct pci_dev *dev;
55385545

5546+
if (!pci_dev_trylock(bus->self))
5547+
return 0;
5548+
55395549
list_for_each_entry(dev, &bus->devices, bus_list) {
5540-
if (!pci_dev_trylock(dev))
5541-
goto unlock;
55425550
if (dev->subordinate) {
5543-
if (!pci_bus_trylock(dev->subordinate)) {
5544-
pci_dev_unlock(dev);
5551+
if (!pci_bus_trylock(dev->subordinate))
55455552
goto unlock;
5546-
}
5547-
}
5553+
} else if (!pci_dev_trylock(dev))
5554+
goto unlock;
55485555
}
55495556
return 1;
55505557

55515558
unlock:
55525559
list_for_each_entry_continue_reverse(dev, &bus->devices, bus_list) {
55535560
if (dev->subordinate)
55545561
pci_bus_unlock(dev->subordinate);
5555-
pci_dev_unlock(dev);
5562+
else
5563+
pci_dev_unlock(dev);
55565564
}
5565+
pci_dev_unlock(bus->self);
55575566
return 0;
55585567
}
55595568

@@ -5585,9 +5594,10 @@ static void pci_slot_lock(struct pci_slot *slot)
55855594
list_for_each_entry(dev, &slot->bus->devices, bus_list) {
55865595
if (!dev->slot || dev->slot != slot)
55875596
continue;
5588-
pci_dev_lock(dev);
55895597
if (dev->subordinate)
55905598
pci_bus_lock(dev->subordinate);
5599+
else
5600+
pci_dev_lock(dev);
55915601
}
55925602
}
55935603

@@ -5613,14 +5623,13 @@ static int pci_slot_trylock(struct pci_slot *slot)
56135623
list_for_each_entry(dev, &slot->bus->devices, bus_list) {
56145624
if (!dev->slot || dev->slot != slot)
56155625
continue;
5616-
if (!pci_dev_trylock(dev))
5617-
goto unlock;
56185626
if (dev->subordinate) {
56195627
if (!pci_bus_trylock(dev->subordinate)) {
56205628
pci_dev_unlock(dev);
56215629
goto unlock;
56225630
}
5623-
}
5631+
} else if (!pci_dev_trylock(dev))
5632+
goto unlock;
56245633
}
56255634
return 1;
56265635

@@ -5631,7 +5640,8 @@ static int pci_slot_trylock(struct pci_slot *slot)
56315640
continue;
56325641
if (dev->subordinate)
56335642
pci_bus_unlock(dev->subordinate);
5634-
pci_dev_unlock(dev);
5643+
else
5644+
pci_dev_unlock(dev);
56355645
}
56365646
return 0;
56375647
}

0 commit comments

Comments
 (0)