From patchwork Tue Sep 26 17:49:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Khuong Dinh X-Patchwork-Id: 818769 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y1pw71t4pz9t3x for ; Wed, 27 Sep 2017 04:12:55 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1031342AbdIZSM3 (ORCPT ); Tue, 26 Sep 2017 14:12:29 -0400 Received: from [198.137.200.161] ([198.137.200.161]:58415 "EHLO denmail01.amcc.com" rhost-flags-FAIL-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1031301AbdIZSM0 (ORCPT ); Tue, 26 Sep 2017 14:12:26 -0400 Received: from apm.com (denlwv018.amcc.com [10.88.160.121]) by denmail01.amcc.com (8.13.8/8.13.8) with ESMTP id v8QHnbDv001998; Tue, 26 Sep 2017 11:49:37 -0600 Received: (from kdinh@localhost) by apm.com (8.14.4/8.14.4/Submit) id v8QHnbKp031009; Tue, 26 Sep 2017 11:49:37 -0600 From: Khuong Dinh To: lorenzo.pieralisi@arm.com, marc.zyngier@arm.com, msalter@redhat.com, bhelgaas@google.com, linux-pci@vger.kernel.org, jcm@redhat.com Cc: patches@apm.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rjw@rjwysocki.net, Khuong Dinh Subject: [PATCH v4 pci 1/2] PCI/MSI: pci-xgene-msi: Enable MSI support in ACPI boot for X-Gene v1 Date: Tue, 26 Sep 2017 11:49:20 -0600 Message-Id: <1506448161-30961-2-git-send-email-kdinh@apm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1506448161-30961-1-git-send-email-kdinh@apm.com> References: <1506448161-30961-1-git-send-email-kdinh@apm.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This patch makes pci-xgene-msi driver ACPI-aware and provides MSI capability for X-Gene v1 PCIe controllers in ACPI boot mode. Signed-off-by: Khuong Dinh [Take over from Duc Dang] --- drivers/pci/host/pci-xgene-msi.c | 38 +++++++++++++++++++++++++++++++++++--- 1 files changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c index 1f42a20..d657248 100644 --- a/drivers/pci/host/pci-xgene-msi.c +++ b/drivers/pci/host/pci-xgene-msi.c @@ -4,6 +4,7 @@ * Copyright (c) 2014, Applied Micro Circuits Corporation * Author: Tanmay Inamdar * Duc Dang + * Khuong Dinh * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -24,6 +25,7 @@ #include #include #include +#include #define MSI_IR0 0x000000 #define MSI_INT0 0x800000 @@ -39,7 +41,7 @@ struct xgene_msi_group { }; struct xgene_msi { - struct device_node *node; + struct fwnode_handle *fwnode; struct irq_domain *inner_domain; struct irq_domain *msi_domain; u64 msi_addr; @@ -249,6 +251,13 @@ static void xgene_irq_domain_free(struct irq_domain *domain, .free = xgene_irq_domain_free, }; +#ifdef CONFIG_ACPI +static struct fwnode_handle *xgene_msi_get_fwnode(struct device *dev) +{ + return xgene_msi_ctrl.fwnode; +} +#endif + static int xgene_allocate_domains(struct xgene_msi *msi) { msi->inner_domain = irq_domain_add_linear(NULL, NR_MSI_VEC, @@ -256,7 +265,7 @@ static int xgene_allocate_domains(struct xgene_msi *msi) if (!msi->inner_domain) return -ENOMEM; - msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(msi->node), + msi->msi_domain = pci_msi_create_irq_domain(msi->fwnode, &xgene_msi_domain_info, msi->inner_domain); @@ -265,6 +274,9 @@ static int xgene_allocate_domains(struct xgene_msi *msi) return -ENOMEM; } +#ifdef CONFIG_ACPI + pci_msi_register_fwnode_provider(&xgene_msi_get_fwnode); +#endif return 0; } @@ -449,6 +461,14 @@ static int xgene_msi_hwirq_free(unsigned int cpu) {}, }; +#ifdef CONFIG_ACPI +static const struct acpi_device_id xgene_msi_acpi_ids[] = { + {"APMC0D0E", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, xgene_msi_acpi_ids); +#endif + static int xgene_msi_probe(struct platform_device *pdev) { struct resource *res; @@ -469,7 +489,18 @@ static int xgene_msi_probe(struct platform_device *pdev) goto error; } xgene_msi->msi_addr = res->start; - xgene_msi->node = pdev->dev.of_node; + + xgene_msi->fwnode = of_node_to_fwnode(pdev->dev.of_node); + if (!xgene_msi->fwnode) { + xgene_msi->fwnode = + irq_domain_alloc_fwnode((void *)xgene_msi->msi_addr); + if (!xgene_msi->fwnode) { + dev_err(&pdev->dev, "Failed to create fwnode\n"); + rc = ENOMEM; + goto error; + } + } + xgene_msi->num_cpus = num_possible_cpus(); rc = xgene_msi_init_allocator(xgene_msi); @@ -540,6 +571,7 @@ static int xgene_msi_probe(struct platform_device *pdev) .driver = { .name = "xgene-msi", .of_match_table = xgene_msi_match_table, + .acpi_match_table = ACPI_PTR(xgene_msi_acpi_ids), }, .probe = xgene_msi_probe, .remove = xgene_msi_remove, From patchwork Tue Sep 26 17:49:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Khuong Dinh X-Patchwork-Id: 818771 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pci-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y1pwT48vxz9t49 for ; Wed, 27 Sep 2017 04:13:13 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1031150AbdIZSMz (ORCPT ); Tue, 26 Sep 2017 14:12:55 -0400 Received: from [198.137.200.161] ([198.137.200.161]:58415 "EHLO denmail01.amcc.com" rhost-flags-FAIL-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1030942AbdIZSM2 (ORCPT ); Tue, 26 Sep 2017 14:12:28 -0400 Received: from apm.com (denlwv018.amcc.com [10.88.160.121]) by denmail01.amcc.com (8.13.8/8.13.8) with ESMTP id v8QHne6J002001; Tue, 26 Sep 2017 11:49:40 -0600 Received: (from kdinh@localhost) by apm.com (8.14.4/8.14.4/Submit) id v8QHneaI031012; Tue, 26 Sep 2017 11:49:40 -0600 From: Khuong Dinh To: lorenzo.pieralisi@arm.com, marc.zyngier@arm.com, msalter@redhat.com, bhelgaas@google.com, linux-pci@vger.kernel.org, jcm@redhat.com Cc: patches@apm.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, rjw@rjwysocki.net, Khuong Dinh Subject: [PATCH v4 pci 2/2] PCI/MSI: Enforce MSI driver loaded before PCIe in ACPI boot Date: Tue, 26 Sep 2017 11:49:21 -0600 Message-Id: <1506448161-30961-3-git-send-email-kdinh@apm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1506448161-30961-1-git-send-email-kdinh@apm.com> References: <1506448161-30961-1-git-send-email-kdinh@apm.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This patch enforces MSI driver loaded before PCIe controller driver in ACPI boot mode. Signed-off-by: Khuong Dinh --- drivers/acpi/Makefile | 2 +- drivers/acpi/acpi_msi.c | 86 ++++++++++++++++++++++++++++++++++++++ drivers/acpi/acpi_platform.c | 3 +- drivers/acpi/internal.h | 1 + drivers/acpi/scan.c | 1 + drivers/pci/host/pci-xgene-msi.c | 22 +++++++++- include/linux/acpi_msi.h | 37 ++++++++++++++++ 7 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 drivers/acpi/acpi_msi.c create mode 100644 include/linux/acpi_msi.h diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 90265ab..b33247e 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -40,7 +40,7 @@ acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o obj-$(CONFIG_ACPI_MCFG) += pci_mcfg.o -acpi-y += acpi_lpss.o acpi_apd.o +acpi-y += acpi_lpss.o acpi_apd.o acpi_msi.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o diff --git a/drivers/acpi/acpi_msi.c b/drivers/acpi/acpi_msi.c new file mode 100644 index 0000000..a254e84 --- /dev/null +++ b/drivers/acpi/acpi_msi.c @@ -0,0 +1,86 @@ +/* + * Enforce MSI driver loaded before PCIe controller driver + * + * Copyright (c) 2017, MACOM Technology Solutions Corporation + * Author: Khuong Dinh + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include "internal.h" +#include + +struct msi_driver_item { + struct list_head msi_drv_list; + struct platform_driver *addr; + unsigned char id[ACPI_ID_LEN]; +}; + +static LIST_HEAD(msi_drv_list); + +static acpi_status acpi_create_msi_device(acpi_handle handle, u32 Level, + void *context, void **retval) +{ + acpi_status status = AE_OK; + int result; + + acpi_scan_lock_acquire(); + result = acpi_bus_scan(handle); + acpi_scan_lock_release(); + if (result) { + status = AE_ERROR; + goto out; + } + result = platform_driver_register((struct platform_driver *) context); + if (result) { + status = AE_ERROR; + goto out; + } +out: + return status; +} + +void __init acpi_msi_init(void) +{ + struct msi_driver_item *current_msi; + struct list_head *pos; + + list_for_each(pos, &msi_drv_list) { + current_msi = list_entry(pos, struct msi_driver_item, + msi_drv_list); + if (!current_msi) + return; + + acpi_get_devices(current_msi->id, + acpi_create_msi_device, + (void *) current_msi->addr, + NULL); + } +} + +void acpi_msi_drv_subscribe(struct acpi_device_id msi_acpi_ids, + struct platform_driver *msi) +{ + struct msi_driver_item *new_msi; + + if (!msi) + return; + + new_msi = kmalloc(sizeof(*new_msi), GFP_KERNEL); + if (!new_msi) + return; + + list_add(&(new_msi->msi_drv_list), &msi_drv_list); + new_msi->addr = msi; + strncpy(new_msi->id, msi_acpi_ids.id, sizeof(new_msi->id)); + new_msi->id[sizeof(new_msi->id) - 1] = '\0'; +} diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 88cd949..a546076 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -44,7 +44,8 @@ static void acpi_platform_fill_resource(struct acpi_device *adev, * If the device has parent we need to take its resources into * account as well because this device might consume part of those. */ - parent = acpi_get_first_physical_node(adev->parent); + parent = adev->parent ? + acpi_get_first_physical_node(adev->parent) : NULL; if (parent && dev_is_pci(parent)) dest->parent = pci_find_resource(to_pci_dev(parent), dest); } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 4361c44..ec81801 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -80,6 +80,7 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, void acpi_lpss_init(void); void acpi_apd_init(void); +void acpi_msi_init(void); acpi_status acpi_hotplug_schedule(struct acpi_device *adev, u32 src); bool acpi_queue_hotplug_work(struct work_struct *work); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 602f8ff..f1d7b96 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2110,6 +2110,7 @@ int __init acpi_scan_init(void) acpi_status status; struct acpi_table_stao *stao_ptr; + acpi_msi_init(); acpi_pci_root_init(); acpi_pci_link_init(); acpi_processor_init(); diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/host/pci-xgene-msi.c index d657248..327e663 100644 --- a/drivers/pci/host/pci-xgene-msi.c +++ b/drivers/pci/host/pci-xgene-msi.c @@ -26,6 +26,7 @@ #include #include #include +#include #define MSI_IR0 0x000000 #define MSI_INT0 0x800000 @@ -577,8 +578,25 @@ static int xgene_msi_probe(struct platform_device *pdev) .remove = xgene_msi_remove, }; -static int __init xgene_pcie_msi_init(void) +static int __init xgene_pcie_msi_subscribe(void) { + int i; + + for (i = 0; i < sizeof(xgene_msi_acpi_ids) + / sizeof(xgene_msi_acpi_ids[0]) - 1; i++) + acpi_msi_drv_subscribe(xgene_msi_acpi_ids[i], + &xgene_msi_driver); + return 0; +} + +static int __init xgene_pcie_msi_register(void) +{ + if (driver_find(xgene_msi_driver.driver.name, &platform_bus_type)) + return -EBUSY; + return platform_driver_register(&xgene_msi_driver); } -subsys_initcall(xgene_pcie_msi_init); + +pure_initcall(xgene_pcie_msi_subscribe); + +module_init(xgene_pcie_msi_register); diff --git a/include/linux/acpi_msi.h b/include/linux/acpi_msi.h new file mode 100644 index 0000000..f132416 --- /dev/null +++ b/include/linux/acpi_msi.h @@ -0,0 +1,37 @@ +/* + * Enforce MSI driver loaded before PCIe controller driver library + * + * Copyright (c) 2017, MACOM Technology Solutions Corporation + * Author: Khuong Dinh + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ACPI_MSI_H__ +#define __ACPI_MSI_H__ + +#include + +/** + * acpi_msi_drv_subscribe - Allow MSI drivers to subscribe its driver + * information (acpi device id and platform driver address) such that + * the ACPI driver layer probes its first before the controller + * enumerated. This enforce that the MSI driver is always probed + * before the PCIe controller driver. + * + * @msi_acpi_ids: The MSI ACPI devive. + * @msi: The MSI platform driver. + * + */ +void acpi_msi_drv_subscribe(struct acpi_device_id msi_acpi_ids, + struct platform_driver *msi); + +#endif /* __ACPI_MSI_H__ */