From patchwork Sat Apr 27 09:12:27 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yijing Wang X-Patchwork-Id: 2496841 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 1F8283FC64 for ; Sat, 27 Apr 2013 09:13:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754229Ab3D0JNi (ORCPT ); Sat, 27 Apr 2013 05:13:38 -0400 Received: from szxga01-in.huawei.com ([119.145.14.64]:57312 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754071Ab3D0JNg (ORCPT ); Sat, 27 Apr 2013 05:13:36 -0400 Received: from 172.24.2.119 (EHLO szxeml207-edg.china.huawei.com) ([172.24.2.119]) by szxrg01-dlp.huawei.com (MOS 4.3.4-GA FastPath queued) with ESMTP id BBG66483; Sat, 27 Apr 2013 17:13:29 +0800 (CST) Received: from SZXEML421-HUB.china.huawei.com (10.82.67.160) by szxeml207-edg.china.huawei.com (172.24.2.56) with Microsoft SMTP Server (TLS) id 14.1.323.7; Sat, 27 Apr 2013 17:13:24 +0800 Received: from localhost (10.135.76.69) by szxeml421-hub.china.huawei.com (10.82.67.160) with Microsoft SMTP Server id 14.1.323.7; Sat, 27 Apr 2013 17:13:19 +0800 From: Yijing Wang To: Bjorn Helgaas CC: , Hanjun Guo , , Yijing Wang , Tony Luck , Fenghua Yu , Yinghai Lu , Greg Kroah-Hartman , Subject: [PATCH 5/7] PCI/IA64: fix memleak for create pci root bus fail Date: Sat, 27 Apr 2013 17:12:27 +0800 Message-ID: <1367053949-38424-6-git-send-email-wangyijing@huawei.com> X-Mailer: git-send-email 1.7.11.msysgit.1 In-Reply-To: <1367053949-38424-1-git-send-email-wangyijing@huawei.com> References: <1367053949-38424-1-git-send-email-wangyijing@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.135.76.69] X-CFilter-Loop: Reflected Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Jiang Liu If pci_create_root_bus() return fail, we should release pci root info, pci controller etc. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Cc: Tony Luck Cc: Fenghua Yu Cc: Yinghai Lu Cc: Greg Kroah-Hartman Cc: linux-ia64@vger.kernel.org --- arch/ia64/include/asm/pci.h | 6 +++ arch/ia64/pci/pci.c | 74 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h index 82a236c..fe813c2 100644 --- a/arch/ia64/include/asm/pci.h +++ b/arch/ia64/include/asm/pci.h @@ -89,6 +89,11 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus, #define pci_legacy_read platform_pci_legacy_read #define pci_legacy_write platform_pci_legacy_write +struct iospace_resource { + struct list_head list; + struct resource res; +}; + struct pci_controller { void *acpi_handle; void *iommu; @@ -105,6 +110,7 @@ struct pci_root_info { struct resource *res; resource_size_t *res_offset; unsigned int res_num; + struct list_head io_resources; char *name; }; diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 1f2779d..658030f 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -162,25 +162,21 @@ new_space (u64 phys_base, int sparse) static u64 add_io_space(struct pci_root_info *info, struct acpi_resource_address64 *addr) { + struct iospace_resource *iospace; struct resource *resource; char *name; unsigned long base, min, max, base_port; unsigned int sparse = 0, space_nr, len; - resource = kzalloc(sizeof(*resource), GFP_KERNEL); - if (!resource) { + len = strlen(info->name) + 32; + iospace = kzalloc(sizeof(*iospace) + len, GFP_KERNEL); + if (!iospace) { printk(KERN_ERR "PCI: No memory for %s I/O port space\n", info->name); goto out; } - len = strlen(info->name) + 32; - name = kzalloc(len, GFP_KERNEL); - if (!name) { - printk(KERN_ERR "PCI: No memory for %s I/O port space name\n", - info->name); - goto free_resource; - } + name = (char *)(iospace + 1); min = addr->minimum; max = min + addr->address_length - 1; @@ -189,7 +185,7 @@ static u64 add_io_space(struct pci_root_info *info, space_nr = new_space(addr->translation_offset, sparse); if (space_nr == ~0) - goto free_name; + goto free_resource; base = __pa(io_space[space_nr].mmio_base); base_port = IO_SPACE_BASE(space_nr); @@ -204,18 +200,23 @@ static u64 add_io_space(struct pci_root_info *info, if (space_nr == 0) sparse = 1; + resource = &iospace->res; resource->name = name; resource->flags = IORESOURCE_MEM; resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min); resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max); - insert_resource(&iomem_resource, resource); + if (insert_resource(&iomem_resource, resource)) { + dev_err(&info->bridge->dev, + "can't allocate host bridge io space resource %pR\n", + resource); + goto free_resource; + } + list_add_tail(&iospace->list, &info->io_resources); return base_port; -free_name: - kfree(name); free_resource: - kfree(resource); + kfree(iospace); out: return ~0; } @@ -316,6 +317,47 @@ static acpi_status add_window(struct acpi_resource *res, void *data) return AE_OK; } +static void free_pci_root_info_res(struct pci_root_info *info) +{ + struct iospace_resource *iospace, *tmp; + + list_for_each_entry_safe(iospace, tmp, &info->io_resources, list) + kfree(iospace); + + kfree(info->res); + info->res = NULL; + kfree(info->res_offset); + info->res_offset = NULL; + info->res_num = 0; + kfree(info->controller); + info->controller = NULL; +} + +static void __release_pci_root_info(struct pci_root_info *info) +{ + int i; + struct resource *res; + struct iospace_resource *iospace; + + list_for_each_entry(iospace, &info->io_resources, list) + release_resource(&iospace->res); + + for (i = 0; i < info->res_num; i++) { + res = &info->res[i]; + + if (!res->parent) + continue; + + if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO))) + continue; + + release_resource(res); + } + + free_pci_root_info_res(info); + kfree(info); +} + struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) { struct acpi_device *device = root->device; @@ -346,7 +388,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) "ignored (out of memory)\n", root->segment, busnum); goto out2; } - + + INIT_LIST_HEAD(&info->io_resources); INIT_LIST_HEAD(&info->resources); /* insert busn resource at first */ pci_add_resource(&info->resources, &root->secondary); @@ -387,6 +430,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) &info->resources); if (!pbus) { pci_free_resource_list(&info->resources); + __release_pci_root_info(info); return NULL; }