Re: [PATCH 06/10] PCI: portdrv: Add runtime PM hooks for port service drivers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thursday, September 6, 2018 5:50:16 PM CEST Mika Westerberg wrote:
> When PCIe port is runtime suspended/resumed some extra steps might be
> needed to be executed from the port service driver side. For instance we
> may need to disable PCIe hotplug interrupt to prevent it from triggering
> immediately when PCIe link to the downstream component goes down.
> 
> To make the above possible add optional ->runtime_suspend() and
> ->runtime_resume() callbacks to struct pcie_port_service_driver and call
> them for each port service in runtime suspend/resume callbacks of portdrv.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx>
> ---
>  drivers/pci/pcie/portdrv.h      |  4 ++++
>  drivers/pci/pcie/portdrv_core.c | 20 ++++++++++++++++++++
>  drivers/pci/pcie/portdrv_pci.c  | 10 ++++------
>  3 files changed, 28 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
> index d59afa42fc14..72fa132060e5 100644
> --- a/drivers/pci/pcie/portdrv.h
> +++ b/drivers/pci/pcie/portdrv.h
> @@ -52,6 +52,8 @@ struct pcie_port_service_driver {
>  	int (*suspend) (struct pcie_device *dev);
>  	int (*resume_noirq) (struct pcie_device *dev);
>  	int (*resume) (struct pcie_device *dev);
> +	int (*runtime_suspend) (struct pcie_device *dev);
> +	int (*runtime_resume) (struct pcie_device *dev);
>  
>  	/* Device driver may resume normal operations */
>  	void (*error_resume)(struct pci_dev *dev);
> @@ -85,6 +87,8 @@ int pcie_port_device_register(struct pci_dev *dev);
>  int pcie_port_device_suspend(struct device *dev);
>  int pcie_port_device_resume_noirq(struct device *dev);
>  int pcie_port_device_resume(struct device *dev);
> +int pcie_port_device_runtime_suspend(struct device *dev);
> +int pcie_port_device_runtime_resume(struct device *dev);
>  #endif
>  void pcie_port_device_remove(struct pci_dev *dev);
>  int __must_check pcie_port_bus_register(void);
> diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
> index 7c37d815229e..6542c48c7f59 100644
> --- a/drivers/pci/pcie/portdrv_core.c
> +++ b/drivers/pci/pcie/portdrv_core.c
> @@ -395,6 +395,26 @@ int pcie_port_device_resume(struct device *dev)
>  	size_t off = offsetof(struct pcie_port_service_driver, resume);
>  	return device_for_each_child(dev, &off, pm_iter);
>  }
> +
> +/**
> + * pcie_port_device_runtime_suspend - runtime suspend port services
> + * @dev: PCI Express port to handle
> + */
> +int pcie_port_device_runtime_suspend(struct device *dev)
> +{
> +	size_t off = offsetof(struct pcie_port_service_driver, runtime_suspend);
> +	return device_for_each_child(dev, &off, pm_iter);
> +}
> +
> +/**
> + * pcie_port_device_runtime_resume - runtime resume port services
> + * @dev: PCI Express port to handle
> + */
> +int pcie_port_device_runtime_resume(struct device *dev)
> +{
> +	size_t off = offsetof(struct pcie_port_service_driver, runtime_resume);
> +	return device_for_each_child(dev, &off, pm_iter);
> +}
>  #endif /* PM */
>  
>  static int remove_iter(struct device *dev, void *data)
> diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
> index 74761f660a30..d018633694e0 100644
> --- a/drivers/pci/pcie/portdrv_pci.c
> +++ b/drivers/pci/pcie/portdrv_pci.c
> @@ -60,12 +60,10 @@ int pcie_port_prepare(struct device *dev)
>  
>  static int pcie_port_runtime_suspend(struct device *dev)
>  {
> -	return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY;
> -}
> +	if (!to_pci_dev(dev)->bridge_d3)
> +		return -EBUSY;
>  
> -static int pcie_port_runtime_resume(struct device *dev)
> -{
> -	return 0;
> +	return pcie_port_device_runtime_suspend(dev);
>  }
>  
>  static int pcie_port_runtime_idle(struct device *dev)
> @@ -89,7 +87,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
>  	.restore_noirq	= pcie_port_device_resume_noirq,
>  	.restore	= pcie_port_device_resume,
>  	.runtime_suspend = pcie_port_runtime_suspend,
> -	.runtime_resume	= pcie_port_runtime_resume,
> +	.runtime_resume	= pcie_port_device_runtime_resume,
>  	.runtime_idle	= pcie_port_runtime_idle,
>  };
>  
> 

Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx>





[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux