summaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2017-12-29 04:42:10 -0500
committerThomas Gleixner <tglx@linutronix.de>2017-12-29 15:13:04 -0500
commitda5dd9e854d2edd6b02ebfe28583052f922104da (patch)
tree3205e6dc1029fff9f0554057aacc73b12a907378 /kernel/irq
parent8880c13734af33635118a1e9567dadc7f9ddb7a8 (diff)
genirq/msi: Handle reactivation only on success
When analyzing the fallout of the x86 vector allocation rework it turned out that the error handling in msi_domain_alloc_irqs() is broken. If MSI_FLAG_MUST_REACTIVATE is set for a MSI domain then it clears the activation flag for a successfully initialized msi descriptor. If a subsequent initialization fails then the error handling code path does not deactivate the interrupt because the activation flag got cleared. Move the clearing of the activation flag outside of the initialization loop so that an eventual failure can be cleaned up correctly. Fixes: 22d0b12f3560 ("genirq/irqdomain: Add force reactivation flag to irq domains") Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Alexandru Chirvasitu <achirvasub@gmail.com> Tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Dou Liyang <douly.fnst@cn.fujitsu.com> Cc: Pavel Machek <pavel@ucw.cz> Cc: Maciej W. Rozycki <macro@linux-mips.org> Cc: Mikael Pettersson <mikpelinux@gmail.com> Cc: Josh Poulson <jopoulso@microsoft.com> Cc: Mihai Costache <v-micos@microsoft.com> Cc: Stephen Hemminger <sthemmin@microsoft.com> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: linux-pci@vger.kernel.org Cc: Haiyang Zhang <haiyangz@microsoft.com> Cc: Dexuan Cui <decui@microsoft.com> Cc: Simon Xiao <sixiao@microsoft.com> Cc: Saeed Mahameed <saeedm@mellanox.com> Cc: Jork Loeser <Jork.Loeser@microsoft.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: devel@linuxdriverproject.org Cc: KY Srinivasan <kys@microsoft.com> Cc: Alan Cox <alan@linux.intel.com> Cc: Sakari Ailus <sakari.ailus@intel.com>, Cc: linux-media@vger.kernel.org
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/msi.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index edb987b2c58d..9ba954331171 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -339,6 +339,13 @@ int msi_domain_populate_irqs(struct irq_domain *domain, struct device *dev,
339 return ret; 339 return ret;
340} 340}
341 341
342static bool msi_check_reservation_mode(struct msi_domain_info *info)
343{
344 if (!(info->flags & MSI_FLAG_MUST_REACTIVATE))
345 return false;
346 return true;
347}
348
342/** 349/**
343 * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain 350 * msi_domain_alloc_irqs - Allocate interrupts from a MSI interrupt domain
344 * @domain: The domain to allocate from 351 * @domain: The domain to allocate from
@@ -353,9 +360,11 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
353{ 360{
354 struct msi_domain_info *info = domain->host_data; 361 struct msi_domain_info *info = domain->host_data;
355 struct msi_domain_ops *ops = info->ops; 362 struct msi_domain_ops *ops = info->ops;
356 msi_alloc_info_t arg; 363 struct irq_data *irq_data;
357 struct msi_desc *desc; 364 struct msi_desc *desc;
365 msi_alloc_info_t arg;
358 int i, ret, virq; 366 int i, ret, virq;
367 bool can_reserve;
359 368
360 ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg); 369 ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg);
361 if (ret) 370 if (ret)
@@ -385,6 +394,8 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
385 if (ops->msi_finish) 394 if (ops->msi_finish)
386 ops->msi_finish(&arg, 0); 395 ops->msi_finish(&arg, 0);
387 396
397 can_reserve = msi_check_reservation_mode(info);
398
388 for_each_msi_entry(desc, dev) { 399 for_each_msi_entry(desc, dev) {
389 virq = desc->irq; 400 virq = desc->irq;
390 if (desc->nvec_used == 1) 401 if (desc->nvec_used == 1)
@@ -397,15 +408,23 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
397 * the MSI entries before the PCI layer enables MSI in the 408 * the MSI entries before the PCI layer enables MSI in the
398 * card. Otherwise the card latches a random msi message. 409 * card. Otherwise the card latches a random msi message.
399 */ 410 */
400 if (info->flags & MSI_FLAG_ACTIVATE_EARLY) { 411 if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
401 struct irq_data *irq_data; 412 continue;
402 413
414 irq_data = irq_domain_get_irq_data(domain, desc->irq);
415 ret = irq_domain_activate_irq(irq_data, true);
416 if (ret)
417 goto cleanup;
418 }
419
420 /*
421 * If these interrupts use reservation mode, clear the activated bit
422 * so request_irq() will assign the final vector.
423 */
424 if (can_reserve) {
425 for_each_msi_entry(desc, dev) {
403 irq_data = irq_domain_get_irq_data(domain, desc->irq); 426 irq_data = irq_domain_get_irq_data(domain, desc->irq);
404 ret = irq_domain_activate_irq(irq_data, true); 427 irqd_clr_activated(irq_data);
405 if (ret)
406 goto cleanup;
407 if (info->flags & MSI_FLAG_MUST_REACTIVATE)
408 irqd_clr_activated(irq_data);
409 } 428 }
410 } 429 }
411 return 0; 430 return 0;