in dino.c [359:399]
static irqreturn_t dino_isr(int irq, void *intr_dev)
{
struct dino_device *dino_dev = intr_dev;
u32 mask;
int ilr_loop = 100;
/* read and acknowledge pending interrupts */
#ifdef DINO_DEBUG
dino_dev->dino_irr0 =
#endif
mask = __raw_readl(dino_dev->hba.base_addr+DINO_IRR0) & DINO_IRR_MASK;
if (mask == 0)
return IRQ_NONE;
ilr_again:
do {
int local_irq = __ffs(mask);
int irq = dino_dev->global_irq[local_irq];
DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n",
__func__, irq, intr_dev, mask);
generic_handle_irq(irq);
mask &= ~DINO_MASK_IRQ(local_irq);
} while (mask);
/* Support for level triggered IRQ lines.
**
** Dropping this support would make this routine *much* faster.
** But since PCI requires level triggered IRQ line to share lines...
** device drivers may assume lines are level triggered (and not
** edge triggered like EISA/ISA can be).
*/
mask = __raw_readl(dino_dev->hba.base_addr+DINO_ILR) & dino_dev->imr;
if (mask) {
if (--ilr_loop > 0)
goto ilr_again;
pr_warn_ratelimited("Dino 0x%px: stuck interrupt %d\n",
dino_dev->hba.base_addr, mask);
}
return IRQ_HANDLED;
}