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

Merge tag 'irq-urgent-2020-04-05' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq fixes from Thomas Gleixner:
 "Two reverts addressing regressions of the Xilinx interrupt controller
  driver which affected the PPC users"

* tag 'irq-urgent-2020-04-05' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  Revert "irqchip/xilinx: Enable generic irq multi handler"
  Revert "irqchip/xilinx: Do not call irq_set_default_host()"
parents 70fbdfef a67cd1fb
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -47,8 +47,6 @@ config MICROBLAZE
	select CPU_NO_EFFICIENT_FFS
	select MMU_GATHER_NO_RANGE if MMU
	select SPARSE_IRQ
	select GENERIC_IRQ_MULTI_HANDLER
	select HANDLE_DOMAIN_IRQ

# Endianness selection
choice
+3 −0
Original line number Diff line number Diff line
@@ -11,4 +11,7 @@
struct pt_regs;
extern void do_IRQ(struct pt_regs *regs);

/* should be defined in each interrupt controller driver */
extern unsigned int xintc_get_irq(void);

#endif /* _ASM_MICROBLAZE_IRQ_H */
+20 −1
Original line number Diff line number Diff line
@@ -20,10 +20,29 @@
#include <linux/irqchip.h>
#include <linux/of_irq.h>

static u32 concurrent_irq;

void __irq_entry do_IRQ(struct pt_regs *regs)
{
	unsigned int irq;
	struct pt_regs *old_regs = set_irq_regs(regs);
	trace_hardirqs_off();
	handle_arch_irq(regs);

	irq_enter();
	irq = xintc_get_irq();
next_irq:
	BUG_ON(!irq);
	generic_handle_irq(irq);

	irq = xintc_get_irq();
	if (irq != -1U) {
		pr_debug("next irq: %d\n", irq);
		++concurrent_irq;
		goto next_irq;
	}

	irq_exit();
	set_irq_regs(old_regs);
	trace_hardirqs_on();
}

+15 −20
Original line number Diff line number Diff line
@@ -124,6 +124,20 @@ static unsigned int xintc_get_irq_local(struct xintc_irq_chip *irqc)
	return irq;
}

unsigned int xintc_get_irq(void)
{
	unsigned int irq = -1;
	u32 hwirq;

	hwirq = xintc_read(primary_intc, IVR);
	if (hwirq != -1U)
		irq = irq_find_mapping(primary_intc->root_domain, hwirq);

	pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);

	return irq;
}

static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
	struct xintc_irq_chip *irqc = d->host_data;
@@ -163,25 +177,6 @@ static void xil_intc_irq_handler(struct irq_desc *desc)
	chained_irq_exit(chip, desc);
}

static void xil_intc_handle_irq(struct pt_regs *regs)
{
	u32 hwirq;
	struct xintc_irq_chip *irqc = primary_intc;

	do {
		hwirq = xintc_read(irqc, IVR);
		if (likely(hwirq != -1U)) {
			int ret;

			ret = handle_domain_irq(irqc->root_domain, hwirq, regs);
			WARN_ONCE(ret, "Unhandled HWIRQ %d\n", hwirq);
			continue;
		}

		break;
	} while (1);
}

static int __init xilinx_intc_of_init(struct device_node *intc,
					     struct device_node *parent)
{
@@ -250,7 +245,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc,
		}
	} else {
		primary_intc = irqc;
		set_handle_irq(xil_intc_handle_irq);
		irq_set_default_host(primary_intc->root_domain);
	}

	return 0;