1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * linux/kernel/irq/manage.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * This file contains driver APIs to the irq subsystem. 7*1da177e4SLinus Torvalds */ 8*1da177e4SLinus Torvalds 9*1da177e4SLinus Torvalds #include <linux/irq.h> 10*1da177e4SLinus Torvalds #include <linux/module.h> 11*1da177e4SLinus Torvalds #include <linux/random.h> 12*1da177e4SLinus Torvalds #include <linux/interrupt.h> 13*1da177e4SLinus Torvalds 14*1da177e4SLinus Torvalds #include "internals.h" 15*1da177e4SLinus Torvalds 16*1da177e4SLinus Torvalds #ifdef CONFIG_SMP 17*1da177e4SLinus Torvalds 18*1da177e4SLinus Torvalds cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; 19*1da177e4SLinus Torvalds 20*1da177e4SLinus Torvalds /** 21*1da177e4SLinus Torvalds * synchronize_irq - wait for pending IRQ handlers (on other CPUs) 22*1da177e4SLinus Torvalds * 23*1da177e4SLinus Torvalds * This function waits for any pending IRQ handlers for this interrupt 24*1da177e4SLinus Torvalds * to complete before returning. If you use this function while 25*1da177e4SLinus Torvalds * holding a resource the IRQ handler may need you will deadlock. 26*1da177e4SLinus Torvalds * 27*1da177e4SLinus Torvalds * This function may be called - with care - from IRQ context. 28*1da177e4SLinus Torvalds */ 29*1da177e4SLinus Torvalds void synchronize_irq(unsigned int irq) 30*1da177e4SLinus Torvalds { 31*1da177e4SLinus Torvalds struct irq_desc *desc = irq_desc + irq; 32*1da177e4SLinus Torvalds 33*1da177e4SLinus Torvalds while (desc->status & IRQ_INPROGRESS) 34*1da177e4SLinus Torvalds cpu_relax(); 35*1da177e4SLinus Torvalds } 36*1da177e4SLinus Torvalds 37*1da177e4SLinus Torvalds EXPORT_SYMBOL(synchronize_irq); 38*1da177e4SLinus Torvalds 39*1da177e4SLinus Torvalds #endif 40*1da177e4SLinus Torvalds 41*1da177e4SLinus Torvalds /** 42*1da177e4SLinus Torvalds * disable_irq_nosync - disable an irq without waiting 43*1da177e4SLinus Torvalds * @irq: Interrupt to disable 44*1da177e4SLinus Torvalds * 45*1da177e4SLinus Torvalds * Disable the selected interrupt line. Disables and Enables are 46*1da177e4SLinus Torvalds * nested. 47*1da177e4SLinus Torvalds * Unlike disable_irq(), this function does not ensure existing 48*1da177e4SLinus Torvalds * instances of the IRQ handler have completed before returning. 49*1da177e4SLinus Torvalds * 50*1da177e4SLinus Torvalds * This function may be called from IRQ context. 51*1da177e4SLinus Torvalds */ 52*1da177e4SLinus Torvalds void disable_irq_nosync(unsigned int irq) 53*1da177e4SLinus Torvalds { 54*1da177e4SLinus Torvalds irq_desc_t *desc = irq_desc + irq; 55*1da177e4SLinus Torvalds unsigned long flags; 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds spin_lock_irqsave(&desc->lock, flags); 58*1da177e4SLinus Torvalds if (!desc->depth++) { 59*1da177e4SLinus Torvalds desc->status |= IRQ_DISABLED; 60*1da177e4SLinus Torvalds desc->handler->disable(irq); 61*1da177e4SLinus Torvalds } 62*1da177e4SLinus Torvalds spin_unlock_irqrestore(&desc->lock, flags); 63*1da177e4SLinus Torvalds } 64*1da177e4SLinus Torvalds 65*1da177e4SLinus Torvalds EXPORT_SYMBOL(disable_irq_nosync); 66*1da177e4SLinus Torvalds 67*1da177e4SLinus Torvalds /** 68*1da177e4SLinus Torvalds * disable_irq - disable an irq and wait for completion 69*1da177e4SLinus Torvalds * @irq: Interrupt to disable 70*1da177e4SLinus Torvalds * 71*1da177e4SLinus Torvalds * Disable the selected interrupt line. Enables and Disables are 72*1da177e4SLinus Torvalds * nested. 73*1da177e4SLinus Torvalds * This function waits for any pending IRQ handlers for this interrupt 74*1da177e4SLinus Torvalds * to complete before returning. If you use this function while 75*1da177e4SLinus Torvalds * holding a resource the IRQ handler may need you will deadlock. 76*1da177e4SLinus Torvalds * 77*1da177e4SLinus Torvalds * This function may be called - with care - from IRQ context. 78*1da177e4SLinus Torvalds */ 79*1da177e4SLinus Torvalds void disable_irq(unsigned int irq) 80*1da177e4SLinus Torvalds { 81*1da177e4SLinus Torvalds irq_desc_t *desc = irq_desc + irq; 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds disable_irq_nosync(irq); 84*1da177e4SLinus Torvalds if (desc->action) 85*1da177e4SLinus Torvalds synchronize_irq(irq); 86*1da177e4SLinus Torvalds } 87*1da177e4SLinus Torvalds 88*1da177e4SLinus Torvalds EXPORT_SYMBOL(disable_irq); 89*1da177e4SLinus Torvalds 90*1da177e4SLinus Torvalds /** 91*1da177e4SLinus Torvalds * enable_irq - enable handling of an irq 92*1da177e4SLinus Torvalds * @irq: Interrupt to enable 93*1da177e4SLinus Torvalds * 94*1da177e4SLinus Torvalds * Undoes the effect of one call to disable_irq(). If this 95*1da177e4SLinus Torvalds * matches the last disable, processing of interrupts on this 96*1da177e4SLinus Torvalds * IRQ line is re-enabled. 97*1da177e4SLinus Torvalds * 98*1da177e4SLinus Torvalds * This function may be called from IRQ context. 99*1da177e4SLinus Torvalds */ 100*1da177e4SLinus Torvalds void enable_irq(unsigned int irq) 101*1da177e4SLinus Torvalds { 102*1da177e4SLinus Torvalds irq_desc_t *desc = irq_desc + irq; 103*1da177e4SLinus Torvalds unsigned long flags; 104*1da177e4SLinus Torvalds 105*1da177e4SLinus Torvalds spin_lock_irqsave(&desc->lock, flags); 106*1da177e4SLinus Torvalds switch (desc->depth) { 107*1da177e4SLinus Torvalds case 0: 108*1da177e4SLinus Torvalds WARN_ON(1); 109*1da177e4SLinus Torvalds break; 110*1da177e4SLinus Torvalds case 1: { 111*1da177e4SLinus Torvalds unsigned int status = desc->status & ~IRQ_DISABLED; 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds desc->status = status; 114*1da177e4SLinus Torvalds if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { 115*1da177e4SLinus Torvalds desc->status = status | IRQ_REPLAY; 116*1da177e4SLinus Torvalds hw_resend_irq(desc->handler,irq); 117*1da177e4SLinus Torvalds } 118*1da177e4SLinus Torvalds desc->handler->enable(irq); 119*1da177e4SLinus Torvalds /* fall-through */ 120*1da177e4SLinus Torvalds } 121*1da177e4SLinus Torvalds default: 122*1da177e4SLinus Torvalds desc->depth--; 123*1da177e4SLinus Torvalds } 124*1da177e4SLinus Torvalds spin_unlock_irqrestore(&desc->lock, flags); 125*1da177e4SLinus Torvalds } 126*1da177e4SLinus Torvalds 127*1da177e4SLinus Torvalds EXPORT_SYMBOL(enable_irq); 128*1da177e4SLinus Torvalds 129*1da177e4SLinus Torvalds /* 130*1da177e4SLinus Torvalds * Internal function that tells the architecture code whether a 131*1da177e4SLinus Torvalds * particular irq has been exclusively allocated or is available 132*1da177e4SLinus Torvalds * for driver use. 133*1da177e4SLinus Torvalds */ 134*1da177e4SLinus Torvalds int can_request_irq(unsigned int irq, unsigned long irqflags) 135*1da177e4SLinus Torvalds { 136*1da177e4SLinus Torvalds struct irqaction *action; 137*1da177e4SLinus Torvalds 138*1da177e4SLinus Torvalds if (irq >= NR_IRQS) 139*1da177e4SLinus Torvalds return 0; 140*1da177e4SLinus Torvalds 141*1da177e4SLinus Torvalds action = irq_desc[irq].action; 142*1da177e4SLinus Torvalds if (action) 143*1da177e4SLinus Torvalds if (irqflags & action->flags & SA_SHIRQ) 144*1da177e4SLinus Torvalds action = NULL; 145*1da177e4SLinus Torvalds 146*1da177e4SLinus Torvalds return !action; 147*1da177e4SLinus Torvalds } 148*1da177e4SLinus Torvalds 149*1da177e4SLinus Torvalds /* 150*1da177e4SLinus Torvalds * Internal function to register an irqaction - typically used to 151*1da177e4SLinus Torvalds * allocate special interrupts that are part of the architecture. 152*1da177e4SLinus Torvalds */ 153*1da177e4SLinus Torvalds int setup_irq(unsigned int irq, struct irqaction * new) 154*1da177e4SLinus Torvalds { 155*1da177e4SLinus Torvalds struct irq_desc *desc = irq_desc + irq; 156*1da177e4SLinus Torvalds struct irqaction *old, **p; 157*1da177e4SLinus Torvalds unsigned long flags; 158*1da177e4SLinus Torvalds int shared = 0; 159*1da177e4SLinus Torvalds 160*1da177e4SLinus Torvalds if (desc->handler == &no_irq_type) 161*1da177e4SLinus Torvalds return -ENOSYS; 162*1da177e4SLinus Torvalds /* 163*1da177e4SLinus Torvalds * Some drivers like serial.c use request_irq() heavily, 164*1da177e4SLinus Torvalds * so we have to be careful not to interfere with a 165*1da177e4SLinus Torvalds * running system. 166*1da177e4SLinus Torvalds */ 167*1da177e4SLinus Torvalds if (new->flags & SA_SAMPLE_RANDOM) { 168*1da177e4SLinus Torvalds /* 169*1da177e4SLinus Torvalds * This function might sleep, we want to call it first, 170*1da177e4SLinus Torvalds * outside of the atomic block. 171*1da177e4SLinus Torvalds * Yes, this might clear the entropy pool if the wrong 172*1da177e4SLinus Torvalds * driver is attempted to be loaded, without actually 173*1da177e4SLinus Torvalds * installing a new handler, but is this really a problem, 174*1da177e4SLinus Torvalds * only the sysadmin is able to do this. 175*1da177e4SLinus Torvalds */ 176*1da177e4SLinus Torvalds rand_initialize_irq(irq); 177*1da177e4SLinus Torvalds } 178*1da177e4SLinus Torvalds 179*1da177e4SLinus Torvalds /* 180*1da177e4SLinus Torvalds * The following block of code has to be executed atomically 181*1da177e4SLinus Torvalds */ 182*1da177e4SLinus Torvalds spin_lock_irqsave(&desc->lock,flags); 183*1da177e4SLinus Torvalds p = &desc->action; 184*1da177e4SLinus Torvalds if ((old = *p) != NULL) { 185*1da177e4SLinus Torvalds /* Can't share interrupts unless both agree to */ 186*1da177e4SLinus Torvalds if (!(old->flags & new->flags & SA_SHIRQ)) { 187*1da177e4SLinus Torvalds spin_unlock_irqrestore(&desc->lock,flags); 188*1da177e4SLinus Torvalds return -EBUSY; 189*1da177e4SLinus Torvalds } 190*1da177e4SLinus Torvalds 191*1da177e4SLinus Torvalds /* add new interrupt at end of irq queue */ 192*1da177e4SLinus Torvalds do { 193*1da177e4SLinus Torvalds p = &old->next; 194*1da177e4SLinus Torvalds old = *p; 195*1da177e4SLinus Torvalds } while (old); 196*1da177e4SLinus Torvalds shared = 1; 197*1da177e4SLinus Torvalds } 198*1da177e4SLinus Torvalds 199*1da177e4SLinus Torvalds *p = new; 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds if (!shared) { 202*1da177e4SLinus Torvalds desc->depth = 0; 203*1da177e4SLinus Torvalds desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | 204*1da177e4SLinus Torvalds IRQ_WAITING | IRQ_INPROGRESS); 205*1da177e4SLinus Torvalds if (desc->handler->startup) 206*1da177e4SLinus Torvalds desc->handler->startup(irq); 207*1da177e4SLinus Torvalds else 208*1da177e4SLinus Torvalds desc->handler->enable(irq); 209*1da177e4SLinus Torvalds } 210*1da177e4SLinus Torvalds spin_unlock_irqrestore(&desc->lock,flags); 211*1da177e4SLinus Torvalds 212*1da177e4SLinus Torvalds new->irq = irq; 213*1da177e4SLinus Torvalds register_irq_proc(irq); 214*1da177e4SLinus Torvalds new->dir = NULL; 215*1da177e4SLinus Torvalds register_handler_proc(irq, new); 216*1da177e4SLinus Torvalds 217*1da177e4SLinus Torvalds return 0; 218*1da177e4SLinus Torvalds } 219*1da177e4SLinus Torvalds 220*1da177e4SLinus Torvalds /** 221*1da177e4SLinus Torvalds * free_irq - free an interrupt 222*1da177e4SLinus Torvalds * @irq: Interrupt line to free 223*1da177e4SLinus Torvalds * @dev_id: Device identity to free 224*1da177e4SLinus Torvalds * 225*1da177e4SLinus Torvalds * Remove an interrupt handler. The handler is removed and if the 226*1da177e4SLinus Torvalds * interrupt line is no longer in use by any driver it is disabled. 227*1da177e4SLinus Torvalds * On a shared IRQ the caller must ensure the interrupt is disabled 228*1da177e4SLinus Torvalds * on the card it drives before calling this function. The function 229*1da177e4SLinus Torvalds * does not return until any executing interrupts for this IRQ 230*1da177e4SLinus Torvalds * have completed. 231*1da177e4SLinus Torvalds * 232*1da177e4SLinus Torvalds * This function must not be called from interrupt context. 233*1da177e4SLinus Torvalds */ 234*1da177e4SLinus Torvalds void free_irq(unsigned int irq, void *dev_id) 235*1da177e4SLinus Torvalds { 236*1da177e4SLinus Torvalds struct irq_desc *desc; 237*1da177e4SLinus Torvalds struct irqaction **p; 238*1da177e4SLinus Torvalds unsigned long flags; 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds if (irq >= NR_IRQS) 241*1da177e4SLinus Torvalds return; 242*1da177e4SLinus Torvalds 243*1da177e4SLinus Torvalds desc = irq_desc + irq; 244*1da177e4SLinus Torvalds spin_lock_irqsave(&desc->lock,flags); 245*1da177e4SLinus Torvalds p = &desc->action; 246*1da177e4SLinus Torvalds for (;;) { 247*1da177e4SLinus Torvalds struct irqaction * action = *p; 248*1da177e4SLinus Torvalds 249*1da177e4SLinus Torvalds if (action) { 250*1da177e4SLinus Torvalds struct irqaction **pp = p; 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds p = &action->next; 253*1da177e4SLinus Torvalds if (action->dev_id != dev_id) 254*1da177e4SLinus Torvalds continue; 255*1da177e4SLinus Torvalds 256*1da177e4SLinus Torvalds /* Found it - now remove it from the list of entries */ 257*1da177e4SLinus Torvalds *pp = action->next; 258*1da177e4SLinus Torvalds if (!desc->action) { 259*1da177e4SLinus Torvalds desc->status |= IRQ_DISABLED; 260*1da177e4SLinus Torvalds if (desc->handler->shutdown) 261*1da177e4SLinus Torvalds desc->handler->shutdown(irq); 262*1da177e4SLinus Torvalds else 263*1da177e4SLinus Torvalds desc->handler->disable(irq); 264*1da177e4SLinus Torvalds } 265*1da177e4SLinus Torvalds spin_unlock_irqrestore(&desc->lock,flags); 266*1da177e4SLinus Torvalds unregister_handler_proc(irq, action); 267*1da177e4SLinus Torvalds 268*1da177e4SLinus Torvalds /* Make sure it's not being used on another CPU */ 269*1da177e4SLinus Torvalds synchronize_irq(irq); 270*1da177e4SLinus Torvalds kfree(action); 271*1da177e4SLinus Torvalds return; 272*1da177e4SLinus Torvalds } 273*1da177e4SLinus Torvalds printk(KERN_ERR "Trying to free free IRQ%d\n",irq); 274*1da177e4SLinus Torvalds spin_unlock_irqrestore(&desc->lock,flags); 275*1da177e4SLinus Torvalds return; 276*1da177e4SLinus Torvalds } 277*1da177e4SLinus Torvalds } 278*1da177e4SLinus Torvalds 279*1da177e4SLinus Torvalds EXPORT_SYMBOL(free_irq); 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds /** 282*1da177e4SLinus Torvalds * request_irq - allocate an interrupt line 283*1da177e4SLinus Torvalds * @irq: Interrupt line to allocate 284*1da177e4SLinus Torvalds * @handler: Function to be called when the IRQ occurs 285*1da177e4SLinus Torvalds * @irqflags: Interrupt type flags 286*1da177e4SLinus Torvalds * @devname: An ascii name for the claiming device 287*1da177e4SLinus Torvalds * @dev_id: A cookie passed back to the handler function 288*1da177e4SLinus Torvalds * 289*1da177e4SLinus Torvalds * This call allocates interrupt resources and enables the 290*1da177e4SLinus Torvalds * interrupt line and IRQ handling. From the point this 291*1da177e4SLinus Torvalds * call is made your handler function may be invoked. Since 292*1da177e4SLinus Torvalds * your handler function must clear any interrupt the board 293*1da177e4SLinus Torvalds * raises, you must take care both to initialise your hardware 294*1da177e4SLinus Torvalds * and to set up the interrupt handler in the right order. 295*1da177e4SLinus Torvalds * 296*1da177e4SLinus Torvalds * Dev_id must be globally unique. Normally the address of the 297*1da177e4SLinus Torvalds * device data structure is used as the cookie. Since the handler 298*1da177e4SLinus Torvalds * receives this value it makes sense to use it. 299*1da177e4SLinus Torvalds * 300*1da177e4SLinus Torvalds * If your interrupt is shared you must pass a non NULL dev_id 301*1da177e4SLinus Torvalds * as this is required when freeing the interrupt. 302*1da177e4SLinus Torvalds * 303*1da177e4SLinus Torvalds * Flags: 304*1da177e4SLinus Torvalds * 305*1da177e4SLinus Torvalds * SA_SHIRQ Interrupt is shared 306*1da177e4SLinus Torvalds * SA_INTERRUPT Disable local interrupts while processing 307*1da177e4SLinus Torvalds * SA_SAMPLE_RANDOM The interrupt can be used for entropy 308*1da177e4SLinus Torvalds * 309*1da177e4SLinus Torvalds */ 310*1da177e4SLinus Torvalds int request_irq(unsigned int irq, 311*1da177e4SLinus Torvalds irqreturn_t (*handler)(int, void *, struct pt_regs *), 312*1da177e4SLinus Torvalds unsigned long irqflags, const char * devname, void *dev_id) 313*1da177e4SLinus Torvalds { 314*1da177e4SLinus Torvalds struct irqaction * action; 315*1da177e4SLinus Torvalds int retval; 316*1da177e4SLinus Torvalds 317*1da177e4SLinus Torvalds /* 318*1da177e4SLinus Torvalds * Sanity-check: shared interrupts must pass in a real dev-ID, 319*1da177e4SLinus Torvalds * otherwise we'll have trouble later trying to figure out 320*1da177e4SLinus Torvalds * which interrupt is which (messes up the interrupt freeing 321*1da177e4SLinus Torvalds * logic etc). 322*1da177e4SLinus Torvalds */ 323*1da177e4SLinus Torvalds if ((irqflags & SA_SHIRQ) && !dev_id) 324*1da177e4SLinus Torvalds return -EINVAL; 325*1da177e4SLinus Torvalds if (irq >= NR_IRQS) 326*1da177e4SLinus Torvalds return -EINVAL; 327*1da177e4SLinus Torvalds if (!handler) 328*1da177e4SLinus Torvalds return -EINVAL; 329*1da177e4SLinus Torvalds 330*1da177e4SLinus Torvalds action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC); 331*1da177e4SLinus Torvalds if (!action) 332*1da177e4SLinus Torvalds return -ENOMEM; 333*1da177e4SLinus Torvalds 334*1da177e4SLinus Torvalds action->handler = handler; 335*1da177e4SLinus Torvalds action->flags = irqflags; 336*1da177e4SLinus Torvalds cpus_clear(action->mask); 337*1da177e4SLinus Torvalds action->name = devname; 338*1da177e4SLinus Torvalds action->next = NULL; 339*1da177e4SLinus Torvalds action->dev_id = dev_id; 340*1da177e4SLinus Torvalds 341*1da177e4SLinus Torvalds retval = setup_irq(irq, action); 342*1da177e4SLinus Torvalds if (retval) 343*1da177e4SLinus Torvalds kfree(action); 344*1da177e4SLinus Torvalds 345*1da177e4SLinus Torvalds return retval; 346*1da177e4SLinus Torvalds } 347*1da177e4SLinus Torvalds 348*1da177e4SLinus Torvalds EXPORT_SYMBOL(request_irq); 349*1da177e4SLinus Torvalds 350