From 406f353c857e4b2dbddb7cd20c67941d829b8b15 Mon Sep 17 00:00:00 2001 From: Matheos Worku Date: Fri, 4 Jan 2008 23:48:26 -0800 Subject: [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 --- drivers/net/niu.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers') 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 @@ static int niu_rx_error(struct niu *np, struct rx_ring_info *rp) 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 @@ static int niu_device_error(struct niu *np) 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 @@ static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp) 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 @@ static int niu_slowpath_interrupt(struct niu *np, struct niu_ldg *lp) 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 @@ static irqreturn_t niu_interrupt(int irq, void *dev_id) } 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; } -- cgit v1.1