From patchwork Mon Nov 21 14:38: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: 23832 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp1628730wrr; Mon, 21 Nov 2022 06:41:48 -0800 (PST) X-Google-Smtp-Source: AA0mqf4guZ1/ViCcVMb0yNvYJxa10V2MwObth9Ei6O7cJu+0zdwsEDQCnUqZlbotuuESqTw52sWs X-Received: by 2002:a17:906:a212:b0:7b2:804f:a31c with SMTP id r18-20020a170906a21200b007b2804fa31cmr15496129ejy.523.1669041708512; Mon, 21 Nov 2022 06:41:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669041708; cv=none; d=google.com; s=arc-20160816; b=BVC1MWNfN7mJ23xeXjbaWjuu5exWrQpdjAbGdIGg/tG2IFh/NamOiH54Tv8+IELDOq H6HKQl/BHVqQkODondt68q7/of1awqzBr4V5zbNenlNLDKcZ5wB/d9B2cZdUzv1yBfoO luQNi99IMgpfeHn7Dxpsb7g9qpAJEqQBvqkoqGGCB2O9MsQAM5rAgMhAhN/R4defEq8+ eotmX95Ajz0dcjIi2ZiulRvNR66hoKlGzcV6PriAvO2a9ntRU7450BvogvaT/+xi7hdw ItGHbXWI6Hs85bP6kpJ/vo1c7jQGSskMgpRWNzy5SOWBytzFJObQVif08NxrtloQaC9W kovw== 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=aPZsUav27NBNGy9CDcKsBA6eS6rPiDVMzp1pfp5Kt2c=; b=lkknpE4uxD4EAYS6OzxVTKEZ9tzhLA9RE5i+7vV8nE+C8gi58bCMpAJIC7y/vR2o1q LQluMSrasaAX9ja7zH0woRtlZq8wx/2qE+PQMXEOvEOVW6Xp2/cehMLJ78655RTSgrar yXN099Aa9bdWzWh5ATCWdYu1pmfjwgPvcZ3q/4uDladIdg5MXxQOOiBt9KIcK7WfFkJ2 QyMgg/N4tdo6nAUvjETpPhLn89NiZfLL6500H9v6isy3nEl4ky3Fr3Tjkb1pUb6kvq5+ 1DIVSj2hyDf9oW/zRjpKP1yrFTzqfVKmXnVIf1a502J0Rv2JLwwPLS5swP0TSTytq8vU RXFw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b="MP/SuT1e"; 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 n10-20020a05640205ca00b004680dcb8900si10191040edx.213.2022.11.21.06.41.11; Mon, 21 Nov 2022 06:41:48 -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="MP/SuT1e"; 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 S231298AbiKUOkn (ORCPT + 99 others); Mon, 21 Nov 2022 09:40:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48034 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231720AbiKUOim (ORCPT ); Mon, 21 Nov 2022 09:38:42 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A90EBC72E1; Mon, 21 Nov 2022 06:38:16 -0800 (PST) Message-ID: <20221121091327.765751899@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1669041495; 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=aPZsUav27NBNGy9CDcKsBA6eS6rPiDVMzp1pfp5Kt2c=; b=MP/SuT1eRbh9P77txd5gKe8HLBx8vQPoQ+Mf25IhzIhO+02JL8aKP/Wlqz2cEC6svkSOhM VCHDdpCOoFCpyQYQ001wNdgqeFrXcf0i+ZL8IBMvsCZqnLMnyfn84bKCbKVQM4ulpd6wgY oZjNfwUTGtjkzozAMfKYsSXhboQVGldg7a3ztLqg72B176HqYxGWmPMB61T5t9zNalwueY KsVT86hs42C2ipGA5OqROd97slYSI8WvhoYbGUJ8w9ArXLZBW6ARY7Ea3SHLgwEb+ydudG tDiCLJ1jLvkajQMI+RlYWF2CJV2QMIl1U+2TJKkT4MtBn0rEgLrKULx2a/TTpg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1669041495; 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=aPZsUav27NBNGy9CDcKsBA6eS6rPiDVMzp1pfp5Kt2c=; b=AbZBfS5PtDXSGoS216fyH+iusnOJ175SCbLGv0W1kvqPWzCUH4jctX6x1aqQoXMDA3ToWx EuLX9euk0Hg3hIDA== 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 V2 23/33] PCI/MSI: Split MSI-X descriptor setup References: <20221121083657.157152924@linutronix.de> MIME-Version: 1.0 Date: Mon, 21 Nov 2022 15:38: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?1750117078483824976?= X-GMAIL-MSGID: =?utf-8?q?1750117078483824976?= The upcoming mechanism to allocate MSI-X vectors after enabling MSI-X needs to share some of the MSI-X descriptor setup. The regular descriptor setup on enable has the following code flow: 1) Allocate descriptor 2) Setup descriptor with PCI specific data 3) Insert descriptor 4) Allocate interrupts which in turn scans the inserted descriptors This cannot be easily changed because the PCI/MSI code needs to handle the legacy architecture specific allocation model and the irq domain model where quite some domains have the assumption that the above flow is how it works. Ideally the code flow should look like this: 1) Invoke allocation at the MSI core 2) MSI core allocates descriptor 3) MSI core calls back into the irq domain which fills in the domain specific parts This could be done for underlying parent MSI domains which support post-enable allocation/free but that would create significantly different code pathes for MSI/MSI-X enable. Though for dynamic allocation which wants to share the allocation code with the upcoming PCI/IMS support it's the right thing to do. Split the MSI-X descriptor setup into the preallocation part which just sets the index and fills in the horrible hack of virtual IRQs and the real PCI specific MSI-X setup part which solely depends on the index in the descriptor. This allows to provide a common dynamic allocation interface at the MSI core level for both PCI/MSI-X and PCI/IMS. Signed-off-by: Thomas Gleixner Acked-by: Bjorn Helgaas --- drivers/pci/msi/msi.c | 72 +++++++++++++++++++++++++++++++------------------- drivers/pci/msi/msi.h | 2 + 2 files changed, 47 insertions(+), 27 deletions(-) --- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -569,34 +569,56 @@ static void __iomem *msix_map_region(str return ioremap(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); } -static int msix_setup_msi_descs(struct pci_dev *dev, void __iomem *base, - struct msix_entry *entries, int nvec, - struct irq_affinity_desc *masks) +/** + * msix_prepare_msi_desc - Prepare a half initialized MSI descriptor for operation + * @dev: The PCI device for which the descriptor is prepared + * @desc: The MSI descriptor for preparation + * + * This is separate from msix_setup_msi_descs() below to handle dynamic + * allocations for MSI-X after initial enablement. + * + * Ideally the whole MSI-X setup would work that way, but there is no way to + * support this for the legacy arch_setup_msi_irqs() mechanism and for the + * fake irq domains like the x86 XEN one. Sigh... + * + * The descriptor is zeroed and only @desc::msi_index and @desc::affinity + * are set. When called from msix_setup_msi_descs() then the is_virtual + * attribute is initialized as well. + * + * Fill in the rest. + */ +void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc) +{ + desc->nvec_used = 1; + desc->pci.msi_attrib.is_msix = 1; + desc->pci.msi_attrib.is_64 = 1; + desc->pci.msi_attrib.default_irq = dev->irq; + desc->pci.mask_base = dev->msix_base; + desc->pci.msi_attrib.can_mask = !pci_msi_ignore_mask && + !desc->pci.msi_attrib.is_virtual; + + if (desc->pci.msi_attrib.can_mask) { + void __iomem *addr = pci_msix_desc_addr(desc); + + desc->pci.msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL); + } +} + +static int msix_setup_msi_descs(struct pci_dev *dev, struct msix_entry *entries, + int nvec, struct irq_affinity_desc *masks) { int ret = 0, i, vec_count = pci_msix_vec_count(dev); struct irq_affinity_desc *curmsk; struct msi_desc desc; - void __iomem *addr; memset(&desc, 0, sizeof(desc)); - desc.nvec_used = 1; - desc.pci.msi_attrib.is_msix = 1; - desc.pci.msi_attrib.is_64 = 1; - desc.pci.msi_attrib.default_irq = dev->irq; - desc.pci.mask_base = base; - for (i = 0, curmsk = masks; i < nvec; i++, curmsk++) { desc.msi_index = entries ? entries[i].entry : i; desc.affinity = masks ? curmsk : NULL; desc.pci.msi_attrib.is_virtual = desc.msi_index >= vec_count; - desc.pci.msi_attrib.can_mask = !pci_msi_ignore_mask && - !desc.pci.msi_attrib.is_virtual; - if (desc.pci.msi_attrib.can_mask) { - addr = pci_msix_desc_addr(&desc); - desc.pci.msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL); - } + msix_prepare_msi_desc(dev, &desc); ret = msi_insert_msi_desc(&dev->dev, &desc); if (ret) @@ -629,9 +651,8 @@ static void msix_mask_all(void __iomem * writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL); } -static int msix_setup_interrupts(struct pci_dev *dev, void __iomem *base, - struct msix_entry *entries, int nvec, - struct irq_affinity *affd) +static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries, + int nvec, struct irq_affinity *affd) { struct irq_affinity_desc *masks = NULL; int ret; @@ -640,7 +661,7 @@ static int msix_setup_interrupts(struct masks = irq_create_affinity_masks(nvec, affd); msi_lock_descs(&dev->dev); - ret = msix_setup_msi_descs(dev, base, entries, nvec, masks); + ret = msix_setup_msi_descs(dev, entries, nvec, masks); if (ret) goto out_free; @@ -678,7 +699,6 @@ static int msix_setup_interrupts(struct static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec, struct irq_affinity *affd) { - void __iomem *base; int ret, tsize; u16 control; @@ -696,15 +716,13 @@ static int msix_capability_init(struct p pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); /* Request & Map MSI-X table region */ tsize = msix_table_size(control); - base = msix_map_region(dev, tsize); - if (!base) { + dev->msix_base = msix_map_region(dev, tsize); + if (!dev->msix_base) { ret = -ENOMEM; goto out_disable; } - dev->msix_base = base; - - ret = msix_setup_interrupts(dev, base, entries, nvec, affd); + ret = msix_setup_interrupts(dev, entries, nvec, affd); if (ret) goto out_disable; @@ -719,7 +737,7 @@ static int msix_capability_init(struct p * which takes the MSI-X mask bits into account even * when MSI-X is disabled, which prevents MSI delivery. */ - msix_mask_all(base, tsize); + msix_mask_all(dev->msix_base, tsize); pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0); pcibios_free_irq(dev); --- a/drivers/pci/msi/msi.h +++ b/drivers/pci/msi/msi.h @@ -84,6 +84,8 @@ static inline __attribute_const__ u32 ms return (1 << (1 << desc->pci.msi_attrib.multi_cap)) - 1; } +void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc); + /* Subsystem variables */ extern int pci_msi_enable;