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: 9972469 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BFCFD6037E for ; Tue, 26 Sep 2017 18:03:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AC69428D65 for ; Tue, 26 Sep 2017 18:03:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A0E6628D78; Tue, 26 Sep 2017 18:03:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EB88428D65 for ; Tue, 26 Sep 2017 18:03:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=MvndlozHfPt4DAGkR+PD9nFp/wJWe3EgpCzDISaImqY=; b=Cc7ZKsg72wlaCEatN3EoV8mYmM Ak9qcyud/5EnRjGTJl7xAMR6D3SNZT+oDhfl5g6ERuaXWjSHw3hPJjWvCsoCMZJjXFQieCLP1SNCr OHX97pQhhP1nWVvqK82YYIGDOXCeydXQTzewl1n/NxsmF4zF4A3L46xqK8GEWQKHT9BTEENX1RmLa BSScz1DMNLn77kEUyvrSuAVWp8ovUrtfGebb91LzjfJjluiHXATWznpmuaDlnn70KrfcyJ/rwBaW1 fCcN7y0Dhnj6JVtg0Y+/2k/BHoQwnIV9cRx6+pxyLyNmZTVQJdfhCkpiewXR/qFj7K2CjIhDZRVgq T3gp4H2A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dwuCl-0003do-Gf; Tue, 26 Sep 2017 18:03:35 +0000 Received: from [198.137.200.161] (helo=denmail01.amcc.com) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dwtzd-0000PK-Lz for linux-arm-kernel@lists.infradead.org; Tue, 26 Sep 2017 17:50:09 +0000 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 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> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170926_105001_960992_111EDA2A X-CRM114-Status: GOOD ( 18.62 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: rjw@rjwysocki.net, Khuong Dinh , patches@apm.com, linux-kernel@vger.kernel.org, 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-Virus-Scanned: ClamAV using ClamSMTP 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__ */