u64 stat = nr64(RX_DMA_CTL_STAT(rp->rx_channel));
int err = 0;
- dev_err(np->device, PFX "%s: RX channel %u error, stat[%llx]\n",
- np->dev->name, rp->rx_channel, (unsigned long long) stat);
-
- niu_log_rxchan_errors(np, rp, stat);
if (stat & (RX_DMA_CTL_STAT_CHAN_FATAL |
RX_DMA_CTL_STAT_PORT_FATAL))
err = -EINVAL;
+ if (err) {
+ dev_err(np->device, PFX "%s: RX channel %u error, stat[%llx]\n",
+ np->dev->name, rp->rx_channel,
+ (unsigned long long) stat);
+
+ niu_log_rxchan_errors(np, rp, stat);
+ }
+
nw64(RX_DMA_CTL_STAT(rp->rx_channel),
stat & RX_DMA_CTL_WRITE_CLEAR_ERRS);
return -ENODEV;
}
-static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp)
+static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp,
+ u64 v0, u64 v1, u64 v2)
{
- u64 v0 = lp->v0;
- u64 v1 = lp->v1;
- u64 v2 = lp->v2;
+
int i, err = 0;
+ lp->v0 = v0;
+ lp->v1 = v1;
+ lp->v2 = v2;
+
if (v1 & 0x00000000ffffffffULL) {
u32 rx_vec = (v1 & 0xffffffff);
if (rx_vec & (1 << rp->rx_channel)) {
int r = niu_rx_error(np, rp);
- if (r)
+ if (r) {
err = r;
+ } else {
+ if (!v0)
+ nw64(RX_DMA_CTL_STAT(rp->rx_channel),
+ RX_DMA_CTL_STAT_MEX);
+ }
}
}
}
if (err)
niu_enable_interrupts(np, 0);
- return -EINVAL;
+ return err;
}
static void niu_rxchan_intr(struct niu *np, struct rx_ring_info *rp,
}
if (unlikely((v0 & ((u64)1 << LDN_MIF)) || v1 || v2)) {
- int err = niu_slowpath_interrupt(np, lp);
+ int err = niu_slowpath_interrupt(np, lp, v0, v1, v2);
if (err)
goto out;
}