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: 8326371 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 07E8F9F38B for ; Tue, 16 Feb 2016 14:01:44 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EE41120268 for ; Tue, 16 Feb 2016 14:01:39 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4FBF520263 for ; Tue, 16 Feb 2016 14:01:37 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aVgAL-0007ot-Ou; Tue, 16 Feb 2016 13:59:45 +0000 Received: from mail-wm0-x22a.google.com ([2a00:1450:400c:c09::22a]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aVg5Q-0002EO-9Z for linux-arm-kernel@lists.infradead.org; Tue, 16 Feb 2016 13:54:45 +0000 Received: by mail-wm0-x22a.google.com with SMTP id g62so153834820wme.0 for ; Tue, 16 Feb 2016 05:54: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=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=A/uf+Dqga3VMl6uj8QqvUlMisRv6JQcXIruONtIWAzuaDgtSXyxrw1spa0NPk49SVO IUrEseUh/fqft0sfoQahXqzmurLOVO50jUeUflu0OB1YPsdZLV43KGLtF6xZRIy0tDd4 lopN6wgCX5BPBorOVCHo1KRZNy+RWoOfDweUINbtC47LE/1DyFq41sDArM6WFNeTp6P9 atTa0iBZtqIWLQa9vjLdLJDsOfXcWEsJFzYF42/gpUxomZqqRJL5zaP+d1hFG8uXKiLz i8Jq7FvZjlNJRHKhLA7lZ5yjDZI2rg9MZB5gY8+U99povvmtsllVCJ/BKiOchMCITxS9 7L1w== X-Gm-Message-State: AG10YORhJkesDUZP3fsaE9EXr4d1ojbJ1tIkgtTHKFJ+wnMgKEgoGjqZb/aYH2QqAwkS7Q== 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 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> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160216_055440_838073_3888955A X-CRM114-Status: GOOD ( 16.55 ) X-Spam-Score: -2.6 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jcm@redhat.com, linaro-acpi@lists.linaro.org, linux-pci@vger.kernel.org, Liviu.Dudau@arm.com, ddaney@caviumnetworks.com, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, robert.richter@caviumnetworks.com, Suravee.Suthikulpanit@amd.com, msalter@redhat.com, wangyijing@huawei.com, Tomasz Nowicki , mw@semihalf.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,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);