[PATCH 1/2] PCI: save and restore device state during bus reset
Bjorn Helgaas
helgaas at kernel.org
Tue Sep 13 14:53:15 PDT 2016
On Thu, Sep 01, 2016 at 07:00:00PM -0400, Sinan Kaya wrote:
> A secondary bus reset causes settings to be lost by all downstream
> devices on the tree. The code is currently saving and restoring device
> states only when called from the VFIO path via pci_probe_reset_bus
> and pci_reset_bus functions.
>
> Moving the save and restore into pci_reset_bridge_secondary_bus
> so that all users of the API have the same behavior.
>
> Signed-off-by: Sinan Kaya <okaya at codeaurora.org>
> ---
> drivers/pci/pci.c | 36 +++++++++++++++---------------------
> 1 file changed, 15 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index aab9d51..b209378 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -3860,19 +3860,6 @@ void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
> pci_reset_secondary_bus(dev);
> }
>
> -/**
> - * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge.
> - * @dev: Bridge device
> - *
> - * Use the bridge control register to assert reset on the secondary bus.
> - * Devices on the secondary bus are left in power-on state.
> - */
> -void pci_reset_bridge_secondary_bus(struct pci_dev *dev)
> -{
> - pcibios_reset_secondary_bus(dev);
> -}
> -EXPORT_SYMBOL_GPL(pci_reset_bridge_secondary_bus);
> -
> static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
> {
> struct pci_dev *pdev;
> @@ -4362,6 +4349,21 @@ static void pci_slot_restore(struct pci_slot *slot)
> }
> }
>
> +/**
> + * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge.
> + * @dev: Bridge device
> + *
> + * Use the bridge control register to assert reset on the secondary bus.
> + * Devices on the secondary bus are left in power-on state.
> + */
> +void pci_reset_bridge_secondary_bus(struct pci_dev *dev)
> +{
> + pci_bus_save_and_disable(dev->bus);
> + pcibios_reset_secondary_bus(dev);
> + pci_bus_restore(dev->bus);
This path eventually writes the Bridge Control register:
pci_reset_bridge_secondary_bus
pcibios_reset_secondary_bus
pci_reset_secondary_bus
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl)
But I think it'd be easy to call this on a non-bridge device, and I
don't think there's anything in the path that checks whether this is
actually a bridge. I wonder if we should check that somewhere, or
maybe even change the interface so it takes a struct pci_bus instead
of a pci_dev.
> +}
> +EXPORT_SYMBOL_GPL(pci_reset_bridge_secondary_bus);
> +
> static int pci_slot_reset(struct pci_slot *slot, int probe)
> {
> int rc;
> @@ -4504,12 +4506,8 @@ int pci_reset_bus(struct pci_bus *bus)
> if (rc)
> return rc;
>
> - pci_bus_save_and_disable(bus);
> -
> rc = pci_bus_reset(bus, 0);
>
> - pci_bus_restore(bus);
> -
> return rc;
> }
> EXPORT_SYMBOL_GPL(pci_reset_bus);
> @@ -4528,8 +4526,6 @@ int pci_try_reset_bus(struct pci_bus *bus)
> if (rc)
> return rc;
>
> - pci_bus_save_and_disable(bus);
> -
> if (pci_bus_trylock(bus)) {
> might_sleep();
> pci_reset_bridge_secondary_bus(bus->self);
> @@ -4537,8 +4533,6 @@ int pci_try_reset_bus(struct pci_bus *bus)
> } else
> rc = -EAGAIN;
>
> - pci_bus_restore(bus);
> -
> return rc;
> }
> EXPORT_SYMBOL_GPL(pci_try_reset_bus);
> --
> 1.9.1
>
More information about the linux-arm-kernel
mailing list