linux-bk/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/linkage.h>
   8#include <linux/bitops.h>
   9#include <linux/preempt.h>
  10#include <linux/cpumask.h>
  11#include <asm/atomic.h>
  12#include <asm/hardirq.h>
  13#include <asm/ptrace.h>
  14#include <asm/system.h>
  15
  16/*
  17 * For 2.4.x compatibility, 2.4.x can use
  18 *
  19 *      typedef void irqreturn_t;
  20 *      #define IRQ_NONE
  21 *      #define IRQ_HANDLED
  22 *      #define IRQ_RETVAL(x)
  23 *
  24 * To mix old-style and new-style irq handler returns.
  25 *
  26 * IRQ_NONE means we didn't handle it.
  27 * IRQ_HANDLED means that we did have a valid interrupt and handled it.
  28 * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled)
  29 */
  30typedef int irqreturn_t;
  31
  32#define IRQ_NONE        (0)
  33#define IRQ_HANDLED     (1)
  34#define IRQ_RETVAL(x)   ((x) != 0)
  35
  36struct irqaction {
  37        irqreturn_t (*handler)(int, void *, struct pt_regs *);
  38        unsigned long flags;
  39        cpumask_t mask;
  40        const char *name;
  41        void *dev_id;
  42        struct irqaction *next;
  43};
  44
  45extern irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs);
  46extern int request_irq(unsigned int,
  47                       irqreturn_t (*handler)(int, void *, struct pt_regs *),
  48                       unsigned long, const char *, void *);
  49extern void free_irq(unsigned int, void *);
  50
  51/*
  52 * Temporary defines for UP kernels, until all code gets fixed.
  53 */
  54#ifndef CONFIG_SMP
  55# define cli()                  local_irq_disable()
  56# define sti()                  local_irq_enable()
  57# define save_flags(x)          local_save_flags(x)
  58# define restore_flags(x)       local_irq_restore(x)
  59# define save_and_cli(x)        local_irq_save(x)
  60#endif
  61
  62/* SoftIRQ primitives.  */
  63#define local_bh_disable() \
  64                do { preempt_count() += SOFTIRQ_OFFSET; barrier(); } while (0)
  65#define __local_bh_enable() \
  66                do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0)
  67
  68extern void local_bh_enable(void);
  69
  70/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
  71   frequency threaded job scheduling. For almost all the purposes
  72   tasklets are more than enough. F.e. all serial device BHs et
  73   al. should be converted to tasklets, not to softirqs.
  74 */
  75
  76enum
  77{
  78        HI_SOFTIRQ=0,
  79        TIMER_SOFTIRQ,
  80        NET_TX_SOFTIRQ,
  81        NET_RX_SOFTIRQ,
  82        SCSI_SOFTIRQ,
  83        TASKLET_SOFTIRQ
  84};
  85
  86/* softirq mask and active fields moved to irq_cpustat_t in
  87 * asm/hardirq.h to get better cache usage.  KAO
  88 */
  89
  90struct softirq_action
  91{
  92        void    (*action)(struct softirq_action *);
  93        void    *data;
  94};
  95
  96asmlinkage void do_softirq(void);
  97extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
  98extern void softirq_init(void);
  99#define __raise_softirq_irqoff(nr) do { local_softirq_pending() |= 1UL << (nr); } while (0)
 100extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
 101extern void FASTCALL(raise_softirq(unsigned int nr));
 102
 103#ifndef invoke_softirq
 104#define invoke_softirq() do_softirq()
 105#endif
 106
 107
 108/* Tasklets --- multithreaded analogue of BHs.
 109
 110   Main feature differing them of generic softirqs: tasklet
 111   is running only on one CPU simultaneously.
 112
 113   Main feature differing them of BHs: different tasklets
 114   may be run simultaneously on different CPUs.
 115
 116   Properties:
 117   * If tasklet_schedule() is called, then tasklet is guaranteed
 118     to be executed on some cpu at least once after this.
 119   * If the tasklet is already scheduled, but its excecution is still not
 120     started, it will be executed only once.
 121   * If this tasklet is already running on another CPU (or schedule is called
 122     from tasklet itself), it is rescheduled for later.
 123   * Tasklet is strictly serialized wrt itself, but not
 124     wrt another tasklets. If client needs some intertask synchronization,
 125     he makes it with spinlocks.
 126 */
 127
 128struct tasklet_struct
 129{
 130        struct tasklet_struct *next;
 131        unsigned long state;
 132        atomic_t count;
 133        void (*func)(unsigned long);
 134        unsigned long data;
 135};
 136
 137#define DECLARE_TASKLET(name, func, data) \
 138struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
 139
 140#define DECLARE_TASKLET_DISABLED(name, func, data) \
 141struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }
 142
 143
 144enum
 145{
 146        TASKLET_STATE_SCHED,    /* Tasklet is scheduled for execution */
 147        TASKLET_STATE_RUN       /* Tasklet is running (SMP only) */
 148};
 149
 150#ifdef CONFIG_SMP
 151static inline int tasklet_trylock(struct tasklet_struct *t)
 152{
 153        return !test_and_set_bit(TASKLET_STATE_RUN, &(t)->state);
 154}
 155
 156static inline void tasklet_unlock(struct tasklet_struct *t)
 157{
 158        smp_mb__before_clear_bit(); 
 159        clear_bit(TASKLET_STATE_RUN, &(t)->state);
 160}
 161
 162static inline void tasklet_unlock_wait(struct tasklet_struct *t)
 163{
 164        while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); }
 165}
 166#else
 167#define tasklet_trylock(t) 1
 168#define tasklet_unlock_wait(t) do { } while (0)
 169#define tasklet_unlock(t) do { } while (0)
 170#endif
 171
 172extern void FASTCALL(__tasklet_schedule(struct tasklet_struct *t));
 173
 174static inline void tasklet_schedule(struct tasklet_struct *t)
 175{
 176        if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
 177                __tasklet_schedule(t);
 178}
 179
 180extern void FASTCALL(__tasklet_hi_schedule(struct tasklet_struct *t));
 181
 182static inline void tasklet_hi_schedule(struct tasklet_struct *t)
 183{
 184        if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
 185                __tasklet_hi_schedule(t);
 186}
 187
 188
 189static inline void tasklet_disable_nosync(struct tasklet_struct *t)
 190{
 191        atomic_inc(&t->count);
 192        smp_mb__after_atomic_inc();
 193}
 194
 195static inline void tasklet_disable(struct tasklet_struct *t)
 196{
 197        tasklet_disable_nosync(t);
 198        tasklet_unlock_wait(t);
 199        smp_mb();
 200}
 201
 202static inline void tasklet_enable(struct tasklet_struct *t)
 203{
 204        smp_mb__before_atomic_dec();
 205        atomic_dec(&t->count);
 206}
 207
 208static inline void tasklet_hi_enable(struct tasklet_struct *t)
 209{
 210        smp_mb__before_atomic_dec();
 211        atomic_dec(&t->count);
 212}
 213
 214extern void tasklet_kill(struct tasklet_struct *t);
 215extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
 216extern void tasklet_init(struct tasklet_struct *t,
 217                         void (*func)(unsigned long), unsigned long data);
 218
 219/*
 220 * Autoprobing for irqs:
 221 *
 222 * probe_irq_on() and probe_irq_off() provide robust primitives
 223 * for accurate IRQ probing during kernel initialization.  They are
 224 * reasonably simple to use, are not "fooled" by spurious interrupts,
 225 * and, unlike other attempts at IRQ probing, they do not get hung on
 226 * stuck interrupts (such as unused PS2 mouse interfaces on ASUS boards).
 227 *
 228 * For reasonably foolproof probing, use them as follows:
 229 *
 230 * 1. clear and/or mask the device's internal interrupt.
 231 * 2. sti();
 232 * 3. irqs = probe_irq_on();      // "take over" all unassigned idle IRQs
 233 * 4. enable the device and cause it to trigger an interrupt.
 234 * 5. wait for the device to interrupt, using non-intrusive polling or a delay.
 235 * 6. irq = probe_irq_off(irqs);  // get IRQ number, 0=none, negative=multiple
 236 * 7. service the device to clear its pending interrupt.
 237 * 8. loop again if paranoia is required.
 238 *
 239 * probe_irq_on() returns a mask of allocated irq's.
 240 *
 241 * probe_irq_off() takes the mask as a parameter,
 242 * and returns the irq number which occurred,
 243 * or zero if none occurred, or a negative irq number
 244 * if more than one irq occurred.
 245 */
 246extern unsigned long probe_irq_on(void);        /* returns 0 on failure */
 247extern int probe_irq_off(unsigned long);        /* returns 0 or negative on failure */
 248extern unsigned int probe_irq_mask(unsigned long);      /* returns mask of ISA interrupts */
 249
 250#endif
 251
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.