aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2007-06-05 00:24:07 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-06-07 16:38:39 -0400
commit02537b0676930b1bd9aff2139e0e645c79986931 (patch)
tree28736a22d1b51d180f2c1bb9a3e845e178e8e7d3
parent0aa38df7cd5b6c5b89f5146f4a2286434bc4a8f3 (diff)
[BNX2]: Fix occasional counter corruption on 5708.
The statistics block DMA on 5708 can be messed up occasionally on the average of about once per hour. If the user is reading the counters within one second after the corruption, the counters will be all messed up. One second later, the counters will be ok again until the next corruption occurs. The workaround is to disable the periodic statistics DMA. Instead, we manually trigger the DMA once a second in bnx2_timer(). This manual trigger of the DMA avoids the problem. As a consequence, we can only allow 0 or 1 second settings for ethtool -C statistics block. Thanks to Jean-Daniel Pauget <jd@disjunkt.com> and CaT <cat@zip.com.au> for reporting this rare problem. Signed-off-by: Michael Chan <mchan@broadcom.com> Acked-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bnx2.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 3b7ca2a455b4..5046b0fa2357 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -3788,7 +3788,10 @@ bnx2_init_chip(struct bnx2 *bp)
3788 REG_WR(bp, BNX2_HC_CMD_TICKS, 3788 REG_WR(bp, BNX2_HC_CMD_TICKS,
3789 (bp->cmd_ticks_int << 16) | bp->cmd_ticks); 3789 (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
3790 3790
3791 REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00); 3791 if (CHIP_NUM(bp) == CHIP_NUM_5708)
3792 REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
3793 else
3794 REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
3792 REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ 3795 REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
3793 3796
3794 if (CHIP_ID(bp) == CHIP_ID_5706_A1) 3797 if (CHIP_ID(bp) == CHIP_ID_5706_A1)
@@ -4641,6 +4644,11 @@ bnx2_timer(unsigned long data)
4641 4644
4642 bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); 4645 bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
4643 4646
4647 /* workaround occasional corrupted counters */
4648 if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks)
4649 REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
4650 BNX2_HC_COMMAND_STATS_NOW);
4651
4644 if (bp->phy_flags & PHY_SERDES_FLAG) { 4652 if (bp->phy_flags & PHY_SERDES_FLAG) {
4645 if (CHIP_NUM(bp) == CHIP_NUM_5706) 4653 if (CHIP_NUM(bp) == CHIP_NUM_5706)
4646 bnx2_5706_serdes_timer(bp); 4654 bnx2_5706_serdes_timer(bp);
@@ -5438,6 +5446,10 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
5438 0xff; 5446 0xff;
5439 5447
5440 bp->stats_ticks = coal->stats_block_coalesce_usecs; 5448 bp->stats_ticks = coal->stats_block_coalesce_usecs;
5449 if (CHIP_NUM(bp) == CHIP_NUM_5708) {
5450 if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
5451 bp->stats_ticks = USEC_PER_SEC;
5452 }
5441 if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00; 5453 if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00;
5442 bp->stats_ticks &= 0xffff00; 5454 bp->stats_ticks &= 0xffff00;
5443 5455