From patchwork Wed Nov 28 14:43:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Robert Richter X-Patchwork-Id: 1004584 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=cavium.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="lWx6EgjT"; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=CAVIUMNETWORKS.onmicrosoft.com header.i=@CAVIUMNETWORKS.onmicrosoft.com header.b="JXVsLaDj"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 434k1D1Qj5z9s8J for ; Thu, 29 Nov 2018 01:43:44 +1100 (AEDT) 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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Content-ID:In-Reply-To: References:Message-ID:Date:Subject:To:From:Reply-To:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=kMY6PVAFzkD0pjLuWi41/JZIQn3IesO6REFCkeFRWdY=; b=lWx6EgjTvhKgsV J+M0bzHd1VmLP3Y1r02DxGZ+K4TFgoPwoEWUNWcku7FZEngxjzq5/pHNuqpC/6/S5WEtbn/JQJk84 Xz3TdUKSA9z7QZrvm8NsGCSKH1jjF+FTnI7U0uwotSQwmeVe/ECv6mj+2+67bsF4HU1270HaZ7Yij h0SyZLT3UDgy7bIPY3udxA5Arm7RzaPwjTf/mfDh5H9Sq6RXvQvT/gBQ4DD2vnqYfG1FoytlAbzvs dGPVlS/W2X9n82GQv+A3Mm7FGB2AhaLR/kwS/gG60WjH32SZAGDlN1VkbHyM1ab8pGj5JVVzk0Djn lHUplaaQUBLQSpr9ecdA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gS13y-0003J4-Hi; Wed, 28 Nov 2018 14:43:38 +0000 Received: from mail-eopbgr800052.outbound.protection.outlook.com ([40.107.80.52] helo=NAM03-DM3-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gS13f-0002zo-Cn for linux-arm-kernel@lists.infradead.org; Wed, 28 Nov 2018 14:43:21 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=CAVIUMNETWORKS.onmicrosoft.com; s=selector1-cavium-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=TYHCRlEizg5103RwzZTClabwWKofx1bNw4wZzNMVTmg=; b=JXVsLaDjZlwfoXiZv1LWuv8rJI9MsrvdU74w7LNSqqLAk2zJyOX83plUJZw2LFW5mn+RoTQg0toHjvxQ8hCHrQFeYIopkvl6FRCy2kskuYkiuzmM+TTmwO8hdm9yUG9OBltw3R3ij8mIiWCXjOtzbEXdJhxGubdyIEU0/ej7y7A= Received: from SN6PR07MB5326.namprd07.prod.outlook.com (52.135.105.33) by SN6PR07MB5182.namprd07.prod.outlook.com (52.135.101.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1361.16; Wed, 28 Nov 2018 14:43:07 +0000 Received: from SN6PR07MB5326.namprd07.prod.outlook.com ([fe80::ccc7:d111:7f3d:667d]) by SN6PR07MB5326.namprd07.prod.outlook.com ([fe80::ccc7:d111:7f3d:667d%4]) with mapi id 15.20.1361.018; Wed, 28 Nov 2018 14:43:07 +0000 From: Robert Richter To: Marc Zyngier , Thomas Gleixner , Jason Cooper Subject: [PATCH v2 01/10] irqdomain: Add interface to request an irq domain Thread-Topic: [PATCH v2 01/10] irqdomain: Add interface to request an irq domain Thread-Index: AQHUhyisHG0MwjEfWkSkFCadyWhX5A== Date: Wed, 28 Nov 2018 14:43:06 +0000 Message-ID: <20181128144240.28727-2-rrichter@cavium.com> References: <20181128144240.28727-1-rrichter@cavium.com> In-Reply-To: <20181128144240.28727-1-rrichter@cavium.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: AM6P194CA0042.EURP194.PROD.OUTLOOK.COM (2603:10a6:209:84::19) To SN6PR07MB5326.namprd07.prod.outlook.com (2603:10b6:805:73::33) x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [77.14.124.106] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; SN6PR07MB5182; 6:EH/OMymsIvzSsDqGmPwyZwwURgLiSQddk1TVBQF+I5RxrbJu8PwP9dIM/SLXtB1U1SZzjOl+B+BvmUM4dX8FAzA3zTvV8Az/TAdtJ4y5Xe7Gh8GjNLYonITX97Wy0GdTIk5s5d82npjJIjfuRbvUIbkPAa4Q4IBvDvYbT5kyiifUE8nXuIQLM/XkiXQ/B+YtuvW2jjVWRP5q5AHBI2ALN1zj7MxE3JVBsr0LFakvFxuUWv1c/vQTvaoR49bXPBeooJyXNzajX55uloer664xMpgbPnWW4flOZGO6iQGv4+jgQGEpPJQzoLDljywnXGj1kXt6075tq3+vPi97pn8D5dEpp3jAUikrtGPqlUcoJhlHxz5PVity24kRyofmxjz9Svf2vV3NHQXLWsKrlyR03Em3o90kv+xtYZVtQrJJOVCPeILWGabV4TacADV1QXvFa+bl7EUylEnstX65qfKVeg==; 5:S1+93suEWh9Z/WtWzzx2VeE3ECFv5odH3O5kEMK9HCM1Lqh/WwNlFJzWQF6Bpja4eP0tFFdq+kJ09c1B5RuDYnF57mmgluUz+H9al9l7XVsIgNz3tCHE//vN3oe88nzlipd9des/rxv8khmYbyz5MBrSo/mkNtL4M/vslYtDDnE=; 7:iL0z23IiXqXlFRzYnM5+WrijMEcXtb6WAMyoKAe9UErhXJQBa2E8OZeAzFrk2dBlXdxVe/vmAb51zJRiqm0V5U9xa9FEygz24KlGFzQLGre0ODUMlc9Zx7ew3opgfmNouNP4i07eI8DV96DyBWQGMg== x-ms-office365-filtering-correlation-id: 279c8a19-fca7-49d6-55f9-08d6553fcebd x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390098)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(2017052603328)(7153060)(7193020); SRVR:SN6PR07MB5182; x-ms-traffictypediagnostic: SN6PR07MB5182: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Robert.Richter@cavium.com; x-microsoft-antispam-prvs: x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(93006095)(93001095)(3002001)(10201501046)(3231443)(999002)(944501410)(52105112)(148016)(149066)(150057)(6041310)(20161123560045)(20161123562045)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(201708071742011)(7699051)(76991095); SRVR:SN6PR07MB5182; BCL:0; PCL:0; RULEID:; SRVR:SN6PR07MB5182; x-forefront-prvs: 0870212862 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(346002)(136003)(376002)(39860400002)(396003)(366004)(189003)(199004)(7416002)(5660300001)(6436002)(36756003)(54906003)(39060400002)(110136005)(446003)(11346002)(6116002)(3846002)(53936002)(97736004)(52116002)(76176011)(102836004)(4326008)(476003)(316002)(14454004)(2616005)(71190400001)(71200400001)(6512007)(1076002)(6506007)(7736002)(305945005)(486006)(81156014)(81166006)(386003)(72206003)(2906002)(575784001)(99286004)(68736007)(8936002)(478600001)(106356001)(186003)(105586002)(6486002)(14444005)(66066001)(26005)(25786009)(256004)(8676002); DIR:OUT; SFP:1101; SCL:1; SRVR:SN6PR07MB5182; H:SN6PR07MB5326.namprd07.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; received-spf: None (protection.outlook.com: cavium.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: 46ao3zkoKEoLH0zt/8JVxpIK+4+PVZg5NH1SmkaI6rhG+WgU0UMRAyTAlmZPLPSD6XQytD0hlqza0mXVrMzHnuexaNX5XohyVXpP0vj2UkooplXm7uFoD1F8iDfk8G7er/KsRFIFlr7BOXMIH9nI0sD/Xl1hNEtvMDTagYeQg15tOi2ZZa5IBgx5EpTYWzSBZMpT4FTEqDbgqXgyEV+Ve4HnfTFb8mGtTWWAbtHq1PSDACcBIRpY9KRAs5U1O3i8mk3/aqS5sD7e26Edo5UZmJb4VEnLQ3IKdKobP+uV7tSgXcSMtRDpIMuqjmE1T6muabQuacefRsmfJ0ktVIUfJfEJa00yGL8On/LnytCejZY= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: MIME-Version: 1.0 X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-Network-Message-Id: 279c8a19-fca7-49d6-55f9-08d6553fcebd X-MS-Exchange-CrossTenant-originalarrivaltime: 28 Nov 2018 14:43:06.5569 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR07MB5182 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181128_064319_482493_82D60A01 X-CRM114-Status: GOOD ( 22.91 ) X-Spam-Score: -0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [40.107.80.52 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.0 DKIMWL_WL_MED DKIMwl.org - Whitelisted Medium sender X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Lorenzo Pieralisi , Stuart Yoder , Julien Thierry , Will Deacon , "linux-kernel@vger.kernel.org" , "Richter, Robert" , Matthias Brugger , "linux-arm-kernel@lists.infradead.org" , Laurentiu Tudor Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org This patch introduces a new interface to allow irq domain initialization regardless of order dependencies. This is done by requesting a domain and registering a callback function that is called as soon as a domain becomes available. A typical irq domain initialization code is the following: Parent initialization: ... domain = msi_create_irq_domain(fwnode, info, parent); if (domain) irq_domain_update_bus_token(domain, bus_token); ... Child initialization: ... parent = irq_find_matching_fwnode(fwnode, bus_token); if (!parent) ... create_irq_domain(parent, ...); ... In case the parent is not yet available, the child initialization fails. Thus, the current implementation requires the parent domain being initialized before the child domain. With a complex irq domain hierarchy it becomes more and more difficult to grant that order as irq domains are enabled in separate subsystems. Care must be taken when initializing parent and child domains in the same initcall level. E.g. Arm's gic-v3-its implementation might have the following tree and dependencies: gic-v3 ├── its-node-0 │ ├── pci-host-0 │ ├── platform-bus │ ... ├── its-node-1 │ ├── pci-host-1 ... All domains must be initialized in top-down order of the tree. This patch introduces an interface that allows domain initialization without any order requirements, e.g. to be able to initialize the irq domains in the same initcall level. The following functions have been introduced to allow the registration of a callback handler: irq_domain_request_fwnode() irq_domain_request_host() Instead of using the irq_find_matching_fwnode() function and it's variants the child code replaces them with the new functions and looks e.g. like the following: ... irq_domain_request_fwnode(fwnode, bus_token, create_irq_domain, name, priv); ... Here, the callback function create_irq_domain() is called as soon as the parent becomes available. All registered handlers are stored in a list. With each update of the bus token using irq_domain_update_bus_ token(), the list is checked if that domain is requested by a handler and if that is the case it's callback function is called and the request removed from the list. With a late_initcall all requests from the list should already have been handled, otherwise all remaining requests are removed with an error reported. Signed-off-by: Robert Richter --- include/linux/irqdomain.h | 15 +++++ kernel/irq/irqdomain.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 068aa46f0d55..27e83803627d 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -311,6 +311,21 @@ static inline struct irq_domain *irq_find_host(struct device_node *node) return d; } +typedef int (*irq_domain_callback_t)(struct irq_domain *, void *); +int irq_domain_request_fwnode(struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token, + irq_domain_callback_t callback, + const char *name, void *priv); + +static inline int irq_domain_request_host(struct device_node *node, + enum irq_domain_bus_token bus_token, + irq_domain_callback_t callback, + void *priv) +{ + return irq_domain_request_fwnode(of_node_to_fwnode(node), bus_token, + callback, node->full_name, priv); +} + /** * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain. * @of_node: pointer to interrupt controller's device tree node. diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 3366d11c3e02..ebe628dad568 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -21,6 +21,7 @@ #include static LIST_HEAD(irq_domain_list); +static LIST_HEAD(irq_domain_requests); static DEFINE_MUTEX(irq_domain_mutex); static struct irq_domain *irq_default_domain; @@ -45,6 +46,111 @@ static inline void debugfs_remove_domain_dir(struct irq_domain *d) { } const struct fwnode_operations irqchip_fwnode_ops; EXPORT_SYMBOL_GPL(irqchip_fwnode_ops); +struct irq_domain_request { + struct list_head list; + struct fwnode_handle *fwnode; + enum irq_domain_bus_token bus_token; + irq_domain_callback_t callback; + char *name; + void *priv; +}; + +static void irq_domain_call_handler(struct irq_domain *domain, + irq_domain_callback_t callback, const char *name, void *priv) +{ + int ret; + + ret = callback(domain, priv); + if (ret) + pr_err("%s: Domain request handler failed: %d\n", + name, ret); + + of_node_put(irq_domain_get_of_node(domain)); +} + +static void irq_domain_free_request(struct irq_domain_request *request) +{ + kfree(request->name); + kfree(request); +} + +static void irq_domain_handle_requests(struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token) +{ + struct irq_domain *domain; + struct irq_domain_request *request; + + if (!fwnode) + return; +redo: + domain = irq_find_matching_fwnode(fwnode, bus_token); + if (!domain) + return; + + mutex_lock(&irq_domain_mutex); + + /* + * For serialization of irq domain updates make sure to handle + * (and remove) the request only if the domain still matches + * the request. + */ + if ((domain->fwnode != fwnode) || (domain->bus_token != bus_token)) { + mutex_unlock(&irq_domain_mutex); + goto redo; + } + + list_for_each_entry(request, &irq_domain_requests, list) { + if (request->fwnode != fwnode || + request->bus_token != bus_token) + continue; + + list_del(&request->list); + mutex_unlock(&irq_domain_mutex); + + irq_domain_call_handler(domain, request->callback, + request->name, request->priv); + irq_domain_free_request(request); + + goto redo; + } + + mutex_unlock(&irq_domain_mutex); +} + +static int __init irq_domain_drain_requests(void) +{ + struct irq_domain_request *request; + struct irq_domain *domain; + int ret = 0; +redo: + mutex_lock(&irq_domain_mutex); + + list_for_each_entry(request, &irq_domain_requests, list) { + list_del(&request->list); + mutex_unlock(&irq_domain_mutex); + + domain = irq_find_matching_fwnode(request->fwnode, + request->bus_token); + if (domain) { + irq_domain_call_handler(domain, request->callback, + request->name, request->priv); + } else { + ret = -ENODEV; + pr_err("%s-%d: Unhandled domain request\n", + request->name, request->bus_token); + } + + irq_domain_free_request(request); + + goto redo; + } + + mutex_unlock(&irq_domain_mutex); + + return ret; +} +late_initcall(irq_domain_drain_requests); + /** * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for * identifying an irq domain @@ -293,6 +399,8 @@ void irq_domain_update_bus_token(struct irq_domain *domain, debugfs_add_domain_dir(domain); mutex_unlock(&irq_domain_mutex); + + irq_domain_handle_requests(domain->fwnode, bus_token); } /** @@ -417,6 +525,61 @@ struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec, EXPORT_SYMBOL_GPL(irq_find_matching_fwspec); /** + * irq_domain_request_fwnode() - Requests a domain for a given fwspec + * @fwspec: FW specifier for an interrupt + * @bus_token: domain-specific data + * @callback: function to be called once domain becomes available + * @name: name to be used for fwnode + * @priv: private data to be passed to callback + * + * The callback function is called as soon as the domain is available. + */ +int irq_domain_request_fwnode(struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token, + irq_domain_callback_t callback, + const char *name, void *priv) +{ + struct irq_domain *parent; + struct irq_domain_request *request; + + if (!fwnode || bus_token == DOMAIN_BUS_ANY || !callback || !name) + return -EINVAL; + + parent = irq_find_matching_fwnode(fwnode, bus_token); + if (parent) { + irq_domain_call_handler(parent, callback, name, priv); + return 0; + } + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (!request) + return -ENOMEM; + + request->fwnode = fwnode; + request->bus_token = bus_token; + request->callback = callback; + request->name = kstrdup(name, GFP_KERNEL); + request->priv = priv; + INIT_LIST_HEAD(&request->list); + + if (!request->name) { + kfree(request); + return -ENOMEM; + } + + of_node_get(to_of_node(fwnode)); + + mutex_lock(&irq_domain_mutex); + list_add_tail(&request->list, &irq_domain_requests); + mutex_unlock(&irq_domain_mutex); + + /* recheck in case list changed */ + irq_domain_handle_requests(fwnode, bus_token); + + return 0; +} + +/** * irq_domain_check_msi_remap - Check whether all MSI irq domains implement * IRQ remapping *