Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1746904pxb; Sat, 23 Jan 2021 04:30:03 -0800 (PST) X-Google-Smtp-Source: ABdhPJy2xEOFynMdmJ/gNgrVuFdYnn8CLLgaDSdX7I+MkRx3XpfGjNbcuMtdfMI6vPlM5urOUUbQ X-Received: by 2002:a05:6402:378:: with SMTP id s24mr1620911edw.376.1611405003007; Sat, 23 Jan 2021 04:30:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1611405003; cv=none; d=google.com; s=arc-20160816; b=oe8Vvy/AVHdmxzcwzquZv9BoZFq/CZoNTr09+9g/vbtOO27LFplaWq0NDUVU1gfUVW 4+iUl++nL4L3/YkZQRbcdkizsgzL7H209LMWDJeRzJCpj9qn1FttiIM1GlrjouDcPMkH GnMGLvZUjLBzhdQz4XW4MDyWp+4Raakh41pOW8r+Du4yc0pTMANxJrlcg+EjJLrTKgca +ylWbwU61aN1wXa352Iilb0TTLMTk+bO8lRekh1T8CxCj4urcZ++QCFhh3UsrliT5ca9 AWLbQgh1Fm67ffo2pCzxg9XrLnDd3Nk3gKbqJ1gie5u3ncXqf1hj3BknPa8kLHhPyiLi Dj3w== 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=sPRz4hizRKr9Xntzto7HTQiMRLrU4wt/ZqsgGi/tCug=; b=H3ZTf2H3d1TowFdayIISnpv5YXsJG14B6WqB0LY0Yq95a4Lr9pNIs1uNqc3jcSnF1Y sNxg5agrEwCfUo+JdFfyK2yyEck3EW5Fv0r4Z+hB633SVNzpwME3KNAUdM7NZO3I4Ng4 eYPcYYedKrShV5eHNd+yYTclH6mrRRy/gqXUD4bXYRXfcb1byd3rOhj+S0/i6v90tmJE 5IsOMEx7Bc7FNY/6GYvCDQUDvtEGCwTVA12YdyPgKGjuNa+nOrocvTTCOZ9clUyjL5rJ QlMZe1r2WAZjk1zuN/UpjASCzNG8zu90he+kHtWwgv9ZB8saxVWdfzF2xbyLAaqnBiIU 7/rw== 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id rn4si1614222ejb.197.2021.01.23.04.29.35; Sat, 23 Jan 2021 04:30:02 -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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726863AbhAWM2u (ORCPT + 99 others); Sat, 23 Jan 2021 07:28:50 -0500 Received: from mail.kernel.org ([198.145.29.99]:41462 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726628AbhAWM2r (ORCPT ); Sat, 23 Jan 2021 07:28:47 -0500 Received: from disco-boy.misterjones.org (disco-boy.misterjones.org [51.254.78.96]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id CAD3722BE8; Sat, 23 Jan 2021 12:28:05 +0000 (UTC) Received: from 78.163-31-62.static.virginmediabusiness.co.uk ([62.31.163.78] helo=hot-poop.lan) by disco-boy.misterjones.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94) (envelope-from ) id 1l3I1L-009bSh-J5; Sat, 23 Jan 2021 12:28:03 +0000 From: Marc Zyngier To: linux-kernel@vger.kernel.org Cc: Thomas Gleixner , Bjorn Helgaas , Shameer Kolothum , stable@vger.kernel.org Subject: [PATCH] genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is set Date: Sat, 23 Jan 2021 12:27:59 +0000 Message-Id: <20210123122759.1781359-1-maz@kernel.org> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SA-Exim-Connect-IP: 62.31.163.78 X-SA-Exim-Rcpt-To: linux-kernel@vger.kernel.org, tglx@linutronix.de, bhelgaas@google.com, shameerali.kolothum.thodi@huawei.com, stable@vger.kernel.org X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When MSI_FLAG_ACTIVATE_EARLY is set (which is the case for PCI), we perform the activation of the interrupt (which in the case of PCI results in the endpoint being programmed) as soon as the interrupt is allocated. But it appears that this is only done for the first vector, introducing an inconsistent behaviour for PCI Multi-MSI. Fix it by iterating over the number of vectors allocated to each MSI descriptor. This is easily achieved by introducing a new "for_each_msi_vector" iterator, together with a tiny bit of refactoring. Fixes: f3b0946d629c ("genirq/msi: Make sure PCI MSIs are activated early") Reported-by: Shameer Kolothum Signed-off-by: Marc Zyngier Cc: stable@vger.kernel.org --- include/linux/msi.h | 6 ++++++ kernel/irq/msi.c | 44 ++++++++++++++++++++------------------------ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/include/linux/msi.h b/include/linux/msi.h index 360a0a7e7341..aef35fd1cf11 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -178,6 +178,12 @@ struct msi_desc { list_for_each_entry((desc), dev_to_msi_list((dev)), list) #define for_each_msi_entry_safe(desc, tmp, dev) \ list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list) +#define for_each_msi_vector(desc, __irq, dev) \ + for_each_msi_entry((desc), (dev)) \ + if ((desc)->irq) \ + for (__irq = (desc)->irq; \ + __irq < ((desc)->irq + (desc)->nvec_used); \ + __irq++) #ifdef CONFIG_IRQ_MSI_IOMMU static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 2c0c4d6d0f83..d924676c8781 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -436,22 +436,22 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, can_reserve = msi_check_reservation_mode(domain, info, dev); - for_each_msi_entry(desc, dev) { - virq = desc->irq; - if (desc->nvec_used == 1) - dev_dbg(dev, "irq %d for MSI\n", virq); - else + /* + * 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)) + goto skip_activate; + + for_each_msi_vector(desc, i, dev) { + if (desc->irq == i) { + virq = desc->irq; 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); + irq_data = irq_domain_get_irq_data(domain, i); if (!can_reserve) { irqd_clr_can_reserve(irq_data); if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) @@ -462,28 +462,24 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, goto cleanup; } +skip_activate: /* * If these interrupts use reservation mode, clear the activated bit * so request_irq() will assign the final vector. */ if (can_reserve) { - for_each_msi_entry(desc, dev) { - irq_data = irq_domain_get_irq_data(domain, desc->irq); + for_each_msi_vector(desc, i, dev) { + irq_data = irq_domain_get_irq_data(domain, i); irqd_clr_activated(irq_data); } } 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); + for_each_msi_vector(desc, i, dev) { + irq_data = irq_domain_get_irq_data(domain, i); + if (irqd_is_activated(irq_data)) + irq_domain_deactivate_irq(irq_data); } msi_domain_free_irqs(domain, dev); return ret; -- 2.29.2