|
@@ -3271,7 +3271,8 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
|
|
|
{
|
|
|
struct pci_dev *pdev;
|
|
|
|
|
|
- if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self)
|
|
|
+ if (pci_is_root_bus(dev->bus) || dev->subordinate ||
|
|
|
+ !dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
|
|
|
return -ENOTTY;
|
|
|
|
|
|
list_for_each_entry(pdev, &dev->bus->devices, bus_list)
|
|
@@ -3305,7 +3306,8 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
|
|
|
{
|
|
|
struct pci_dev *pdev;
|
|
|
|
|
|
- if (dev->subordinate || !dev->slot)
|
|
|
+ if (dev->subordinate || !dev->slot ||
|
|
|
+ dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
|
|
|
return -ENOTTY;
|
|
|
|
|
|
list_for_each_entry(pdev, &dev->bus->devices, bus_list)
|
|
@@ -3557,6 +3559,20 @@ int pci_try_reset_function(struct pci_dev *dev)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(pci_try_reset_function);
|
|
|
|
|
|
+/* Do any devices on or below this bus prevent a bus reset? */
|
|
|
+static bool pci_bus_resetable(struct pci_bus *bus)
|
|
|
+{
|
|
|
+ struct pci_dev *dev;
|
|
|
+
|
|
|
+ list_for_each_entry(dev, &bus->devices, bus_list) {
|
|
|
+ if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
|
|
|
+ (dev->subordinate && !pci_bus_resetable(dev->subordinate)))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
/* Lock devices from the top of the tree down */
|
|
|
static void pci_bus_lock(struct pci_bus *bus)
|
|
|
{
|
|
@@ -3607,6 +3623,22 @@ unlock:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/* Do any devices on or below this slot prevent a bus reset? */
|
|
|
+static bool pci_slot_resetable(struct pci_slot *slot)
|
|
|
+{
|
|
|
+ struct pci_dev *dev;
|
|
|
+
|
|
|
+ list_for_each_entry(dev, &slot->bus->devices, bus_list) {
|
|
|
+ if (!dev->slot || dev->slot != slot)
|
|
|
+ continue;
|
|
|
+ if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
|
|
|
+ (dev->subordinate && !pci_bus_resetable(dev->subordinate)))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
/* Lock devices from the top of the tree down */
|
|
|
static void pci_slot_lock(struct pci_slot *slot)
|
|
|
{
|
|
@@ -3728,7 +3760,7 @@ static int pci_slot_reset(struct pci_slot *slot, int probe)
|
|
|
{
|
|
|
int rc;
|
|
|
|
|
|
- if (!slot)
|
|
|
+ if (!slot || !pci_slot_resetable(slot))
|
|
|
return -ENOTTY;
|
|
|
|
|
|
if (!probe)
|
|
@@ -3820,7 +3852,7 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot);
|
|
|
|
|
|
static int pci_bus_reset(struct pci_bus *bus, int probe)
|
|
|
{
|
|
|
- if (!bus->self)
|
|
|
+ if (!bus->self || !pci_bus_resetable(bus))
|
|
|
return -ENOTTY;
|
|
|
|
|
|
if (probe)
|