--- drivers/net/niu.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 60 insertions(+), 1 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 2b17453..a40653e 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -4210,26 +4210,85 @@ static void __niu_fastpath_interrupt(struct niu *np, int ldg, u64 v0) continue; nw64(LD_IM0(ldn), LD_IM0_MASK); if (tx_vec & (1 << rp->tx_channel)) niu_txchan_intr(np, rp, ldn); } } +// HHP +static void niu_dump_ldg_irq(struct niu *np, int ldg, u64 v0) +{ + static DEFINE_PER_CPU(unsigned long, spurious_count) = { 4 }; + + struct niu_parent *parent = np->parent; + u64 ld_im0_reg, ldg_imgmt_reg; + u32 rx_vec, tx_vec; + int ldn, i; + + if (!__get_cpu_var(spurious_count)) + return; + + __get_cpu_var(spurious_count)--; + printk(KERN_DEBUG "NIU: %s CPU=%i LDG=%i: interrupt received while NAPI is in progress\n", + np->dev->name, smp_processor_id(), ldg); + + tx_vec = (v0 >> 32); + rx_vec = (v0 & 0xffffffff); + + for (i = 0; i < np->num_rx_rings; i++) { + struct rx_ring_info *rp = &np->rx_rings[i]; + + ldn = LDN_RXDMA(rp->rx_channel); + if (parent->ldg_map[ldn] != ldg) + continue; + + ld_im0_reg = LD_IM0(ldn); + ldg_imgmt_reg = LDG_IMGMT(ldn); + printk(KERN_DEBUG " rx_vec=0x%04x LD_IM0[ldf_mask]=0x%02lx\n", + rx_vec, + (unsigned long)(ld_im0_reg & LD_IM0_MASK)), + printk(KERN_DEBUG " LDG_IMGMT=0x%016lx [arm=0x%02lx timer=0x%02lx]\n", + (unsigned long)ldg_imgmt_reg, + (unsigned long)((ldg_imgmt_reg & LDG_IMGMT_ARM) >> 31), + (unsigned long)(ldg_imgmt_reg & LDG_IMGMT_TIMER)); + } + + /* Spurious TX interrupts should not happen */ + for (i = 0; i < np->num_tx_rings; i++) { + struct tx_ring_info *rp = &np->tx_rings[i]; + ldn = LDN_TXDMA(rp->tx_channel); + + if (parent->ldg_map[ldn] != ldg) + continue; + + ld_im0_reg = LD_IM0(ldn); + ldg_imgmt_reg = LDG_IMGMT(ldn); + printk(KERN_DEBUG " tx_vec=0x%04x LD_IM0[ldf_mask]=0x%02lx\n", + tx_vec, + (unsigned long)(ld_im0_reg & LD_IM0_MASK)), + printk(KERN_DEBUG " LDG_IMGMT=0x%016lx [arm=0x%02lx timer=0x%02lx]\n", + (unsigned long)ldg_imgmt_reg, + (unsigned long)((ldg_imgmt_reg & LDG_IMGMT_ARM) >> 31), + (unsigned long)(ldg_imgmt_reg & LDG_IMGMT_TIMER)); + } +} + static void niu_schedule_napi(struct niu *np, struct niu_ldg *lp, u64 v0, u64 v1, u64 v2) { if (likely(napi_schedule_prep(&lp->napi))) { lp->v0 = v0; lp->v1 = v1; lp->v2 = v2; __niu_fastpath_interrupt(np, lp->ldg_num, v0); __napi_schedule(&lp->napi); - } + } else + niu_dump_ldg_irq(np, lp->ldg_num, v0); } static irqreturn_t niu_interrupt(int irq, void *dev_id) { struct niu_ldg *lp = dev_id; struct niu *np = lp->np; int ldg = lp->ldg_num; unsigned long flags;