Commit 02537b06 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

[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: default avatarMichael Chan <mchan@broadcom.com>
Acked-by: default avatarJeff Garzik <jeff@garzik.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0aa38df7
...@@ -3788,7 +3788,10 @@ bnx2_init_chip(struct bnx2 *bp) ...@@ -3788,7 +3788,10 @@ bnx2_init_chip(struct bnx2 *bp)
REG_WR(bp, BNX2_HC_CMD_TICKS, REG_WR(bp, BNX2_HC_CMD_TICKS,
(bp->cmd_ticks_int << 16) | bp->cmd_ticks); (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00); if (CHIP_NUM(bp) == CHIP_NUM_5708)
REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
else
REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */ REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
if (CHIP_ID(bp) == CHIP_ID_5706_A1) if (CHIP_ID(bp) == CHIP_ID_5706_A1)
...@@ -4641,6 +4644,11 @@ bnx2_timer(unsigned long data) ...@@ -4641,6 +4644,11 @@ bnx2_timer(unsigned long data)
bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
/* workaround occasional corrupted counters */
if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks)
REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
BNX2_HC_COMMAND_STATS_NOW);
if (bp->phy_flags & PHY_SERDES_FLAG) { if (bp->phy_flags & PHY_SERDES_FLAG) {
if (CHIP_NUM(bp) == CHIP_NUM_5706) if (CHIP_NUM(bp) == CHIP_NUM_5706)
bnx2_5706_serdes_timer(bp); bnx2_5706_serdes_timer(bp);
...@@ -5438,6 +5446,10 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) ...@@ -5438,6 +5446,10 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
0xff; 0xff;
bp->stats_ticks = coal->stats_block_coalesce_usecs; bp->stats_ticks = coal->stats_block_coalesce_usecs;
if (CHIP_NUM(bp) == CHIP_NUM_5708) {
if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
bp->stats_ticks = USEC_PER_SEC;
}
if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00; if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00;
bp->stats_ticks &= 0xffff00; bp->stats_ticks &= 0xffff00;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment