diff options
Diffstat (limited to 'drivers/net/sky2.c')
| -rw-r--r-- | drivers/net/sky2.c | 84 |
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 */ | ||
| 485 | static 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 | |||
| 484 | static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | 492 | static 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 | ||
| 1016 | err_out: | 1024 | err_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) | |||
| 2389 | static int sky2_nway_reset(struct net_device *dev) | 2414 | static 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 | ||
| 2496 | static void sky2_set_multicast(struct net_device *dev) | 2515 | static 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 | } |
