Re: [PATCH v6 2/9] PCI: Export pci_dev_save_and_disable() and pci_dev_restore()

From: Dave Jiang

Date: Tue Jun 02 2026 - 16:18:23 EST




On 5/28/26 1:31 AM, Srirangan Madhavan wrote:
> Export pci_dev_save_and_disable() and pci_dev_restore() so CXL reset
> orchestration can reuse the PCI core reset lifecycle for non-standard
> reset flows.
>
> These helpers invoke driver reset_prepare/reset_done callbacks, save and
> restore PCI config state, and disable the device while the caller holds
> the device lock.
>
> Signed-off-by: Srirangan Madhavan <smadhavan@xxxxxxxxxx>
> ---
> drivers/pci/pci.c | 22 ++++++++++++++++++++--
> include/linux/pci.h | 2 ++
> 2 files changed, 22 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index d34266651ad0..75d2f4074750 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -5003,7 +5003,15 @@ void pci_dev_unlock(struct pci_dev *dev)
> }
> EXPORT_SYMBOL_GPL(pci_dev_unlock);
>
> -static void pci_dev_save_and_disable(struct pci_dev *dev)
> +/**
> + * pci_dev_save_and_disable - Save device state and disable it
> + * @dev: PCI device to save and disable
> + *
> + * Save the PCI configuration state, invoke the driver's reset_prepare()
> + * callback if present, and disable the device by clearing the Command
> + * register. The device lock must be held by the caller.
> + */
> +void pci_dev_save_and_disable(struct pci_dev *dev)
> {
> const struct pci_error_handlers *err_handler =
> dev->driver ? dev->driver->err_handler : NULL;
> @@ -5036,8 +5044,17 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
> */
> pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_INTX_DISABLE);
> }
> +EXPORT_SYMBOL_GPL(pci_dev_save_and_disable);

Maybe only export it to CXL namespace to reduce the scope?

>
> -static void pci_dev_restore(struct pci_dev *dev)
> +/**
> + * pci_dev_restore - Restore device state after reset
> + * @dev: PCI device to restore
> + *
> + * Restore the saved PCI configuration state and invoke the driver's
> + * reset_done() callback if present. The device lock must be held by the
> + * caller.
> + */
> +void pci_dev_restore(struct pci_dev *dev)
> {
> const struct pci_error_handlers *err_handler =
> dev->driver ? dev->driver->err_handler : NULL;
> @@ -5054,6 +5071,7 @@ static void pci_dev_restore(struct pci_dev *dev)
> else if (dev->driver)
> pci_warn(dev, "reset done");
> }
> +EXPORT_SYMBOL_GPL(pci_dev_restore);

same comment as above

>
> /* dev->reset_methods[] is a 0-terminated list of indices into this array */
> const struct pci_reset_fn_method pci_reset_fn_methods[] = {
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 2c4454583c11..d6303e16e11b 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -2012,6 +2012,8 @@ void pci_dev_lock(struct pci_dev *dev);
> int pci_dev_trylock(struct pci_dev *dev);
> void pci_dev_unlock(struct pci_dev *dev);
> DEFINE_GUARD(pci_dev, struct pci_dev *, pci_dev_lock(_T), pci_dev_unlock(_T))
> +void pci_dev_save_and_disable(struct pci_dev *dev);
> +void pci_dev_restore(struct pci_dev *dev);
>
> /*
> * PCI domain support. Sometimes called PCI segment (eg by ACPI),