Commit 9e38e690 authored by Nishka Dasgupta's avatar Nishka Dasgupta Committed by Lorenzo Pieralisi

PCI: tegra: Fix OF node reference leak

Each iteration of for_each_child_of_node() executes of_node_put() on the
previous node, but in some return paths in the middle of the loop
of_node_put() is missing thus causing a reference leak.

Hence stash these mid-loop return values in a variable 'err' and add a
new label err_node_put which executes of_node_put() on the previous node
and returns 'err' on failure.

Change mid-loop return statements to point to jump to this label to
fix the reference leak.

Issue found with Coccinelle.
Signed-off-by: default avatarNishka Dasgupta <nishkadg.linux@gmail.com>
[lorenzo.pieralisi@arm.com: rewrote commit log]
Signed-off-by: default avatarLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
parent 5f9e832c
...@@ -2237,14 +2237,15 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) ...@@ -2237,14 +2237,15 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
err = of_pci_get_devfn(port); err = of_pci_get_devfn(port);
if (err < 0) { if (err < 0) {
dev_err(dev, "failed to parse address: %d\n", err); dev_err(dev, "failed to parse address: %d\n", err);
return err; goto err_node_put;
} }
index = PCI_SLOT(err); index = PCI_SLOT(err);
if (index < 1 || index > soc->num_ports) { if (index < 1 || index > soc->num_ports) {
dev_err(dev, "invalid port number: %d\n", index); dev_err(dev, "invalid port number: %d\n", index);
return -EINVAL; err = -EINVAL;
goto err_node_put;
} }
index--; index--;
...@@ -2253,12 +2254,13 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) ...@@ -2253,12 +2254,13 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
if (err < 0) { if (err < 0) {
dev_err(dev, "failed to parse # of lanes: %d\n", dev_err(dev, "failed to parse # of lanes: %d\n",
err); err);
return err; goto err_node_put;
} }
if (value > 16) { if (value > 16) {
dev_err(dev, "invalid # of lanes: %u\n", value); dev_err(dev, "invalid # of lanes: %u\n", value);
return -EINVAL; err = -EINVAL;
goto err_node_put;
} }
lanes |= value << (index << 3); lanes |= value << (index << 3);
...@@ -2272,13 +2274,15 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) ...@@ -2272,13 +2274,15 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
lane += value; lane += value;
rp = devm_kzalloc(dev, sizeof(*rp), GFP_KERNEL); rp = devm_kzalloc(dev, sizeof(*rp), GFP_KERNEL);
if (!rp) if (!rp) {
return -ENOMEM; err = -ENOMEM;
goto err_node_put;
}
err = of_address_to_resource(port, 0, &rp->regs); err = of_address_to_resource(port, 0, &rp->regs);
if (err < 0) { if (err < 0) {
dev_err(dev, "failed to parse address: %d\n", err); dev_err(dev, "failed to parse address: %d\n", err);
return err; goto err_node_put;
} }
INIT_LIST_HEAD(&rp->list); INIT_LIST_HEAD(&rp->list);
...@@ -2330,6 +2334,10 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) ...@@ -2330,6 +2334,10 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
return err; return err;
return 0; return 0;
err_node_put:
of_node_put(port);
return err;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment