Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/kernel/irq/resend.c
10818 views
1
/*
2
* linux/kernel/irq/resend.c
3
*
4
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
5
* Copyright (C) 2005-2006, Thomas Gleixner
6
*
7
* This file contains the IRQ-resend code
8
*
9
* If the interrupt is waiting to be processed, we try to re-run it.
10
* We can't directly run it from here since the caller might be in an
11
* interrupt-protected region. Not all irq controller chips can
12
* retrigger interrupts at the hardware level, so in those cases
13
* we allow the resending of IRQs via a tasklet.
14
*/
15
16
#include <linux/irq.h>
17
#include <linux/module.h>
18
#include <linux/random.h>
19
#include <linux/interrupt.h>
20
21
#include "internals.h"
22
23
#ifdef CONFIG_HARDIRQS_SW_RESEND
24
25
/* Bitmap to handle software resend of interrupts: */
26
static DECLARE_BITMAP(irqs_resend, IRQ_BITMAP_BITS);
27
28
/*
29
* Run software resends of IRQ's
30
*/
31
static void resend_irqs(unsigned long arg)
32
{
33
struct irq_desc *desc;
34
int irq;
35
36
while (!bitmap_empty(irqs_resend, nr_irqs)) {
37
irq = find_first_bit(irqs_resend, nr_irqs);
38
clear_bit(irq, irqs_resend);
39
desc = irq_to_desc(irq);
40
local_irq_disable();
41
desc->handle_irq(irq, desc);
42
local_irq_enable();
43
}
44
}
45
46
/* Tasklet to handle resend: */
47
static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0);
48
49
#endif
50
51
/*
52
* IRQ resend
53
*
54
* Is called with interrupts disabled and desc->lock held.
55
*/
56
void check_irq_resend(struct irq_desc *desc, unsigned int irq)
57
{
58
/*
59
* We do not resend level type interrupts. Level type
60
* interrupts are resent by hardware when they are still
61
* active.
62
*/
63
if (irq_settings_is_level(desc))
64
return;
65
if (desc->istate & IRQS_REPLAY)
66
return;
67
if (desc->istate & IRQS_PENDING) {
68
desc->istate &= ~IRQS_PENDING;
69
desc->istate |= IRQS_REPLAY;
70
71
if (!desc->irq_data.chip->irq_retrigger ||
72
!desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
73
#ifdef CONFIG_HARDIRQS_SW_RESEND
74
/* Set it pending and activate the softirq: */
75
set_bit(irq, irqs_resend);
76
tasklet_schedule(&resend_tasklet);
77
#endif
78
}
79
}
80
}
81
82