From: "Maciej W. Rozycki" This is a fix for the interrupt handler in the defxx driver to use irqreturn_t. Beside the obvious fix of returning a proper status at all, it actually checks board registers as appropriate for determining if an interrupt has been recorded in the bus-specific interface logic. The patch also includes an obvious one-line fix for SET_NETDEV_DEV needed for the EISA variation, for which I've decided there is no point in sending separately. Signed-off-by: Maciej W. Rozycki Cc: Jeff Garzik Signed-off-by: Andrew Morton --- drivers/net/defxx.c | 88 ++++++++++++++++++++++++++++++---------------------- 1 files changed, 51 insertions(+), 37 deletions(-) diff -puN drivers/net/defxx.c~defxx-use-irqreturn_t-for-the-interrupt-handler drivers/net/defxx.c --- 25/drivers/net/defxx.c~defxx-use-irqreturn_t-for-the-interrupt-handler 2005-06-14 13:41:23.000000000 -0700 +++ 25-akpm/drivers/net/defxx.c 2005-06-14 13:41:23.000000000 -0700 @@ -191,6 +191,7 @@ * Feb 2001 davej PCI enable cleanups. * 04 Aug 2003 macro Converted to the DMA API. * 14 Aug 2004 macro Fix device names reported. + * 14 Jun 2005 macro Use irqreturn_t. */ /* Include files */ @@ -217,8 +218,8 @@ /* Version information string should be updated prior to each new release! */ #define DRV_NAME "defxx" -#define DRV_VERSION "v1.07" -#define DRV_RELDATE "2004/08/14" +#define DRV_VERSION "v1.08" +#define DRV_RELDATE "2005/06/14" static char version[] __devinitdata = DRV_NAME ": " DRV_VERSION " " DRV_RELDATE @@ -247,7 +248,8 @@ static int dfx_close(struct net_device static void dfx_int_pr_halt_id(DFX_board_t *bp); static void dfx_int_type_0_process(DFX_board_t *bp); static void dfx_int_common(struct net_device *dev); -static void dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t dfx_interrupt(int irq, void *dev_id, + struct pt_regs *regs); static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev); static void dfx_ctl_set_multicast_list(struct net_device *dev); @@ -437,7 +439,8 @@ static int __devinit dfx_init_one_pci_or } SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); + if (pdev != NULL) + SET_NETDEV_DEV(dev, &pdev->dev); bp = dev->priv; @@ -1225,7 +1228,7 @@ static int dfx_open(struct net_device *d /* Register IRQ - support shared interrupts by passing device ptr */ - ret = request_irq(dev->irq, (void *)dfx_interrupt, SA_SHIRQ, dev->name, dev); + ret = request_irq(dev->irq, dfx_interrupt, SA_SHIRQ, dev->name, dev); if (ret) { printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); return ret; @@ -1680,13 +1683,13 @@ static void dfx_int_common(struct net_de * ================= * = dfx_interrupt = * ================= - * + * * Overview: * Interrupt processing routine - * + * * Returns: - * None - * + * Whether a valid interrupt was seen. + * * Arguments: * irq - interrupt vector * dev_id - pointer to device information @@ -1699,7 +1702,8 @@ static void dfx_int_common(struct net_de * structure context. * * Return Codes: - * None + * IRQ_HANDLED - an IRQ was handled. + * IRQ_NONE - no IRQ was handled. * * Assumptions: * The interrupt acknowledgement at the hardware level (eg. ACKing the PIC @@ -1712,60 +1716,70 @@ static void dfx_int_common(struct net_de * Interrupts are disabled, then reenabled at the adapter. */ -static void dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs) - { +static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ struct net_device *dev = dev_id; DFX_board_t *bp; /* private board structure pointer */ - u8 tmp; /* used for disabling/enabling ints */ /* Get board pointer only if device structure is valid */ bp = dev->priv; - spin_lock(&bp->lock); - /* See if we're already servicing an interrupt */ /* Service adapter interrupts */ - if (bp->bus_type == DFX_BUS_TYPE_PCI) - { - /* Disable PDQ-PFI interrupts at PFI */ + if (bp->bus_type == DFX_BUS_TYPE_PCI) { + u32 status; - dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, PFI_MODE_M_DMA_ENB); + dfx_port_read_long(bp, PFI_K_REG_STATUS, &status); + if (!(status & PFI_STATUS_M_PDQ_INT)) + return IRQ_NONE; - /* Call interrupt service routine for this adapter */ + spin_lock(&bp->lock); + + /* Disable PDQ-PFI interrupts at PFI */ + dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, + PFI_MODE_M_DMA_ENB); + /* Call interrupt service routine for this adapter */ dfx_int_common(dev); /* Clear PDQ interrupt status bit and reenable interrupts */ - - dfx_port_write_long(bp, PFI_K_REG_STATUS, PFI_STATUS_M_PDQ_INT); + dfx_port_write_long(bp, PFI_K_REG_STATUS, + PFI_STATUS_M_PDQ_INT); dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, - (PFI_MODE_M_PDQ_INT_ENB + PFI_MODE_M_DMA_ENB)); - } - else - { - /* Disable interrupts at the ESIC */ + (PFI_MODE_M_PDQ_INT_ENB | + PFI_MODE_M_DMA_ENB)); - dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp); - tmp &= ~PI_CONFIG_STAT_0_M_INT_ENB; - dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp); + spin_unlock(&bp->lock); + } else { + u8 status; - /* Call interrupt service routine for this adapter */ + dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status); + if (!(status & PI_CONFIG_STAT_0_M_PEND)) + return IRQ_NONE; + spin_lock(&bp->lock); + + /* Disable interrupts at the ESIC */ + status &= ~PI_CONFIG_STAT_0_M_INT_ENB; + dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status); + + /* Call interrupt service routine for this adapter */ dfx_int_common(dev); /* Reenable interrupts at the ESIC */ + dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status); + status |= PI_CONFIG_STAT_0_M_INT_ENB; + dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status); - dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp); - tmp |= PI_CONFIG_STAT_0_M_INT_ENB; - dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp); - } - - spin_unlock(&bp->lock); + spin_unlock(&bp->lock); } + return IRQ_HANDLED; +} + /* * ===================== _