[PATCH] pci: pcie_dw_rockchip: release resources on failing probe

Kever Yang kever.yang at rock-chips.com
Tue May 9 12:26:14 CEST 2023


On 2023/4/13 22:11, Eugen Hristev wrote:
> Implement a resource release mechanism on failing probe.
> Without this, a strange situation can happen e.g. when init port fails,
> or attempting to get the PHY fails, because the gpios have been
> requested first, and if the user tries to do 'pci enum' again, the
> driver will fail with 'can't find reset gpios' even if the gpios are
> there, just because they were blocked by a previous probe attempt.
> It is only natural to release the acquired resources if the probe fails,
> just for consistency if nothing else.
> This way on subsequent probe attempts, the user will get the same error
> message, and not something different that doesn't make sense.
>
> Signed-off-by: Eugen Hristev <eugen.hristev at collabora.com>
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>

Thanks,
- Kever
> ---
>   drivers/pci/pcie_dw_rockchip.c | 41 +++++++++++++++++++++++++---------
>   1 file changed, 30 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/pci/pcie_dw_rockchip.c b/drivers/pci/pcie_dw_rockchip.c
> index 9322e735b9c3..6155710a9f5f 100644
> --- a/drivers/pci/pcie_dw_rockchip.c
> +++ b/drivers/pci/pcie_dw_rockchip.c
> @@ -375,29 +375,39 @@ static int rockchip_pcie_parse_dt(struct udevice *dev)
>   	ret = reset_get_bulk(dev, &priv->rsts);
>   	if (ret) {
>   		dev_err(dev, "Can't get reset: %d\n", ret);
> -		return ret;
> +		goto rockchip_pcie_parse_dt_err_reset_get_bulk;
>   	}
>   
>   	ret = clk_get_bulk(dev, &priv->clks);
>   	if (ret) {
>   		dev_err(dev, "Can't get clock: %d\n", ret);
> -		return ret;
> +		goto rockchip_pcie_parse_dt_err_clk_get_bulk;
>   	}
>   
>   	ret = device_get_supply_regulator(dev, "vpcie3v3-supply",
>   					  &priv->vpcie3v3);
>   	if (ret && ret != -ENOENT) {
>   		dev_err(dev, "failed to get vpcie3v3 supply (ret=%d)\n", ret);
> -		return ret;
> +		goto rockchip_pcie_parse_dt_err_supply_regulator;
>   	}
>   
>   	ret = generic_phy_get_by_index(dev, 0, &priv->phy);
>   	if (ret) {
>   		dev_err(dev, "failed to get pcie phy (ret=%d)\n", ret);
> -		return ret;
> +		goto rockchip_pcie_parse_dt_err_phy_get_by_index;
>   	}
>   
>   	return 0;
> +
> +rockchip_pcie_parse_dt_err_phy_get_by_index:
> +	/* regulators don't need release */
> +rockchip_pcie_parse_dt_err_supply_regulator:
> +	clk_release_bulk(&priv->clks);
> +rockchip_pcie_parse_dt_err_clk_get_bulk:
> +	reset_release_bulk(&priv->rsts);
> +rockchip_pcie_parse_dt_err_reset_get_bulk:
> +	dm_gpio_free(dev, &priv->rst_gpio);
> +	return ret;
>   }
>   
>   /**
> @@ -426,7 +436,7 @@ static int rockchip_pcie_probe(struct udevice *dev)
>   
>   	ret = rockchip_pcie_init_port(dev);
>   	if (ret)
> -		return ret;
> +		goto rockchip_pcie_probe_err_init_port;
>   
>   	dev_info(dev, "PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
>   		 dev_seq(dev), pcie_dw_get_link_speed(&priv->dw),
> @@ -434,12 +444,21 @@ static int rockchip_pcie_probe(struct udevice *dev)
>   		 hose->first_busno);
>   
>   
> -	return pcie_dw_prog_outbound_atu_unroll(&priv->dw,
> -						PCIE_ATU_REGION_INDEX0,
> -						PCIE_ATU_TYPE_MEM,
> -						priv->dw.mem.phys_start,
> -						priv->dw.mem.bus_start,
> -						priv->dw.mem.size);
> +	ret = pcie_dw_prog_outbound_atu_unroll(&priv->dw,
> +					       PCIE_ATU_REGION_INDEX0,
> +					       PCIE_ATU_TYPE_MEM,
> +					       priv->dw.mem.phys_start,
> +					       priv->dw.mem.bus_start,
> +					       priv->dw.mem.size);
> +	if (!ret)
> +		return ret;
> +
> +rockchip_pcie_probe_err_init_port:
> +	clk_release_bulk(&priv->clks);
> +	reset_release_bulk(&priv->rsts);
> +	dm_gpio_free(dev, &priv->rst_gpio);
> +
> +	return ret;
>   }
>   
>   static const struct dm_pci_ops rockchip_pcie_ops = {


More information about the U-Boot mailing list