diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 2b17453..125450a 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -3724,6 +3724,10 @@ static int niu_rx_work(struct napi_struct *napi, struct niu *np, mbox->rx_dma_ctl_stat = 0; mbox->rcrstat_a = 0; + if (!qlen) + printk(KERN_DEBUG PFX "%s() CPU=%i rx_channel=%i qlen is zero!\n", + __FUNCTION__, raw_smp_processor_id(), rp->rx_channel); + niudbg(RX_STATUS, "%s: niu_rx_work(chan[%d]), stat[%llx] qlen=%d\n", np->dev->name, rp->rx_channel, (unsigned long long) stat, qlen); @@ -4193,10 +4197,17 @@ static void __niu_fastpath_interrupt(struct niu *np, int ldg, u64 v0) for (i = 0; i < np->num_rx_rings; i++) { struct rx_ring_info *rp = &np->rx_rings[i]; int ldn = LDN_RXDMA(rp->rx_channel); + u64 qlen; if (parent->ldg_map[ldn] != ldg) continue; + qlen = nr64(RCRSTAT_A(rp->rx_channel)) & RCRSTAT_A_QLEN; + if (!qlen) { + printk(KERN_DEBUG PFX "%s() CPU=%i rx_channel=%i qlen is 0!\n", + __FUNCTION__, smp_processor_id(), rp->rx_channel); + } + nw64(LD_IM0(ldn), LD_IM0_MASK); if (rx_vec & (1 << rp->rx_channel)) niu_rxchan_intr(np, rp, ldn); @@ -4215,6 +4226,22 @@ static void __niu_fastpath_interrupt(struct niu *np, int ldg, u64 v0) } } +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; + int qlen, ldn, i; + + if (!__get_cpu_var(spurious_count)) + return; + + __get_cpu_var(spurious_count)--; + + printk(KERN_DEBUG PFX "%s CPU=%i LDG=%i v0=%p: spurious interrupt\n", + np->dev->name, smp_processor_id(), ldg, (void *)v0); +} + static void niu_schedule_napi(struct niu *np, struct niu_ldg *lp, u64 v0, u64 v1, u64 v2) { @@ -4224,7 +4251,8 @@ static void niu_schedule_napi(struct niu *np, struct niu_ldg *lp, 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) @@ -4251,6 +4279,10 @@ static irqreturn_t niu_interrupt(int irq, void *dev_id) (unsigned long long) v1, (unsigned long long) v2); + if (!v0) + printk(KERN_DEBUG PFX "%s() CPU=%i LDG=%i v0 is zero!\n", + __FUNCTION__, smp_processor_id(), ldg); + if (unlikely(!v0 && !v1 && !v2)) { spin_unlock_irqrestore(&np->lock, flags); return IRQ_NONE; @@ -4263,8 +4295,11 @@ static irqreturn_t niu_interrupt(int irq, void *dev_id) } if (likely(v0 & ~((u64)1 << LDN_MIF))) niu_schedule_napi(np, lp, v0, v1, v2); - else + else { + printk(KERN_DEBUG PFX "%s() CPU=%i no DMA work, rearming LDG\n", + __FUNCTION__, smp_processor_id()); niu_ldg_rearm(np, lp, 1); + } out: spin_unlock_irqrestore(&np->lock, flags);