Skip to content

Commit fc6c0ae

Browse files
committed
Merge tag 'irq_urgent_for_v5.11_rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Borislav Petkov: - Prevent device managed IRQ allocation helpers from returning IRQ 0 - A fix for MSI activation of PCI endpoints with multiple MSIs * tag 'irq_urgent_for_v5.11_rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: genirq: Prevent [devm_]irq_alloc_desc from returning irq 0 genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is set
2 parents c6792d4 + 4c7bcb5 commit fc6c0ae

File tree

3 files changed

+28
-26
lines changed

3 files changed

+28
-26
lines changed

include/linux/irq.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,7 +928,7 @@ int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
928928
__irq_alloc_descs(irq, from, cnt, node, THIS_MODULE, NULL)
929929

930930
#define irq_alloc_desc(node) \
931-
irq_alloc_descs(-1, 0, 1, node)
931+
irq_alloc_descs(-1, 1, 1, node)
932932

933933
#define irq_alloc_desc_at(at, node) \
934934
irq_alloc_descs(at, at, 1, node)
@@ -943,7 +943,7 @@ int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
943943
__devm_irq_alloc_descs(dev, irq, from, cnt, node, THIS_MODULE, NULL)
944944

945945
#define devm_irq_alloc_desc(dev, node) \
946-
devm_irq_alloc_descs(dev, -1, 0, 1, node)
946+
devm_irq_alloc_descs(dev, -1, 1, 1, node)
947947

948948
#define devm_irq_alloc_desc_at(dev, at, node) \
949949
devm_irq_alloc_descs(dev, at, at, 1, node)

include/linux/msi.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ struct msi_desc {
178178
list_for_each_entry((desc), dev_to_msi_list((dev)), list)
179179
#define for_each_msi_entry_safe(desc, tmp, dev) \
180180
list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
181+
#define for_each_msi_vector(desc, __irq, dev) \
182+
for_each_msi_entry((desc), (dev)) \
183+
if ((desc)->irq) \
184+
for (__irq = (desc)->irq; \
185+
__irq < ((desc)->irq + (desc)->nvec_used); \
186+
__irq++)
181187

182188
#ifdef CONFIG_IRQ_MSI_IOMMU
183189
static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)

kernel/irq/msi.c

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -436,22 +436,22 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
436436

437437
can_reserve = msi_check_reservation_mode(domain, info, dev);
438438

439-
for_each_msi_entry(desc, dev) {
440-
virq = desc->irq;
441-
if (desc->nvec_used == 1)
442-
dev_dbg(dev, "irq %d for MSI\n", virq);
443-
else
439+
/*
440+
* This flag is set by the PCI layer as we need to activate
441+
* the MSI entries before the PCI layer enables MSI in the
442+
* card. Otherwise the card latches a random msi message.
443+
*/
444+
if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
445+
goto skip_activate;
446+
447+
for_each_msi_vector(desc, i, dev) {
448+
if (desc->irq == i) {
449+
virq = desc->irq;
444450
dev_dbg(dev, "irq [%d-%d] for MSI\n",
445451
virq, virq + desc->nvec_used - 1);
446-
/*
447-
* This flag is set by the PCI layer as we need to activate
448-
* the MSI entries before the PCI layer enables MSI in the
449-
* card. Otherwise the card latches a random msi message.
450-
*/
451-
if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
452-
continue;
452+
}
453453

454-
irq_data = irq_domain_get_irq_data(domain, desc->irq);
454+
irq_data = irq_domain_get_irq_data(domain, i);
455455
if (!can_reserve) {
456456
irqd_clr_can_reserve(irq_data);
457457
if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK)
@@ -462,28 +462,24 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
462462
goto cleanup;
463463
}
464464

465+
skip_activate:
465466
/*
466467
* If these interrupts use reservation mode, clear the activated bit
467468
* so request_irq() will assign the final vector.
468469
*/
469470
if (can_reserve) {
470-
for_each_msi_entry(desc, dev) {
471-
irq_data = irq_domain_get_irq_data(domain, desc->irq);
471+
for_each_msi_vector(desc, i, dev) {
472+
irq_data = irq_domain_get_irq_data(domain, i);
472473
irqd_clr_activated(irq_data);
473474
}
474475
}
475476
return 0;
476477

477478
cleanup:
478-
for_each_msi_entry(desc, dev) {
479-
struct irq_data *irqd;
480-
481-
if (desc->irq == virq)
482-
break;
483-
484-
irqd = irq_domain_get_irq_data(domain, desc->irq);
485-
if (irqd_is_activated(irqd))
486-
irq_domain_deactivate_irq(irqd);
479+
for_each_msi_vector(desc, i, dev) {
480+
irq_data = irq_domain_get_irq_data(domain, i);
481+
if (irqd_is_activated(irq_data))
482+
irq_domain_deactivate_irq(irq_data);
487483
}
488484
msi_domain_free_irqs(domain, dev);
489485
return ret;

0 commit comments

Comments
 (0)