diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index c419554d0b4b..460d046ab6fe 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -3199,7 +3199,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) | |||
3199 | { | 3199 | { |
3200 | u16 csr; | 3200 | u16 csr; |
3201 | 3201 | ||
3202 | if (!dev->pm_cap) | 3202 | if (!dev->pm_cap || dev->dev_flags & PCI_DEV_FLAGS_NO_PM_RESET) |
3203 | return -ENOTTY; | 3203 | return -ENOTTY; |
3204 | 3204 | ||
3205 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr); | 3205 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr); |
@@ -3273,7 +3273,8 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) | |||
3273 | { | 3273 | { |
3274 | struct pci_dev *pdev; | 3274 | struct pci_dev *pdev; |
3275 | 3275 | ||
3276 | if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self) | 3276 | if (pci_is_root_bus(dev->bus) || dev->subordinate || |
3277 | !dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) | ||
3277 | return -ENOTTY; | 3278 | return -ENOTTY; |
3278 | 3279 | ||
3279 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | 3280 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) |
@@ -3307,7 +3308,8 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe) | |||
3307 | { | 3308 | { |
3308 | struct pci_dev *pdev; | 3309 | struct pci_dev *pdev; |
3309 | 3310 | ||
3310 | if (dev->subordinate || !dev->slot) | 3311 | if (dev->subordinate || !dev->slot || |
3312 | dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET) | ||
3311 | return -ENOTTY; | 3313 | return -ENOTTY; |
3312 | 3314 | ||
3313 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | 3315 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) |
@@ -3559,6 +3561,20 @@ int pci_try_reset_function(struct pci_dev *dev) | |||
3559 | } | 3561 | } |
3560 | EXPORT_SYMBOL_GPL(pci_try_reset_function); | 3562 | EXPORT_SYMBOL_GPL(pci_try_reset_function); |
3561 | 3563 | ||
3564 | /* Do any devices on or below this bus prevent a bus reset? */ | ||
3565 | static bool pci_bus_resetable(struct pci_bus *bus) | ||
3566 | { | ||
3567 | struct pci_dev *dev; | ||
3568 | |||
3569 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
3570 | if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || | ||
3571 | (dev->subordinate && !pci_bus_resetable(dev->subordinate))) | ||
3572 | return false; | ||
3573 | } | ||
3574 | |||
3575 | return true; | ||
3576 | } | ||
3577 | |||
3562 | /* Lock devices from the top of the tree down */ | 3578 | /* Lock devices from the top of the tree down */ |
3563 | static void pci_bus_lock(struct pci_bus *bus) | 3579 | static void pci_bus_lock(struct pci_bus *bus) |
3564 | { | 3580 | { |
@@ -3609,6 +3625,22 @@ unlock: | |||
3609 | return 0; | 3625 | return 0; |
3610 | } | 3626 | } |
3611 | 3627 | ||
3628 | /* Do any devices on or below this slot prevent a bus reset? */ | ||
3629 | static bool pci_slot_resetable(struct pci_slot *slot) | ||
3630 | { | ||
3631 | struct pci_dev *dev; | ||
3632 | |||
3633 | list_for_each_entry(dev, &slot->bus->devices, bus_list) { | ||
3634 | if (!dev->slot || dev->slot != slot) | ||
3635 | continue; | ||
3636 | if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET || | ||
3637 | (dev->subordinate && !pci_bus_resetable(dev->subordinate))) | ||
3638 | return false; | ||
3639 | } | ||
3640 | |||
3641 | return true; | ||
3642 | } | ||
3643 | |||
3612 | /* Lock devices from the top of the tree down */ | 3644 | /* Lock devices from the top of the tree down */ |
3613 | static void pci_slot_lock(struct pci_slot *slot) | 3645 | static void pci_slot_lock(struct pci_slot *slot) |
3614 | { | 3646 | { |
@@ -3730,7 +3762,7 @@ static int pci_slot_reset(struct pci_slot *slot, int probe) | |||
3730 | { | 3762 | { |
3731 | int rc; | 3763 | int rc; |
3732 | 3764 | ||
3733 | if (!slot) | 3765 | if (!slot || !pci_slot_resetable(slot)) |
3734 | return -ENOTTY; | 3766 | return -ENOTTY; |
3735 | 3767 | ||
3736 | if (!probe) | 3768 | if (!probe) |
@@ -3822,7 +3854,7 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot); | |||
3822 | 3854 | ||
3823 | static int pci_bus_reset(struct pci_bus *bus, int probe) | 3855 | static int pci_bus_reset(struct pci_bus *bus, int probe) |
3824 | { | 3856 | { |
3825 | if (!bus->self) | 3857 | if (!bus->self || !pci_bus_resetable(bus)) |
3826 | return -ENOTTY; | 3858 | return -ENOTTY; |
3827 | 3859 | ||
3828 | if (probe) | 3860 | if (probe) |