@@ -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;