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: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
d22558dd0a
commit
a3016b26ee
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
/*
|
||||
* 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 (likely(IS_ENABLED(CONFIG_IRQ_DOMAIN) && lookup)) {
|
||||
/* The irqdomain code provides boundary checks */
|
||||
desc = irq_resolve_mapping(domain, hwirq);
|
||||
} else {
|
||||
generic_handle_irq(irq);
|
||||
/*
|
||||
* Some hardware gives randomly wrong interrupts. Rather
|
||||
* than crashing, do something sensible.
|
||||
*/
|
||||
if (unlikely(!hwirq || hwirq >= nr_irqs)) {
|
||||
ack_bad_irq(hwirq);
|
||||
desc = NULL;
|
||||
} else {
|
||||
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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue