PPC32: This changeset adds preemptible kernel support for ppc32
[opensuse:kernel.git] / include / asm-ppc / hardirq.h
1 /*
2  * BK Id: %F% %I% %G% %U% %#%
3  */
4 #ifdef __KERNEL__
5 #ifndef __ASM_HARDIRQ_H
6 #define __ASM_HARDIRQ_H
7
8 #include <linux/config.h>
9 #include <asm/smp.h>
10
11 /* The __last_jiffy_stamp field is needed to ensure that no decrementer 
12  * interrupt is lost on SMP machines. Since on most CPUs it is in the same 
13  * cache line as local_irq_count, it is cheap to access and is also used on UP 
14  * for uniformity.
15  */
16 typedef struct {
17         unsigned long __softirq_pending;        /* set_bit is used on this */
18         unsigned int __local_irq_count;
19         unsigned int __local_bh_count;
20         unsigned int __syscall_count;
21         struct task_struct * __ksoftirqd_task;
22         unsigned int __last_jiffy_stamp;
23 } ____cacheline_aligned irq_cpustat_t;
24
25 #include <linux/irq_cpustat.h>  /* Standard mappings for irq_cpustat_t above */
26
27 #define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp)
28 /*
29  * Are we in an interrupt context? Either doing bottom half
30  * or hardware interrupt processing?
31  */
32 #define in_interrupt() ({ int __cpu = smp_processor_id(); \
33         (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
34
35 #define in_irq() (local_irq_count(smp_processor_id()) != 0)
36
37 #ifndef CONFIG_SMP
38
39 #define hardirq_trylock(cpu)    (local_irq_count(cpu) == 0)
40 #define hardirq_endlock(cpu)    do { } while (0)
41
42 #define hardirq_enter(cpu)      do { preempt_disable(); local_irq_count(cpu)++; } while (0)
43 #define hardirq_exit(cpu)       do { local_irq_count(cpu)--; preempt_enable(); } while (0)
44
45 #define synchronize_irq()       do { } while (0)
46 #define release_irqlock(cpu)    do { } while (0)
47
48 #else /* CONFIG_SMP */
49
50 #include <asm/atomic.h>
51
52 extern unsigned char global_irq_holder;
53 extern unsigned volatile long global_irq_lock;
54
55 static inline int irqs_running (void)
56 {
57         int i;
58
59         for (i = 0; i < smp_num_cpus; i++)
60                 if (local_irq_count(i))
61                         return 1;
62                 return 0;
63 }
64
65 static inline void release_irqlock(int cpu)
66 {
67         /* if we didn't own the irq lock, just ignore.. */
68         if (global_irq_holder == (unsigned char) cpu) {
69                 global_irq_holder = NO_PROC_ID;
70                 clear_bit(0,&global_irq_lock);
71         }
72 }
73
74 static inline void hardirq_enter(int cpu)
75 {
76         unsigned int loops = 10000000;
77
78         preempt_disable();
79         ++local_irq_count(cpu);
80         while (test_bit(0,&global_irq_lock)) {
81                 if (cpu == global_irq_holder) {
82                         printk("uh oh, interrupt while we hold global irq lock! (CPU %d)\n", cpu);
83 #ifdef CONFIG_XMON
84                         xmon(0);
85 #endif
86                         break;
87                 }
88                 if (loops-- == 0) {
89                         printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
90 #ifdef CONFIG_XMON
91                         xmon(0);
92 #endif
93                 }
94         }
95 }
96
97 static inline void hardirq_exit(int cpu)
98 {
99         --local_irq_count(cpu);
100         preempt_enable();
101 }
102
103 static inline int hardirq_trylock(int cpu)
104 {
105         return !test_bit(0,&global_irq_lock);
106 }
107
108 #define hardirq_endlock(cpu)    do { } while (0)
109
110 extern void synchronize_irq(void);
111
112 #endif /* CONFIG_SMP */
113
114 #endif /* __ASM_HARDIRQ_H */
115 #endif /* __KERNEL__ */