Received: by 2002:a05:6358:d09b:b0:dc:cd0c:909e with SMTP id jc27csp9661688rwb; Thu, 24 Nov 2022 16:53:33 -0800 (PST) X-Google-Smtp-Source: AA0mqf7diSEN3Rz6LKER6Pso5YwyYywsisC5bPMnGv2ZhlwiIAW3EgcYE9QJ96t6KJ1Ls2Ea9zob X-Received: by 2002:a63:cc15:0:b0:476:ccde:6694 with SMTP id x21-20020a63cc15000000b00476ccde6694mr13193228pgf.603.1669337612803; Thu, 24 Nov 2022 16:53:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669337612; cv=none; d=google.com; s=arc-20160816; b=Vq/shj2RW54eldIjB6Oewwjm+tattBDa2uuCLkEQa50GH5pohfyYZ8i47qQ/mVHFw8 Xcq5v5NQ831nhOvuvH8aA1OHVy+fFjC46bDcGSldLVAKGPhkx0KHx/uVKTHzL/73NIxL ySem4IiYU3gVxAkWDLWATWfNmIy3yzA06BC0V1MmmDdteqi0ZjYKftN/nhJweFXa4w5G XCdMqg4Nmu70qs0T4gBe9b0GHP4Wh64TVChaNls7pfK2GsKdecTnjyIZVasSZH8kOYAv zp0efvHW8XvJjgnHeqYB63EttUz+0K6hK0vjwNLzOQmEw4STxNNkl0hlEp/3j4nYXx1e G7yQ== 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=H4LgR27rxWvowkqduv+44wQH1yKk935seCxATvwOx3U=; b=gVyHhLjN/DxwgRJLNUDv4Gl13CFegV0MIiFv2sabuelUjeURTaG83v/bMP4O+JHHax b9Y4wboT1hU7KZpN+40G1oCSR0HK3S+EE/oWmdat++Xf+quF+o9TyOIridVubRndLiTx WU+dCitDMpK94SwQUPoe/S0yArcdowIODsmD4LfLbaer0Gc05HiS1gzqcy0383IRQua/ JO6s+lmeK12qhTom+Kg6opnZIdP8vElmsPu9r9a2TnRWf1yIfc0f8nUs2V2rQCuP4UBH 1X9yGsEznrtOFMXHi5moDZ/qv44fTDWntYys1sWvtbRuYs7dJYX4EwhN1dokAQQKAJXG npqQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=Zpb6D8Gi; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=UHT4mxiD; 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 Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id h13-20020a170902680d00b001869c2b3a3csi2147881plk.537.2022.11.24.16.53.21; Thu, 24 Nov 2022 16:53:32 -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=Zpb6D8Gi; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=UHT4mxiD; 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 S229538AbiKXXY7 (ORCPT + 87 others); Thu, 24 Nov 2022 18:24:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229755AbiKXXYi (ORCPT ); Thu, 24 Nov 2022 18:24:38 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 55AE38A158; Thu, 24 Nov 2022 15:24:26 -0800 (PST) Message-ID: <20221124230313.985498981@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1669332264; 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=H4LgR27rxWvowkqduv+44wQH1yKk935seCxATvwOx3U=; b=Zpb6D8GiMXq+Hbac5EKd7HZxAaZ1f16BYQtjxy+TNJ041MURdG3QxWOhCE1e4HVsyIZKzF gmcTxUpcgEQCSzWYVri/vpDfsZDbs2j11eERMVVdRPMig1geQTtUiXmbY8GMYm4Qh8JI76 xKu28jHNkF8fWTc9xOeMFfoxLZByiOvuBFFsM7VmKtz+b5efE7dS3Feny1do38AQzXY0U1 HL3KxpHDJZkKlgZXa4l+t33xdNR14muOGdaNkoQ9jWFtZiVe2lxN9Xxj4yu2cmSNfn3ilH 6uPMzEiqmiR+Ww1tCh7Dv3xknjM0r57XjoIrjxR7RmKtlnVOlwe9XD9S8/bNfA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1669332264; 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=H4LgR27rxWvowkqduv+44wQH1yKk935seCxATvwOx3U=; b=UHT4mxiDh70tN1igdVL2dT88X6PGfKDYxSHMCHNQIqOwNb9rUpyd5t1ALKspooR41O108O 1Z8dS9iROL7TgyCQ== 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 Subject: [patch V3 10/22] genirq/msi: Make MSI descriptor iterators device domain aware References: <20221124225331.464480443@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Date: Fri, 25 Nov 2022 00:24:24 +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 To support multiple MSI interrupt domains per device it is necessary to segment the xarray MSI descriptor storage. Each domain gets up to MSI_MAX_INDEX entries. Change the iterators so they operate with domain ids and take the domain offsets into account. The publicly available iterators which are mostly used in legacy implementations and the PCI/MSI core default to MSI_DEFAULT_DOMAIN (0) which is the id for the existing "global" domains. No functional change. Signed-off-by: Thomas Gleixner --- V2: Fix the off by one so the index space is including MSI_MAX_INDEX (Kevin) V3: Adopt to the domain/xarray storage change --- include/linux/msi.h | 48 ++++++++++++++++++++++++++++++++++++++++++------ kernel/irq/msi.c | 35 +++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 18 deletions(-) --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -206,11 +206,48 @@ int msi_setup_device_data(struct device void msi_lock_descs(struct device *dev); void msi_unlock_descs(struct device *dev); -struct msi_desc *msi_first_desc(struct device *dev, enum msi_desc_filter filter); -struct msi_desc *msi_next_desc(struct device *dev, enum msi_desc_filter filter); +struct msi_desc *msi_domain_first_desc(struct device *dev, unsigned int domid, + enum msi_desc_filter filter); /** - * msi_for_each_desc - Iterate the MSI descriptors + * msi_first_desc - Get the first MSI descriptor of the default irqdomain + * @dev: Device to operate on + * @filter: Descriptor state filter + * + * Must be called with the MSI descriptor mutex held, i.e. msi_lock_descs() + * must be invoked before the call. + * + * Return: Pointer to the first MSI descriptor matching the search + * criteria, NULL if none found. + */ +static inline struct msi_desc *msi_first_desc(struct device *dev, + enum msi_desc_filter filter) +{ + return msi_domain_first_desc(dev, MSI_DEFAULT_DOMAIN, filter); +} + +struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid, + enum msi_desc_filter filter); + +/** + * msi_domain_for_each_desc - Iterate the MSI descriptors in a specific domain + * + * @desc: struct msi_desc pointer used as iterator + * @dev: struct device pointer - device to iterate + * @domid: The id of the interrupt domain which should be walked. + * @filter: Filter for descriptor selection + * + * Notes: + * - The loop must be protected with a msi_lock_descs()/msi_unlock_descs() + * pair. + * - It is safe to remove a retrieved MSI descriptor in the loop. + */ +#define msi_domain_for_each_desc(desc, dev, domid, filter) \ + for ((desc) = msi_domain_first_desc((dev), (domid), (filter)); (desc); \ + (desc) = msi_next_desc((dev), (domid), (filter))) + +/** + * msi_for_each_desc - Iterate the MSI descriptors in the default irqdomain * * @desc: struct msi_desc pointer used as iterator * @dev: struct device pointer - device to iterate @@ -221,9 +258,8 @@ struct msi_desc *msi_next_desc(struct de * pair. * - It is safe to remove a retrieved MSI descriptor in the loop. */ -#define msi_for_each_desc(desc, dev, filter) \ - for ((desc) = msi_first_desc((dev), (filter)); (desc); \ - (desc) = msi_next_desc((dev), (filter))) +#define msi_for_each_desc(desc, dev, filter) \ + msi_domain_for_each_desc((desc), (dev), MSI_DEFAULT_DOMAIN, (filter)) #define msi_desc_to_dev(desc) ((desc)->dev) --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -19,8 +19,14 @@ #include "internals.h" +/* Invalid Xarray index which is outside of any searchable range */ +#define MSI_XA_MAX_INDEX (ULONG_MAX - 1) +/* The maximum domain size */ +#define MSI_XA_DOMAIN_SIZE (MSI_MAX_INDEX + 1) + static inline int msi_sysfs_create_group(struct device *dev); + /** * msi_alloc_desc - Allocate an initialized msi_desc * @dev: Pointer to the device for which this is allocated @@ -252,27 +258,29 @@ EXPORT_SYMBOL_GPL(msi_lock_descs); void msi_unlock_descs(struct device *dev) { /* Invalidate the index which was cached by the iterator */ - dev->msi.data->__iter_idx = MSI_MAX_INDEX; + dev->msi.data->__iter_idx = MSI_XA_MAX_INDEX; mutex_unlock(&dev->msi.data->mutex); } EXPORT_SYMBOL_GPL(msi_unlock_descs); -static struct msi_desc *msi_find_desc(struct msi_device_data *md, enum msi_desc_filter filter) +static struct msi_desc *msi_find_desc(struct msi_device_data *md, unsigned int domid, + enum msi_desc_filter filter) { - struct xarray *xa = &md->__domains[MSI_DEFAULT_DOMAIN].store; + struct xarray *xa = &md->__domains[domid].store; struct msi_desc *desc; xa_for_each_start(xa, md->__iter_idx, desc, md->__iter_idx) { if (msi_desc_match(desc, filter)) return desc; } - md->__iter_idx = MSI_MAX_INDEX; + md->__iter_idx = MSI_XA_MAX_INDEX; return NULL; } /** - * msi_first_desc - Get the first MSI descriptor of a device + * msi_domain_first_desc - Get the first MSI descriptor of an irqdomain associated to a device * @dev: Device to operate on + * @domid: The id of the interrupt domain which should be walked. * @filter: Descriptor state filter * * Must be called with the MSI descriptor mutex held, i.e. msi_lock_descs() @@ -281,23 +289,25 @@ static struct msi_desc *msi_find_desc(st * Return: Pointer to the first MSI descriptor matching the search * criteria, NULL if none found. */ -struct msi_desc *msi_first_desc(struct device *dev, enum msi_desc_filter filter) +struct msi_desc *msi_domain_first_desc(struct device *dev, unsigned int domid, + enum msi_desc_filter filter) { struct msi_device_data *md = dev->msi.data; - if (WARN_ON_ONCE(!md)) + if (WARN_ON_ONCE(!md || domid >= MSI_MAX_DEVICE_IRQDOMAINS)) return NULL; lockdep_assert_held(&md->mutex); md->__iter_idx = 0; - return msi_find_desc(md, filter); + return msi_find_desc(md, domid, filter); } -EXPORT_SYMBOL_GPL(msi_first_desc); +EXPORT_SYMBOL_GPL(msi_domain_first_desc); /** * msi_next_desc - Get the next MSI descriptor of a device * @dev: Device to operate on + * @domid: The id of the interrupt domain which should be walked. * @filter: Descriptor state filter * * The first invocation of msi_next_desc() has to be preceeded by a @@ -308,11 +318,12 @@ EXPORT_SYMBOL_GPL(msi_first_desc); * Return: Pointer to the next MSI descriptor matching the search * criteria, NULL if none found. */ -struct msi_desc *msi_next_desc(struct device *dev, enum msi_desc_filter filter) +struct msi_desc *msi_next_desc(struct device *dev, unsigned int domid, + enum msi_desc_filter filter) { struct msi_device_data *md = dev->msi.data; - if (WARN_ON_ONCE(!md)) + if (WARN_ON_ONCE(!md || domid >= MSI_MAX_DEVICE_IRQDOMAINS)) return NULL; lockdep_assert_held(&md->mutex); @@ -321,7 +332,7 @@ struct msi_desc *msi_next_desc(struct de return NULL; md->__iter_idx++; - return msi_find_desc(md, filter); + return msi_find_desc(md, domid, filter); } EXPORT_SYMBOL_GPL(msi_next_desc);