Commit fc6c0ae5 authored by Linus Torvalds's avatar Linus Torvalds

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
parents c6792d44 4c7bcb51
...@@ -928,7 +928,7 @@ int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from, ...@@ -928,7 +928,7 @@ int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
__irq_alloc_descs(irq, from, cnt, node, THIS_MODULE, NULL) __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE, NULL)
#define irq_alloc_desc(node) \ #define irq_alloc_desc(node) \
irq_alloc_descs(-1, 0, 1, node) irq_alloc_descs(-1, 1, 1, node)
#define irq_alloc_desc_at(at, node) \ #define irq_alloc_desc_at(at, node) \
irq_alloc_descs(at, at, 1, node) irq_alloc_descs(at, at, 1, node)
...@@ -943,7 +943,7 @@ int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from, ...@@ -943,7 +943,7 @@ int __devm_irq_alloc_descs(struct device *dev, int irq, unsigned int from,
__devm_irq_alloc_descs(dev, irq, from, cnt, node, THIS_MODULE, NULL) __devm_irq_alloc_descs(dev, irq, from, cnt, node, THIS_MODULE, NULL)
#define devm_irq_alloc_desc(dev, node) \ #define devm_irq_alloc_desc(dev, node) \
devm_irq_alloc_descs(dev, -1, 0, 1, node) devm_irq_alloc_descs(dev, -1, 1, 1, node)
#define devm_irq_alloc_desc_at(dev, at, node) \ #define devm_irq_alloc_desc_at(dev, at, node) \
devm_irq_alloc_descs(dev, at, at, 1, node) devm_irq_alloc_descs(dev, at, at, 1, node)
......
...@@ -178,6 +178,12 @@ struct msi_desc { ...@@ -178,6 +178,12 @@ struct msi_desc {
list_for_each_entry((desc), dev_to_msi_list((dev)), list) list_for_each_entry((desc), dev_to_msi_list((dev)), list)
#define for_each_msi_entry_safe(desc, tmp, dev) \ #define for_each_msi_entry_safe(desc, tmp, dev) \
list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list) 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 #ifdef CONFIG_IRQ_MSI_IOMMU
static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc) static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
......
...@@ -436,22 +436,22 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, ...@@ -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); can_reserve = msi_check_reservation_mode(domain, info, dev);
for_each_msi_entry(desc, dev) { /*
virq = desc->irq; * This flag is set by the PCI layer as we need to activate
if (desc->nvec_used == 1) * the MSI entries before the PCI layer enables MSI in the
dev_dbg(dev, "irq %d for MSI\n", virq); * card. Otherwise the card latches a random msi message.
else */
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", dev_dbg(dev, "irq [%d-%d] for MSI\n",
virq, virq + desc->nvec_used - 1); 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) { if (!can_reserve) {
irqd_clr_can_reserve(irq_data); irqd_clr_can_reserve(irq_data);
if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK)
...@@ -462,28 +462,24 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, ...@@ -462,28 +462,24 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
goto cleanup; goto cleanup;
} }
skip_activate:
/* /*
* If these interrupts use reservation mode, clear the activated bit * If these interrupts use reservation mode, clear the activated bit
* so request_irq() will assign the final vector. * so request_irq() will assign the final vector.
*/ */
if (can_reserve) { if (can_reserve) {
for_each_msi_entry(desc, dev) { for_each_msi_vector(desc, i, dev) {
irq_data = irq_domain_get_irq_data(domain, desc->irq); irq_data = irq_domain_get_irq_data(domain, i);
irqd_clr_activated(irq_data); irqd_clr_activated(irq_data);
} }
} }
return 0; return 0;
cleanup: cleanup:
for_each_msi_entry(desc, dev) { for_each_msi_vector(desc, i, dev) {
struct irq_data *irqd; irq_data = irq_domain_get_irq_data(domain, i);
if (irqd_is_activated(irq_data))
if (desc->irq == virq) irq_domain_deactivate_irq(irq_data);
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); msi_domain_free_irqs(domain, dev);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment