Re: [PATCH v2] PCI: merge slot and bus reset implementations

From: Bjorn Helgaas
Date: Mon May 24 2021 - 18:31:15 EST


On Thu, Apr 08, 2021 at 06:23:40PM +0000, Raphael Norwitz wrote:
> Slot resets are bus resets with additional logic to prevent a device
> from being removed during the reset. Currently slot and bus resets have
> separate implementations in pci.c, complicating higher level logic. As
> discussed on the mailing list, they should be combined into a generic
> function which performs an SBR. This change adds a function,
> pci_reset_bus_function(), which first attempts a slot reset and then
> attempts a bus reset if -ENOTTY is returned, such that there is now a
> single device agnostic function to perform an SBR.
>
> This new function is also needed to add SBR reset quirks and therefore
> is exposed in pci.h.

I dropped this exposure in pci.h because there's no user yet. We can
expose it when we add the user.

> Link: https://lkml.org/lkml/2021/3/23/911
>
> Suggested-by: Alex Williamson <alex.williamson@xxxxxxxxxx>
> Signed-off-by: Amey Narkhede <ameynarkhede03@xxxxxxxxx>
> Signed-off-by: Raphael Norwitz <raphael.norwitz@xxxxxxxxxxx>

Applied to pci/reset for v5.14 with subject
"PCI: Add pci_reset_bus_function() Secondary Bus Reset interface"

I attached the patch as applied.

> ---
> drivers/pci/pci.c | 19 +++++++++++--------
> include/linux/pci.h | 1 +
> 2 files changed, 12 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 16a17215f633..a8f8dd588d15 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -4982,6 +4982,15 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
> return pci_reset_hotplug_slot(dev->slot->hotplug, probe);
> }
>
> +int pci_reset_bus_function(struct pci_dev *dev, int probe)
> +{
> + int rc = pci_dev_reset_slot_function(dev, probe);
> +
> + if (rc != -ENOTTY)
> + return rc;
> + return pci_parent_bus_reset(dev, probe);
> +}
> +
> static void pci_dev_lock(struct pci_dev *dev)
> {
> pci_cfg_access_lock(dev);
> @@ -5102,10 +5111,7 @@ int __pci_reset_function_locked(struct pci_dev *dev)
> rc = pci_pm_reset(dev, 0);
> if (rc != -ENOTTY)
> return rc;
> - rc = pci_dev_reset_slot_function(dev, 0);
> - if (rc != -ENOTTY)
> - return rc;
> - return pci_parent_bus_reset(dev, 0);
> + return pci_reset_bus_function(dev, 0);
> }
> EXPORT_SYMBOL_GPL(__pci_reset_function_locked);
>
> @@ -5135,13 +5141,10 @@ int pci_probe_reset_function(struct pci_dev *dev)
> if (rc != -ENOTTY)
> return rc;
> rc = pci_pm_reset(dev, 1);
> - if (rc != -ENOTTY)
> - return rc;
> - rc = pci_dev_reset_slot_function(dev, 1);
> if (rc != -ENOTTY)
> return rc;
>
> - return pci_parent_bus_reset(dev, 1);
> + return pci_reset_bus_function(dev, 1);
> }
>
> /**
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 86c799c97b77..979d54335ac1 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1228,6 +1228,7 @@ int pci_probe_reset_bus(struct pci_bus *bus);
> int pci_reset_bus(struct pci_dev *dev);
> void pci_reset_secondary_bus(struct pci_dev *dev);
> void pcibios_reset_secondary_bus(struct pci_dev *dev);
> +int pci_reset_bus_function(struct pci_dev *dev, int probe);
> void pci_update_resource(struct pci_dev *dev, int resno);
> int __must_check pci_assign_resource(struct pci_dev *dev, int i);
> int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align);
> --
> 2.20.1

commit 0dad3ce523c2 ("PCI: Add pci_reset_bus_function() Secondary Bus Reset interface")
Author: Raphael Norwitz <raphael.norwitz@xxxxxxxxxxx>
Date: Thu Apr 8 18:23:40 2021 +0000

PCI: Add pci_reset_bus_function() Secondary Bus Reset interface

pci_parent_bus_reset() resets a device by performing a Secondary Bus Reset
on a PCI-to-PCI bridge leading to the device.

pci_dev_reset_slot_function() does the same, except that it uses a hotplug
driver to keep the reset from looking like a hot-remove followed by a
hot-add.

Add a pci_reset_bus_function() wrapper, which attempts the hotplug driver
slot reset and falls back to the parent bus reset if that fails. This
provides a single interface for performing a Secondary Bus Reset.

[bhelgaas: commit log, don't expose yet]
Suggested-by: Alex Williamson <alex.williamson@xxxxxxxxxx>
Link: https://lore.kernel.org/r/20210323100625.0021a943@xxxxxxxxxxxxxxxxxxxxx/
Link: https://lore.kernel.org/r/20210408182328.12323-1-raphael.norwitz@xxxxxxxxxxx
Signed-off-by: Amey Narkhede <ameynarkhede03@xxxxxxxxx>
Signed-off-by: Raphael Norwitz <raphael.norwitz@xxxxxxxxxxx>
Signed-off-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>
Reviewed-by: Leon Romanovsky <leonro@xxxxxxxxxx>

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b717680377a9..452351025a09 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -5020,6 +5020,16 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
return pci_reset_hotplug_slot(dev->slot->hotplug, probe);
}

+static int pci_reset_bus_function(struct pci_dev *dev, int probe)
+{
+ int rc;
+
+ rc = pci_dev_reset_slot_function(dev, probe);
+ if (rc != -ENOTTY)
+ return rc;
+ return pci_parent_bus_reset(dev, probe);
+}
+
static void pci_dev_lock(struct pci_dev *dev)
{
pci_cfg_access_lock(dev);
@@ -5140,10 +5150,7 @@ int __pci_reset_function_locked(struct pci_dev *dev)
rc = pci_pm_reset(dev, 0);
if (rc != -ENOTTY)
return rc;
- rc = pci_dev_reset_slot_function(dev, 0);
- if (rc != -ENOTTY)
- return rc;
- return pci_parent_bus_reset(dev, 0);
+ return pci_reset_bus_function(dev, 0);
}
EXPORT_SYMBOL_GPL(__pci_reset_function_locked);

@@ -5173,13 +5180,10 @@ int pci_probe_reset_function(struct pci_dev *dev)
if (rc != -ENOTTY)
return rc;
rc = pci_pm_reset(dev, 1);
- if (rc != -ENOTTY)
- return rc;
- rc = pci_dev_reset_slot_function(dev, 1);
if (rc != -ENOTTY)
return rc;

- return pci_parent_bus_reset(dev, 1);
+ return pci_reset_bus_function(dev, 1);
}

/**