Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp161097pxb; Thu, 21 Jan 2021 04:07:58 -0800 (PST) X-Google-Smtp-Source: ABdhPJyaOWo5dSFNOb/zQpal6duzytEl3Fq5kzEfwRD+J6PySjPhXH1vkNKKHJXRyWXkyFxrODC8 X-Received: by 2002:a05:6402:556:: with SMTP id i22mr10576093edx.56.1611230878405; Thu, 21 Jan 2021 04:07:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1611230878; cv=none; d=google.com; s=arc-20160816; b=XIpTUEpvIPqJujjJxDSR+AC4Jd5gIzLRGOkQSw7qxZyOeT6TWY2jhlTgo75kIxNmnq pg7GeYX7Ux+hnIsBV8rJyM5M7yL12w76NOowNUl2gXjopLOGAc8qKt2wCsr46v25S7ty Aq7FuC6TzbuEgEPjR2iGpUpG86B2rLa2lRQ4AZpCbC1ICPajZ0PvIKNZMMT29zfHEfQY 0/rg1VYGAYxRN3+2kUdXPvaXK1vGPoSafuN2oRZ5/QR+TbqRYuH6jx/PoQ0gD09y4a9w 8c2x0uzdYNiqJtQcKPtEZgSEX3t+0Zx6JhjBY9VjDtH6S0fEy+Z7BVxxC3GfkESBrUro CjjA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=XN8E/RWsfICc3r4Tdh23L9UaW9pdeN1mHRy2N/fw7Vo=; b=BacjA6gqnvanLNHk3kepU8YQP5/ViqOQH1cka/mJVftxduFmr9B7VJSTCp/4zA0YOx qhAh/sDrkAuZnN/5mTrZ9/HzEvYpnt/G/k2Fcx2ruGWiL410QAH1+qS7I2hfYK2l0Dv8 hTpLkoYhrmpN4Uy1OekL12QoBZGePOvLX+sSf0IeocIu+SBwJ/ckj3d5ZNHdLzkaHSq3 vdfbXuhAxSC5nGEW1p2uU8ny9PY60DToqShp6c+7bIb1CvwLka/JZh8yBp7V0fzQDsn/ w44YZ9M/XFSqYfTYqWeBjDuVHUS4PlZs7u6PmMBQmw4E4H6lhdvz/P20CrFuZIwoRxJI xmUA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id b16si1675139ejc.647.2021.01.21.04.07.24; Thu, 21 Jan 2021 04:07:58 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730954AbhAUMGc (ORCPT + 99 others); Thu, 21 Jan 2021 07:06:32 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:11846 "EHLO szxga07-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729609AbhAULEY (ORCPT ); Thu, 21 Jan 2021 06:04:24 -0500 Received: from DGGEMS406-HUB.china.huawei.com (unknown [172.30.72.60]) by szxga07-in.huawei.com (SkyGuard) with ESMTP id 4DLzxG2g2Bz7YPx; Thu, 21 Jan 2021 19:02:10 +0800 (CST) Received: from S00345302A-PC.china.huawei.com (10.47.88.171) by DGGEMS406-HUB.china.huawei.com (10.3.19.206) with Microsoft SMTP Server id 14.3.498.0; Thu, 21 Jan 2021 19:03:07 +0800 From: Shameer Kolothum To: , CC: , , , , , Subject: [PATCH] genirq/msi: Make sure early activation of all PCI MSIs Date: Thu, 21 Jan 2021 11:02:47 +0000 Message-ID: <20210121110247.20320-1-shameerali.kolothum.thodi@huawei.com> X-Mailer: git-send-email 2.12.0.windows.1 MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit X-Originating-IP: [10.47.88.171] X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We currently do early activation of MSI irqs for PCI/MSI based on the MSI_FLAG_ACTIVATE_EARLY flag. Though this activates all the allocated MSIs in the case of MSI-X, it only does so for the base irq in the case of MSI. This is because, for MSI, there is only one msi_desc entry for all the 32 irqs it can support and the current implementation iterates over the msi entries and ends up activating the base irq only. The above creates an issue on platforms where the msi controller supports direct injection of vLPIs(eg: ARM GICv4 ITS). On these platforms, upon irq activation, ITS driver maps the event to an ITT entry. And for Guest pass-through to work, early mapping of all the dev MSI vectors is required. Otherwise, the vfio irq bypass manager registration will fail. eg, On a HiSilicon D06 platform with GICv4 enabled, Guest boot with zip dev pass-through reports, "vfio-pci 0000:75:00.1: irq bypass producer (token 0000000006e5176a) registration fails: 66311" and Guest boot fails. This is traced to,    kvm_arch_irq_bypass_add_producer      kvm_vgic_v4_set_forwarding        vgic_its_resolve_lpi --> returns E_ITS_INT_UNMAPPED_INTERRUPT Hence make sure we activate all the irqs for both MSI and MSI-x cases. Signed-off-by: Shameer Kolothum --- It is unclear to me whether not performing the early activation of all MSI irqs was deliberate and has consequences on any other platforms. Please let me know. Thanks, Shameer --- kernel/irq/msi.c | 114 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 24 deletions(-) diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 2c0c4d6d0f83..eec187fc32a9 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -395,6 +395,78 @@ static bool msi_check_reservation_mode(struct irq_domain *domain, return desc->msi_attrib.is_msix || desc->msi_attrib.maskbit; } +static void msi_domain_deactivate_irq(struct irq_domain *domain, int irq) +{ + struct irq_data *irqd; + + irqd = irq_domain_get_irq_data(domain, irq); + if (irqd_is_activated(irqd)) + irq_domain_deactivate_irq(irqd); +} + +static int msi_domain_activate_irq(struct irq_domain *domain, + int irq, bool can_reserve) +{ + struct irq_data *irqd; + + irqd = irq_domain_get_irq_data(domain, irq); + if (!can_reserve) { + irqd_clr_can_reserve(irqd); + if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) + irqd_set_msi_nomask_quirk(irqd); + } + return irq_domain_activate_irq(irqd, can_reserve); +} + +static int msi_domain_activate_msix_irqs(struct irq_domain *domain, + struct device *dev, bool can_reserve) +{ + struct msi_desc *desc; + int ret, irq; + + for_each_msi_entry(desc, dev) { + irq = desc->irq; + ret = msi_domain_activate_irq(domain, irq, can_reserve); + if (ret) + goto out; + } + return 0; + +out: + for_each_msi_entry(desc, dev) { + if (irq == desc->irq) + break; + msi_domain_deactivate_irq(domain, desc->irq); + } + return ret; +} + +static int msi_domain_activate_msi_irqs(struct irq_domain *domain, + struct device *dev, bool can_reserve) +{ + struct msi_desc *desc; + int i, ret, base, irq; + + desc = first_msi_entry(dev); + base = desc->irq; + + for (i = 0; i < desc->nvec_used; i++) { + irq = base + i; + ret = msi_domain_activate_irq(domain, irq, can_reserve); + if (ret) + goto out; + } + return 0; + +out: + for (i = 0; i < desc->nvec_used; i++) { + if (irq == base + i) + break; + msi_domain_deactivate_irq(domain, base + i); + } + return ret; +} + int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, int nvec) { @@ -443,21 +515,25 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, else dev_dbg(dev, "irq [%d-%d] for MSI\n", virq, virq + desc->nvec_used - 1); - /* - * This flag is set by the PCI layer as we need to activate - * the MSI entries before the PCI layer enables MSI in the - * card. Otherwise the card latches a random msi message. - */ - if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY)) - continue; + } - irq_data = irq_domain_get_irq_data(domain, desc->irq); - if (!can_reserve) { - irqd_clr_can_reserve(irq_data); - if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) - irqd_set_msi_nomask_quirk(irq_data); - } - ret = irq_domain_activate_irq(irq_data, can_reserve); + /* + * This flag is set by the PCI layer as we need to activate + * the MSI entries before the PCI layer enables MSI in the + * card. Otherwise the card latches a random msi message. + * Early activation is also required when the msi controller + * supports direct injection of virtual LPIs(eg. ARM GICv4 ITS). + * Otherwise, the DevID/EventID -> LPI translation for pass-through + * devices will fail. Make sure we do activate all the allocated + * irqs for MSI and MSI-X cases. + */ + if ((info->flags & MSI_FLAG_ACTIVATE_EARLY)) { + desc = first_msi_entry(dev); + + if (desc->msi_attrib.is_msix) + ret = msi_domain_activate_msix_irqs(domain, dev, can_reserve); + else + ret = msi_domain_activate_msi_irqs(domain, dev, can_reserve); if (ret) goto cleanup; } @@ -475,16 +551,6 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, return 0; cleanup: - for_each_msi_entry(desc, dev) { - struct irq_data *irqd; - - if (desc->irq == virq) - break; - - irqd = irq_domain_get_irq_data(domain, desc->irq); - if (irqd_is_activated(irqd)) - irq_domain_deactivate_irq(irqd); - } msi_domain_free_irqs(domain, dev); return ret; } -- 2.17.1