linux-old/include/linux/interrupt.h
<<
>>
Prefs
   1/* interrupt.h */
   2#ifndef _LINUX_INTERRUPT_H
   3#define _LINUX_INTERRUPT_H
   4
   5#include <linux/config.h>
   6#include <linux/kernel.h>
   7#include <linux/smp.h>
   8#include <linux/cache.h>
   9
  10#include <asm/bitops.h>
  11#include <asm/atomic.h>
  12#include <asm/ptrace.h>
  13
  14struct irqaction {
  15        void (*handler)(int, void *, struct pt_regs *);
  16        unsigned long flags;
  17        unsigned long mask;
  18        const char *name;
  19        void *dev_id;
  20        struct irqaction *next;
  21};
  22
  23
  24/* Who gets which entry in bh_base.  Things which will occur most often
  25   should come first */
  26   
  27enum {
  28        TIMER_BH = 0,
  29        TQUEUE_BH,
  30        DIGI_BH,
  31        SERIAL_BH,
  32        RISCOM8_BH,
  33        SPECIALIX_BH,
  34        AURORA_BH,
  35        ESP_BH,
  36        SCSI_BH,
  37        IMMEDIATE_BH,
  38        CYCLADES_BH,
  39        CM206_BH,
  40        JS_BH,
  41        MACSERIAL_BH,
  42        ISICOM_BH
  43};
  44
  45#include <asm/hardirq.h>
  46#include <asm/softirq.h>
  47
  48
  49
  50/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
  51   frequency threaded job scheduling. For almost all the purposes
  52   tasklets are more than enough. F.e. all serial device BHs et
  53   al. should be converted to tasklets, not to softirqs.
  54 */
  55
  56enum
  57{
  58        HI_SOFTIRQ=0,
  59        NET_TX_SOFTIRQ,
  60        NET_RX_SOFTIRQ,
  61        TASKLET_SOFTIRQ
  62};
  63
  64/* softirq mask and active fields moved to irq_cpustat_t in
  65 * asm/hardirq.h to get better cache usage.  KAO
  66 */
  67
  68struct softirq_action
  69{
  70        void    (*action)(struct softirq_action *);
  71        void    *data;
  72};
  73
  74asmlinkage void do_softirq(void);
  75extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
  76extern void softirq_init(void);
  77#define __cpu_raise_softirq(cpu, nr) do { softirq_pending(cpu) |= 1UL << (nr); } while (0)
  78extern void FASTCALL(cpu_raise_softirq(unsigned int cpu, unsigned int nr));
  79extern void FASTCALL(raise_softirq(unsigned int nr));
  80
  81
  82
  83/* Tasklets --- multithreaded analogue of BHs.
  84
  85   Main feature differing them of generic softirqs: tasklet
  86   is running only on one CPU simultaneously.
  87
  88   Main feature differing them of BHs: different tasklets
  89   may be run simultaneously on different CPUs.
  90
  91   Properties:
  92   * If tasklet_schedule() is called, then tasklet is guaranteed
  93     to be executed on some cpu at least once after this.
  94   * If the tasklet is already scheduled, but its excecution is still not
  95     started, it will be executed only once.
  96   * If this tasklet is already running on another CPU (or schedule is called
  97     from tasklet itself), it is rescheduled for later.
  98   * Tasklet is strictly serialized wrt itself, but not
  99     wrt another tasklets. If client needs some intertask synchronization,
 100     he makes it with spinlocks.
 101 */
 102
 103struct tasklet_struct
 104{
 105        struct tasklet_struct *next;
 106        unsigned long state;
 107        atomic_t count;
 108        void (*func)(unsigned long);
 109        unsigned long data;
 110};
 111
 112#define DECLARE_TASKLET(name, func, data) \
 113struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
 114
 115#define DECLARE_TASKLET_DISABLED(name, func, data) \
 116struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }
 117
 118
 119enum
 120{
 121        TASKLET_STATE_SCHED,    /* Tasklet is scheduled for execution */
 122        TASKLET_STATE_RUN       /* Tasklet is running (SMP only) */
 123};
 124
 125struct tasklet_head
 126{
 127        struct tasklet_struct *list;
 128} __attribute__ ((__aligned__(SMP_CACHE_BYTES)));
 129
 130extern struct tasklet_head tasklet_vec[NR_CPUS];
 131extern struct tasklet_head tasklet_hi_vec[NR_CPUS];
 132
 133#ifdef CONFIG_SMP
 134static inline int tasklet_trylock(struct tasklet_struct *t)
 135{
 136        return !test_and_set_bit(TASKLET_STATE_RUN, &(t)->state);
 137}
 138
 139static inline void tasklet_unlock(struct tasklet_struct *t)
 140{
 141        smp_mb__before_clear_bit(); 
 142        clear_bit(TASKLET_STATE_RUN, &(t)->state);
 143}
 144
 145static inline void tasklet_unlock_wait(struct tasklet_struct *t)
 146{
 147        while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); }
 148}
 149#else
 150#define tasklet_trylock(t) 1
 151#define tasklet_unlock_wait(t) do { } while (0)
 152#define tasklet_unlock(t) do { } while (0)
 153#endif
 154
 155extern void FASTCALL(__tasklet_schedule(struct tasklet_struct *t));
 156
 157static inline void tasklet_schedule(struct tasklet_struct *t)
 158{
 159        if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
 160                __tasklet_schedule(t);
 161}
 162
 163extern void FASTCALL(__tasklet_hi_schedule(struct tasklet_struct *t));
 164
 165static inline void tasklet_hi_schedule(struct tasklet_struct *t)
 166{
 167        if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
 168                __tasklet_hi_schedule(t);
 169}
 170
 171
 172static inline void tasklet_disable_nosync(struct tasklet_struct *t)
 173{
 174        atomic_inc(&t->count);
 175        smp_mb__after_atomic_inc();
 176}
 177
 178static inline void tasklet_disable(struct tasklet_struct *t)
 179{
 180        tasklet_disable_nosync(t);
 181        tasklet_unlock_wait(t);
 182        smp_mb();
 183}
 184
 185static inline void tasklet_enable(struct tasklet_struct *t)
 186{
 187        smp_mb__before_atomic_dec();
 188        atomic_dec(&t->count);
 189}
 190
 191static inline void tasklet_hi_enable(struct tasklet_struct *t)
 192{
 193        smp_mb__before_atomic_dec();
 194        atomic_dec(&t->count);
 195}
 196
 197extern void tasklet_kill(struct tasklet_struct *t);
 198extern void tasklet_init(struct tasklet_struct *t,
 199                         void (*func)(unsigned long), unsigned long data);
 200
 201#ifdef CONFIG_SMP
 202
 203#define SMP_TIMER_NAME(name) name##__thr
 204
 205#define SMP_TIMER_DEFINE(name, task) \
 206DECLARE_TASKLET(task, name##__thr, 0); \
 207static void name (unsigned long dummy) \
 208{ \
 209        tasklet_schedule(&(task)); \
 210}
 211
 212#else /* CONFIG_SMP */
 213
 214#define SMP_TIMER_NAME(name) name
 215#define SMP_TIMER_DEFINE(name, task)
 216
 217#endif /* CONFIG_SMP */
 218
 219
 220/* Old BH definitions */
 221
 222extern struct tasklet_struct bh_task_vec[];
 223
 224/* It is exported _ONLY_ for wait_on_irq(). */
 225extern spinlock_t global_bh_lock;
 226
 227static inline void mark_bh(int nr)
 228{
 229        tasklet_hi_schedule(bh_task_vec+nr);
 230}
 231
 232extern void init_bh(int nr, void (*routine)(void));
 233extern void remove_bh(int nr);
 234
 235
 236/*
 237 * Autoprobing for irqs:
 238 *
 239 * probe_irq_on() and probe_irq_off() provide robust primitives
 240 * for accurate IRQ probing during kernel initialization.  They are
 241 * reasonably simple to use, are not "fooled" by spurious interrupts,
 242 * and, unlike other attempts at IRQ probing, they do not get hung on
 243 * stuck interrupts (such as unused PS2 mouse interfaces on ASUS boards).
 244 *
 245 * For reasonably foolproof probing, use them as follows:
 246 *
 247 * 1. clear and/or mask the device's internal interrupt.
 248 * 2. sti();
 249 * 3. irqs = probe_irq_on();      // "take over" all unassigned idle IRQs
 250 * 4. enable the device and cause it to trigger an interrupt.
 251 * 5. wait for the device to interrupt, using non-intrusive polling or a delay.
 252 * 6. irq = probe_irq_off(irqs);  // get IRQ number, 0=none, negative=multiple
 253 * 7. service the device to clear its pending interrupt.
 254 * 8. loop again if paranoia is required.
 255 *
 256 * probe_irq_on() returns a mask of allocated irq's.
 257 *
 258 * probe_irq_off() takes the mask as a parameter,
 259 * and returns the irq number which occurred,
 260 * or zero if none occurred, or a negative irq number
 261 * if more than one irq occurred.
 262 */
 263extern unsigned long probe_irq_on(void);        /* returns 0 on failure */
 264extern int probe_irq_off(unsigned long);        /* returns 0 or negative on failure */
 265extern unsigned int probe_irq_mask(unsigned long);      /* returns mask of ISA interrupts */
 266
 267#endif
 268
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.