From patchwork Thu Feb 4 17:28:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 579067 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id CC4F4140CAC for ; Fri, 5 Feb 2016 04:38:33 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=semihalf-com.20150623.gappssmtp.com header.i=@semihalf-com.20150623.gappssmtp.com header.b=YxGsu9OY; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756120AbcBDRiE (ORCPT ); Thu, 4 Feb 2016 12:38:04 -0500 Received: from mail-wm0-f47.google.com ([74.125.82.47]:34076 "EHLO mail-wm0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934620AbcBDR2z (ORCPT ); Thu, 4 Feb 2016 12:28:55 -0500 Received: by mail-wm0-f47.google.com with SMTP id 128so37619691wmz.1 for ; Thu, 04 Feb 2016 09:28:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=lp9bxGtW+2MygXEobIV41BZp2rB34cdZ91q7rhOYg9M=; b=YxGsu9OY/4iejwOjU2X9QhQvZ0w5k07mucxdPs6tfcjVCOut5ELFuVpkcTqK0FWvIh 2ZMgtPoXizpNuc66nJTmjsRBa29FDrRRl3ap4FKq6coLA2fBl0VCjLIsKHWS+Ur+6EUh /8DhdyNfs0Xg0pJWiailC8lceYZdkVqd2WVlO7tGxzSuyGMh2Q5m3Wx3S+s94dZgHYhC IaN3JUHXpvH3G32WYt+1lOc1Gqu7A7KgWWwF0aYL96vr1t6wRSEJ1JSYuOX0SPC8cW4O OzmlBdqURRNB7uNEKg/jR6aYKxw5rnHu1y8JOic8A10TlworGrVIIZXmsTKfVC3Ercu7 wnGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=lp9bxGtW+2MygXEobIV41BZp2rB34cdZ91q7rhOYg9M=; b=QKNpYPxqXf3Bnb7Tdo4SN1SQoQivi4mSj3/wBs6A1B+pkfUqCoUFR//lY9e/WTC0mL 00Az8lYNVSmOjQtFS7XfAxLrzwY8yo8L9YaKT7XN1cX2D4Hbh5dxv+cQrRkJkTVlwwqG eOT7lbCD/3OKK8aD7fqEx83nqY3o6HMGIUPPY3ds/Qi8SRCYDUvuRUhkhjlBIsDFrnsU iZ4ETeug6GJh29hCTkoala2CwGQMzKiJMFoNyMqShxHp/f08i6nNLuLplksFBXoysxR8 4IrIbatIbPj3CGA9uGbr9KXTJ0HFo6Ss1cNtgUhQM5E4YC+CA0aYojhXGuYyl5+5p7wh X5EQ== X-Gm-Message-State: AG10YOSzwttX8QG0Y9AbnuCbynrq8+QIk2A2qQzOIlP66jKLH/kYDcuKBJwVVlmH/TWKGQ== X-Received: by 10.28.150.66 with SMTP id y63mr14666702wmd.17.1454606934442; Thu, 04 Feb 2016 09:28:54 -0800 (PST) Received: from tn-HP-4.semihalf.local (cardhu.semihalf.com. [213.17.239.108]) by smtp.gmail.com with ESMTPSA id w8sm12238889wjx.21.2016.02.04.09.28.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 04 Feb 2016 09:28:53 -0800 (PST) From: Tomasz Nowicki To: bhelgaas@google.com, arnd@arndb.de, will.deacon@arm.com, catalin.marinas@arm.com, rjw@rjwysocki.net, hanjun.guo@linaro.org, Lorenzo.Pieralisi@arm.com, okaya@codeaurora.org, jiang.liu@linux.intel.com, Stefano.Stabellini@eu.citrix.com Cc: robert.richter@caviumnetworks.com, mw@semihalf.com, Liviu.Dudau@arm.com, ddaney@caviumnetworks.com, wangyijing@huawei.com, Suravee.Suthikulpanit@amd.com, msalter@redhat.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, linaro-acpi@lists.linaro.org, jchandra@broadcom.com, jcm@redhat.com, Tomasz Nowicki , Tomasz Nowicki Subject: [PATCH V4 01/23] x86, pci: Reorder logic of pci_mmconfig_insert() function Date: Thu, 4 Feb 2016 18:28:39 +0100 Message-Id: <1454606941-9523-2-git-send-email-tn@semihalf.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1454606941-9523-1-git-send-email-tn@semihalf.com> References: <1454606941-9523-1-git-send-email-tn@semihalf.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This patch is the first step for MMCONFIG refactoring process. Code that uses pci_mmcfg_lock will be moved to common file and become accessible for all architectures. pci_mmconfig_insert() cannot be moved so easily since it is mixing generic mmconfig code with x86 specific logic inside of mutual exclusive block guarded by pci_mmcfg_lock. To get rid of that constraint, we reorder actions as follow: 1. sanity check for mmconfig region presence, if we already have such region it doesn't make snese to alloc new mmconfig list entry 2. mmconfig entry allocation, no need to lock 3. insertion to iomem_resource has its own lock, no need to wrap it into mutex 4. insertion to mmconfig list can be done as the final step in separate function (candidate for further refactoring) and needs another mmconfig lookup to avoid race condition. Signed-off-by: Tomasz Nowicki Tested-by: Suravee Suthikulpanit Tested-by: Jeremy Linton Tested-by: Duc Dang Tested-by: Dongdong Liu Tested-by: Hanjun Guo Tested-by: Graeme Gregory Tested-by: Sinan Kaya --- arch/x86/pci/mmconfig-shared.c | 101 +++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index dd30b7e..c8bb9b0 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -720,6 +720,38 @@ static int __init pci_mmcfg_late_insert_resources(void) */ late_initcall(pci_mmcfg_late_insert_resources); +static int pci_mmconfig_inject(struct pci_mmcfg_region *cfg) +{ + struct pci_mmcfg_region *cfg_conflict; + int err = 0; + + mutex_lock(&pci_mmcfg_lock); + cfg_conflict = pci_mmconfig_lookup(cfg->segment, cfg->start_bus); + if (cfg_conflict) { + if (cfg_conflict->end_bus < cfg->end_bus) + pr_info(FW_INFO "MMCONFIG for " + "domain %04x [bus %02x-%02x] " + "only partially covers this bridge\n", + cfg_conflict->segment, cfg_conflict->start_bus, + cfg_conflict->end_bus); + err = -EEXIST; + goto out; + } + + if (pci_mmcfg_arch_map(cfg)) { + pr_warn("fail to map MMCONFIG %pR.\n", &cfg->res); + err = -ENOMEM; + goto out; + } else { + list_add_sorted(cfg); + pr_info("MMCONFIG at %pR (base %#lx)\n", + &cfg->res, (unsigned long)cfg->address); + } +out: + mutex_unlock(&pci_mmcfg_lock); + return err; +} + /* Add MMCFG information for host bridges */ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, phys_addr_t addr) @@ -734,63 +766,46 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, if (start > end) return -EINVAL; - mutex_lock(&pci_mmcfg_lock); + rcu_read_lock(); cfg = pci_mmconfig_lookup(seg, start); - if (cfg) { - if (cfg->end_bus < end) - dev_info(dev, FW_INFO - "MMCONFIG for " - "domain %04x [bus %02x-%02x] " - "only partially covers this bridge\n", - cfg->segment, cfg->start_bus, cfg->end_bus); - mutex_unlock(&pci_mmcfg_lock); + rcu_read_unlock(); + if (cfg) return -EEXIST; - } - if (!addr) { - mutex_unlock(&pci_mmcfg_lock); + if (!addr) return -EINVAL; - } - rc = -EBUSY; cfg = pci_mmconfig_alloc(seg, start, end, addr); - if (cfg == NULL) { + if (!cfg) { dev_warn(dev, "fail to add MMCONFIG (out of memory)\n"); - rc = -ENOMEM; - } else if (!pci_mmcfg_check_reserved(dev, cfg, 0)) { + return -ENOMEM; + } + + rc = -EBUSY; + if (!pci_mmcfg_check_reserved(dev, cfg, 0)) { dev_warn(dev, FW_BUG "MMCONFIG %pR isn't reserved\n", &cfg->res); - } else { - /* Insert resource if it's not in boot stage */ - if (pci_mmcfg_running_state) - tmp = insert_resource_conflict(&iomem_resource, - &cfg->res); - - if (tmp) { - dev_warn(dev, - "MMCONFIG %pR conflicts with " - "%s %pR\n", - &cfg->res, tmp->name, tmp); - } else if (pci_mmcfg_arch_map(cfg)) { - dev_warn(dev, "fail to map MMCONFIG %pR.\n", - &cfg->res); - } else { - list_add_sorted(cfg); - dev_info(dev, "MMCONFIG at %pR (base %#lx)\n", - &cfg->res, (unsigned long)addr); - cfg = NULL; - rc = 0; - } + goto error; } - if (cfg) { - if (cfg->res.parent) - release_resource(&cfg->res); - kfree(cfg); + /* Insert resource if it's not in boot stage */ + if (pci_mmcfg_running_state) + tmp = insert_resource_conflict(&iomem_resource, &cfg->res); + + if (tmp) { + dev_warn(dev, "MMCONFIG %pR conflicts with %s %pR\n", + &cfg->res, tmp->name, tmp); + goto error; } - mutex_unlock(&pci_mmcfg_lock); + rc = pci_mmconfig_inject(cfg); + if (!rc) + return 0; +error: + if (cfg->res.parent) + release_resource(&cfg->res); + kfree(cfg); return rc; }