From patchwork Fri Sep 9 19:24:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 9324201 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 70213607D3 for ; Fri, 9 Sep 2016 19:25:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 57D6B29871 for ; Fri, 9 Sep 2016 19:25:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4784229FC9; Fri, 9 Sep 2016 19:25:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8846D29FB0 for ; Fri, 9 Sep 2016 19:25:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754720AbcIITY5 (ORCPT ); Fri, 9 Sep 2016 15:24:57 -0400 Received: from mail-lf0-f50.google.com ([209.85.215.50]:35726 "EHLO mail-lf0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754487AbcIITYy (ORCPT ); Fri, 9 Sep 2016 15:24:54 -0400 Received: by mail-lf0-f50.google.com with SMTP id l131so50873678lfl.2 for ; Fri, 09 Sep 2016 12:24:49 -0700 (PDT) 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=AO2dfgYnZ40rLWVG+1EdPkvYvZD+w0LjlJsWgABY374=; b=z2e8mUu6rjqdRBqvZ7NL/npF/HEbW+TBv8CWLxONgXADQcHV+WMWOd+d9X00d4QHhI XSYYn1WBXqHZytZTbmbbnZFaipyyQy3CaQRMrH2Au4vdgbUjSyRhac626xDvC40AQEGT vo4e04XmT4ynmf1eihoeqtrNa7DJSUfm5m+91BA/G8piDMPpUMEMaga/5Jm8ksKCiIPm yTxu3ov/ynkhk0FWUgJH+xmH9pT9mZFHtuhh98Q6edTsmeH4lBguGJyphMtjoBCebQdZ pNnu+TukGw06CeSq2SZocBilJregLItYa9GqgWLDkc7+e9cqDCG0eFB2uZkIEYULjbkB xYPA== 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=AO2dfgYnZ40rLWVG+1EdPkvYvZD+w0LjlJsWgABY374=; b=ZS03Z2pw0HdX8cX5z3y147Njhc3FRt90b7C7BEF4TJfSzfDXCH0Acw0SHasi7z7276 N/np6dSOCoe258IUkZstfZ5GFYVQvW036jwCSoDUL+lnpxxgX7lE4Tc2+rwmmlkOTqTX wjlrov4kvaf0LX73w35yb9Kft4DxgCJCO7RX9FzquHmIFDNip2l+xiKsn1wJ9Pdk73VV CnUfyWmBzu55m34b5KH5t5fJ/Mm5CEvQA+Wa4naFfLU41o5FEsaORjUcSIyayd0GmD5L /Jnr+FrWnQB/haHJOHoyAKqiMMp0WW0pMqXQWHAczpjHS8j9uWHMayBeGj1FIWmUPegH fpoQ== X-Gm-Message-State: AE9vXwOOSR4G88+UfKppuBLoQHUA/E0D8SvFdHAM9PA12DuFBP4Bda+Uute3Yy8wdmuGXQ== X-Received: by 10.25.16.101 with SMTP id f98mr1976134lfi.54.1473449087992; Fri, 09 Sep 2016 12:24:47 -0700 (PDT) Received: from localhost.localdomain (bbservice74.mmpnet215.tnp.pl. [87.116.215.74]) by smtp.gmail.com with ESMTPSA id 143sm846673ljj.2.2016.09.09.12.24.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 09 Sep 2016 12:24:47 -0700 (PDT) From: Tomasz Nowicki To: helgaas@kernel.org, will.deacon@arm.com, catalin.marinas@arm.com, rafael@kernel.org, Lorenzo.Pieralisi@arm.com Cc: arnd@arndb.de, hanjun.guo@linaro.org, okaya@codeaurora.org, jchandra@broadcom.com, cov@codeaurora.org, dhdang@apm.com, ard.biesheuvel@linaro.org, robert.richter@caviumnetworks.com, mw@semihalf.com, Liviu.Dudau@arm.com, ddaney@caviumnetworks.com, wangyijing@huawei.com, msalter@redhat.com, linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linaro-acpi@lists.linaro.org, jcm@redhat.com, andrea.gallo@linaro.org, jeremy.linton@arm.com, liudongdong3@huawei.com, gabriele.paoloni@huawei.com, jhugo@codeaurora.org, linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, Tomasz Nowicki Subject: [PATCH V6 2/5] PCI/ACPI: Check platform specific ECAM quirks Date: Fri, 9 Sep 2016 21:24:04 +0200 Message-Id: <1473449047-10499-3-git-send-email-tn@semihalf.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1473449047-10499-1-git-send-email-tn@semihalf.com> References: <1473449047-10499-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 X-Virus-Scanned: ClamAV using ClamSMTP Some platforms may not be fully compliant with generic set of PCI config accessors. For these cases we implement the way to overwrite CFG accessors set and configuration space range. In first place pci_mcfg_parse() saves machine's IDs and revision number (these come from MCFG header) in order to match against known quirk entries. Then the algorithm traverses available quirk list (static array), matches against and returns custom PCI config ops and/or CFG resource structure. When adding new quirk there are two possibilities: 1. Override default pci_generic_ecam_ops ops but CFG resource comes from MCFG { "OEM_ID", "OEM_TABLE_ID", , , , &foo_ops, MCFG_RES_EMPTY }, 2. Override default pci_generic_ecam_ops ops and CFG resource. For this case it is also allowed get CFG resource from quirk entry w/o having it in MCFG. { "OEM_ID", "OEM_TABLE_ID", , , , &boo_ops, DEFINE_RES_MEM(START, SIZE) }, pci_generic_ecam_ops and MCFG entries will be used for platforms free from quirks. Signed-off-by: Tomasz Nowicki Signed-off-by: Dongdong Liu Signed-off-by: Christopher Covington --- drivers/acpi/pci_mcfg.c | 80 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c index ffcc651..2b8acc7 100644 --- a/drivers/acpi/pci_mcfg.c +++ b/drivers/acpi/pci_mcfg.c @@ -32,6 +32,59 @@ struct mcfg_entry { u8 bus_start; u8 bus_end; }; +struct mcfg_fixup { + char oem_id[ACPI_OEM_ID_SIZE + 1]; + char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; + u32 oem_revision; + u16 seg; + struct resource bus_range; + struct pci_ecam_ops *ops; + struct resource cfgres; +}; + +#define MCFG_DOM_ANY (-1) +#define MCFG_BUS_RANGE(start, end) DEFINE_RES_NAMED((start), \ + ((end) - (start) + 1), \ + NULL, IORESOURCE_BUS) +#define MCFG_BUS_ANY MCFG_BUS_RANGE(0x0, 0xff) +#define MCFG_RES_EMPTY DEFINE_RES_NAMED(0, 0, NULL, 0) + +static struct mcfg_fixup mcfg_quirks[] = { +/* { OEM_ID, OEM_TABLE_ID, REV, DOMAIN, BUS_RANGE, cfgres, ops }, */ +}; + +static char mcfg_oem_id[ACPI_OEM_ID_SIZE]; +static char mcfg_oem_table_id[ACPI_OEM_TABLE_ID_SIZE]; +static u32 mcfg_oem_revision; + +static void pci_mcfg_match_quirks(struct acpi_pci_root *root, + struct resource *cfgres, + struct pci_ecam_ops **ecam_ops) +{ + struct mcfg_fixup *f; + int i; + + /* + * First match against PCI topology then use OEM ID, OEM + * table ID, and OEM revision from MCFG table standard header. + */ + for (i = 0, f = mcfg_quirks; i < ARRAY_SIZE(mcfg_quirks); i++, f++) { + if (f->seg == root->segment && + resource_contains(&f->bus_range, &root->secondary) && + !memcmp(f->oem_id, mcfg_oem_id, ACPI_OEM_ID_SIZE) && + !memcmp(f->oem_table_id, mcfg_oem_table_id, + ACPI_OEM_TABLE_ID_SIZE) && + f->oem_revision == mcfg_oem_revision) { + if (f->cfgres.start) + *cfgres = f->cfgres; + if (f->ops) + *ecam_ops = f->ops; + dev_info(&root->device->dev, "Applying PCI MCFG quirks for %s %s rev: %d\n", + f->oem_id, f->oem_table_id, f->oem_revision); + return; + } + } +} /* List to save MCFG entries */ static LIST_HEAD(pci_mcfg_list); @@ -61,14 +114,24 @@ int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres, } - if (!root->mcfg_addr) - return -ENXIO; - skip_lookup: memset(&res, 0, sizeof(res)); - res.start = root->mcfg_addr + (bus_res->start << 20); - res.end = res.start + (resource_size(bus_res) << 20) - 1; - res.flags = IORESOURCE_MEM; + if (root->mcfg_addr) { + res.start = root->mcfg_addr + (bus_res->start << 20); + res.end = res.start + (resource_size(bus_res) << 20) - 1; + res.flags = IORESOURCE_MEM; + } + + /* + * Let to override default ECAM ops and CFG resource range. + * Also, this might even retrieve CFG resource range in case MCFG + * does not have it. Invalid CFG start address means MCFG firmware bug + * or we need another quirk in array. + */ + pci_mcfg_match_quirks(root, &res, &ops); + if (!res.start) + return -ENXIO; + *cfgres = res; *ecam_ops = ops; return 0; @@ -101,6 +164,11 @@ static __init int pci_mcfg_parse(struct acpi_table_header *header) list_add(&e->list, &pci_mcfg_list); } + /* Save MCFG IDs and revision for quirks matching */ + memcpy(mcfg_oem_id, header->oem_id, ACPI_OEM_ID_SIZE); + memcpy(mcfg_oem_table_id, header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); + mcfg_oem_revision = header->revision; + pr_info("MCFG table detected, %d entries\n", n); return 0; }