aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2006-03-23 04:11:56 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-23 04:11:56 -0500
commitbf5295bba804a6aead9bc1c0d5970173a9d4e08e (patch)
tree561708042eb3348d0693f4d2a4035bf4b58fd8e9
parentca6549af77f0f28ac5d23b662fb8f72713eb16d3 (diff)
[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 7d213707008a..c56888e66351 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -313,8 +313,6 @@ bnx2_disable_int(struct bnx2 *bp)
313static void 313static void
314bnx2_enable_int(struct bnx2 *bp) 314bnx2_enable_int(struct bnx2 *bp)
315{ 315{
316 u32 val;
317
318 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 316 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
319 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | 317 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
320 BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx); 318 BNX2_PCICFG_INT_ACK_CMD_MASK_INT | bp->last_status_idx);
@@ -322,8 +320,7 @@ bnx2_enable_int(struct bnx2 *bp)
322 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, 320 REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
323 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx); 321 BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx);
324 322
325 val = REG_RD(bp, BNX2_HC_COMMAND); 323 REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
326 REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
327} 324}
328 325
329static void 326static void
@@ -1926,6 +1923,13 @@ bnx2_poll(struct net_device *dev, int *budget)
1926 spin_lock(&bp->phy_lock); 1923 spin_lock(&bp->phy_lock);
1927 bnx2_phy_int(bp); 1924 bnx2_phy_int(bp);
1928 spin_unlock(&bp->phy_lock); 1925 spin_unlock(&bp->phy_lock);
1926
1927 /* This is needed to take care of transient status
1928 * during link changes.
1929 */
1930 REG_WR(bp, BNX2_HC_COMMAND,
1931 bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
1932 REG_RD(bp, BNX2_HC_COMMAND);
1929 } 1933 }
1930 1934
1931 if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons) 1935 if (bp->status_blk->status_tx_quick_consumer_index0 != bp->hw_tx_cons)
@@ -3307,6 +3311,8 @@ bnx2_init_chip(struct bnx2 *bp)
3307 3311
3308 udelay(20); 3312 udelay(20);
3309 3313
3314 bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
3315
3310 return rc; 3316 return rc;
3311} 3317}
3312 3318
@@ -3746,7 +3752,6 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
3746 struct sk_buff *skb, *rx_skb; 3752 struct sk_buff *skb, *rx_skb;
3747 unsigned char *packet; 3753 unsigned char *packet;
3748 u16 rx_start_idx, rx_idx; 3754 u16 rx_start_idx, rx_idx;
3749 u32 val;
3750 dma_addr_t map; 3755 dma_addr_t map;
3751 struct tx_bd *txbd; 3756 struct tx_bd *txbd;
3752 struct sw_bd *rx_buf; 3757 struct sw_bd *rx_buf;
@@ -3777,8 +3782,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
3777 map = pci_map_single(bp->pdev, skb->data, pkt_size, 3782 map = pci_map_single(bp->pdev, skb->data, pkt_size,
3778 PCI_DMA_TODEVICE); 3783 PCI_DMA_TODEVICE);
3779 3784
3780 val = REG_RD(bp, BNX2_HC_COMMAND); 3785 REG_WR(bp, BNX2_HC_COMMAND,
3781 REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); 3786 bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
3787
3782 REG_RD(bp, BNX2_HC_COMMAND); 3788 REG_RD(bp, BNX2_HC_COMMAND);
3783 3789
3784 udelay(5); 3790 udelay(5);
@@ -3802,8 +3808,9 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
3802 3808
3803 udelay(100); 3809 udelay(100);
3804 3810
3805 val = REG_RD(bp, BNX2_HC_COMMAND); 3811 REG_WR(bp, BNX2_HC_COMMAND,
3806 REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT); 3812 bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
3813
3807 REG_RD(bp, BNX2_HC_COMMAND); 3814 REG_RD(bp, BNX2_HC_COMMAND);
3808 3815
3809 udelay(5); 3816 udelay(5);
@@ -3939,7 +3946,6 @@ static int
3939bnx2_test_intr(struct bnx2 *bp) 3946bnx2_test_intr(struct bnx2 *bp)
3940{ 3947{
3941 int i; 3948 int i;
3942 u32 val;
3943 u16 status_idx; 3949 u16 status_idx;
3944 3950
3945 if (!netif_running(bp->dev)) 3951 if (!netif_running(bp->dev))
@@ -3948,8 +3954,7 @@ bnx2_test_intr(struct bnx2 *bp)
3948 status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff; 3954 status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
3949 3955
3950 /* This register is not touched during run-time. */ 3956 /* This register is not touched during run-time. */
3951 val = REG_RD(bp, BNX2_HC_COMMAND); 3957 REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
3952 REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
3953 REG_RD(bp, BNX2_HC_COMMAND); 3958 REG_RD(bp, BNX2_HC_COMMAND);
3954 3959
3955 for (i = 0; i < 10; i++) { 3960 for (i = 0; i < 10; i++) {
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index fd4b7f2eb477..18bc0919cc9e 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -4038,6 +4038,7 @@ struct bnx2 {
4038 struct statistics_block *stats_blk; 4038 struct statistics_block *stats_blk;
4039 dma_addr_t stats_blk_mapping; 4039 dma_addr_t stats_blk_mapping;
4040 4040
4041 u32 hc_cmd;
4041 u32 rx_mode; 4042 u32 rx_mode;
4042 4043
4043 u16 req_line_speed; 4044 u16 req_line_speed;