aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2007-01-27 02:59:57 -0500
committerJeff Garzik <jeff@garzik.org>2007-01-30 09:36:01 -0500
commit5fc7d61aee1a7f7d3448f8fbccaa93371ebeecb0 (patch)
treecebe78adc2313c6890562d0f3e79a61eeb6f28c7
parentc0d4d573feed199b16094c072e7cb07afb01c598 (diff)
b44: Fix frequent link changes
This fixes the issue of frequent link changes under heavy traffic reported below: http://bugzilla.kernel.org/show_bug.cgi?id=7696 https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=216338 The b44 chip occasionally needs to be reset when ISTAT_ERRORS are encountered. The reset sequence includes a PHY reset that will take many seconds to complete and cause the link to go down and up. By skipping the PHY reset, it will greatly reduce the interruption when ISTAT_ERRORS are encountered. Change the full_reset parameter to reset_kind parameter in b44_init_hw(). This will allow PHY reset to be skipped when ISTAT_ERRORS are encountered. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/b44.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 5eb2ec68393f..1c8fb8e7df59 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -110,6 +110,11 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
110 110
111static void b44_halt(struct b44 *); 111static void b44_halt(struct b44 *);
112static void b44_init_rings(struct b44 *); 112static void b44_init_rings(struct b44 *);
113
114#define B44_FULL_RESET 1
115#define B44_FULL_RESET_SKIP_PHY 2
116#define B44_PARTIAL_RESET 3
117
113static void b44_init_hw(struct b44 *, int); 118static void b44_init_hw(struct b44 *, int);
114 119
115static int dma_desc_align_mask; 120static int dma_desc_align_mask;
@@ -884,7 +889,7 @@ static int b44_poll(struct net_device *netdev, int *budget)
884 spin_lock_irqsave(&bp->lock, flags); 889 spin_lock_irqsave(&bp->lock, flags);
885 b44_halt(bp); 890 b44_halt(bp);
886 b44_init_rings(bp); 891 b44_init_rings(bp);
887 b44_init_hw(bp, 1); 892 b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
888 netif_wake_queue(bp->dev); 893 netif_wake_queue(bp->dev);
889 spin_unlock_irqrestore(&bp->lock, flags); 894 spin_unlock_irqrestore(&bp->lock, flags);
890 done = 1; 895 done = 1;
@@ -954,7 +959,7 @@ static void b44_tx_timeout(struct net_device *dev)
954 959
955 b44_halt(bp); 960 b44_halt(bp);
956 b44_init_rings(bp); 961 b44_init_rings(bp);
957 b44_init_hw(bp, 1); 962 b44_init_hw(bp, B44_FULL_RESET);
958 963
959 spin_unlock_irq(&bp->lock); 964 spin_unlock_irq(&bp->lock);
960 965
@@ -1071,7 +1076,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
1071 b44_halt(bp); 1076 b44_halt(bp);
1072 dev->mtu = new_mtu; 1077 dev->mtu = new_mtu;
1073 b44_init_rings(bp); 1078 b44_init_rings(bp);
1074 b44_init_hw(bp, 1); 1079 b44_init_hw(bp, B44_FULL_RESET);
1075 spin_unlock_irq(&bp->lock); 1080 spin_unlock_irq(&bp->lock);
1076 1081
1077 b44_enable_ints(bp); 1082 b44_enable_ints(bp);
@@ -1368,12 +1373,12 @@ static int b44_set_mac_addr(struct net_device *dev, void *p)
1368 * packet processing. Invoked with bp->lock held. 1373 * packet processing. Invoked with bp->lock held.
1369 */ 1374 */
1370static void __b44_set_rx_mode(struct net_device *); 1375static void __b44_set_rx_mode(struct net_device *);
1371static void b44_init_hw(struct b44 *bp, int full_reset) 1376static void b44_init_hw(struct b44 *bp, int reset_kind)
1372{ 1377{
1373 u32 val; 1378 u32 val;
1374 1379
1375 b44_chip_reset(bp); 1380 b44_chip_reset(bp);
1376 if (full_reset) { 1381 if (reset_kind == B44_FULL_RESET) {
1377 b44_phy_reset(bp); 1382 b44_phy_reset(bp);
1378 b44_setup_phy(bp); 1383 b44_setup_phy(bp);
1379 } 1384 }
@@ -1390,7 +1395,10 @@ static void b44_init_hw(struct b44 *bp, int full_reset)
1390 bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN); 1395 bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
1391 1396
1392 bw32(bp, B44_TX_WMARK, 56); /* XXX magic */ 1397 bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
1393 if (full_reset) { 1398 if (reset_kind == B44_PARTIAL_RESET) {
1399 bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
1400 (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
1401 } else {
1394 bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE); 1402 bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
1395 bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset); 1403 bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
1396 bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE | 1404 bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
@@ -1401,9 +1409,6 @@ static void b44_init_hw(struct b44 *bp, int full_reset)
1401 bp->rx_prod = bp->rx_pending; 1409 bp->rx_prod = bp->rx_pending;
1402 1410
1403 bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); 1411 bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
1404 } else {
1405 bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
1406 (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
1407 } 1412 }
1408 1413
1409 val = br32(bp, B44_ENET_CTRL); 1414 val = br32(bp, B44_ENET_CTRL);
@@ -1420,7 +1425,7 @@ static int b44_open(struct net_device *dev)
1420 goto out; 1425 goto out;
1421 1426
1422 b44_init_rings(bp); 1427 b44_init_rings(bp);
1423 b44_init_hw(bp, 1); 1428 b44_init_hw(bp, B44_FULL_RESET);
1424 1429
1425 b44_check_phy(bp); 1430 b44_check_phy(bp);
1426 1431
@@ -1629,7 +1634,7 @@ static int b44_close(struct net_device *dev)
1629 netif_poll_enable(dev); 1634 netif_poll_enable(dev);
1630 1635
1631 if (bp->flags & B44_FLAG_WOL_ENABLE) { 1636 if (bp->flags & B44_FLAG_WOL_ENABLE) {
1632 b44_init_hw(bp, 0); 1637 b44_init_hw(bp, B44_PARTIAL_RESET);
1633 b44_setup_wol(bp); 1638 b44_setup_wol(bp);
1634 } 1639 }
1635 1640
@@ -1905,7 +1910,7 @@ static int b44_set_ringparam(struct net_device *dev,
1905 1910
1906 b44_halt(bp); 1911 b44_halt(bp);
1907 b44_init_rings(bp); 1912 b44_init_rings(bp);
1908 b44_init_hw(bp, 1); 1913 b44_init_hw(bp, B44_FULL_RESET);
1909 netif_wake_queue(bp->dev); 1914 netif_wake_queue(bp->dev);
1910 spin_unlock_irq(&bp->lock); 1915 spin_unlock_irq(&bp->lock);
1911 1916
@@ -1948,7 +1953,7 @@ static int b44_set_pauseparam(struct net_device *dev,
1948 if (bp->flags & B44_FLAG_PAUSE_AUTO) { 1953 if (bp->flags & B44_FLAG_PAUSE_AUTO) {
1949 b44_halt(bp); 1954 b44_halt(bp);
1950 b44_init_rings(bp); 1955 b44_init_rings(bp);
1951 b44_init_hw(bp, 1); 1956 b44_init_hw(bp, B44_FULL_RESET);
1952 } else { 1957 } else {
1953 __b44_set_flow_ctrl(bp, bp->flags); 1958 __b44_set_flow_ctrl(bp, bp->flags);
1954 } 1959 }
@@ -2304,7 +2309,7 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
2304 2309
2305 free_irq(dev->irq, dev); 2310 free_irq(dev->irq, dev);
2306 if (bp->flags & B44_FLAG_WOL_ENABLE) { 2311 if (bp->flags & B44_FLAG_WOL_ENABLE) {
2307 b44_init_hw(bp, 0); 2312 b44_init_hw(bp, B44_PARTIAL_RESET);
2308 b44_setup_wol(bp); 2313 b44_setup_wol(bp);
2309 } 2314 }
2310 pci_disable_device(pdev); 2315 pci_disable_device(pdev);
@@ -2329,7 +2334,7 @@ static int b44_resume(struct pci_dev *pdev)
2329 spin_lock_irq(&bp->lock); 2334 spin_lock_irq(&bp->lock);
2330 2335
2331 b44_init_rings(bp); 2336 b44_init_rings(bp);
2332 b44_init_hw(bp, 1); 2337 b44_init_hw(bp, B44_FULL_RESET);
2333 netif_device_attach(bp->dev); 2338 netif_device_attach(bp->dev);
2334 spin_unlock_irq(&bp->lock); 2339 spin_unlock_irq(&bp->lock);
2335 2340