From patchwork Tue Feb 16 13:53:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 8325881 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 35A17C02AA for ; Tue, 16 Feb 2016 13:55:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0EF76202A1 for ; Tue, 16 Feb 2016 13:55:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5B9E220295 for ; Tue, 16 Feb 2016 13:54:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932595AbcBPNy2 (ORCPT ); Tue, 16 Feb 2016 08:54:28 -0500 Received: from mail-wm0-f52.google.com ([74.125.82.52]:34581 "EHLO mail-wm0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932621AbcBPNyT (ORCPT ); Tue, 16 Feb 2016 08:54:19 -0500 Received: by mail-wm0-f52.google.com with SMTP id b205so111068503wmb.1 for ; Tue, 16 Feb 2016 05:54:18 -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=pEXWiSliKRTY7Z0yhoUv3tNJ/LuM0iBC1DFioFSgWZs=; b=pAL0GkkEnq9aawh66ApO3fTeql9ZA6ka/24uf3/wmv0MJe4wKG3KBf/hnqg45CQfG3 3xDrDz9k0ExPL82FldvC3dk76KsFknAf4bicMXrmi2An8M1CuhukLSq7XzGUTLWVcGbc HrHQkatZ5FTYjVxSkrWT+HcN0wnqbvHZrfkUdb12Y0MegYpV6OMg9Rd1mpKOzydZ2MOx dq8HODcojxpBFECd/tEGgW66IDou3u7lgPW4bKkyD9Nb3uIUZBE0D82G/cbyRiSuWNwg MK+P7SHAeQ0cWF5gaUXiI2GfLcg1z7Qt8z0amSMgTuZo8qAwPu3RK/awgdg6NHR5yWyJ FM+Q== 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=pEXWiSliKRTY7Z0yhoUv3tNJ/LuM0iBC1DFioFSgWZs=; b=CYEJOab8lZwe9Wc8TjmF3KzmRR1/B5xATz9M+VYi749dUfUdtHjjGjgBvpO1TLaeE0 abk1kmpO1ugP2xIRC2i/bbkmFsPSB2HTjK1AeTtT0EDHOgh5OcHKirGFVJl8g9Y5tUXg QSJYjBI3l5UesdqBgS0MU75zBh0S/UivNotdBA71g976iTp/QEZRM/bqqzqWp18Gnxmd F9HFh7FJiru5tczA/zGi3KCkTGrdX2xKnbjS5/LKF+7utz7bIk2z+gfcNj0ALujHoulR urKzQ8riekbm6pc0boMAzEGGTLK8oWbrj5PiGb0uTGcsaM08rdezYaYkNqrBqlMblgBg 08XQ== X-Gm-Message-State: AG10YOTThHrtLjQ5Ei3bknBKbbxR2EzHhMtBpwfPymwLxlFXjhrXreRvmZQjElnOR2U61g== X-Received: by 10.28.111.135 with SMTP id c7mr20727416wmi.46.1455630857793; Tue, 16 Feb 2016 05:54:17 -0800 (PST) Received: from tn-HP-4.semihalf.local ([80.82.22.190]) by smtp.gmail.com with ESMTPSA id q129sm20833462wmd.14.2016.02.16.05.54.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 16 Feb 2016 05:54:16 -0800 (PST) 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, 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, jcm@redhat.com, Tomasz Nowicki Subject: [PATCH V5 13/15] pci, acpi: Match PCI config space accessors against platfrom specific quirks. Date: Tue, 16 Feb 2016 14:53:43 +0100 Message-Id: <1455630825-27253-14-git-send-email-tn@semihalf.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1455630825-27253-1-git-send-email-tn@semihalf.com> References: <1455630825-27253-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-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,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 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 returns corresponding accessors. All quirks can be defined using: DECLARE_ACPI_MCFG_FIXUP() and kept self contained. Example, static const struct dmi_system_id foo_dmi[] = { { .ident = "", .callback = , .matches = { DMI_MATCH(DMI_SYS_VENDOR, ""), DMI_MATCH(DMI_PRODUCT_NAME, ""), DMI_MATCH(DMI_PRODUCT_VERSION, "product version"), }, }, { } }; static struct pci_ops foo_ecam_pci_ops = { .map_bus = pci_mcfg_dev_base, .read = foo_ecam_config_read, .write = foo_ecam_config_write, }; DECLARE_ACPI_MCFG_FIXUP(foo_dmi, NULL, &foo_ecam_pci_ops, , ); More custom (non-DMI) matching can be done via an extra call. Note that there is possibility to assign quirk related private data to root->sysdata which will be available along read/wriate accessor, example: static int boo_match(struct pci_mcfg_fixup *fixup, struct acpi_pci_root *root) { return [condition] ? 1 : 0; } int boo_ecam_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { struct acpi_pci_root *root = bus->sysdata; struct boo_priv_data *boo_data = root->sysdata; [..] } static struct pci_ops boo_ecam_pci_ops = { .map_bus = pci_mcfg_dev_base, .read = boo_ecam_config_read, .write = boo_ecam_config_write, }; DECLARE_ACPI_MCFG_FIXUP(NULL, boo_match, &boo_ecam_pci_ops, , ); Signed-off-by: Tomasz Nowicki Tested-by: Duc Dang Tested-by: Dongdong Liu Tested-by: Hanjun Guo Tested-by: Graeme Gregory Tested-by: Sinan Kaya --- drivers/acpi/pci_mcfg.c | 32 ++++++++++++++++++++++++++++++-- include/acpi/acpi_bus.h | 1 + include/asm-generic/vmlinux.lds.h | 7 +++++++ include/linux/pci-acpi.h | 18 ++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c index 0062257..b343547 100644 --- a/drivers/acpi/pci_mcfg.c +++ b/drivers/acpi/pci_mcfg.c @@ -41,6 +41,29 @@ int __weak raw_pci_write(unsigned int domain, unsigned int bus, return PCIBIOS_DEVICE_NOT_FOUND; } +extern struct pci_mcfg_fixup __start_acpi_mcfg_fixups[]; +extern struct pci_mcfg_fixup __end_acpi_mcfg_fixups[]; + +static struct pci_ops *pci_mcfg_check_quirks(struct acpi_pci_root *root) +{ + struct pci_mcfg_fixup *f; + int bus_num = root->secondary.start; + int domain = root->segment; + + /* + * 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; + } + return NULL; +} + void __iomem * pci_mcfg_dev_base(struct pci_bus *bus, unsigned int devfn, int offset) { @@ -63,10 +86,15 @@ static struct pci_ops default_pci_mcfg_ops = { struct pci_ops *pci_mcfg_get_ops(struct acpi_pci_root *root) { + struct pci_ops *pci_mcfg_ops_quirk; + /* - * TODO: Match against platform specific quirks and return - * corresponding PCI config space accessor set. + * Match against platform specific quirks and return corresponding + * PCI config space accessor set. */ + pci_mcfg_ops_quirk = pci_mcfg_check_quirks(root); + if (pci_mcfg_ops_quirk) + return pci_mcfg_ops_quirk; return &default_pci_mcfg_ops; } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 14362a8..0fc6f13 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -556,6 +556,7 @@ struct acpi_pci_root { struct pci_bus *bus; u16 segment; struct resource secondary; /* downstream bus range */ + void *sysdata; u32 osc_support_set; /* _OSC state of support bits */ u32 osc_control_set; /* _OSC state of control bits */ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c4bd0e2..c93fc97 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 93feb04..9e1bedd 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -123,6 +123,24 @@ struct pci_mmcfg_region { bool hot_added; }; +struct pci_mcfg_fixup { + const struct dmi_system_id *system; + int (*match)(struct pci_mcfg_fixup *, struct acpi_pci_root *); + struct pci_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_mcfg_fixup __mcfg_fixup_##system##dom##bus\ + __used __attribute__((__section__(".acpi_fixup_mcfg"), \ + aligned((sizeof(void *))))) = \ + { system, match, ops, dom, bus }; + extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus); extern struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start, int end, u64 addr);