[NIU]: Fix slowpath interrupt handling.

niu_slowpath_interrupt() expects values to be setup in lp->{v0,v1,v2}
but they aren't.  That's only done by niu_schedule_napi() which is
done later in the interrupt path.

If niu_rx_error() returns zero, and v0 is clear, hit the
RX_DMA_CTL_STATE register with a RX_DMA_CTL_STAT_MEX.

Only emit verbose RX error logs if a fatal channel or port error is
signalled.  Other cases will be recorded into statistics by
niu_log_rxchan_errors().

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index abfc61c..32ed87d 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -2508,15 +2508,19 @@
 	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);
 
@@ -2749,13 +2753,16 @@
 	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);
 
@@ -2764,8 +2771,13 @@
 
 			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);
+				}
 			}
 		}
 	}
@@ -2803,7 +2815,7 @@
 	if (err)
 		niu_enable_interrupts(np, 0);
 
-	return -EINVAL;
+	return err;
 }
 
 static void niu_rxchan_intr(struct niu *np, struct rx_ring_info *rp,
@@ -2905,7 +2917,7 @@
 	}
 
 	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;
 	}