|
14 | 14 | #include <linux/kernel_stat.h> |
15 | 15 | #include <linux/radix-tree.h> |
16 | 16 | #include <linux/bitmap.h> |
| 17 | +#include <linux/irqdomain.h> |
17 | 18 |
|
18 | 19 | #include "internals.h" |
19 | 20 |
|
@@ -336,6 +337,47 @@ int generic_handle_irq(unsigned int irq) |
336 | 337 | } |
337 | 338 | EXPORT_SYMBOL_GPL(generic_handle_irq); |
338 | 339 |
|
| 340 | +#ifdef CONFIG_HANDLE_DOMAIN_IRQ |
| 341 | +/** |
| 342 | + * __handle_domain_irq - Invoke the handler for a HW irq belonging to a domain |
| 343 | + * @domain: The domain where to perform the lookup |
| 344 | + * @hwirq: The HW irq number to convert to a logical one |
| 345 | + * @lookup: Whether to perform the domain lookup or not |
| 346 | + * @regs: Register file coming from the low-level handling code |
| 347 | + * |
| 348 | + * Returns: 0 on success, or -EINVAL if conversion has failed |
| 349 | + */ |
| 350 | +int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, |
| 351 | + bool lookup, struct pt_regs *regs) |
| 352 | +{ |
| 353 | + struct pt_regs *old_regs = set_irq_regs(regs); |
| 354 | + unsigned int irq = hwirq; |
| 355 | + int ret = 0; |
| 356 | + |
| 357 | + irq_enter(); |
| 358 | + |
| 359 | +#ifdef CONFIG_IRQ_DOMAIN |
| 360 | + if (lookup) |
| 361 | + irq = irq_find_mapping(domain, hwirq); |
| 362 | +#endif |
| 363 | + |
| 364 | + /* |
| 365 | + * Some hardware gives randomly wrong interrupts. Rather |
| 366 | + * than crashing, do something sensible. |
| 367 | + */ |
| 368 | + if (unlikely(!irq || irq >= nr_irqs)) { |
| 369 | + ack_bad_irq(irq); |
| 370 | + ret = -EINVAL; |
| 371 | + } else { |
| 372 | + generic_handle_irq(irq); |
| 373 | + } |
| 374 | + |
| 375 | + irq_exit(); |
| 376 | + set_irq_regs(old_regs); |
| 377 | + return ret; |
| 378 | +} |
| 379 | +#endif |
| 380 | + |
339 | 381 | /* Dynamic interrupt handling */ |
340 | 382 |
|
341 | 383 | /** |
|
0 commit comments