From patchwork Sat Oct 3 18:13:02 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King X-Patchwork-Id: 7322191 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 3586F9F302 for ; Sat, 3 Oct 2015 18:15:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4023D2042B for ; Sat, 3 Oct 2015 18:15:55 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5A03220421 for ; Sat, 3 Oct 2015 18:15:54 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZiRJZ-0004WA-VZ; Sat, 03 Oct 2015 18:13:46 +0000 Received: from pandora.arm.linux.org.uk ([2001:4d48:ad52:3201:214:fdff:fe10:1be6]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZiRJM-0004JN-T1 for linux-arm-kernel@lists.infradead.org; Sat, 03 Oct 2015 18:13:34 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=arm.linux.org.uk; s=pandora-2014; h=Date:Sender:Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Subject:Cc:To:From:References:In-Reply-To; bh=moWAvIXRTdbQoJjjC28fsLW7rSU0mrWneX/1ruG25rY=; b=mRqn1g1Vlyk4pGl23QFRm2drG1fX2/Yafdtsn5c5mzZcBm6LpxBwRws0W0V0vLyTred5D5O9mq7WoCHt0JvEnDIabo/FCwW/Xomh36pszMgWjsmkecmB2eesHgQljeAbuTLU5+PQi9Zg9ApHvqpGJNMnWzZXlvr/IgLpkec4eVk=; Received: from e0022681537dd.dyn.arm.linux.org.uk ([2001:4d48:ad52:3201:222:68ff:fe15:37dd]:43239 helo=rmk-PC.arm.linux.org.uk) by pandora.arm.linux.org.uk with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1ZiRIu-0005sd-Hm; Sat, 03 Oct 2015 19:13:04 +0100 Received: from rmk by rmk-PC.arm.linux.org.uk with local (Exim 4.82_1-5b7a7c0-XX) (envelope-from ) id 1ZiRIs-0004Id-AN; Sat, 03 Oct 2015 19:13:02 +0100 In-Reply-To: <20151003181228.GI21513@n2100.arm.linux.org.uk> References: <20151003181228.GI21513@n2100.arm.linux.org.uk> From: Russell King To: Jason Cooper , Thomas Petazzoni Subject: [PATCH 2/9] pci: mvebu: fix memory leaks and refcount leaks MIME-Version: 1.0 Content-Disposition: inline Message-Id: Date: Sat, 03 Oct 2015 19:13:02 +0100 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151003_111333_750773_6B55300D X-CRM114-Status: GOOD ( 16.19 ) X-Spam-Score: -4.3 (----) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Bjorn Helgaas , linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The mvebu PCI port parsing is weak due to: 1) allocations via kasprintf() were not cleaned up when we encounter an error or decide to skip the port. 2) kasprintf() wasn't checked for failure. 3) of_get_named_gpio_flags() returns EPROBE_DEFER if the GPIO is not present, not devm_gpio_request_one(). 4) the of_node was not being put when terminating the loop. Fix these oversights. Signed-off-by: Russell King --- drivers/pci/host/pci-mvebu.c | 50 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 13ab0350f7fb..e8c51bb58e99 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -928,6 +928,13 @@ static int mvebu_pcie_resume(struct device *dev) return 0; } +static void mvebu_pcie_port_clk_put(void *data) +{ + struct mvebu_pcie_port *port = data; + + clk_put(port->clk); +} + static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, struct mvebu_pcie_port *port, struct device_node *child) { @@ -946,7 +953,12 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane)) port->lane = 0; - port->name = kasprintf(GFP_KERNEL, "pcie%d.%d", port->port, port->lane); + port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port, + port->lane); + if (!port->name) { + ret = -ENOMEM; + goto err; + } port->devfn = of_pci_get_devfn(child); if (port->devfn < 0) @@ -960,20 +972,29 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, goto skip; } - if (resource_size(&pcie->io) != 0) + if (resource_size(&pcie->io) != 0) { mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_IO, &port->io_target, &port->io_attr); - else { + } else { port->io_target = -1; port->io_attr = -1; } port->reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags); + if (port->reset_gpio == -EPROBE_DEFER) { + ret = port->reset_gpio; + goto err; + } + if (gpio_is_valid(port->reset_gpio)) { port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; - port->reset_name = kasprintf(GFP_KERNEL, "%s-reset", - port->name); + port->reset_name = devm_kasprintf(dev, GFP_KERNEL, "%s-reset", + port->name); + if (!port->reset_name) { + ret = -ENOMEM; + goto err; + } ret = devm_gpio_request_one(dev, port->reset_gpio, GPIOF_DIR_OUT, port->reset_name); @@ -990,10 +1011,23 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, goto skip; } + ret = devm_add_action(dev, mvebu_pcie_port_clk_put, port); + if (ret < 0) { + clk_put(port->clk); + goto err; + } + return 1; skip: ret = 0; + + /* In the case of skipping, we need to free these */ + devm_kfree(dev, port->reset_name); + port->reset_name = NULL; + devm_kfree(dev, port->name); + port->name = NULL; + err: return ret; } @@ -1052,10 +1086,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev) struct mvebu_pcie_port *port = &pcie->ports[i]; ret = mvebu_pcie_parse_port(pcie, port, child); - if (ret < 0) + if (ret < 0) { + of_node_put(child); return ret; - else if (ret == 0) + } else if (ret == 0) { continue; + } if (gpio_is_valid(port->reset_gpio)) { u32 reset_udelay = 20000;