From patchwork Tue May 26 12:49:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanjun Guo X-Patchwork-Id: 6479731 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 50498C0020 for ; Tue, 26 May 2015 12:53:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5ABED205C1 for ; Tue, 26 May 2015 12:53:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4934E20614 for ; Tue, 26 May 2015 12:53:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753139AbbEZMxR (ORCPT ); Tue, 26 May 2015 08:53:17 -0400 Received: from [209.85.192.174] ([209.85.192.174]:34819 "EHLO mail-pd0-f174.google.com" rhost-flags-FAIL-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1753117AbbEZMxP (ORCPT ); Tue, 26 May 2015 08:53:15 -0400 Received: by pdea3 with SMTP id a3so90223914pde.2 for ; Tue, 26 May 2015 05:50:24 -0700 (PDT) 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=Bpc/6Mda+qd+HsEVWDdbPhc46eVLDB5dYjHM6VRId2o=; b=C1OD9C3Ki8bA4/JDAg6/SMCuPflsV7XrvjopYvaG0hiaMG66wKVVWczuRVc84dAdr2 UENMScND8tU71EFKujkrbUilNajEI/5kke7z1gvbvUno/H7DgMq+ZA3ugbPy3bcOVtCj MeY3LC/4rhiaUjscdIvS8jkijHxQARNFSJsP2is8KryY9JvgwHJRJmnzmTQlo0D3d1P8 dRSoL2nKeEObwCZ7glPsNFfLKnziHqAhUUVarKcFRoWbwpP9s+L8jUP5cNVF2jI9Cctt 3QjH5zZsd4K9g3ZfBUKuH9VrZyRNxfQV3HmEwtRKxrKYbdEkikKgO+3jQyKQN8TNuEgw P4gg== X-Gm-Message-State: ALoCoQkXFEpA4kBnIJDuqgDZCfyUhFN1Drpby5u3ywtXZNL8LNpBlOde26qfR+tEK0ZAe1Il4Rld X-Received: by 10.68.65.17 with SMTP id t17mr49065487pbs.9.1432644624778; Tue, 26 May 2015 05:50:24 -0700 (PDT) Received: from localhost ([180.150.153.56]) by mx.google.com with ESMTPSA id nq2sm13047509pdb.70.2015.05.26.05.50.23 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Tue, 26 May 2015 05:50:24 -0700 (PDT) From: Hanjun Guo To: Bjorn Helgaas , Arnd Bergmann , Catalin Marinas , Will Deacon , "Rafael J. Wysocki" Cc: Jiang Liu , Liviu Dudau , Thomas Gleixner , Yijing Wang , Lorenzo Pieralisi , Tomasz Nowicki , Suravee Suthikulpanit , Mark Salter , 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, Hanjun Guo Subject: [PATCH 04/11] x86, pci: Reorder logic of pci_mmconfig_insert() function Date: Tue, 26 May 2015 20:49:17 +0800 Message-Id: <1432644564-24746-5-git-send-email-hanjun.guo@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1432644564-24746-1-git-send-email-hanjun.guo@linaro.org> References: <1432644564-24746-1-git-send-email-hanjun.guo@linaro.org> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 From: Tomasz Nowicki 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 Signed-off-by: Hanjun Guo Tested-by: Suravee Suthikulpanit --- arch/x86/pci/mmconfig-shared.c | 99 +++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 8b3bc4f..e770b70 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -834,6 +834,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) @@ -845,66 +877,43 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed) return -ENODEV; - if (start > end) + if ((start > end) || !addr) 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); - 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; + return -ENOMEM; } else 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; }