[PATCH v4 6/6] PCI: dwc: Skip failure during dw_pcie_resume_noirq() if no device is available

Manivannan Sadhasivam via B4 Relay posted 6 patches 1 month ago
There is a newer version of this series
[PATCH v4 6/6] PCI: dwc: Skip failure during dw_pcie_resume_noirq() if no device is available
Posted by Manivannan Sadhasivam via B4 Relay 1 month ago
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>

If there is no device attached to any of the Root Ports available under the
Root bus before suspend and during resume, then there is no point in
returning failure.

So skip returning failure so that the resume succeeds and allow the device
to get attached later.

If there was a device before suspend and not available during resume, then
propagate the error to indicate that the device got removed during suspend.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
---
 drivers/pci/controller/dwc/pcie-designware-host.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index ccde12b85463..c30a2ed324cd 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 
 #include "../../pci.h"
+#include "../pci-host-common.h"
 #include "pcie-designware.h"
 
 static struct pci_ops dw_pcie_ops;
@@ -1227,6 +1228,7 @@ EXPORT_SYMBOL_GPL(dw_pcie_suspend_noirq);
 
 int dw_pcie_resume_noirq(struct dw_pcie *pci)
 {
+	struct dw_pcie_rp *pp = &pci->pp;
 	int ret;
 
 	if (!pci->suspended)
@@ -1234,23 +1236,28 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
 
 	pci->suspended = false;
 
-	if (pci->pp.ops->init) {
-		ret = pci->pp.ops->init(&pci->pp);
+	if (pp->ops->init) {
+		ret = pp->ops->init(pp);
 		if (ret) {
 			dev_err(pci->dev, "Host init failed: %d\n", ret);
 			return ret;
 		}
 	}
 
-	dw_pcie_setup_rc(&pci->pp);
+	dw_pcie_setup_rc(pp);
 
 	ret = dw_pcie_start_link(pci);
 	if (ret)
 		return ret;
 
 	ret = dw_pcie_wait_for_link(pci);
-	if (ret)
-		return ret;
+	/*
+	 * Skip failure if there is no device attached to the bus now and before
+	 * suspend. But the error should be returned if a device was attached
+	 * before suspend and not available now.
+	 */
+	if (ret == -ENODEV && !pci_root_ports_have_device(pp->bridge->bus))
+		return 0;
 
 	return ret;
 }

-- 
2.48.1
Re: [PATCH v4 6/6] PCI: dwc: Skip failure during dw_pcie_resume_noirq() if no device is available
Posted by Shawn Lin 1 month ago
在 2026/01/07 星期三 16:11, Manivannan Sadhasivam via B4 Relay 写道:
> From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> 
> If there is no device attached to any of the Root Ports available under the
> Root bus before suspend and during resume, then there is no point in
> returning failure.
> 
> So skip returning failure so that the resume succeeds and allow the device
> to get attached later.
> 
> If there was a device before suspend and not available during resume, then
> propagate the error to indicate that the device got removed during suspend.
> 

Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>


> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> ---
>   drivers/pci/controller/dwc/pcie-designware-host.c | 17 ++++++++++++-----
>   1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index ccde12b85463..c30a2ed324cd 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -20,6 +20,7 @@
>   #include <linux/platform_device.h>
>   
>   #include "../../pci.h"
> +#include "../pci-host-common.h"
>   #include "pcie-designware.h"
>   
>   static struct pci_ops dw_pcie_ops;
> @@ -1227,6 +1228,7 @@ EXPORT_SYMBOL_GPL(dw_pcie_suspend_noirq);
>   
>   int dw_pcie_resume_noirq(struct dw_pcie *pci)
>   {
> +	struct dw_pcie_rp *pp = &pci->pp;
>   	int ret;
>   
>   	if (!pci->suspended)
> @@ -1234,23 +1236,28 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci)
>   
>   	pci->suspended = false;
>   
> -	if (pci->pp.ops->init) {
> -		ret = pci->pp.ops->init(&pci->pp);
> +	if (pp->ops->init) {
> +		ret = pp->ops->init(pp);
>   		if (ret) {
>   			dev_err(pci->dev, "Host init failed: %d\n", ret);
>   			return ret;
>   		}
>   	}
>   
> -	dw_pcie_setup_rc(&pci->pp);
> +	dw_pcie_setup_rc(pp);
>   
>   	ret = dw_pcie_start_link(pci);
>   	if (ret)
>   		return ret;
>   
>   	ret = dw_pcie_wait_for_link(pci);
> -	if (ret)
> -		return ret;
> +	/*
> +	 * Skip failure if there is no device attached to the bus now and before
> +	 * suspend. But the error should be returned if a device was attached
> +	 * before suspend and not available now.
> +	 */
> +	if (ret == -ENODEV && !pci_root_ports_have_device(pp->bridge->bus))
> +		return 0;
>   
>   	return ret;
>   }
>