Skip to content

Commit 75def1f

Browse files
authored
Merge pull request torvalds#242 from tavip/more-irqs
lkl: increase the number of irqs
2 parents d936b0d + f640ba8 commit 75def1f

File tree

2 files changed

+64
-22
lines changed

2 files changed

+64
-22
lines changed

arch/lkl/include/asm/irq.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#ifndef _ASM_LKL_IRQ_H
22
#define _ASM_LKL_IRQ_H
33

4-
#define NR_IRQS ((int)sizeof(long) * 8)
4+
#define IRQ_STATUS_BITS (sizeof(long) * 8)
5+
#define NR_IRQS ((int)IRQ_STATUS_BITS * IRQ_STATUS_BITS)
56

67
#include <uapi/asm/irq.h>
78

arch/lkl/kernel/irq.c

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,48 @@
99
#include <asm/irqflags.h>
1010
#include <asm/host_ops.h>
1111

12-
static unsigned long irq_status;
13-
static bool irqs_enabled;
12+
/*
13+
* To avoid much overhead we use an indirect approach: the irqs are marked using
14+
* a bitmap (array of longs) and a summary of the modified bits is kept in a
15+
* separate "index" long - one bit for each sizeof(long). Thus we can support
16+
* 4096 irqs on 64bit platforms and 1024 irqs on 32bit platforms.
17+
*
18+
* Whenever an irq is trigger both the array and the index is updated. To find
19+
* which irqs were triggered we first search the index and then the
20+
* corresponding part of the arrary.
21+
*/
22+
static unsigned long irq_status[NR_IRQS/IRQ_STATUS_BITS];
23+
static unsigned long irq_index_status;
24+
25+
static inline unsigned long test_and_clear_irq_index_status(void)
26+
{
27+
if (!irq_index_status)
28+
return 0;
29+
return __sync_fetch_and_and(&irq_index_status, 0);
30+
}
31+
32+
static inline unsigned long test_and_clear_irq_status(int index)
33+
{
34+
if (!&irq_status[index])
35+
return 0;
36+
return __sync_fetch_and_and(&irq_status[index], 0);
37+
}
38+
39+
static inline void set_irq_status(int irq)
40+
{
41+
int index = irq / IRQ_STATUS_BITS;
42+
int bit = irq % IRQ_STATUS_BITS;
43+
44+
__sync_fetch_and_or(&irq_status[index], BIT(bit));
45+
__sync_fetch_and_or(&irq_index_status, BIT(index));
46+
}
1447

15-
#define TEST_AND_CLEAR_IRQ_STATUS(x) __sync_fetch_and_and(&irq_status, 0)
16-
#define IRQ_BIT(x) BIT(x-1)
17-
#define SET_IRQ_STATUS(x) __sync_fetch_and_or(&irq_status, BIT(x - 1))
1848

1949
static struct irq_info {
2050
const char *user;
2151
} irqs[NR_IRQS];
2252

53+
2354
/**
2455
* DO NOT run any linux calls (e.g. printk) here as they may race with the
2556
* existing linux threads.
@@ -29,34 +60,42 @@ int lkl_trigger_irq(int irq)
2960
if (!irq || irq > NR_IRQS)
3061
return -EINVAL;
3162

32-
SET_IRQ_STATUS(irq);
63+
set_irq_status(irq);
3364

3465
wakeup_cpu();
3566

3667
return 0;
3768
}
3869

39-
static void run_irqs(void)
70+
static inline void for_each_bit(unsigned long word, void (*f)(int, int), int j)
4071
{
41-
int i = 1;
42-
unsigned long status;
43-
44-
if (!irq_status)
45-
return;
46-
47-
status = TEST_AND_CLEAR_IRQ_STATUS(IRQS_MASK);
72+
int i = 0;
4873

49-
while (status) {
50-
if (status & 1) {
51-
irq_enter();
52-
generic_handle_irq(i);
53-
irq_exit();
54-
}
55-
status = status >> 1;
74+
while (word) {
75+
if (word & 1)
76+
f(i, j);
77+
word >>= 1;
5678
i++;
5779
}
5880
}
5981

82+
static inline void deliver_irq(int bit, int index)
83+
{
84+
irq_enter();
85+
generic_handle_irq(index * IRQ_STATUS_BITS + bit);
86+
irq_exit();
87+
}
88+
89+
static inline void check_irq_status(int i, int unused)
90+
{
91+
for_each_bit(test_and_clear_irq_status(i), deliver_irq, i);
92+
}
93+
94+
static void run_irqs(void)
95+
{
96+
for_each_bit(test_and_clear_irq_index_status(), check_irq_status, 0);
97+
}
98+
6099
int show_interrupts(struct seq_file *p, void *v)
61100
{
62101
return 0;
@@ -89,6 +128,8 @@ void lkl_put_irq(int i, const char *user)
89128
irqs[i].user = NULL;
90129
}
91130

131+
static bool irqs_enabled;
132+
92133
unsigned long arch_local_save_flags(void)
93134
{
94135
return irqs_enabled;

0 commit comments

Comments
 (0)