From patchwork Mon Dec 5 21:41:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: tip-bot2 for Thomas Gleixner X-Patchwork-Id: 29952 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2487423wrr; Mon, 5 Dec 2022 13:44:47 -0800 (PST) X-Google-Smtp-Source: AA0mqf7nj6flPAxSyZfNFsmrEgglUaGeoExncIvDI32IY/z582ju/BVKQZNUew06wavF9WwqXfUg X-Received: by 2002:a17:906:180e:b0:7a2:6d38:1085 with SMTP id v14-20020a170906180e00b007a26d381085mr54800823eje.114.1670276687295; Mon, 05 Dec 2022 13:44:47 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670276687; cv=none; d=google.com; s=arc-20160816; b=CPDiChcS3IvG+6DJ2Hk9dGrqzWvcZQE2nJOtsbW62OTVFr9nDq1f56Wj6xsOaRPIFQ sx8w375rx7J6+5X/eoE6Uf86c1S3Bb4x/3M4zp/wNuyKeYTu989myHdXcCiAyIyI3UIV QulBMn9GWwvz9qbS7sMxMzm1RP+X8n/mJEYViVt6MTct5BavpHuqEdV/0mW2RHm28v4/ roOtSerPKxNyqJMGcySg/g5jdXzXY2kWTyEBkC2FEy5DTgcogRpzhHbPULby6Ft5TzML Q8beZgk3/TMfqnursMafltRZUQDnQlj62u9b5pQSsEPWD6tnsLjnZaTlfTAECykklr/5 vDaw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:robot-unsubscribe :robot-id:message-id:mime-version:references:in-reply-to:cc:subject :to:reply-to:sender:from:dkim-signature:dkim-signature:date; bh=PFyZt2kTroGdJGvrhcnPCI5y1KcdBRPvXEWgQfUajk4=; b=AhxEDA5tuoGc0hvur/jmgfSZPOfwQP13LsOMRrx8UN+T3YzM/bG70RuBsxXNnvGFjb MFaFm9IctrpXivblx3sSk6euXeG3jXHbXI3J6GX2ZrGXreDJmLypSW8MTxrr/pPnfcLy NT6PmypA/yX64UxC5v9HrIfIi34jiOTQKJYsVxlS0zfQ1C45nDxPTPuY3vpRkPJCUuL7 lYGpElPIysa2aoFdlgztRZ+do3W1BFQwjKCih2eT4s052BZIT6RU+hrUKWbZ8qVKqeIT qO3CeExX/pQZsQBvjtxoLhY31KidMG29eAu8lVPzFArWq0VgALeKpeRtwUwq8XtMwo02 EQfQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=4ZK3fjH8; 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 g23-20020a170906349700b007addbdb9fbbsi8057632ejb.558.2022.12.05.13.44.23; Mon, 05 Dec 2022 13:44:47 -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=4ZK3fjH8; 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 S234065AbiLEVnD (ORCPT + 99 others); Mon, 5 Dec 2022 16:43:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40938 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233854AbiLEVly (ORCPT ); Mon, 5 Dec 2022 16:41:54 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A44F2CDF8; Mon, 5 Dec 2022 13:41:52 -0800 (PST) Date: Mon, 05 Dec 2022 21:41:48 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1670276508; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PFyZt2kTroGdJGvrhcnPCI5y1KcdBRPvXEWgQfUajk4=; b=4ZK3fjH8P8YlhnwW3RrLP+ujQk+eJICnSOsT2ppJ5HHsShLFUwBhcuqk1NPpLXhZFhZmHY T3lduC6ttZv1fL9DAwJAmnIoqScqtCoAp9UtXPIg15XQ86RNsQwmrdYuncsUbyS6RmSHsP 4305/d06UZ7xKYLiYOcsURFD1lt+ihg3lQOe8YycDshMtJxT6uqhnizRwsKoQV85SX5+Ti UlY7tT8WyExRU+S66gr1bPPQCICCs7ZeBpzCsMs277vjNLgPMuJpvhF7Ceki+qSg1FsLhS bpPvlREcqE8DIvciA2s8OBPpw1SD+xKXiwDnkd6R/wYsIQjS/v0TjGVC/OmA6Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1670276508; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PFyZt2kTroGdJGvrhcnPCI5y1KcdBRPvXEWgQfUajk4=; b=+vkHG/otYjUEdGSxqqBdB7/wy2rW0Rd6PfLZ2/1iZmZX+Q+47PhhRJgIC20rGKy00JGEoc CKzYDe2bEkKZekBA== From: "tip-bot2 for Thomas Gleixner" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: irq/core] genirq/msi: Provide msi_domain_alloc_irq_at() Cc: Thomas Gleixner , Kevin Tian , Marc Zyngier , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20221124232326.501359457@linutronix.de> References: <20221124232326.501359457@linutronix.de> MIME-Version: 1.0 Message-ID: <167027650807.4906.1258890273217247689.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails 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?1750422786015106480?= X-GMAIL-MSGID: =?utf-8?q?1751412047452626983?= The following commit has been merged into the irq/core branch of tip: Commit-ID: 3d393b21740bffbeeae7d4fa534a6b16c3e3e832 Gitweb: https://git.kernel.org/tip/3d393b21740bffbeeae7d4fa534a6b16c3e3e832 Author: Thomas Gleixner AuthorDate: Fri, 25 Nov 2022 00:26:18 +01:00 Committer: Thomas Gleixner CommitterDate: Mon, 05 Dec 2022 22:22:34 +01:00 genirq/msi: Provide msi_domain_alloc_irq_at() For supporting post MSI-X enable allocations and for the upcoming PCI/IMS support a separate interface is required which allows not only the allocation of a specific index, but also the allocation of any, i.e. the next free index. The latter is especially required for IMS because IMS completely does away with index to functionality mappings which are often found in MSI/MSI-X implementation. But even with MSI-X there are devices where only the first few indices have a fixed functionality and the rest is freely assignable by software, e.g. to queues. msi_domain_alloc_irq_at() is also different from the range based interfaces as it always enforces that the MSI descriptor is allocated by the core code and not preallocated by the caller like the PCI/MSI[-X] enable code path does. msi_domain_alloc_irq_at() can be invoked with the index argument set to MSI_ANY_INDEX which makes the core code pick the next free index. The irq domain can provide a prepare_desc() operation callback in it's msi_domain_ops to do domain specific post allocation initialization before the actual Linux interrupt and the associated interrupt descriptor and hierarchy alloccations are conducted. The function also takes an optional @icookie argument which is of type union msi_instance_cookie. This cookie is not used by the core code and is stored in the allocated msi_desc::data::icookie. The meaning of the cookie is completely implementation defined. In case of IMS this might be a PASID or a pointer to a device queue, but for the MSI core it's opaque and not used in any way. The function returns a struct msi_map which on success contains the allocated index number and the Linux interrupt number so the caller can spare the index to Linux interrupt number lookup. On failure map::index contains the error code and map::virq is 0. Signed-off-by: Thomas Gleixner Reviewed-by: Kevin Tian Acked-by: Marc Zyngier Link: https://lore.kernel.org/r/20221124232326.501359457@linutronix.de --- include/linux/msi.h | 4 +- include/linux/msi_api.h | 7 +++- kernel/irq/msi.c | 105 +++++++++++++++++++++++++++++++++++---- 3 files changed, 106 insertions(+), 10 deletions(-) diff --git a/include/linux/msi.h b/include/linux/msi.h index cb0bee3..00c5019 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -80,6 +80,7 @@ struct pci_dev; struct platform_msi_priv_data; struct device_attribute; struct irq_domain; +struct irq_affinity_desc; void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg); #ifdef CONFIG_GENERIC_MSI_IRQ @@ -602,6 +603,9 @@ int msi_domain_alloc_irqs_range(struct device *dev, unsigned int domid, unsigned int first, unsigned int last); int msi_domain_alloc_irqs_all_locked(struct device *dev, unsigned int domid, int nirqs); +struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, unsigned int index, + const struct irq_affinity_desc *affdesc, + union msi_instance_cookie *cookie); void msi_domain_free_irqs_range_locked(struct device *dev, unsigned int domid, unsigned int first, unsigned int last); diff --git a/include/linux/msi_api.h b/include/linux/msi_api.h index 2e4456e..5ae72d1 100644 --- a/include/linux/msi_api.h +++ b/include/linux/msi_api.h @@ -48,6 +48,13 @@ struct msi_map { int virq; }; +/* + * Constant to be used for dynamic allocations when the allocation is any + * free MSI index, which is either an entry in a hardware table or a + * software managed index. + */ +#define MSI_ANY_INDEX UINT_MAX + unsigned int msi_domain_get_virq(struct device *dev, unsigned int domid, unsigned int index); /** diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 6370ea5..bd4d4dd 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -90,17 +90,30 @@ static int msi_insert_desc(struct device *dev, struct msi_desc *desc, int ret; hwsize = msi_domain_get_hwsize(dev, domid); - if (index >= hwsize) { - ret = -ERANGE; - goto fail; - } - desc->msi_index = index; - ret = xa_insert(xa, index, desc, GFP_KERNEL); - if (ret) - goto fail; - return 0; + if (index == MSI_ANY_INDEX) { + struct xa_limit limit = { .min = 0, .max = hwsize - 1 }; + unsigned int index; + /* Let the xarray allocate a free index within the limit */ + ret = xa_alloc(xa, &index, desc, limit, GFP_KERNEL); + if (ret) + goto fail; + + desc->msi_index = index; + return 0; + } else { + if (index >= hwsize) { + ret = -ERANGE; + goto fail; + } + + desc->msi_index = index; + ret = xa_insert(xa, index, desc, GFP_KERNEL); + if (ret) + goto fail; + return 0; + } fail: msi_free_desc(desc); return ret; @@ -294,7 +307,7 @@ int msi_setup_device_data(struct device *dev) } for (i = 0; i < MSI_MAX_DEVICE_IRQDOMAINS; i++) - xa_init(&md->__domains[i].store); + xa_init_flags(&md->__domains[i].store, XA_FLAGS_ALLOC); /* * If @dev::msi::domain is set and is a global MSI domain, copy the @@ -1402,6 +1415,78 @@ int msi_domain_alloc_irqs_all_locked(struct device *dev, unsigned int domid, int return msi_domain_alloc_locked(dev, &ctrl); } +/** + * msi_domain_alloc_irq_at - Allocate an interrupt from a MSI interrupt domain at + * a given index - or at the next free index + * + * @dev: Pointer to device struct of the device for which the interrupts + * are allocated + * @domid: Id of the interrupt domain to operate on + * @index: Index for allocation. If @index == %MSI_ANY_INDEX the allocation + * uses the next free index. + * @affdesc: Optional pointer to an interrupt affinity descriptor structure + * @icookie: Optional pointer to a domain specific per instance cookie. If + * non-NULL the content of the cookie is stored in msi_desc::data. + * Must be NULL for MSI-X allocations + * + * This requires a MSI interrupt domain which lets the core code manage the + * MSI descriptors. + * + * Return: struct msi_map + * + * On success msi_map::index contains the allocated index number and + * msi_map::virq the corresponding Linux interrupt number + * + * On failure msi_map::index contains the error code and msi_map::virq + * is %0. + */ +struct msi_map msi_domain_alloc_irq_at(struct device *dev, unsigned int domid, unsigned int index, + const struct irq_affinity_desc *affdesc, + union msi_instance_cookie *icookie) +{ + struct msi_ctrl ctrl = { .domid = domid, .nirqs = 1, }; + struct irq_domain *domain; + struct msi_map map = { }; + struct msi_desc *desc; + int ret; + + msi_lock_descs(dev); + domain = msi_get_device_domain(dev, domid); + if (!domain) { + map.index = -ENODEV; + goto unlock; + } + + desc = msi_alloc_desc(dev, 1, affdesc); + if (!desc) { + map.index = -ENOMEM; + goto unlock; + } + + if (icookie) + desc->data.icookie = *icookie; + + ret = msi_insert_desc(dev, desc, domid, index); + if (ret) { + map.index = ret; + goto unlock; + } + + ctrl.first = ctrl.last = desc->msi_index; + + ret = __msi_domain_alloc_irqs(dev, domain, &ctrl); + if (ret) { + map.index = ret; + msi_domain_free_locked(dev, &ctrl); + } else { + map.index = desc->msi_index; + map.virq = desc->irq; + } +unlock: + msi_unlock_descs(dev); + return map; +} + static void __msi_domain_free_irqs(struct device *dev, struct irq_domain *domain, struct msi_ctrl *ctrl) {