From patchwork Wed Jan 13 13:21:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Nowicki X-Patchwork-Id: 566916 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 7A01014076E for ; Thu, 14 Jan 2016 00:22:56 +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=my4LqZxv; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752877AbcAMNWh (ORCPT ); Wed, 13 Jan 2016 08:22:37 -0500 Received: from mail-wm0-f41.google.com ([74.125.82.41]:34088 "EHLO mail-wm0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933434AbcAMNV5 (ORCPT ); Wed, 13 Jan 2016 08:21:57 -0500 Received: by mail-wm0-f41.google.com with SMTP id u188so297602216wmu.1 for ; Wed, 13 Jan 2016 05:21:57 -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=PlnOk5LCsufAyY5kYJWH57iNpMUTj5hI3JZLHO3Bokw=; b=my4LqZxvWwNfhpbA4ypZyZMu5pvjvbweZRiRz7YnajF5tB1naHduz4shAT7GKZGVBg tge01c3zhmIO9iuos0HNKxSHgG8jJOxQIG2wSYLFN8Ctg2CX4Lv2sZXJ4Vn6LdGf1ZbW fMARZ4e4Ou8Nf0IMEMvY9B2XHNw30QrsE8dYgjbyqWQXw/5SAf03CCyPwgGMrcfVbm2w vVjufsat1SMjS8oKkvxGovZp64zmlwkHkmWNLL5GML1LY1UK/izEI+EZRZBN5I4F00fl FLrtb7mEd9kgfjCOkaJVL6XNhyG0NX/RBUoidiW2SaN1niJY7AwaFgn+fYnVTUUJb0m0 G3cg== 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=PlnOk5LCsufAyY5kYJWH57iNpMUTj5hI3JZLHO3Bokw=; b=TbMTleOzeYeWTCwt13kT9mRPzEDVGMDF0iLj28iHqHMq5DqQDUPq9d42yswLelS6s1 hThivQKVzhzaL8mvD+pFH0T0qUsGEQoN+gQwSK6iyTD5FVYNoVL8aWY8Wg+DNnpK5CyL iKRZTU9EckYEkZX07CbIc1ukCwZaJyMtKZ2OIsnkeYtohfhmnVSacizJfLpDEBIUajjs 9MaldWczx8hwjdqbb+avgSRIsIcp7TDc5hcj70mNxsxILxXN4Senma3Pr6eKPLE+8A3p O8pMCP8Jq3q/VGhrxHpcCiMSLFPV0gLZvt1iRnFMkhhrcsudI4GafTK1d5quqnXuu7cL OKAQ== X-Gm-Message-State: ALoCoQmxLewjM2JYn3bcyXWqMmpA7cHx9VKoZw+K8T13pWIHF9zZiX+2kslC54yp3kt8y2fEjPSfJIYiTL7CnliIKYxWF5DGWg== X-Received: by 10.194.88.73 with SMTP id be9mr142810237wjb.44.1452691316547; Wed, 13 Jan 2016 05:21:56 -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.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 13 Jan 2016 05:21:55 -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 Subject: [PATCH V3 20/21] pci, acpi: Match PCI config space accessors against platfrom specific quirks. Date: Wed, 13 Jan 2016 14:21:06 +0100 Message-Id: <1452691267-32240-21-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 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 keep 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 alternative 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 --- drivers/acpi/mcfg.c | 33 +++++++++++++++++++++++++++++++-- include/acpi/acpi_bus.h | 1 + include/asm-generic/vmlinux.lds.h | 7 +++++++ include/linux/ecam.h | 18 ++++++++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/mcfg.c b/drivers/acpi/mcfg.c index dfc2d14..ec5fe7b 100644 --- a/drivers/acpi/mcfg.c +++ b/drivers/acpi/mcfg.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -34,6 +35,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) : 0 || + f->match ? f->match(f, root) : 0)) + return f->ops; + } + return NULL; +} + void __iomem * pci_mcfg_dev_base(struct pci_bus *bus, unsigned int devfn, int offset) { @@ -56,10 +80,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 ad0a5ff..ea4d2b5 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -554,6 +554,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/ecam.h b/include/linux/ecam.h index e0f322e..21215be 100644 --- a/include/linux/ecam.h +++ b/include/linux/ecam.h @@ -20,6 +20,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 }; + struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus); struct pci_mmcfg_region *pci_mmconfig_alloc(int segment, int start, int end, u64 addr);