[PATCH] pci: rockchip: Release resources on failing probe
Kever Yang
kever.yang at rock-chips.com
Wed Jul 26 09:44:25 CEST 2023
On 2023/7/12 07:13, Jonas Karlman wrote:
> The PCIe driver for RK3399 is affected by a similar issue that was fixed
> for RK35xx in the commit e04b67a7f4c1 ("pci: pcie_dw_rockchip: release
> resources on failing probe").
>
> Resources are not released on failing probe, e.g. regulators may be left
> enabled and the ep-gpio may be left in a requested state.
>
> Change to use regulator_set_enable_if_allowed and disable regulators
> after failure to keep regulator enable count balanced, ep-gpio is also
> released on regulator failure.
>
> Also add support for the vpcie12v-supply, remove unused include and
> check return value from dev_read_addr_name.
>
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>
Thanks,
- Kever
> ---
> drivers/pci/pcie_rockchip.c | 108 +++++++++++++++++++-----------------
> 1 file changed, 57 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/pci/pcie_rockchip.c b/drivers/pci/pcie_rockchip.c
> index 72b41398f27b..624841e9d8b8 100644
> --- a/drivers/pci/pcie_rockchip.c
> +++ b/drivers/pci/pcie_rockchip.c
> @@ -12,23 +12,15 @@
> */
>
> #include <common.h>
> -#include <clk.h>
> #include <dm.h>
> -#include <asm/global_data.h>
> #include <dm/device_compat.h>
> #include <generic-phy.h>
> #include <pci.h>
> -#include <power-domain.h>
> #include <power/regulator.h>
> #include <reset.h>
> -#include <syscon.h>
> -#include <asm/io.h>
> #include <asm-generic/gpio.h>
> -#include <asm/arch-rockchip/clock.h>
> #include <linux/iopoll.h>
>
> -DECLARE_GLOBAL_DATA_PTR;
> -
> #define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val))
> #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val)
>
> @@ -383,41 +375,38 @@ static int rockchip_pcie_set_vpcie(struct udevice *dev)
> struct rockchip_pcie *priv = dev_get_priv(dev);
> int ret;
>
> - if (priv->vpcie3v3) {
> - ret = regulator_set_enable(priv->vpcie3v3, true);
> - if (ret) {
> - dev_err(dev, "failed to enable vpcie3v3 (ret=%d)\n",
> - ret);
> - return ret;
> - }
> + ret = regulator_set_enable_if_allowed(priv->vpcie12v, true);
> + if (ret && ret != -ENOSYS) {
> + dev_err(dev, "failed to enable vpcie12v (ret=%d)\n", ret);
> + return ret;
> }
>
> - if (priv->vpcie1v8) {
> - ret = regulator_set_enable(priv->vpcie1v8, true);
> - if (ret) {
> - dev_err(dev, "failed to enable vpcie1v8 (ret=%d)\n",
> - ret);
> - goto err_disable_3v3;
> - }
> + ret = regulator_set_enable_if_allowed(priv->vpcie3v3, true);
> + if (ret && ret != -ENOSYS) {
> + dev_err(dev, "failed to enable vpcie3v3 (ret=%d)\n", ret);
> + goto err_disable_12v;
> }
>
> - if (priv->vpcie0v9) {
> - ret = regulator_set_enable(priv->vpcie0v9, true);
> - if (ret) {
> - dev_err(dev, "failed to enable vpcie0v9 (ret=%d)\n",
> - ret);
> - goto err_disable_1v8;
> - }
> + ret = regulator_set_enable_if_allowed(priv->vpcie1v8, true);
> + if (ret && ret != -ENOSYS) {
> + dev_err(dev, "failed to enable vpcie1v8 (ret=%d)\n", ret);
> + goto err_disable_3v3;
> + }
> +
> + ret = regulator_set_enable_if_allowed(priv->vpcie0v9, true);
> + if (ret && ret != -ENOSYS) {
> + dev_err(dev, "failed to enable vpcie0v9 (ret=%d)\n", ret);
> + goto err_disable_1v8;
> }
>
> return 0;
>
> err_disable_1v8:
> - if (priv->vpcie1v8)
> - regulator_set_enable(priv->vpcie1v8, false);
> + regulator_set_enable_if_allowed(priv->vpcie1v8, false);
> err_disable_3v3:
> - if (priv->vpcie3v3)
> - regulator_set_enable(priv->vpcie3v3, false);
> + regulator_set_enable_if_allowed(priv->vpcie3v3, false);
> +err_disable_12v:
> + regulator_set_enable_if_allowed(priv->vpcie12v, false);
> return ret;
> }
>
> @@ -427,19 +416,12 @@ static int rockchip_pcie_parse_dt(struct udevice *dev)
> int ret;
>
> priv->axi_base = dev_read_addr_name(dev, "axi-base");
> - if (!priv->axi_base)
> - return -ENODEV;
> + if (priv->axi_base == FDT_ADDR_T_NONE)
> + return -EINVAL;
>
> priv->apb_base = dev_read_addr_name(dev, "apb-base");
> - if (!priv->axi_base)
> - return -ENODEV;
> -
> - ret = gpio_request_by_name(dev, "ep-gpios", 0,
> - &priv->ep_gpio, GPIOD_IS_OUT);
> - if (ret) {
> - dev_err(dev, "failed to find ep-gpios property\n");
> - return ret;
> - }
> + if (priv->apb_base == FDT_ADDR_T_NONE)
> + return -EINVAL;
>
> ret = reset_get_by_name(dev, "core", &priv->core_rst);
> if (ret) {
> @@ -483,6 +465,13 @@ static int rockchip_pcie_parse_dt(struct udevice *dev)
> return ret;
> }
>
> + ret = device_get_supply_regulator(dev, "vpcie12v-supply",
> + &priv->vpcie12v);
> + if (ret && ret != -ENOENT) {
> + dev_err(dev, "failed to get vpcie12v supply (ret=%d)\n", ret);
> + return ret;
> + }
> +
> ret = device_get_supply_regulator(dev, "vpcie3v3-supply",
> &priv->vpcie3v3);
> if (ret && ret != -ENOENT) {
> @@ -510,6 +499,13 @@ static int rockchip_pcie_parse_dt(struct udevice *dev)
> return ret;
> }
>
> + ret = gpio_request_by_name(dev, "ep-gpios", 0,
> + &priv->ep_gpio, GPIOD_IS_OUT);
> + if (ret) {
> + dev_err(dev, "failed to find ep-gpios property\n");
> + return ret;
> + }
> +
> return 0;
> }
>
> @@ -529,16 +525,26 @@ static int rockchip_pcie_probe(struct udevice *dev)
>
> ret = rockchip_pcie_set_vpcie(dev);
> if (ret)
> - return ret;
> + goto err_gpio_free;
>
> ret = rockchip_pcie_init_port(dev);
> if (ret)
> - return ret;
> + goto err_disable_vpcie;
>
> dev_info(dev, "PCIE-%d: Link up (Bus%d)\n",
> dev_seq(dev), hose->first_busno);
>
> return 0;
> +
> +err_disable_vpcie:
> + regulator_set_enable_if_allowed(priv->vpcie0v9, false);
> + regulator_set_enable_if_allowed(priv->vpcie1v8, false);
> + regulator_set_enable_if_allowed(priv->vpcie3v3, false);
> + regulator_set_enable_if_allowed(priv->vpcie12v, false);
> +err_gpio_free:
> + if (dm_gpio_is_valid(&priv->ep_gpio))
> + dm_gpio_free(dev, &priv->ep_gpio);
> + return ret;
> }
>
> static const struct dm_pci_ops rockchip_pcie_ops = {
> @@ -552,10 +558,10 @@ static const struct udevice_id rockchip_pcie_ids[] = {
> };
>
> U_BOOT_DRIVER(rockchip_pcie) = {
> - .name = "rockchip_pcie",
> - .id = UCLASS_PCI,
> - .of_match = rockchip_pcie_ids,
> - .ops = &rockchip_pcie_ops,
> - .probe = rockchip_pcie_probe,
> + .name = "rockchip_pcie",
> + .id = UCLASS_PCI,
> + .of_match = rockchip_pcie_ids,
> + .ops = &rockchip_pcie_ops,
> + .probe = rockchip_pcie_probe,
> .priv_auto = sizeof(struct rockchip_pcie),
> };
More information about the U-Boot
mailing list