From patchwork Mon Dec 6 22:51:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Gleixner X-Patchwork-Id: 12660317 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 26458C4321E for ; Mon, 6 Dec 2021 22:51:21 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.240127.416559 (Exim 4.92) (envelope-from ) id 1muMpC-0000l2-4X; Mon, 06 Dec 2021 22:51:10 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 240127.416559; Mon, 06 Dec 2021 22:51:10 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1muMpB-0000js-Vf; Mon, 06 Dec 2021 22:51:09 +0000 Received: by outflank-mailman (input) for mailman id 240127; Mon, 06 Dec 2021 22:51:09 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1muMpB-0000Tb-3Y for xen-devel@lists.xenproject.org; Mon, 06 Dec 2021 22:51:09 +0000 Received: from galois.linutronix.de (galois.linutronix.de [193.142.43.55]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 0014bea5-56e7-11ec-8a4d-196798b21f7b; Mon, 06 Dec 2021 23:51:08 +0100 (CET) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 0014bea5-56e7-11ec-8a4d-196798b21f7b Message-ID: <20211206210747.765371053@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1638831067; 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=8alToGL9fYMb4xPGuPdsGAFru/EhSrl8FqKzfYt/JtU=; b=gWEfbNzjHgtt1whL7/2Ldvh4oL4jk1evo9k12mpsqw9v8oK0N6JiLmbHM2BwGH5GkvMZ+r rA7z/FV+oGQH7D1ssy2wpa3XaN9ajGMAENYZeWjHvjVO9wNjS9xVYlcVw3bu3q8iOAr39y lG/9r+Rf0tRk7NZ0cBGPN0+K4Gz2NxGj5rxROcuTCf52xH8U4mmRyFQdmlUT7q/T85JVgw /ZG3LY51iCYfB20Dp0XdM0VP70YFPv3YVAcIUtsBdHhiGnGx6I81qkFhgImp2PMgcMs97H sZZB+/3dE3pQJDomBHYflaEoXLGGEdfBHmHoekcJiNOEoivZWVQA+MTanxBfdw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1638831067; 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=8alToGL9fYMb4xPGuPdsGAFru/EhSrl8FqKzfYt/JtU=; b=gMmqzb5kigzp75WDzIWIKMC5D8xSaRztVQaVOdi8fXblcVRHtmbTPZztIRuhJAxNMr6oMn Z9A1ViGU0PFB/7DA== From: Thomas Gleixner To: LKML Cc: Bjorn Helgaas , Marc Zygnier , Alex Williamson , Kevin Tian , Jason Gunthorpe , Megha Dey , Ashok Raj , linux-pci@vger.kernel.org, Cedric Le Goater , xen-devel@lists.xenproject.org, Juergen Gross , Greg Kroah-Hartman , Niklas Schnelle , linux-s390@vger.kernel.org, Heiko Carstens , Christian Borntraeger , Logan Gunthorpe , Jon Mason , Dave Jiang , Allen Hubbe , linux-ntb@googlegroups.com Subject: [patch V2 03/31] genirq/msi: Provide msi_domain_alloc/free_irqs_descs_locked() References: <20211206210600.123171746@linutronix.de> MIME-Version: 1.0 Date: Mon, 6 Dec 2021 23:51:07 +0100 (CET) Usage sites which do allocations of the MSI descriptors before invoking msi_domain_alloc_irqs() require to lock the MSI decriptors accross the operation. Provide entry points which can be called with the MSI mutex held and lock the mutex in the existing entry points. Signed-off-by: Thomas Gleixner --- include/linux/msi.h | 3 ++ kernel/irq/msi.c | 74 ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 16 deletions(-) --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -399,9 +399,12 @@ struct irq_domain *msi_create_irq_domain struct irq_domain *parent); int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nvec); +int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device *dev, + int nvec); int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nvec); void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev); +void msi_domain_free_irqs_descs_locked(struct irq_domain *domain, struct device *dev); void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev); struct msi_domain_info *msi_get_domain_info(struct irq_domain *domain); --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -689,10 +689,8 @@ int __msi_domain_alloc_irqs(struct irq_d virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used, dev_to_node(dev), &arg, false, desc->affinity); - if (virq < 0) { - ret = msi_handle_pci_fail(domain, desc, allocated); - goto cleanup; - } + if (virq < 0) + return msi_handle_pci_fail(domain, desc, allocated); for (i = 0; i < desc->nvec_used; i++) { irq_set_msi_desc_off(virq, i, desc); @@ -726,7 +724,7 @@ int __msi_domain_alloc_irqs(struct irq_d } ret = irq_domain_activate_irq(irq_data, can_reserve); if (ret) - goto cleanup; + return ret; } skip_activate: @@ -741,38 +739,63 @@ int __msi_domain_alloc_irqs(struct irq_d } } return 0; - -cleanup: - msi_domain_free_irqs(domain, dev); - return ret; } /** - * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain + * msi_domain_alloc_irqs_descs_locked - Allocate interrupts from a MSI interrupt domain * @domain: The domain to allocate from * @dev: Pointer to device struct of the device for which the interrupts * are allocated * @nvec: The number of interrupts to allocate * + * Must be invoked from within a msi_lock_descs() / msi_unlock_descs() + * pair. Use this for MSI irqdomains which implement their own vector + * allocation/free. + * * Return: %0 on success or an error code. */ -int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, - int nvec) +int msi_domain_alloc_irqs_descs_locked(struct irq_domain *domain, struct device *dev, + int nvec) { struct msi_domain_info *info = domain->host_data; struct msi_domain_ops *ops = info->ops; int ret; + lockdep_assert_held(&dev->msi.data->mutex); + ret = ops->domain_alloc_irqs(domain, dev, nvec); if (ret) - return ret; + goto cleanup; if (!(info->flags & MSI_FLAG_DEV_SYSFS)) return 0; ret = msi_device_populate_sysfs(dev); if (ret) - msi_domain_free_irqs(domain, dev); + goto cleanup; + return 0; + +cleanup: + msi_domain_free_irqs_descs_locked(domain, dev); + return ret; +} + +/** + * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain + * @domain: The domain to allocate from + * @dev: Pointer to device struct of the device for which the interrupts + * are allocated + * @nvec: The number of interrupts to allocate + * + * Return: %0 on success or an error code. + */ +int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nvec) +{ + int ret; + + msi_lock_descs(dev); + ret = msi_domain_alloc_irqs_descs_locked(domain, dev, nvec); + msi_unlock_descs(dev); return ret; } @@ -802,22 +825,41 @@ void __msi_domain_free_irqs(struct irq_d } /** - * msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated to @dev + * msi_domain_free_irqs_descs_locked - Free interrupts from a MSI interrupt @domain associated to @dev * @domain: The domain to managing the interrupts * @dev: Pointer to device struct of the device for which the interrupts * are free + * + * Must be invoked from within a msi_lock_descs() / msi_unlock_descs() + * pair. Use this for MSI irqdomains which implement their own vector + * allocation. */ -void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) +void msi_domain_free_irqs_descs_locked(struct irq_domain *domain, struct device *dev) { struct msi_domain_info *info = domain->host_data; struct msi_domain_ops *ops = info->ops; + lockdep_assert_held(&dev->msi.data->mutex); + if (info->flags & MSI_FLAG_DEV_SYSFS) msi_device_destroy_sysfs(dev); ops->domain_free_irqs(domain, dev); } /** + * msi_domain_free_irqs - Free interrupts from a MSI interrupt @domain associated to @dev + * @domain: The domain to managing the interrupts + * @dev: Pointer to device struct of the device for which the interrupts + * are free + */ +void msi_domain_free_irqs(struct irq_domain *domain, struct device *dev) +{ + msi_lock_descs(dev); + msi_domain_free_irqs_descs_locked(domain, dev); + msi_unlock_descs(dev); +} + +/** * msi_get_domain_info - Get the MSI interrupt domain info for @domain * @domain: The interrupt domain to retrieve data from *