aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-12-20 18:08:07 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-12-24 09:38:35 -0500
commit1b537565a85cbe5cc9d5174d348a9014381af718 (patch)
treefa61606c4426c3384703db9b2bacc84b6d6ad8b4 /drivers/net/sky2.c
parentedd702e847fb8a9774a2ed8d50d2b8299b8c7f89 (diff)
[PATCH] sky2: handle out of memory on admin changes
Don't die if we run out of memory on mtu or ring parameter change. For other admin operations, don't rebuild Rx ring, just restart the PHY. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c84
1 files changed, 52 insertions, 32 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 7af72cdd473c..1d183d5177a1 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -481,6 +481,14 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
481 gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); 481 gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
482} 482}
483 483
484/* Force a renegotiation */
485static void sky2_phy_reinit(struct sky2_port *sky2)
486{
487 down(&sky2->phy_sema);
488 sky2_phy_init(sky2->hw, sky2->port);
489 up(&sky2->phy_sema);
490}
491
484static void sky2_mac_init(struct sky2_hw *hw, unsigned port) 492static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
485{ 493{
486 struct sky2_port *sky2 = netdev_priv(hw->dev[port]); 494 struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -1014,18 +1022,22 @@ static int sky2_up(struct net_device *dev)
1014 return 0; 1022 return 0;
1015 1023
1016err_out: 1024err_out:
1017 if (sky2->rx_le) 1025 if (sky2->rx_le) {
1018 pci_free_consistent(hw->pdev, RX_LE_BYTES, 1026 pci_free_consistent(hw->pdev, RX_LE_BYTES,
1019 sky2->rx_le, sky2->rx_le_map); 1027 sky2->rx_le, sky2->rx_le_map);
1020 if (sky2->tx_le) 1028 sky2->rx_le = NULL;
1029 }
1030 if (sky2->tx_le) {
1021 pci_free_consistent(hw->pdev, 1031 pci_free_consistent(hw->pdev,
1022 TX_RING_SIZE * sizeof(struct sky2_tx_le), 1032 TX_RING_SIZE * sizeof(struct sky2_tx_le),
1023 sky2->tx_le, sky2->tx_le_map); 1033 sky2->tx_le, sky2->tx_le_map);
1024 if (sky2->tx_ring) 1034 sky2->tx_le = NULL;
1025 kfree(sky2->tx_ring); 1035 }
1026 if (sky2->rx_ring) 1036 kfree(sky2->tx_ring);
1027 kfree(sky2->rx_ring); 1037 kfree(sky2->rx_ring);
1028 1038
1039 sky2->tx_ring = NULL;
1040 sky2->rx_ring = NULL;
1029 return err; 1041 return err;
1030} 1042}
1031 1043
@@ -1291,6 +1303,10 @@ static int sky2_down(struct net_device *dev)
1291 unsigned port = sky2->port; 1303 unsigned port = sky2->port;
1292 u16 ctrl; 1304 u16 ctrl;
1293 1305
1306 /* Never really got started! */
1307 if (!sky2->tx_le)
1308 return 0;
1309
1294 if (netif_msg_ifdown(sky2)) 1310 if (netif_msg_ifdown(sky2))
1295 printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); 1311 printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
1296 1312
@@ -1365,6 +1381,12 @@ static int sky2_down(struct net_device *dev)
1365 sky2->tx_le, sky2->tx_le_map); 1381 sky2->tx_le, sky2->tx_le_map);
1366 kfree(sky2->tx_ring); 1382 kfree(sky2->tx_ring);
1367 1383
1384 sky2->tx_le = NULL;
1385 sky2->rx_le = NULL;
1386
1387 sky2->rx_ring = NULL;
1388 sky2->tx_ring = NULL;
1389
1368 return 0; 1390 return 0;
1369} 1391}
1370 1392
@@ -1636,12 +1658,17 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
1636 sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD); 1658 sky2_write8(hw, RB_ADDR(rxqaddr[sky2->port], RB_CTRL), RB_ENA_OP_MD);
1637 1659
1638 err = sky2_rx_start(sky2); 1660 err = sky2_rx_start(sky2);
1639 gma_write16(hw, sky2->port, GM_GP_CTRL, ctl);
1640
1641 netif_poll_disable(hw->dev[0]);
1642 netif_wake_queue(dev);
1643 sky2_write32(hw, B0_IMSK, hw->intr_mask); 1661 sky2_write32(hw, B0_IMSK, hw->intr_mask);
1644 1662
1663 if (err)
1664 dev_close(dev);
1665 else {
1666 gma_write16(hw, sky2->port, GM_GP_CTRL, ctl);
1667
1668 netif_poll_enable(hw->dev[0]);
1669 netif_wake_queue(dev);
1670 }
1671
1645 return err; 1672 return err;
1646} 1673}
1647 1674
@@ -2315,10 +2342,8 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
2315 sky2->autoneg = ecmd->autoneg; 2342 sky2->autoneg = ecmd->autoneg;
2316 sky2->advertising = ecmd->advertising; 2343 sky2->advertising = ecmd->advertising;
2317 2344
2318 if (netif_running(dev)) { 2345 if (netif_running(dev))
2319 sky2_down(dev); 2346 sky2_phy_reinit(sky2);
2320 sky2_up(dev);
2321 }
2322 2347
2323 return 0; 2348 return 0;
2324} 2349}
@@ -2389,17 +2414,11 @@ static u32 sky2_get_msglevel(struct net_device *netdev)
2389static int sky2_nway_reset(struct net_device *dev) 2414static int sky2_nway_reset(struct net_device *dev)
2390{ 2415{
2391 struct sky2_port *sky2 = netdev_priv(dev); 2416 struct sky2_port *sky2 = netdev_priv(dev);
2392 struct sky2_hw *hw = sky2->hw;
2393 2417
2394 if (sky2->autoneg != AUTONEG_ENABLE) 2418 if (sky2->autoneg != AUTONEG_ENABLE)
2395 return -EINVAL; 2419 return -EINVAL;
2396 2420
2397 netif_stop_queue(dev); 2421 sky2_phy_reinit(sky2);
2398
2399 down(&sky2->phy_sema);
2400 sky2_phy_reset(hw, sky2->port);
2401 sky2_phy_init(hw, sky2->port);
2402 up(&sky2->phy_sema);
2403 2422
2404 return 0; 2423 return 0;
2405} 2424}
@@ -2477,20 +2496,20 @@ static int sky2_set_mac_address(struct net_device *dev, void *p)
2477{ 2496{
2478 struct sky2_port *sky2 = netdev_priv(dev); 2497 struct sky2_port *sky2 = netdev_priv(dev);
2479 struct sockaddr *addr = p; 2498 struct sockaddr *addr = p;
2480 int err = 0;
2481 2499
2482 if (!is_valid_ether_addr(addr->sa_data)) 2500 if (!is_valid_ether_addr(addr->sa_data))
2483 return -EADDRNOTAVAIL; 2501 return -EADDRNOTAVAIL;
2484 2502
2485 sky2_down(dev);
2486 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); 2503 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
2487 memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8, 2504 memcpy_toio(sky2->hw->regs + B2_MAC_1 + sky2->port * 8,
2488 dev->dev_addr, ETH_ALEN); 2505 dev->dev_addr, ETH_ALEN);
2489 memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8, 2506 memcpy_toio(sky2->hw->regs + B2_MAC_2 + sky2->port * 8,
2490 dev->dev_addr, ETH_ALEN); 2507 dev->dev_addr, ETH_ALEN);
2491 if (dev->flags & IFF_UP) 2508
2492 err = sky2_up(dev); 2509 if (netif_running(dev))
2493 return err; 2510 sky2_phy_reinit(sky2);
2511
2512 return 0;
2494} 2513}
2495 2514
2496static void sky2_set_multicast(struct net_device *dev) 2515static void sky2_set_multicast(struct net_device *dev)
@@ -2648,10 +2667,7 @@ static int sky2_set_pauseparam(struct net_device *dev,
2648 sky2->tx_pause = ecmd->tx_pause != 0; 2667 sky2->tx_pause = ecmd->tx_pause != 0;
2649 sky2->rx_pause = ecmd->rx_pause != 0; 2668 sky2->rx_pause = ecmd->rx_pause != 0;
2650 2669
2651 if (netif_running(dev)) { 2670 sky2_phy_reinit(sky2);
2652 sky2_down(dev);
2653 err = sky2_up(dev);
2654 }
2655 2671
2656 return err; 2672 return err;
2657} 2673}
@@ -2813,8 +2829,11 @@ static int sky2_set_ringparam(struct net_device *dev,
2813 sky2->rx_pending = ering->rx_pending; 2829 sky2->rx_pending = ering->rx_pending;
2814 sky2->tx_pending = ering->tx_pending; 2830 sky2->tx_pending = ering->tx_pending;
2815 2831
2816 if (netif_running(dev)) 2832 if (netif_running(dev)) {
2817 err = sky2_up(dev); 2833 err = sky2_up(dev);
2834 if (err)
2835 dev_close(dev);
2836 }
2818 2837
2819 return err; 2838 return err;
2820} 2839}
@@ -3195,7 +3214,8 @@ static int sky2_resume(struct pci_dev *pdev)
3195 if (dev) { 3214 if (dev) {
3196 if (netif_running(dev)) { 3215 if (netif_running(dev)) {
3197 netif_device_attach(dev); 3216 netif_device_attach(dev);
3198 sky2_up(dev); 3217 if (sky2_up(dev))
3218 dev_close(dev);
3199 } 3219 }
3200 } 3220 }
3201 } 3221 }