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
1949static 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+
6099int 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+
92133unsigned long arch_local_save_flags (void )
93134{
94135 return irqs_enabled ;
0 commit comments