Commit fc6c0ae5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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)

#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)		\
	irq_alloc_descs(at, at, 1, node)
@@ -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)

#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)			\
	devm_irq_alloc_descs(dev, at, at, 1, node)
+6 −0
Original line number Diff line number Diff line
@@ -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)
+20 −24
Original line number Diff line number Diff line
@@ -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
			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;
		goto skip_activate;

		irq_data = irq_domain_get_irq_data(domain, desc->irq);
	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);
		}

		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;