From patchwork Fri Apr 15 17:06:46 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 611054 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 3qmkWW5jdfz9t3Z for ; Sat, 16 Apr 2016 03:08:07 +1000 (AEST) 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=Y8C0Ijl4; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752904AbcDORHj (ORCPT ); Fri, 15 Apr 2016 13:07:39 -0400 Received: from mail-wm0-f51.google.com ([74.125.82.51]:36053 "EHLO mail-wm0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753171AbcDORHg (ORCPT ); Fri, 15 Apr 2016 13:07:36 -0400 Received: by mail-wm0-f51.google.com with SMTP id v188so39802555wme.1 for ; Fri, 15 Apr 2016 10:07:35 -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=YDe7UXF8BwEXCA5MVrlU1gYg3/PiV6KJPx0dwtG/y3g=; b=Y8C0Ijl4Z841XJxRztsLrhrNiZadsAmJEWFKweEpP5A71ri4iCR3hdxKhIeC0LdA2i /3wShMIb4pfdorwl+5xyO8slJWpHhtB46FTis7wWD4iDBsRW6UrKfkdbAgvBjZ1u7zq4 bLqox6sY8qQNWKnhOEaFOVVxObnmudcWLcxdmnuSH4ynMpiGNZSWDrArAKurh4giYRdl ONqDbyVor+MpVBdHLNG+7h+01QepEqLxcvFFGZXnJa7h62QciiQPHtI/3lGgmtrG9CbX Ahnqiqr0tYOVW/Dd+ufM3LzRaxOMxvaZehQppHpgwkY2QfZAFoM7/ueQlr7JXDt7dV9t PlSQ== 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=YDe7UXF8BwEXCA5MVrlU1gYg3/PiV6KJPx0dwtG/y3g=; b=CJaznA7+3dRrKyDBjcRYchOn6VMGVuSGv3ldiI1BCEXUVBVKEJfZcaYu2hcjcgE+Al 4pnsMvZm/yMRkicHId2Ie6Q43lkggdq2DbP2QJStXRjDiRnRckNJkuC8jr/wmurh+oxS tzIhDovTR3JRaGWa34Bo7Oytr/jOgktJolDuq9ziLr4erwuUfsjWnauE/vGSOrC0HJ0Y f3mP6ixreYOZq2Zca7lGmPkp7VvFfGYMeRHlg51QEQVSkEQLEI34PaYtstA9vEFcgyjO 394GoOKpvDaf2SE9rnD1WiYrAqeDKeHhAYabfgwhBF2DM3r+TnEw2dX64Z2Rx33h6mDW oqFA== X-Gm-Message-State: AOPr4FVsOgQ6JU57vwhrxRAloajxBsuKuZVmDd1xZsGbKX45ymvPhAgCwQNdmRMboIW8eg== X-Received: by 10.28.168.72 with SMTP id r69mr5340999wme.37.1460740054726; Fri, 15 Apr 2016 10:07:34 -0700 (PDT) Received: from tn-HP-4.semihalf.local (cardhu.semihalf.com. [213.17.239.108]) by smtp.gmail.com with ESMTPSA id gr4sm14282723wjd.23.2016.04.15.10.07.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 15 Apr 2016 10:07:33 -0700 (PDT) From: Tomasz Nowicki To: helgaas@kernel.org, arnd@arndb.de, will.deacon@arm.com, catalin.marinas@arm.com, rafael@kernel.org, hanjun.guo@linaro.org, Lorenzo.Pieralisi@arm.com, okaya@codeaurora.org, jiang.liu@linux.intel.com, jchandra@broadcom.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, jcm@redhat.com, Tomasz Nowicki Subject: [PATCH V6 11/13] pci, acpi: Match PCI config space accessors against platfrom specific quirks. Date: Fri, 15 Apr 2016 19:06:46 +0200 Message-Id: <1460740008-19489-12-git-send-email-tn@semihalf.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1460740008-19489-1-git-send-email-tn@semihalf.com> References: <1460740008-19489-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 Some platforms may not be fully compliant with generic set of PCI config accessors. For these cases we implement the way to overwrite accessors set prior to PCI buses enumeration. Algorithm traverses available quirk list, matches against tuple and an extra match call and returns corresponding PCI config ops. All quirks can be defined using: DECLARE_ACPI_MCFG_FIXUP() macro and kept self contained. Example: /* Additional DMI platform identification (optional) */ static const struct dmi_system_id foo_dmi[] = { { .ident = "", .matches = { DMI_MATCH(DMI_SYS_VENDOR, ""), DMI_MATCH(DMI_PRODUCT_NAME, ""), DMI_MATCH(DMI_PRODUCT_VERSION, "product version"), }, }, { } }; /* Custom PCI config ops */ static struct pci_generic_ecam_ops foo_pci_ops = { .bus_shift = 24, .pci_ops = { .map_bus = pci_mcfg_dev_base, .read = foo_ecam_config_read, .write = foo_ecam_config_write, } }; static int foo_match(struct pci_mcfg_fixup *fixup, struct acpi_pci_root *root) { if (additional platform identification) return true; return false; } DECLARE_ACPI_MCFG_FIXUP(foo_dmi, foo_init, &foo_root_ops, , ); Signed-off-by: Tomasz Nowicki --- drivers/acpi/pci_gen_host.c | 30 +++++++++++++++++++++++++++++- include/asm-generic/vmlinux.lds.h | 7 +++++++ include/linux/pci-acpi.h | 18 ++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_gen_host.c b/drivers/acpi/pci_gen_host.c index fd360b5..e55dfca 100644 --- a/drivers/acpi/pci_gen_host.c +++ b/drivers/acpi/pci_gen_host.c @@ -11,6 +11,8 @@ * You should have received a copy of the GNU General Public License * version 2 (GPLv2) along with this source code. */ + +#include #include #include #include @@ -54,6 +56,32 @@ static struct mcfg_entry *pci_mcfg_lookup(u16 seg, u8 bus_start) return NULL; } +extern struct pci_cfg_fixup __start_acpi_mcfg_fixups[]; +extern struct pci_cfg_fixup __end_acpi_mcfg_fixups[]; + +static struct pci_generic_ecam_ops *pci_acpi_get_ops(struct acpi_pci_root *root) +{ + int bus_num = root->secondary.start; + int domain = root->segment; + struct pci_cfg_fixup *f; + + /* + * Match against platform specific quirks and return corresponding + * CAM ops. + * + * First match against PCI topology then use DMI or + * custom match handler. + */ + for (f = __start_acpi_mcfg_fixups; f < __end_acpi_mcfg_fixups; f++) { + if ((f->domain == domain || f->domain == PCI_MCFG_DOMAIN_ANY) && + (f->bus_num == bus_num || f->bus_num == PCI_MCFG_BUS_ANY) && + (f->system ? dmi_check_system(f->system) : 1) && + (f->match ? f->match(f, root) : 1)) + return f->ops; + } + /* No quirks, use ECAM */ + return &pci_generic_ecam_default_ops; +} /* * Lookup the bus range for the domain in MCFG, and set up config space @@ -95,7 +123,7 @@ static int pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root, } cfg = pci_generic_ecam_create(&root->device->dev, addr, bus_start, - bus_end, &pci_generic_ecam_default_ops); + bus_end, pci_acpi_get_ops(root)); if (IS_ERR(cfg)) { err = PTR_ERR(cfg); pr_err("%04x:%02x-%02x error %d mapping CAM\n", seg, diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 339125b..c53b6b7 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -298,6 +298,13 @@ VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .; \ } \ \ + /* ACPI MCFG quirks */ \ + .acpi_fixup : AT(ADDR(.acpi_fixup) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start_acpi_mcfg_fixups) = .; \ + *(.acpi_fixup_mcfg) \ + VMLINUX_SYMBOL(__end_acpi_mcfg_fixups) = .; \ + } \ + \ /* Built-in firmware blobs */ \ .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start_builtin_fw) = .; \ diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index a72e22d..9545988 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -71,6 +71,24 @@ struct acpi_pci_root_ops { int (*prepare_resources)(struct acpi_pci_root_info *info); }; +struct pci_cfg_fixup { + const struct dmi_system_id *system; + bool (*match)(struct pci_cfg_fixup *, struct acpi_pci_root *); + struct pci_generic_ecam_ops *ops; + int domain; + int bus_num; +}; + +#define PCI_MCFG_DOMAIN_ANY -1 +#define PCI_MCFG_BUS_ANY -1 + +/* Designate a routine to fix up buggy MCFG */ +#define DECLARE_ACPI_MCFG_FIXUP(system, match, ops, dom, bus) \ + static const struct pci_cfg_fixup __mcfg_fixup_##system##dom##bus\ + __used __attribute__((__section__(".acpi_fixup_mcfg"), \ + aligned((sizeof(void *))))) = \ + { system, match, ops, dom, bus }; + extern int acpi_pci_probe_root_resources(struct acpi_pci_root_info *info); extern struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, struct acpi_pci_root_ops *ops,