From 3132fdcb2d8590098732317f3dbe2718c3506cfd Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 20 Apr 2003 00:14:34 -0700 Subject: [PATCH] Interrupt handlers should return whether the interrupt was for them or not, so that the irq subsystem can properly handle screaming shared interrupts. So change the irq handlers to return a "irqretval_t", which is either IRQ_HANDLED or IRQ_NONE. --- arch/i386/kernel/i8259.c | 5 +++-- arch/i386/kernel/irq.c | 19 ++++++++++++++++--- arch/i386/kernel/time.c | 4 ++-- arch/i386/kernel/vm86.c | 9 +++++++-- arch/i386/pci/irq.c | 3 ++- drivers/acpi/osl.c | 4 +++- drivers/block/floppy.c | 9 ++++++--- drivers/char/drm/drmP.h | 2 +- drivers/char/drm/radeon_irq.c | 5 +++-- drivers/ide/ide-io.c | 11 ++++++----- drivers/input/serio/i8042.c | 6 ++++-- drivers/net/e100/e100_main.c | 9 +++++---- drivers/net/pcmcia/pcnet_cs.c | 6 ++++-- drivers/parport/parport_pc.c | 4 +++- drivers/pcmcia/rsrc_mgr.c | 2 +- drivers/pcmcia/yenta.c | 4 +++- drivers/pnp/resource.c | 3 ++- drivers/scsi/aic7xxx/aic7xxx_osm.c | 4 +++- drivers/scsi/aic7xxx/aic7xxx_osm.h | 2 +- drivers/scsi/qla1280.c | 5 ++++- drivers/scsi/qla1280.h | 2 +- drivers/serial/8250.c | 4 +++- drivers/usb/core/hcd.c | 5 +++-- drivers/usb/core/hcd.h | 2 +- include/asm-i386/arch_hooks.h | 4 +++- include/asm-i386/floppy.h | 13 ++++++------- include/linux/ide.h | 2 +- include/linux/interrupt.h | 27 +++++++++++++++++++++++++-- include/linux/irq.h | 1 - include/sound/mpu401.h | 2 +- sound/drivers/mpu401/mpu401_uart.c | 11 +++++++---- sound/pci/intel8x0.c | 5 +++-- 32 files changed, 133 insertions(+), 61 deletions(-) diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 9b90e52458bd8..581fc388cf8a4 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -325,15 +325,16 @@ void init_8259A(int auto_eoi) * =PC9800NOTE= In NEC PC-9800, we use irq8 instead of irq13! */ -static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs) +static irqreturn_t math_error_irq(int cpl, void *dev_id, struct pt_regs *regs) { extern void math_error(void *); #ifndef CONFIG_X86_PC9800 outb(0,0xF0); #endif if (ignore_fpu_irq || !boot_cpu_data.hard_math) - return; + return IRQ_NONE; math_error((void *)regs->eip); + return IRQ_HANDLED; } /* diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index 6337c92c025d9..966931bf79f3f 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -74,7 +74,8 @@ static void register_irq_proc (unsigned int irq); * Special irq handlers. */ -void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) +{ return IRQ_NONE; } /* * Generic no controller code @@ -205,18 +206,30 @@ inline void synchronize_irq(unsigned int irq) int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { int status = 1; /* Force the "do bottom halves" bit */ + int retval = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= action->flags; - action->handler(irq, action->dev_id, regs); + retval |= action->handler(irq, action->dev_id, regs).val; action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); + if (retval != 1) { + static int count = 100; + while (count) { + count--; + printk(retval + ? "irq event %d: bogus retval mask %x\n" + : "irq %d: nobody cared!n", + irq, + retval); + } + } return status; } @@ -447,7 +460,7 @@ out: */ int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index ab0f09bfe3d15..a4daeb2d3b2a9 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -267,7 +267,7 @@ static inline void detect_lost_tick(void) * Time Stamp Counter value at the time of the timer interrupt, so that * we later on can estimate the time of day more exactly. */ -void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* * Here we are in the timer irq handler. We just have irqs locally @@ -284,7 +284,7 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) do_timer_interrupt(irq, NULL, regs); write_sequnlock(&xtime_lock); - + return IRQ_HANDLED; } /* not static: needed by APM */ diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index 66a5235c6f37c..9c49cd96d76ed 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -695,7 +695,8 @@ static int irqbits; | (1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGIO) | (1 << SIGURG) \ | (1 << SIGUNUSED) ) -static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) { +static irqreturn_t irq_handler(int intno, void *dev_id, struct pt_regs * regs) +{ int irq_bit; unsigned long flags; @@ -709,6 +710,7 @@ static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) { /* else user will poll for IRQs */ out: spin_unlock_irqrestore(&irqbits_lock, flags); + return IRQ_NONE; } static inline void free_vm86_irq(int irqnumber) @@ -742,7 +744,10 @@ static inline int get_and_reset_irq(int irqnumber) bit = irqbits & (1 << irqnumber); irqbits &= ~bit; spin_unlock_irqrestore(&irqbits_lock, flags); - return bit; + if (!bit) + return 0; + enable_irq(irqnumber); + return 1; } diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index bd831d480d362..71368631e75c9 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c @@ -560,8 +560,9 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev) return NULL; } -static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { + return IRQ_NONE; } static int pcibios_lookup_irq(struct pci_dev *dev, int assign) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index dab6100c2ae6e..5e09194dd6298 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -234,10 +234,12 @@ acpi_os_table_override (struct acpi_table_header *existing_table, return AE_OK; } -static void +static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs) { (*acpi_irq_handler)(acpi_irq_context); + /* FIXME!! We really should check that the irq was really ours! */ + return IRQ_HANDLED; } acpi_status diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 0e227376497d5..48dba2a715aa3 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -217,7 +217,7 @@ static int use_virtual_dma; static spinlock_t floppy_lock = SPIN_LOCK_UNLOCKED; static unsigned short virtual_dma_port=0x3f0; -void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs); +irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs); static int set_dor(int fdc, char mask, char data); static void register_devfs_entries (int drive) __init; @@ -1743,7 +1743,7 @@ static void print_result(char *message, int inr) } /* interrupt handler. Note that this can be called externally on the Sparc */ -void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) { void (*handler)(void) = do_floppy; int do_print; @@ -1764,7 +1764,7 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) printk("floppy interrupt on bizarre fdc %d\n",fdc); printk("handler=%p\n", handler); is_alive("bizarre fdc"); - return; + return IRQ_NONE; } FDCS->reset = 0; @@ -1797,6 +1797,9 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) } else FDCS->reset = 1; is_alive("normal interrupt end"); + + /* FIXME! Was it really for us? */ + return IRQ_HANDLED; } static void recalibrate_floppy(void) diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 03959def0efe2..821029c548999 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -837,7 +837,7 @@ extern int DRM(control)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int DRM(irq_install)( drm_device_t *dev, int irq ); extern int DRM(irq_uninstall)( drm_device_t *dev ); -extern void DRM(dma_service)( int irq, void *device, +extern irqreturn_t DRM(dma_service)( int irq, void *device, struct pt_regs *regs ); extern void DRM(driver_irq_preinstall)( drm_device_t *dev ); extern void DRM(driver_irq_postinstall)( drm_device_t *dev ); diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c index 9199fbbf25f18..c233838874365 100644 --- a/drivers/char/drm/radeon_irq.c +++ b/drivers/char/drm/radeon_irq.c @@ -54,7 +54,7 @@ * tied to dma at all, this is just a hangover from dri prehistory. */ -void DRM(dma_service)( DRM_IRQ_ARGS ) +irqreturn_t DRM(dma_service)( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_radeon_private_t *dev_priv = @@ -67,7 +67,7 @@ void DRM(dma_service)( DRM_IRQ_ARGS ) stat = RADEON_READ(RADEON_GEN_INT_STATUS) & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); if (!stat) - return; + return IRQ_NONE; /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) { @@ -83,6 +83,7 @@ void DRM(dma_service)( DRM_IRQ_ARGS ) /* Acknowledge interrupts we handle */ RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); + return IRQ_HANDLED; } static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 44db5ddac3d37..93f4f66b9f3f1 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1112,7 +1112,7 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) * on the hwgroup and the process begins again. */ -void ide_intr (int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs) { unsigned long flags; ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; @@ -1126,7 +1126,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) if (!ide_ack_intr(hwif)) { spin_unlock_irqrestore(&ide_lock, flags); - return; + return IRQ_NONE; } if ((handler = hwgroup->handler) == NULL || @@ -1165,7 +1165,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) #endif /* CONFIG_BLK_DEV_IDEPCI */ } spin_unlock_irqrestore(&ide_lock, flags); - return; + return IRQ_HANDLED; } drive = hwgroup->drive; if (!drive) { @@ -1176,7 +1176,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) * [Note - this can occur if the drive is hot unplugged] */ spin_unlock_irqrestore(&ide_lock, flags); - return; + return IRQ_HANDLED; } if (!drive_is_ready(drive)) { /* @@ -1187,7 +1187,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) * enough advance overhead that the latter isn't a problem. */ spin_unlock_irqrestore(&ide_lock, flags); - return; + return IRQ_HANDLED; } if (!hwgroup->busy) { hwgroup->busy = 1; /* paranoia */ @@ -1222,6 +1222,7 @@ void ide_intr (int irq, void *dev_id, struct pt_regs *regs) } } spin_unlock_irqrestore(&ide_lock, flags); + return IRQ_HANDLED; } EXPORT_SYMBOL(ide_intr); diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index ec774de5c420e..b2f26c794c28e 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -74,7 +74,7 @@ static unsigned char i8042_unxlate_table[128] = { 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110 }; -static void i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); /* * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to @@ -332,7 +332,7 @@ static char i8042_mux_phys[4][32]; * to the upper layers. */ -static void i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned long flags; unsigned char str, data; @@ -415,6 +415,8 @@ static void i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs) serio_interrupt(&i8042_kbd_port, data, dfl, regs); } + /* FIXME - was it really ours? */ + return IRQ_HANDLED; } /* diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 2f3f6f6b1e8da..bfad0a28c3df9 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -190,7 +190,7 @@ static unsigned char e100_init(struct e100_private *); static int e100_set_mac(struct net_device *, void *); struct net_device_stats *e100_get_stats(struct net_device *); -static void e100intr(int, void *, struct pt_regs *); +static irqreturn_t e100intr(int, void *, struct pt_regs *); static void e100_print_brd_conf(struct e100_private *); static void e100_set_multi(struct net_device *); void e100_set_speed_duplex(struct e100_private *); @@ -1837,7 +1837,7 @@ e100_manage_adaptive_ifs(struct e100_private *bdp) * the RX & TX queues & starts the RU if it has stopped due * to no resources. */ -void +irqreturn_t e100intr(int irq, void *dev_inst, struct pt_regs *regs) { struct net_device *dev; @@ -1850,7 +1850,7 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs) intr_status = readw(&bdp->scb->scb_status); /* If not my interrupt, just return */ if (!(intr_status & SCB_STATUS_ACK_MASK) || (intr_status == 0xffff)) { - return; + return IRQ_NONE; } /* disable and ack intr */ @@ -1859,7 +1859,7 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs) /* the device is closed, don't continue or else bad things may happen. */ if (!netif_running(dev)) { e100_set_intr_mask(bdp); - return; + return IRQ_NONE; } /* SWI intr (triggered by watchdog) is signal to allocate new skb buffers */ @@ -1877,6 +1877,7 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs) e100_tx_srv(bdp); e100_set_intr_mask(bdp); + return IRQ_HANDLED; } /** diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 47de0671c99ba..81210905c2f64 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -117,7 +117,7 @@ static int pcnet_open(struct net_device *dev); static int pcnet_close(struct net_device *dev); static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int do_ioctl_light(struct net_device *dev, struct ifreq *rq, int cmd); -static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs); static void ei_watchdog(u_long arg); static void pcnet_reset_8390(struct net_device *dev); static int set_config(struct net_device *dev, struct ifmap *map); @@ -1121,11 +1121,13 @@ static int set_config(struct net_device *dev, struct ifmap *map) /*====================================================================*/ -static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs) { pcnet_dev_t *info = dev_id; info->stale = 0; ei_interrupt(irq, dev_id, regs); + /* FIXME! Was it really ours? */ + return IRQ_HANDLED; } static void ei_watchdog(u_long arg) diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 4c8c25c2e20e1..f0754f3b160df 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -262,9 +262,11 @@ static int clear_epp_timeout(struct parport *pb) * of these are in parport_pc.h. */ -static void parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { parport_generic_irq(irq, (struct parport *) dev_id, regs); + /* FIXME! Was it really ours? */ + return IRQ_HANDLED; } void parport_pc_write_data(struct parport *p, unsigned char d) diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 01727ab93359b..16fdf1cb2786b 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -599,7 +599,7 @@ int find_mem_region(u_long *base, u_long num, u_long align, #ifdef CONFIG_PCMCIA_PROBE -static void fake_irq(int i, void *d, struct pt_regs *r) { } +static irqreturn_t fake_irq(int i, void *d, struct pt_regs *r) { return IRQ_NONE; } static inline int check_irq(int irq) { if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0) diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c index 4bb9cc7257baa..2a3a49d0b72f9 100644 --- a/drivers/pcmcia/yenta.c +++ b/drivers/pcmcia/yenta.c @@ -429,7 +429,7 @@ static void yenta_bh(void *data) socket->handler(socket->info, events); } -static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int events; pci_socket_t *socket = (pci_socket_t *) dev_id; @@ -440,7 +440,9 @@ static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) socket->events |= events; spin_unlock(&socket->event_lock); schedule_work(&socket->tq_task); + return IRQ_HANDLED; } + return IRQ_NONE; } static void yenta_interrupt_wrapper(unsigned long data) diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index e252d35bf7100..7d1ba24e716a9 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -420,8 +420,9 @@ struct pnp_dev * pnp_check_irq_conflicts(struct pnp_dev * dev, int idx, int mode return NULL; } -static void pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs) { + return IRQ_NONE; } int pnp_check_irq(struct pnp_dev * dev, int idx) diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 4c5389c237e8b..ed22493de98bb 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -3863,7 +3863,7 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev) /* * SCSI controller interrupt handler. */ -void +irqreturn_t ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) { struct ahc_softc *ahc; @@ -3883,6 +3883,8 @@ ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) ahc_schedule_completeq(ahc, acmd); } ahc_unlock(ahc, &flags); + /* FIXME! Was it really ours? */ + return IRQ_HANDLED; } void diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index 17ed9a587a04f..3e1434c723a00 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -1224,7 +1224,7 @@ void ahc_platform_set_tags(struct ahc_softc *ahc, int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, int lun, u_int tag, role_t role, uint32_t status); -void ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs); +irqreturn_t ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs); void ahc_platform_flushwork(struct ahc_softc *ahc); int ahc_softc_comp(struct ahc_softc *, struct ahc_softc *); void ahc_done(struct ahc_softc*, struct scb*); diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 54d0776edde4f..6de4a1ee1c064 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -1736,11 +1736,12 @@ qla1280_biosparam(struct scsi_device *sdev, struct block_device *bdev, * qla1280_intr_handler * Handles the H/W interrupt **************************************************************************/ -void +irqreturn_t qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) { struct scsi_qla_host *ha; struct device_reg *reg; + int handled = 0; u16 data; ENTER_INTR ("qla1280_intr_handler"); @@ -1757,6 +1758,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) /* Check for pending interrupts. */ if (data & RISC_INT) { qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last); + handled = 1; } else { /* spurious interrupts can happen legally */ dprintk(1, "scsi(%ld): Spurious interrupt - ignoring\n", @@ -1772,6 +1774,7 @@ qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs) WRT_REG_WORD(®->ictrl, (ISP_EN_INT | ISP_EN_RISC)); LEAVE_INTR("qla1280_intr_handler"); + return IRQ_RETVAL(handled); } /************************************************************************** diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h index 21e79aed05da5..71524e9178562 100644 --- a/drivers/scsi/qla1280.h +++ b/drivers/scsi/qla1280.h @@ -1316,7 +1316,7 @@ int qla1280_reset(Scsi_Cmnd *, unsigned int); int qla1280_biosparam(struct scsi_device *, struct block_device *, sector_t, int[]); static int qla1280_slave_configure(Scsi_Device *); -void qla1280_intr_handler(int, void *, struct pt_regs *); +irqreturn_t qla1280_intr_handler(int, void *, struct pt_regs *); void qla1280_setup(char *s, int *dummy); /* diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 09e0165f45a9b..1e9777bf6e433 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -984,7 +984,7 @@ serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs) * This means we need to loop through all ports. checking that they * don't have an interrupt pending. */ -static void serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct irq_info *i = dev_id; struct list_head *l, *end = NULL; @@ -1024,6 +1024,8 @@ static void serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) spin_unlock(&i->lock); DEBUG_INTR("end.\n"); + /* FIXME! Was it really ours? */ + return IRQ_HANDLED; } /* diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 3d868e2812b51..4422832d9e392 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1436,17 +1436,18 @@ EXPORT_SYMBOL (usb_hcd_giveback_urb); * to handle interrupts. The PCI glue layer does so automatically; only * bus glue for non-PCI system busses will need to use this. */ -void usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) +irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) { struct usb_hcd *hcd = __hcd; int start = hcd->state; if (unlikely (hcd->state == USB_STATE_HALT)) /* irq sharing? */ - return; + return IRQ_NONE; hcd->driver->irq (hcd, r); if (hcd->state != start && hcd->state == USB_STATE_HALT) usb_hc_died (hcd); + return IRQ_HANDLED; } EXPORT_SYMBOL (usb_hcd_irq); diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 215a3112d6242..f0d9f800e6aac 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -239,7 +239,7 @@ void hcd_buffer_free (struct usb_bus *bus, size_t size, /* generic bus glue, needed for host controllers that don't use PCI */ extern struct usb_operations usb_hcd_operations; -extern void usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); +extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); extern void usb_hc_died (struct usb_hcd *hcd); /* -------------------------------------------------------------------------- */ diff --git a/include/asm-i386/arch_hooks.h b/include/asm-i386/arch_hooks.h index 0bf28a32894a7..28b96a6fb9faa 100644 --- a/include/asm-i386/arch_hooks.h +++ b/include/asm-i386/arch_hooks.h @@ -1,6 +1,8 @@ #ifndef _ASM_ARCH_HOOKS_H #define _ASM_ARCH_HOOKS_H +#include + /* * linux/include/asm/arch_hooks.h * @@ -12,7 +14,7 @@ extern void init_ISA_irqs(void); extern void apic_intr_init(void); extern void smp_intr_init(void); -extern void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); /* these are the defined hooks */ extern void intr_init_hook(void); diff --git a/include/asm-i386/floppy.h b/include/asm-i386/floppy.h index 9b6140df91f45..605f57ac56b59 100644 --- a/include/asm-i386/floppy.h +++ b/include/asm-i386/floppy.h @@ -51,7 +51,7 @@ static char *virtual_dma_addr; static int virtual_dma_mode; static int doing_pdma; -static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) { register unsigned char st; @@ -63,10 +63,8 @@ static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) static int bytes=0; static int dma_wait=0; #endif - if(!doing_pdma) { - floppy_interrupt(irq, dev_id, regs); - return; - } + if (!doing_pdma) + return floppy_interrupt(irq, dev_id, regs); #ifdef TRACE_FLPY_INT if(!calls) @@ -130,7 +128,7 @@ static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) calls++; #endif if(st == 0x20) - return; + return IRQ_HANDLED; if(!(st & 0x20)) { virtual_dma_residue += virtual_dma_count; virtual_dma_count=0; @@ -143,12 +141,13 @@ static void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) #endif doing_pdma = 0; floppy_interrupt(irq, dev_id, regs); - return; + return IRQ_HANDLED; } #ifdef TRACE_FLPY_INT if(!virtual_dma_count) dma_wait++; #endif + return IRQ_HANDLED; } static void fd_disable_dma(void) diff --git a/include/linux/ide.h b/include/linux/ide.h index 1e678d06373b4..a06f010335847 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1568,7 +1568,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); extern int ide_spin_wait_hwgroup(ide_drive_t *); extern void ide_timer_expiry(unsigned long); -extern void ide_intr(int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t ide_intr(int irq, void *dev_id, struct pt_regs *regs); extern void do_ide_request(request_queue_t *); extern void ide_init_subdrivers(void); diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 78969bb605212..0c489083d7c70 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -11,8 +11,30 @@ #include #include +/* + * For 2.4.x compatibility, 2.4.x can use + * + * typedef void irqreturn_t; + * #define IRQ_NONE + * #define IRQ_HANDLED + * #define IRQ_RETVAL(x) + * + * To mix old-style and new-style irq handler returns. + * + * IRQ_NONE means we didn't handle it. + * IRQ_HANDLED means that we did have a valid interrupt and handled it. + * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled) + */ +typedef struct irqreturn { + unsigned int val; +} irqreturn_t; + +#define IRQ_NONE ((struct irqreturn) { 0 }) +#define IRQ_HANDLED ((struct irqreturn) { 1 }) +#define IRQ_RETVAL(x) ((struct irqreturn) { (x) != 0 }) + struct irqaction { - void (*handler)(int, void *, struct pt_regs *); + irqreturn_t (*handler)(int, void *, struct pt_regs *); unsigned long flags; unsigned long mask; const char *name; @@ -20,8 +42,9 @@ struct irqaction { struct irqaction *next; }; +extern irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs); extern int request_irq(unsigned int, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long, const char *, void *); extern void free_irq(unsigned int, void *); diff --git a/include/linux/irq.h b/include/linux/irq.h index 2791f0edbf577..c9bb7be100f36 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -72,7 +72,6 @@ extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); extern int setup_irq(unsigned int , struct irqaction * ); extern hw_irq_controller no_irq_type; /* needed in every arch ? */ -extern void no_action(int cpl, void *dev_id, struct pt_regs *regs); #endif diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h index 7cdbc79cb9874..3ae91b26b0616 100644 --- a/include/sound/mpu401.h +++ b/include/sound/mpu401.h @@ -102,7 +102,7 @@ struct _snd_mpu401 { */ -void snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs); +irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs); int snd_mpu401_uart_new(snd_card_t * card, int device, diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index a19a8734b4dce..8e73b3b97f0d1 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -90,7 +90,7 @@ static void snd_mpu401_uart_clear_rx(mpu401_t *mpu) #endif } -static void _snd_mpu401_uart_interrupt(mpu401_t *mpu) +static irqreturn_t _snd_mpu401_uart_interrupt(mpu401_t *mpu) { if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { if (! test_and_set_bit(MPU401_MODE_BIT_RX_LOOP, &mpu->mode)) { @@ -108,6 +108,9 @@ static void _snd_mpu401_uart_interrupt(mpu401_t *mpu) snd_mpu401_uart_output_write(mpu); spin_unlock(&mpu->output_lock); } + + /* FIXME! This should really check whether the irq was for us */ + return IRQ_HANDLED; } /** @@ -118,13 +121,13 @@ static void _snd_mpu401_uart_interrupt(mpu401_t *mpu) * * Processes the interrupt for MPU401-UART i/o. */ -void snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs) { mpu401_t *mpu = snd_magic_cast(mpu401_t, dev_id, return); if (mpu == NULL) - return; - _snd_mpu401_uart_interrupt(mpu); + return IRQ_NONE; + return _snd_mpu401_uart_interrupt(mpu); } /* diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 7cfb6a06b1a2c..1a8bc1034ec15 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -716,7 +716,7 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev) iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); } -static void snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs) { intel8x0_t *chip = snd_magic_cast(intel8x0_t, dev_id, return); ichdev_t *ichdev; @@ -727,7 +727,7 @@ static void snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs) status = igetdword(chip, chip->int_sta_reg); if ((status & chip->int_sta_mask) == 0) { spin_unlock(&chip->reg_lock); - return; + return IRQ_NONE; } /* ack first */ iputdword(chip, chip->int_sta_reg, status & ~chip->int_sta_mask); @@ -738,6 +738,7 @@ static void snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (status & ichdev->int_sta_mask) snd_intel8x0_update(chip, ichdev); } + return IRQ_HANDLED; } /* -- 2.53.0