diff options
author | Michael Chan <mchan@broadcom.com> | 2006-03-23 04:11:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-23 04:11:56 -0500 |
commit | bf5295bba804a6aead9bc1c0d5970173a9d4e08e (patch) | |
tree | 561708042eb3348d0693f4d2a4035bf4b58fd8e9 /drivers/net/bnx2.c | |
parent | ca6549af77f0f28ac5d23b662fb8f72713eb16d3 (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>
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 29 |
1 files changed, 17 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) | |||
313 | static void | 313 | static void |
314 | bnx2_enable_int(struct bnx2 *bp) | 314 | bnx2_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 | ||
329 | static void | 326 | static 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 | |||
3939 | bnx2_test_intr(struct bnx2 *bp) | 3946 | bnx2_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++) { |