aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2014-01-15 12:53:35 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-01-15 12:53:35 -0500
commit6e2d98dc1af49a6736cd9c54e2e44b5d5234d242 (patch)
treef17178aad8cc3e721c8da14ad439379a03a488ef /drivers/pci
parent40304618468cae5259f77c15511e4feb7bfb624b (diff)
parent890ed578df82f5b7b5a874f9f2fa4f117305df5f (diff)
Merge branch 'pci/reset' into next
* pci/reset: vfio-pci: Use pci "try" reset interface PCI: Add pci_try_reset_function(), pci_try_reset_slot(), pci_try_reset_bus()
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 95c97bec8018..b6d4afa8ba40 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3250,6 +3250,18 @@ static void pci_dev_lock(struct pci_dev *dev)
3250 device_lock(&dev->dev); 3250 device_lock(&dev->dev);
3251} 3251}
3252 3252
3253/* Return 1 on successful lock, 0 on contention */
3254static int pci_dev_trylock(struct pci_dev *dev)
3255{
3256 if (pci_cfg_access_trylock(dev)) {
3257 if (device_trylock(&dev->dev))
3258 return 1;
3259 pci_cfg_access_unlock(dev);
3260 }
3261
3262 return 0;
3263}
3264
3253static void pci_dev_unlock(struct pci_dev *dev) 3265static void pci_dev_unlock(struct pci_dev *dev)
3254{ 3266{
3255 device_unlock(&dev->dev); 3267 device_unlock(&dev->dev);
@@ -3393,6 +3405,34 @@ int pci_reset_function(struct pci_dev *dev)
3393} 3405}
3394EXPORT_SYMBOL_GPL(pci_reset_function); 3406EXPORT_SYMBOL_GPL(pci_reset_function);
3395 3407
3408/**
3409 * pci_try_reset_function - quiesce and reset a PCI device function
3410 * @dev: PCI device to reset
3411 *
3412 * Same as above, except return -EAGAIN if unable to lock device.
3413 */
3414int pci_try_reset_function(struct pci_dev *dev)
3415{
3416 int rc;
3417
3418 rc = pci_dev_reset(dev, 1);
3419 if (rc)
3420 return rc;
3421
3422 pci_dev_save_and_disable(dev);
3423
3424 if (pci_dev_trylock(dev)) {
3425 rc = __pci_dev_reset(dev, 0);
3426 pci_dev_unlock(dev);
3427 } else
3428 rc = -EAGAIN;
3429
3430 pci_dev_restore(dev);
3431
3432 return rc;
3433}
3434EXPORT_SYMBOL_GPL(pci_try_reset_function);
3435
3396/* Lock devices from the top of the tree down */ 3436/* Lock devices from the top of the tree down */
3397static void pci_bus_lock(struct pci_bus *bus) 3437static void pci_bus_lock(struct pci_bus *bus)
3398{ 3438{
@@ -3417,6 +3457,32 @@ static void pci_bus_unlock(struct pci_bus *bus)
3417 } 3457 }
3418} 3458}
3419 3459
3460/* Return 1 on successful lock, 0 on contention */
3461static int pci_bus_trylock(struct pci_bus *bus)
3462{
3463 struct pci_dev *dev;
3464
3465 list_for_each_entry(dev, &bus->devices, bus_list) {
3466 if (!pci_dev_trylock(dev))
3467 goto unlock;
3468 if (dev->subordinate) {
3469 if (!pci_bus_trylock(dev->subordinate)) {
3470 pci_dev_unlock(dev);
3471 goto unlock;
3472 }
3473 }
3474 }
3475 return 1;
3476
3477unlock:
3478 list_for_each_entry_continue_reverse(dev, &bus->devices, bus_list) {
3479 if (dev->subordinate)
3480 pci_bus_unlock(dev->subordinate);
3481 pci_dev_unlock(dev);
3482 }
3483 return 0;
3484}
3485
3420/* Lock devices from the top of the tree down */ 3486/* Lock devices from the top of the tree down */
3421static void pci_slot_lock(struct pci_slot *slot) 3487static void pci_slot_lock(struct pci_slot *slot)
3422{ 3488{
@@ -3445,6 +3511,37 @@ static void pci_slot_unlock(struct pci_slot *slot)
3445 } 3511 }
3446} 3512}
3447 3513
3514/* Return 1 on successful lock, 0 on contention */
3515static int pci_slot_trylock(struct pci_slot *slot)
3516{
3517 struct pci_dev *dev;
3518
3519 list_for_each_entry(dev, &slot->bus->devices, bus_list) {
3520 if (!dev->slot || dev->slot != slot)
3521 continue;
3522 if (!pci_dev_trylock(dev))
3523 goto unlock;
3524 if (dev->subordinate) {
3525 if (!pci_bus_trylock(dev->subordinate)) {
3526 pci_dev_unlock(dev);
3527 goto unlock;
3528 }
3529 }
3530 }
3531 return 1;
3532
3533unlock:
3534 list_for_each_entry_continue_reverse(dev,
3535 &slot->bus->devices, bus_list) {
3536 if (!dev->slot || dev->slot != slot)
3537 continue;
3538 if (dev->subordinate)
3539 pci_bus_unlock(dev->subordinate);
3540 pci_dev_unlock(dev);
3541 }
3542 return 0;
3543}
3544
3448/* Save and disable devices from the top of the tree down */ 3545/* Save and disable devices from the top of the tree down */
3449static void pci_bus_save_and_disable(struct pci_bus *bus) 3546static void pci_bus_save_and_disable(struct pci_bus *bus)
3450{ 3547{
@@ -3568,6 +3665,35 @@ int pci_reset_slot(struct pci_slot *slot)
3568} 3665}
3569EXPORT_SYMBOL_GPL(pci_reset_slot); 3666EXPORT_SYMBOL_GPL(pci_reset_slot);
3570 3667
3668/**
3669 * pci_try_reset_slot - Try to reset a PCI slot
3670 * @slot: PCI slot to reset
3671 *
3672 * Same as above except return -EAGAIN if the slot cannot be locked
3673 */
3674int pci_try_reset_slot(struct pci_slot *slot)
3675{
3676 int rc;
3677
3678 rc = pci_slot_reset(slot, 1);
3679 if (rc)
3680 return rc;
3681
3682 pci_slot_save_and_disable(slot);
3683
3684 if (pci_slot_trylock(slot)) {
3685 might_sleep();
3686 rc = pci_reset_hotplug_slot(slot->hotplug, 0);
3687 pci_slot_unlock(slot);
3688 } else
3689 rc = -EAGAIN;
3690
3691 pci_slot_restore(slot);
3692
3693 return rc;
3694}
3695EXPORT_SYMBOL_GPL(pci_try_reset_slot);
3696
3571static int pci_bus_reset(struct pci_bus *bus, int probe) 3697static int pci_bus_reset(struct pci_bus *bus, int probe)
3572{ 3698{
3573 if (!bus->self) 3699 if (!bus->self)
@@ -3627,6 +3753,35 @@ int pci_reset_bus(struct pci_bus *bus)
3627EXPORT_SYMBOL_GPL(pci_reset_bus); 3753EXPORT_SYMBOL_GPL(pci_reset_bus);
3628 3754
3629/** 3755/**
3756 * pci_try_reset_bus - Try to reset a PCI bus
3757 * @bus: top level PCI bus to reset
3758 *
3759 * Same as above except return -EAGAIN if the bus cannot be locked
3760 */
3761int pci_try_reset_bus(struct pci_bus *bus)
3762{
3763 int rc;
3764
3765 rc = pci_bus_reset(bus, 1);
3766 if (rc)
3767 return rc;
3768
3769 pci_bus_save_and_disable(bus);
3770
3771 if (pci_bus_trylock(bus)) {
3772 might_sleep();
3773 pci_reset_bridge_secondary_bus(bus->self);
3774 pci_bus_unlock(bus);
3775 } else
3776 rc = -EAGAIN;
3777
3778 pci_bus_restore(bus);
3779
3780 return rc;
3781}
3782EXPORT_SYMBOL_GPL(pci_try_reset_bus);
3783
3784/**
3630 * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count 3785 * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
3631 * @dev: PCI device to query 3786 * @dev: PCI device to query
3632 * 3787 *