summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2006-03-23 09:11:56 (GMT)
committerDavid S. Miller <davem@davemloft.net>2006-03-23 09:11:56 (GMT)
commitbf5295bba804a6aead9bc1c0d5970173a9d4e08e (patch)
tree561708042eb3348d0693f4d2a4035bf4b58fd8e9
parentca6549af77f0f28ac5d23b662fb8f72713eb16d3 (diff)
downloadlinux-bf5295bba804a6aead9bc1c0d5970173a9d4e08e.tar.xz
[BNX2]: Fix link change handling
Fix some link-related problems by doing a coalesce_now after link change interrupt to flush out the transient link status. To facilitate this, the host coalesce cmd register value is cached in the device structure. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bnx2.c29
-rw-r--r--drivers/net/bnx2.h1
2 files changed, 18 insertions, 12 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 7d21370..c56888e 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -313,8 +313,6 @@ bnx2_disable_int(struct bnx2 *bp)
static void
bnx2_enable_int(struct bnx2 *bp)
{
- u32 val;
-
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx);
@@ -322,8 +320,7 @@ bnx2_enable_int(struct bnx2 *bp)
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx);
- val = REG_RD(bp, BNX2_HC_COMMAND);
- REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
+ REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
}
static void
@@ -1926,6 +1923,13 @@ bnx2_poll(struct net_device *dev, int *budget)
spin_lock(&bp->phy_lock);
bnx2_phy_int(bp);
spin_unlock(&bp->phy_lock);
+
+ /* This is needed to take care of transient status
+ * during link changes.
+ */
+ REG_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_RD(bp, BNX2_HC_COMMAND);
}
if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
@@ -3307,6 +3311,8 @@ bnx2_init_chip(struct bnx2 *bp)
udelay(20);
+ bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
+
return rc;
}
@@ -3746,7 +3752,6 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
struct sk_buff *skb, *rx_skb;
unsigned char *packet;
u16 rx_start_idx, rx_idx;
- u32 val;
dma_addr_t map;
struct tx_bd *txbd;
struct sw_bd *rx_buf;
@@ -3777,8 +3782,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
map = pci_map_single(bp->pdev, skb->data, pkt_size,
PCI_DMA_TODEVICE);
- val = REG_RD(bp, BNX2_HC_COMMAND);
- REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+
REG_RD(bp, BNX2_HC_COMMAND);
udelay(5);
@@ -3802,8 +3808,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
udelay(100);
- val = REG_RD(bp, BNX2_HC_COMMAND);
- REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_WR(bp, BNX2_HC_COMMAND,
+ bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+
REG_RD(bp, BNX2_HC_COMMAND);
udelay(5);
@@ -3939,7 +3946,6 @@ static int
bnx2_test_intr(struct bnx2 *bp)
{
int i;
- u32 val;
u16 status_idx;
if (!netif_running(bp->dev))
@@ -3948,8 +3954,7 @@ bnx2_test_intr(struct bnx2 *bp)
status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
/* This register is not touched during run-time. */
- val = REG_RD(bp, BNX2_HC_COMMAND);
- REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
+ REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
REG_RD(bp, BNX2_HC_COMMAND);
for (i = 0; i < 10; i++) {
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index fd4b7f2..18bc091 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -4038,6 +4038,7 @@ struct bnx2 {
struct statistics_block *stats_blk;
dma_addr_t stats_blk_mapping;
+ u32 hc_cmd;
u32 rx_mode;
u16 req_line_speed;