From patchwork Wed Jan 13 13:20:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 566934 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 C1C0F140C02 for ; Thu, 14 Jan 2016 00:29:34 +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=YLOFATS1; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758454AbcAMNVb (ORCPT ); Wed, 13 Jan 2016 08:21:31 -0500 Received: from mail-wm0-f48.google.com ([74.125.82.48]:37762 "EHLO mail-wm0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754776AbcAMNVU (ORCPT ); Wed, 13 Jan 2016 08:21:20 -0500 Received: by mail-wm0-f48.google.com with SMTP id f206so371454756wmf.0 for ; Wed, 13 Jan 2016 05:21:19 -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=PbtZbhkCDqaW02QRwzkYxQVUpqEdZzwEc8n3jJma3xM=; b=YLOFATS1+AdRDc0ZYb/fc1AS2hG0TfzRp8lc652AmaPjRJcxxSt9D60zxK1OfqyV5u uQlqu/s/e1ojQS2BcCGmHejdHvIUcaipj6n6hQ+KulkdoIg9D67IaeUi9ev/YuJeJ3EL auGTp33OrIH7n/W2xQgkxSioBg6zKuLrGLYuhoUYZfs2AZY7/SABD9U0GGW/h1hRe1xK PM3EKu3CUUVpoX5tS+VxPxs5+fdoqYBwZxx4zfk9ldARpvTL+kITWVko8VLZUIDRVECa ez9EXU+mYsq4m5Nbti+a9qCzV7AfifT3SUgRXJbAzKYEv2VOowxKc5OJ+pUkjO0FFHgL mNkA== 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=PbtZbhkCDqaW02QRwzkYxQVUpqEdZzwEc8n3jJma3xM=; b=CAfvH8Ldy9PvT5IjTkx75XZeunwaWyTmHCqfvI7b30q1Z5OnNndVid0Twr2937bXRc EnkM4GFS1bmyJ4AzNHJ4UwatlNIFpDzh8S9mRodb986NTkqDadgyw4i3/qFhvxvF5D9M rlvkYJTrWMYgRTXFOrsWzQ6jyrHuYsJZomdcwaK93HwXbHrMSSpp1XSrerCTqanFge8E 7skzbtu9X41gUAEY0TpWVGcweCiC4jFYJPjcoPNOKUudc5Tv9uANjRsRTITchEIbqQAx 3cB40/KZRnr0jsNCEaU6PyhsFXo9KaOSUuBf7vf03MQIdDKloPehDm0Rz4Rk/RvwCPA6 0ESQ== X-Gm-Message-State: ALoCoQmZTA0hYh1m70KT6Wdl4tFeHMr+AuFXk/aY/MlXPGduXYjFuAe4Ccy8VSqko8s++OV7hSUxBjINrDncWw2uHBnVbHh4DA== X-Received: by 10.28.8.142 with SMTP id 136mr27239127wmi.54.1452691278816; Wed, 13 Jan 2016 05:21:18 -0800 (PST) Received: from tn-HP-4.semihalf.local (cardhu.semihalf.com. [213.17.239.108]) by smtp.gmail.com with ESMTPSA id y124sm8858741wmg.3.2016.01.13.05.21.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 13 Jan 2016 05:21:17 -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, tglx@linutronix.de, 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 V3 01/21] x86, pci: Reorder logic of pci_mmconfig_insert() function Date: Wed, 13 Jan 2016 14:20:47 +0100 Message-Id: <1452691267-32240-2-git-send-email-tn@semihalf.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1452691267-32240-1-git-send-email-tn@semihalf.com> References: <1452691267-32240-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 --- 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; }