linux-old/arch/sh/kernel/irq.c
<<
>>
Prefs
   1/* $Id: irq.c,v 1.21 2001/07/17 02:26:53 gniibe Exp $
   2 *
   3 * linux/arch/sh/kernel/irq.c
   4 *
   5 *      Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
   6 *
   7 *
   8 * SuperH version:  Copyright (C) 1999  Niibe Yutaka
   9 */
  10
  11/*
  12 * IRQs are in fact implemented a bit like signal handlers for the kernel.
  13 * Naturally it's not a 1:1 relation, but there are similarities.
  14 */
  15
  16#include <linux/config.h>
  17#include <linux/ptrace.h>
  18#include <linux/errno.h>
  19#include <linux/kernel_stat.h>
  20#include <linux/signal.h>
  21#include <linux/sched.h>
  22#include <linux/ioport.h>
  23#include <linux/interrupt.h>
  24#include <linux/timex.h>
  25#include <linux/slab.h>
  26#include <linux/random.h>
  27#include <linux/smp.h>
  28#include <linux/smp_lock.h>
  29#include <linux/init.h>
  30
  31#include <asm/system.h>
  32#include <asm/io.h>
  33#include <asm/bitops.h>
  34#include <asm/pgalloc.h>
  35#include <asm/delay.h>
  36#include <asm/irq.h>
  37#include <linux/irq.h>
  38
  39/*
  40 * Controller mappings for all interrupt sources:
  41 */
  42irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
  43                                { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
  44
  45/*
  46 * Special irq handlers.
  47 */
  48
  49void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
  50
  51/*
  52 * Generic no controller code
  53 */
  54
  55static void enable_none(unsigned int irq) { }
  56static unsigned int startup_none(unsigned int irq) { return 0; }
  57static void disable_none(unsigned int irq) { }
  58static void ack_none(unsigned int irq)
  59{
  60/*
  61 * 'what should we do if we get a hw irq event on an illegal vector'.
  62 * each architecture has to answer this themselves, it doesnt deserve
  63 * a generic callback i think.
  64 */
  65        printk("unexpected IRQ trap at vector %02x\n", irq);
  66}
  67
  68/* startup is the same as "enable", shutdown is same as "disable" */
  69#define shutdown_none   disable_none
  70#define end_none        enable_none
  71
  72struct hw_interrupt_type no_irq_type = {
  73        "none",
  74        startup_none,
  75        shutdown_none,
  76        enable_none,
  77        disable_none,
  78        ack_none,
  79        end_none
  80};
  81
  82/*
  83 * Generic, controller-independent functions:
  84 */
  85
  86#if defined(CONFIG_PROC_FS)
  87int get_irq_list(char *buf)
  88{
  89        int i, j;
  90        struct irqaction * action;
  91        char *p = buf;
  92
  93        p += sprintf(p, "           ");
  94        for (j=0; j<smp_num_cpus; j++)
  95                p += sprintf(p, "CPU%d       ",j);
  96        *p++ = '\n';
  97
  98        for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
  99                action = irq_desc[i].action;
 100                if (!action) 
 101                        continue;
 102                p += sprintf(p, "%3d: ",i);
 103                p += sprintf(p, "%10u ", kstat_irqs(i));
 104                p += sprintf(p, " %14s", irq_desc[i].handler->typename);
 105                p += sprintf(p, "  %s", action->name);
 106
 107                for (action=action->next; action; action = action->next)
 108                        p += sprintf(p, ", %s", action->name);
 109                *p++ = '\n';
 110        }
 111        return p - buf;
 112}
 113#endif
 114
 115/*
 116 * This should really return information about whether
 117 * we should do bottom half handling etc. Right now we
 118 * end up _always_ checking the bottom half, which is a
 119 * waste of time and is not what some drivers would
 120 * prefer.
 121 */
 122int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 123{
 124        int status;
 125        int cpu = smp_processor_id();
 126
 127        irq_enter(cpu, irq);
 128
 129        status = 1;     /* Force the "do bottom halves" bit */
 130
 131        if (!(action->flags & SA_INTERRUPT))
 132                __sti();
 133
 134        do {
 135                status |= action->flags;
 136                action->handler(irq, action->dev_id, regs);
 137                action = action->next;
 138        } while (action);
 139        if (status & SA_SAMPLE_RANDOM)
 140                add_interrupt_randomness(irq);
 141        __cli();
 142
 143        irq_exit(cpu, irq);
 144
 145        return status;
 146}
 147
 148/*
 149 * Generic enable/disable code: this just calls
 150 * down into the PIC-specific version for the actual
 151 * hardware disable after having gotten the irq
 152 * controller lock. 
 153 */
 154void disable_irq_nosync(unsigned int irq)
 155{
 156        irq_desc_t *desc = irq_desc + irq;
 157        unsigned long flags;
 158
 159        spin_lock_irqsave(&desc->lock, flags);
 160        if (!desc->depth++) {
 161                desc->status |= IRQ_DISABLED;
 162                desc->handler->disable(irq);
 163        }
 164        spin_unlock_irqrestore(&desc->lock, flags);
 165}
 166
 167/*
 168 * Synchronous version of the above, making sure the IRQ is
 169 * no longer running on any other IRQ..
 170 */
 171void disable_irq(unsigned int irq)
 172{
 173        disable_irq_nosync(irq);
 174
 175        if (!local_irq_count(smp_processor_id())) {
 176                do {
 177                        barrier();
 178                } while (irq_desc[irq].status & IRQ_INPROGRESS);
 179        }
 180}
 181
 182void enable_irq(unsigned int irq)
 183{
 184        irq_desc_t *desc = irq_desc + irq;
 185        unsigned long flags;
 186
 187        spin_lock_irqsave(&desc->lock, flags);
 188        switch (desc->depth) {
 189        case 1: {
 190                unsigned int status = desc->status & ~IRQ_DISABLED;
 191                desc->status = status;
 192                if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
 193                        desc->status = status | IRQ_REPLAY;
 194                        hw_resend_irq(desc->handler,irq);
 195                }
 196                desc->handler->enable(irq);
 197                /* fall-through */
 198        }
 199        default:
 200                desc->depth--;
 201                break;
 202        case 0:
 203                printk("enable_irq() unbalanced from %p\n",
 204                       __builtin_return_address(0));
 205        }
 206        spin_unlock_irqrestore(&desc->lock, flags);
 207}
 208
 209/*
 210 * do_IRQ handles all normal device IRQ's.
 211 */
 212asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
 213                      unsigned long r6, unsigned long r7,
 214                      struct pt_regs regs)
 215{       
 216        /* 
 217         * We ack quickly, we don't want the irq controller
 218         * thinking we're snobs just because some other CPU has
 219         * disabled global interrupts (we have already done the
 220         * INT_ACK cycles, it's too late to try to pretend to the
 221         * controller that we aren't taking the interrupt).
 222         *
 223         * 0 return value means that this irq is already being
 224         * handled by some other CPU. (or is disabled)
 225         */
 226        int irq;
 227        int cpu = smp_processor_id();
 228        irq_desc_t *desc;
 229        struct irqaction * action;
 230        unsigned int status;
 231
 232        /* Get IRQ number */
 233        asm volatile("stc       r2_bank, %0\n\t"
 234                     "shlr2     %0\n\t"
 235                     "shlr2     %0\n\t"
 236                     "shlr      %0\n\t"
 237                     "add       #-16, %0\n\t"
 238                     :"=z" (irq));
 239        irq = irq_demux(irq);
 240
 241        kstat.irqs[cpu][irq]++;
 242        desc = irq_desc + irq;
 243        spin_lock(&desc->lock);
 244        desc->handler->ack(irq);
 245        /*
 246           REPLAY is when Linux resends an IRQ that was dropped earlier
 247           WAITING is used by probe to mark irqs that are being tested
 248           */
 249        status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING | IRQ_INPROGRESS);
 250        status |= IRQ_PENDING; /* we _want_ to handle it */
 251
 252        /*
 253         * If the IRQ is disabled for whatever reason, we cannot
 254         * use the action we have.
 255         */
 256        action = NULL;
 257        if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 258                action = desc->action;
 259                status &= ~IRQ_PENDING; /* we commit to handling */
 260                status |= IRQ_INPROGRESS; /* we are handling it */
 261        }
 262        desc->status = status;
 263
 264        /*
 265         * If there is no IRQ handler or it was disabled, exit early.
 266           Since we set PENDING, if another processor is handling
 267           a different instance of this same irq, the other processor
 268           will take care of it.
 269         */
 270        if (!action)
 271                goto out;
 272
 273        /*
 274         * Edge triggered interrupts need to remember
 275         * pending events.
 276         * This applies to any hw interrupts that allow a second
 277         * instance of the same irq to arrive while we are in do_IRQ
 278         * or in the handler. But the code here only handles the _second_
 279         * instance of the irq, not the third or fourth. So it is mostly
 280         * useful for irq hardware that does not mask cleanly in an
 281         * SMP environment.
 282         */
 283        for (;;) {
 284                spin_unlock(&desc->lock);
 285                handle_IRQ_event(irq, &regs, action);
 286                spin_lock(&desc->lock);
 287
 288                if (!(desc->status & IRQ_PENDING))
 289                        break;
 290                desc->status &= ~IRQ_PENDING;
 291        }
 292        desc->status &= ~IRQ_INPROGRESS;
 293out:
 294        /*
 295         * The ->end() handler has to deal with interrupts which got
 296         * disabled while the handler was running.
 297         */
 298        desc->handler->end(irq);
 299        spin_unlock(&desc->lock);
 300
 301        if (softirq_pending(cpu))
 302                do_softirq();
 303        return 1;
 304}
 305
 306int request_irq(unsigned int irq, 
 307                void (*handler)(int, void *, struct pt_regs *),
 308                unsigned long irqflags, 
 309                const char * devname,
 310                void *dev_id)
 311{
 312        int retval;
 313        struct irqaction * action;
 314
 315        if (irq >= ACTUAL_NR_IRQS)
 316                return -EINVAL;
 317        if (!handler)
 318                return -EINVAL;
 319
 320        action = (struct irqaction *)
 321                        kmalloc(sizeof(struct irqaction), GFP_KERNEL);
 322        if (!action)
 323                return -ENOMEM;
 324
 325        action->handler = handler;
 326        action->flags = irqflags;
 327        action->mask = 0;
 328        action->name = devname;
 329        action->next = NULL;
 330        action->dev_id = dev_id;
 331
 332        retval = setup_irq(irq, action);
 333        if (retval)
 334                kfree(action);
 335        return retval;
 336}
 337
 338void free_irq(unsigned int irq, void *dev_id)
 339{
 340        irq_desc_t *desc;
 341        struct irqaction **p;
 342        unsigned long flags;
 343
 344        if (irq >= ACTUAL_NR_IRQS)
 345                return;
 346
 347        desc = irq_desc + irq;
 348        spin_lock_irqsave(&desc->lock,flags);
 349        p = &desc->action;
 350        for (;;) {
 351                struct irqaction * action = *p;
 352                if (action) {
 353                        struct irqaction **pp = p;
 354                        p = &action->next;
 355                        if (action->dev_id != dev_id)
 356                                continue;
 357
 358                        /* Found it - now remove it from the list of entries */
 359                        *pp = action->next;
 360                        if (!desc->action) {
 361                                desc->status |= IRQ_DISABLED;
 362                                desc->handler->shutdown(irq);
 363                        }
 364                        spin_unlock_irqrestore(&desc->lock,flags);
 365                        kfree(action);
 366                        return;
 367                }
 368                printk("Trying to free free IRQ%d\n",irq);
 369                spin_unlock_irqrestore(&desc->lock,flags);
 370                return;
 371        }
 372}
 373
 374static DECLARE_MUTEX(probe_sem);
 375
 376/*
 377 * IRQ autodetection code..
 378 *
 379 * This depends on the fact that any interrupt that
 380 * comes in on to an unassigned handler will get stuck
 381 * with "IRQ_WAITING" cleared and the interrupt
 382 * disabled.
 383 */
 384unsigned long probe_irq_on(void)
 385{
 386        unsigned int i;
 387        irq_desc_t *desc;
 388        unsigned long val;
 389        unsigned long delay;
 390
 391        down(&probe_sem);
 392        /* 
 393         * something may have generated an irq long ago and we want to
 394         * flush such a longstanding irq before considering it as spurious. 
 395         */
 396        for (i = NR_IRQS-1; i > 0; i--) {
 397                desc = irq_desc + i;
 398
 399                spin_lock_irq(&desc->lock);
 400                if (!desc->action)
 401                        desc->handler->startup(i);
 402                spin_unlock_irq(&desc->lock);
 403        }
 404
 405        /* Wait for longstanding interrupts to trigger. */
 406        for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
 407                /* about 20ms delay */ synchronize_irq();
 408
 409        /*
 410         * enable any unassigned irqs
 411         * (we must startup again here because if a longstanding irq
 412         * happened in the previous stage, it may have masked itself)
 413         */
 414        for (i = NR_IRQS-1; i > 0; i--) {
 415                desc = irq_desc + i;
 416
 417                spin_lock_irq(&desc->lock);
 418                if (!desc->action) {
 419                        desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
 420                        if (desc->handler->startup(i))
 421                                desc->status |= IRQ_PENDING;
 422                }
 423                spin_unlock_irq(&desc->lock);
 424        }
 425
 426        /*
 427         * Wait for spurious interrupts to trigger
 428         */
 429        for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
 430                /* about 100ms delay */ synchronize_irq();
 431
 432        /*
 433         * Now filter out any obviously spurious interrupts
 434         */
 435        val = 0;
 436        for (i=0; i<NR_IRQS; i++) {
 437                desc = irq_desc + i;
 438                unsigned int status;
 439
 440                spin_lock_irq(&desc->lock);
 441                status = desc->status;
 442
 443                if (status & IRQ_AUTODETECT) {
 444                        /* It triggered already - consider it spurious. */
 445                        if (!(status & IRQ_WAITING)) {
 446                                desc->status = status & ~IRQ_AUTODETECT;
 447                                desc->handler->shutdown(i);
 448                        } else
 449                                if (i < 32)
 450                                        val |= 1 << i;
 451                }
 452                spin_unlock_irq(&desc->lock);
 453        }
 454
 455        return val;
 456}
 457
 458int probe_irq_off(unsigned long val)
 459{
 460        int i, irq_found, nr_irqs;
 461
 462        nr_irqs = 0;
 463        irq_found = 0;
 464        for (i=0; i<NR_IRQS; i++) {
 465                irq_desc_t *desc = irq_desc + i;
 466                unsigned int status;
 467
 468                spin_lock_irq(&desc->lock);
 469                status = desc->status;
 470
 471                if (status & IRQ_AUTODETECT) {
 472                        if (!(status & IRQ_WAITING)) {
 473                                if (!nr_irqs)
 474                                        irq_found = i;
 475                                nr_irqs++;
 476                        }
 477                        desc->status = status & ~IRQ_AUTODETECT;
 478                        desc->handler->shutdown(i);
 479                }
 480                spin_unlock_irq(&desc->lock);
 481        }
 482        up(&probe_sem);
 483
 484        if (nr_irqs > 1)
 485                irq_found = -irq_found;
 486        return irq_found;
 487}
 488
 489int setup_irq(unsigned int irq, struct irqaction * new)
 490{
 491        int shared = 0;
 492        struct irqaction *old, **p;
 493        unsigned long flags;
 494        irq_desc_t *desc = irq_desc + irq;
 495
 496        /*
 497         * Some drivers like serial.c use request_irq() heavily,
 498         * so we have to be careful not to interfere with a
 499         * running system.
 500         */
 501        if (new->flags & SA_SAMPLE_RANDOM) {
 502                /*
 503                 * This function might sleep, we want to call it first,
 504                 * outside of the atomic block.
 505                 * Yes, this might clear the entropy pool if the wrong
 506                 * driver is attempted to be loaded, without actually
 507                 * installing a new handler, but is this really a problem,
 508                 * only the sysadmin is able to do this.
 509                 */
 510                rand_initialize_irq(irq);
 511        }
 512
 513        /*
 514         * The following block of code has to be executed atomically
 515         */
 516        spin_lock_irqsave(&desc->lock,flags);
 517        p = &desc->action;
 518        if ((old = *p) != NULL) {
 519                /* Can't share interrupts unless both agree to */
 520                if (!(old->flags & new->flags & SA_SHIRQ)) {
 521                        spin_unlock_irqrestore(&desc->lock,flags);
 522                        return -EBUSY;
 523                }
 524
 525                /* add new interrupt at end of irq queue */
 526                do {
 527                        p = &old->next;
 528                        old = *p;
 529                } while (old);
 530                shared = 1;
 531        }
 532
 533        *p = new;
 534
 535        if (!shared) {
 536                desc->depth = 0;
 537                desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
 538                desc->handler->startup(irq);
 539        }
 540        spin_unlock_irqrestore(&desc->lock,flags);
 541        return 0;
 542}
 543
 544#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
 545
 546void init_irq_proc(void)
 547{
 548}
 549#endif
 550
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.