Commit a3016b26 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

genirq: Use irq_resolve_mapping() to implement __handle_domain_irq() and co



In order to start reaping the benefits of irq_resolve_mapping(),
start using it in __handle_domain_irq() and handle_domain_nmi().

This involves splitting generic_handle_irq() to be able to directly
provide the irq_desc.

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent d22558dd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ static inline void generic_handle_irq_desc(struct irq_desc *desc)
	desc->handle_irq(desc);
}

int handle_irq_desc(struct irq_desc *desc);
int generic_handle_irq(unsigned int irq);

#ifdef CONFIG_HANDLE_DOMAIN_IRQ
+35 −25
Original line number Diff line number Diff line
@@ -632,14 +632,8 @@ void irq_init_desc(unsigned int irq)

#endif /* !CONFIG_SPARSE_IRQ */

/**
 * generic_handle_irq - Invoke the handler for a particular irq
 * @irq:	The irq number to handle
 *
 */
int generic_handle_irq(unsigned int irq)
int handle_irq_desc(struct irq_desc *desc)
{
	struct irq_desc *desc = irq_to_desc(irq);
	struct irq_data *data;

	if (!desc)
@@ -652,6 +646,17 @@ int generic_handle_irq(unsigned int irq)
	generic_handle_irq_desc(desc);
	return 0;
}
EXPORT_SYMBOL_GPL(handle_irq_desc);

/**
 * generic_handle_irq - Invoke the handler for a particular irq
 * @irq:	The irq number to handle
 *
 */
int generic_handle_irq(unsigned int irq)
{
	return handle_irq_desc(irq_to_desc(irq));
}
EXPORT_SYMBOL_GPL(generic_handle_irq);

#ifdef CONFIG_HANDLE_DOMAIN_IRQ
@@ -668,27 +673,32 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
			bool lookup, struct pt_regs *regs)
{
	struct pt_regs *old_regs = set_irq_regs(regs);
	unsigned int irq = hwirq;
	struct irq_desc *desc;
	int ret = 0;

	irq_enter();

#ifdef CONFIG_IRQ_DOMAIN
	if (lookup)
		irq = irq_find_mapping(domain, hwirq);
#endif

	if (likely(IS_ENABLED(CONFIG_IRQ_DOMAIN) && lookup)) {
		/* The irqdomain code provides boundary checks */
		desc = irq_resolve_mapping(domain, hwirq);
	} else {
		/*
		 * Some hardware gives randomly wrong interrupts.  Rather
		 * than crashing, do something sensible.
		 */
	if (unlikely(!irq || irq >= nr_irqs)) {
		ack_bad_irq(irq);
		ret = -EINVAL;
		if (unlikely(!hwirq || hwirq >= nr_irqs)) {
			ack_bad_irq(hwirq);
			desc = NULL;
		} else {
		generic_handle_irq(irq);
			desc = irq_to_desc(hwirq);
		}
	}

	if (likely(desc))
		handle_irq_desc(desc);
	else
		ret = -EINVAL;

	irq_exit();
	set_irq_regs(old_regs);
	return ret;
@@ -709,7 +719,7 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
		      struct pt_regs *regs)
{
	struct pt_regs *old_regs = set_irq_regs(regs);
	unsigned int irq;
	struct irq_desc *desc;
	int ret = 0;

	/*
@@ -717,14 +727,14 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
	 */
	WARN_ON(!in_nmi());

	irq = irq_find_mapping(domain, hwirq);
	desc = irq_resolve_mapping(domain, hwirq);

	/*
	 * ack_bad_irq is not NMI-safe, just report
	 * an invalid interrupt.
	 */
	if (likely(irq))
		generic_handle_irq(irq);
	if (likely(desc))
		handle_irq_desc(desc);
	else
		ret = -EINVAL;