Hi Bjorn,

Since this is adding to the PCI reset framework, this patch needs your
approval.

Please see below for my questions. I'm happy to change the code however
you see fit.

On Fri, Jul 24, 2026 at 04:08:42PM -0700, [email protected] wrote:
> From: Wei Liu <[email protected]>
> 
> Some PCI controllers provide a function reset mechanism that is not
> advertised in PCI configuration space. Allow them to expose it through an
> optional pci_ops callback.
> 
> Add the controller reset method to the standard reset_method interface.
> Prefer FLR and AF FLR by default, and use the controller operation before
> PM and bus reset fallbacks.
> 
> Signed-off-by: Wei Liu <[email protected]>
> ---
>  drivers/pci/pci.c   | 22 ++++++++++++++++++++++
>  include/linux/pci.h |  3 ++-
>  2 files changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 77b17b13ee61..4e55da202cad 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -4962,6 +4962,27 @@ static int pci_reset_bus_function(struct pci_dev *dev, 
> bool probe)
>       return rc;
>  }
>  
> +static int pci_controller_reset(struct pci_dev *dev, bool probe)
> +{
> +     int rc;
> +
> +     if (!dev->bus->ops->reset)
> +             return -ENOTTY;
> +
> +     if (probe)
> +             return dev->bus->ops->reset(dev, probe);
> +
> +     rc = pci_dev_reset_iommu_prepare(dev);
> +     if (rc) {
> +             pci_err(dev, "failed to stop IOMMU for a PCI reset: %d\n", rc);
> +             return rc;
> +     }
> +
> +     rc = dev->bus->ops->reset(dev, probe);
> +     pci_dev_reset_iommu_done(dev);
> +     return rc;
> +}
> +

The first question is whether modelling this on the controller level
is the correct approach.

Please refer to the second patch for the intended usage in the Hyper-V
vPCI code.

Whatever is added here, a new reset_method value will be added to the
table. I chose "controller" to reflect the decision above.


>  static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
>  {
>       struct pci_dev *bridge;
> @@ -5094,6 +5115,7 @@ const struct pci_reset_fn_method pci_reset_fn_methods[] 
> = {
>       { pci_dev_acpi_reset, .name = "acpi" },
>       { pcie_reset_flr, .name = "flr" },
>       { pci_af_flr, .name = "af_flr" },
> +     { pci_controller_reset, .name = "controller" },

The second question is whether this ordering is okay.

Thanks,
Wei

>       { pci_pm_reset, .name = "pm" },
>       { pci_reset_bus_function, .name = "bus" },
>       { cxl_reset_bus_function, .name = "cxl_bus" },
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 64b308b6e61c..d7759ee70670 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -52,7 +52,7 @@
>                              PCI_STATUS_PARITY)
>  
>  /* Number of reset methods used in pci_reset_fn_methods array in pci.c */
> -#define PCI_NUM_RESET_METHODS 8
> +#define PCI_NUM_RESET_METHODS 9
>  
>  #define PCI_RESET_PROBE              true
>  #define PCI_RESET_DO_RESET   false
> @@ -875,6 +875,7 @@ struct pci_ops {
>       void __iomem *(*map_bus)(struct pci_bus *bus, unsigned int devfn, int 
> where);
>       int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int 
> size, u32 *val);
>       int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int 
> size, u32 val);
> +     int (*reset)(struct pci_dev *dev, bool probe);
>  };
>  
>  /*
> -- 
> 2.53.0
> 

Reply via email to