1/* hardirq.h: PA-RISC hard IRQ support. 2 * 3 * Copyright (C) 2001 Matthew Wilcox <matthew@wil.cx> 4 * 5 * The locking is really quite interesting. There's a cpu-local 6 * count of how many interrupts are being handled, and a global 7 * lock. An interrupt can only be serviced if the global lock 8 * is free. You can't be sure no more interrupts are being 9 * serviced until you've acquired the lock and then checked 10 * all the per-cpu interrupt counts are all zero. It's a specialised 11 * br_lock, and that's exactly how Sparc does it. We don't because 12 * it's more locking for us. This way is lock-free in the interrupt path. 13 */ 14 15#ifndef _PARISC_HARDIRQ_H 16#define _PARISC_HARDIRQ_H 17 18#include <linux/config.h> 19#include <linux/threads.h> 20 21typedef struct { 22 unsigned long __softirq_pending; /* set_bit is used on this */ 23 unsigned int __local_irq_count; 24 unsigned int __local_bh_count; 25 unsigned int __syscall_count; 26 struct task_struct * __ksoftirqd_task; 27} ____cacheline_aligned irq_cpustat_t; 28 29#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ 30 31/* 32 * Are we in an interrupt context? Either doing bottom half 33 * or hardware interrupt processing? 34 */ 35#define in_interrupt() ({ int __cpu = smp_processor_id(); \ 36 (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) 37 38#define in_irq() ({ int __cpu = smp_processor_id(); \ 39 (local_irq_count(__cpu) != 0); }) 40 41#ifndef CONFIG_SMP 42 43#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) 44#define hardirq_endlock(cpu) do { } while (0) 45 46#define irq_enter(cpu, irq) (local_irq_count(cpu)++) 47#define irq_exit(cpu, irq) (local_irq_count(cpu)--) 48 49#define synchronize_irq() barrier() 50 51#else 52 53#include <asm/system.h> 54#include <asm/atomic.h> 55#include <linux/spinlock.h> 56#include <asm/smp.h> 57 58extern int global_irq_holder; 59extern spinlock_t global_irq_lock; 60 61static inline int irqs_running (void) 62{ 63 int i; 64 65 for (i = 0; i < smp_num_cpus; i++) 66 if (local_irq_count(i)) 67 return 1; 68 return 0; 69} 70 71 72static inline void release_irqlock(int cpu) 73{ 74 /* if we didn't own the irq lock, just ignore.. */ 75 if (global_irq_holder == (unsigned char) cpu) { 76 global_irq_holder = NO_PROC_ID; 77 spin_unlock(&global_irq_lock); 78 } 79} 80 81static inline void irq_enter(int cpu, int irq) 82{ 83 ++local_irq_count(cpu); 84 85 while (spin_is_locked(&global_irq_lock)) 86 barrier(); 87} 88 89static inline void irq_exit(int cpu, int irq) 90{ 91 --local_irq_count(cpu); 92} 93 94static inline int hardirq_trylock(int cpu) 95{ 96 return !local_irq_count(cpu) && !spin_is_locked (&global_irq_lock); 97} 98 99#define hardirq_endlock(cpu) do { } while (0) 100 101extern void synchronize_irq(void); 102 103#endif /* CONFIG_SMP */ 104 105#endif /* _PARISC_HARDIRQ_H */ 106