Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: uniphier: Fix a leaked reference by adding missing of_node_put()

The call to of_get_child_by_name() returns a node pointer with refcount
incremented thus it must be explicitly decremented after the last
usage.

irq_domain_add_linear() also calls of_node_get() to increase refcount,
so irq_domain will not be affected when it is released.

Detected by coccinelle with the following warnings:
./drivers/pci/controller/dwc/pcie-uniphier.c:283:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 274, but without a corresponding object release within this function.
./drivers/pci/controller/dwc/pcie-uniphier.c:290:2-8: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 274, but without a corresponding object release within this function.
./drivers/pci/controller/dwc/pcie-uniphier.c:296:1-7: ERROR: missing of_node_put; acquired a node pointer with refcount incremented on line 274, but without a corresponding object release within this function.

Signed-off-by: Wen Yang <wen.yang99@zte.com.cn>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
Cc: linux-pci@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org

authored by

Wen Yang and committed by
Lorenzo Pieralisi
e12bfa01 91e0a58e

+8 -3
+8 -3
drivers/pci/controller/dwc/pcie-uniphier.c
··· 270 270 struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); 271 271 struct device_node *np = pci->dev->of_node; 272 272 struct device_node *np_intc; 273 + int ret = 0; 273 274 274 275 np_intc = of_get_child_by_name(np, "legacy-interrupt-controller"); 275 276 if (!np_intc) { ··· 281 280 pp->irq = irq_of_parse_and_map(np_intc, 0); 282 281 if (!pp->irq) { 283 282 dev_err(pci->dev, "Failed to get an IRQ entry in legacy-interrupt-controller\n"); 284 - return -EINVAL; 283 + ret = -EINVAL; 284 + goto out_put_node; 285 285 } 286 286 287 287 priv->legacy_irq_domain = irq_domain_add_linear(np_intc, PCI_NUM_INTX, 288 288 &uniphier_intx_domain_ops, pp); 289 289 if (!priv->legacy_irq_domain) { 290 290 dev_err(pci->dev, "Failed to get INTx domain\n"); 291 - return -ENODEV; 291 + ret = -ENODEV; 292 + goto out_put_node; 292 293 } 293 294 294 295 irq_set_chained_handler_and_data(pp->irq, uniphier_pcie_irq_handler, 295 296 pp); 296 297 297 - return 0; 298 + out_put_node: 299 + of_node_put(np_intc); 300 + return ret; 298 301 } 299 302 300 303 static int uniphier_pcie_host_init(struct pcie_port *pp)