From patchwork Fri Nov 11 13:58:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Gleixner X-Patchwork-Id: 18821 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp758895wru; Fri, 11 Nov 2022 06:06:41 -0800 (PST) X-Google-Smtp-Source: AA0mqf5pt3Y+2iJn0JxYA4IwUc211zWt293qc1jpJUjXVtT6Dy4sEXS6e6frFaNl8DBQFt77SnPr X-Received: by 2002:a63:1a59:0:b0:473:c377:b82 with SMTP id a25-20020a631a59000000b00473c3770b82mr1909287pgm.113.1668175601528; Fri, 11 Nov 2022 06:06:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668175601; cv=none; d=google.com; s=arc-20160816; b=QB7IDxv7cK25ApPmC8GLZGh5filw1OPppxAyzcLoyDJsFWgqRdpWpGDq/w5H4Bd1Im pzz3c5Q+berekFPdcKnf87VS84mehqlOUAmJnIZ9ssWdzVU2+8r49hp68FvjZe0MvxZ8 Vz0zC6HZCSDZAmZgZW+/KRbgopvTgDhWlHLHcTUbiundtiXIAn2Bu6TIuz8h2izp8UP9 sKxImUcM3qfpzZwakr9lXjUprDET0zTbF80yK3no4nNfq/JwoxfuKZ/XtukKBJN9Q2vy /gmXm0PcpfPSnsteUhygqFCLdxPXrWX38OQNIdIx+4BhCubqJVLz4EbjhvGVKfDpIlfP Q+Yg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:date:mime-version:references:subject:cc:to:from :dkim-signature:dkim-signature:message-id; bh=e8FMSieAN/nuamC9qf7yvRciPl3gkYlctlSfz55sfqw=; b=UI0YiHSPtXmf6H8YZAKN9X7NyZRcLYHilImC2f1fJpkHfy7lquWna5+6LQvuBW1gRF /7SWAQro57EorXOTXnfU091j5v4BTizVmrB1DV6sF0Y8h1YiWj5iEeLKZd8OjOckRKpI Iu1Ee/cN3Fuh3d6rzGsLrzw04enT3hRQvFmsMYxuqW6jmJ8ifZoF46qyAucLKxaUsB1E teci+YnjVC8c96cAHjK4MF4ZM+b061P6zO8n049fYi1LDsB8OhWjIrxm91he8b7yD4pS S4Jk7tPT3T5AI4+v3rci0H/UmrnlGCDyqB21um1MfzmBotCi8w577ZOjI/q4NpRdrRqc EnBA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=whPHvmGs; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id jc13-20020a17090325cd00b00186b280a430si2214561plb.242.2022.11.11.06.06.27; Fri, 11 Nov 2022 06:06:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=whPHvmGs; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234415AbiKKOFK (ORCPT + 99 others); Fri, 11 Nov 2022 09:05:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42164 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234082AbiKKOEo (ORCPT ); Fri, 11 Nov 2022 09:04:44 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2363987B2B; Fri, 11 Nov 2022 05:58:53 -0800 (PST) Message-ID: <20221111135205.368911521@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1668175094; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: references:references; bh=e8FMSieAN/nuamC9qf7yvRciPl3gkYlctlSfz55sfqw=; b=whPHvmGsSTEAxU0UpyWL+s2V98t8wQyMTkxmtcd3cFXgOGnWMjhx4YnxJWu8M+OFve1iEm 2kWzHThXQzkJZEDdJ+9EQpyEOLJryPs0CK/4lYS55RTgMuSWVTXxLvjJge6071up38G8z3 wPW65B7I/v5uiVDEb2yXTphln4iR2r2RDa/5hLeytVR/f0z4j+K8DcyxNbMFEHJLNAYeTI O0CSuItSz2dT03GPUIn7DqDRlrQBxvhMcn197ojQcoj8x6FRTqeaqahntGPSGiIax1pn4Z 9ORsvROp++bdSHkjnorAcyg606IZ5KyGkduPbjClPaizcHMI2fWXXKgArNyV0Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1668175094; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: references:references; bh=e8FMSieAN/nuamC9qf7yvRciPl3gkYlctlSfz55sfqw=; b=Easie5wEeQFjls8M+15mkYyIDobQYmQxU9KI3o95c+umHJwBwacQjMprgv1YGq2vfl5Pn8 uzq5ge9MfxJaxgAA== From: Thomas Gleixner To: LKML Cc: x86@kernel.org, Joerg Roedel , Will Deacon , linux-pci@vger.kernel.org, Bjorn Helgaas , Lorenzo Pieralisi , Marc Zyngier , Greg Kroah-Hartman , Jason Gunthorpe , Dave Jiang , Alex Williamson , Kevin Tian , Dan Williams , Logan Gunthorpe , Ashok Raj , Jon Mason , Allen Hubbe , "Ahmed S. Darwish" , Reinette Chatre Subject: [patch 02/33] genirq/msi: Provide struct msi_parent_ops References: <20221111133158.196269823@linutronix.de> MIME-Version: 1.0 Date: Fri, 11 Nov 2022 14:58:14 +0100 (CET) X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749208899665101927?= X-GMAIL-MSGID: =?utf-8?q?1749208899665101927?= MSI parent domains must have some control over the MSI domains which are built on top. On domain creation they need to fill in e.g. architecture specific chip callbacks or msi domain ops to make the outermost domain parent agnostic which is obviously required for architecture independence etc. The structure contains: 1) A bitfield which exposes the supported functional features. This allows to check for features and is also used in the initialization callback to mask out unsupported features when the actual domain implementation requests a broader range, e.g. on x86 PCI multi-MSI is only supported by remapping domains but not by the underlying vector domain. The PCI/MSI code can then always request multi-MSI support, but the resulting feature set after creation might not have it set. 2) An optional string prefix which is put in front of domain and chip names during creation of the MSI domain. That allows to keep the naming schemes e.g. on x86 where PCI-MSI domains have a IR- prefix when interrupt remapping is enabled. 3) An initialization callback to sanity check the domain info of the to be created MSI domain, to restrict features and to apply changes in MSI ops and interrupt chip callbacks to accomodate to the particular MSI parent implementation and/or the underlying hierarchy. Add a conveniance function to delegate the initialization from the MSI parent domain to an underlying domain in the hierarchy. Signed-off-by: Thomas Gleixner --- include/linux/irqdomain.h | 5 +++++ include/linux/msi.h | 20 ++++++++++++++++++++ kernel/irq/msi.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -46,6 +46,7 @@ struct irq_desc; struct cpumask; struct seq_file; struct irq_affinity_desc; +struct msi_parent_ops; #define IRQ_DOMAIN_IRQ_SPEC_PARAMS 16 @@ -134,6 +135,7 @@ struct irq_domain_chip_generic; * @pm_dev: Pointer to a device that can be utilized for power management * purposes related to the irq domain. * @parent: Pointer to parent irq_domain to support hierarchy irq_domains + * @msi_parent_ops: Pointer to MSI parent domain methods for per device domain init * * Revmap data, used internally by the irq domain code: * @revmap_size: Size of the linear map table @revmap[] @@ -157,6 +159,9 @@ struct irq_domain { #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY struct irq_domain *parent; #endif +#ifdef CONFIG_GENERIC_MSI_IRQ + const struct msi_parent_ops *msi_parent_ops; +#endif /* reverse map data. The linear map gets appended to the irq_domain */ irq_hw_number_t hwirq_max; --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -488,6 +488,26 @@ enum { }; +/** + * struct msi_parent_ops - MSI parent domain callbacks and configuration info + * + * @supported_flags: Required: The supported MSI flags of the parent domain + * @prefix: Optional: Prefix for the domain and chip name + * @init_dev_msi_info: Required: Callback for MSI parent domains to setup parent + * domain specific domain flags, domain ops and interrupt chip + * callbacks when a per device domain is created. + */ +struct msi_parent_ops { + u32 supported_flags; + const char *prefix; + bool (*init_dev_msi_info)(struct device *dev, struct irq_domain *domain, + struct irq_domain *real_parent, + struct msi_domain_info *info); +}; + +bool msi_parent_init_dev_msi_info(struct device *dev, struct irq_domain *domain, + struct irq_domain *real_parent, struct msi_domain_info *info); + int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force); --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -825,6 +825,42 @@ struct irq_domain *msi_create_irq_domain return domain; } +/** + * msi_parent_init_dev_msi_info - Delegate initialization of device MSI info to parent domain + * @dev: The device for which the domain should be created + * @domain: The domain which delegates + * @real_parent: The real parent domain of the to be initialized MSI domain + * @info: The MSI domain info to initialize + * + * Return: true on success, false otherwise + * + * This is the most complex problem of per device MSI domains and the + * underlying interrupt domain hierarchy: + * + * The device domain to be initialized requests the broadest feature set + * possible and the underlying domain hierarchy puts restrictions on it. + * + * That's working perfectly fine for a strict parent->device model, but it + * falls apart with a root_parent->real_parent->device chain because the + * intermediate 'real parent' can expand the capabilities which the + * 'root_parent' domain is providing. So that creates a classic hen and egg + * problem: Which entity is doing the restrictions/expansions? + * + * One solution is to let the root parent domain handle the initialization + * that's why there is the @domain and the @real_parent pointer. + */ +bool msi_parent_init_dev_msi_info(struct device *dev, struct irq_domain *domain, + struct irq_domain *real_parent, struct msi_domain_info *info) +{ + struct irq_domain *parent = domain->parent; + + if (WARN_ON_ONCE(!parent || !parent->msi_parent_ops || + !parent->msi_parent_ops->init_dev_msi_info)) + return false; + + return parent->msi_parent_ops->init_dev_msi_info(dev, parent, real_parent, info); +} + int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev, int nvec, msi_alloc_info_t *arg) {