diff options
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r-- | drivers/net/skge.c | 81 |
1 files changed, 50 insertions, 31 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 00d683063c01..b538e3038058 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -25,6 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/config.h> | 27 | #include <linux/config.h> |
28 | #include <linux/in.h> | ||
28 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
30 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
@@ -43,7 +44,7 @@ | |||
43 | #include "skge.h" | 44 | #include "skge.h" |
44 | 45 | ||
45 | #define DRV_NAME "skge" | 46 | #define DRV_NAME "skge" |
46 | #define DRV_VERSION "1.2" | 47 | #define DRV_VERSION "1.3" |
47 | #define PFX DRV_NAME " " | 48 | #define PFX DRV_NAME " " |
48 | 49 | ||
49 | #define DEFAULT_TX_RING_SIZE 128 | 50 | #define DEFAULT_TX_RING_SIZE 128 |
@@ -88,15 +89,14 @@ MODULE_DEVICE_TABLE(pci, skge_id_table); | |||
88 | 89 | ||
89 | static int skge_up(struct net_device *dev); | 90 | static int skge_up(struct net_device *dev); |
90 | static int skge_down(struct net_device *dev); | 91 | static int skge_down(struct net_device *dev); |
92 | static void skge_phy_reset(struct skge_port *skge); | ||
91 | static void skge_tx_clean(struct skge_port *skge); | 93 | static void skge_tx_clean(struct skge_port *skge); |
92 | static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); | 94 | static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); |
93 | static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); | 95 | static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); |
94 | static void genesis_get_stats(struct skge_port *skge, u64 *data); | 96 | static void genesis_get_stats(struct skge_port *skge, u64 *data); |
95 | static void yukon_get_stats(struct skge_port *skge, u64 *data); | 97 | static void yukon_get_stats(struct skge_port *skge, u64 *data); |
96 | static void yukon_init(struct skge_hw *hw, int port); | 98 | static void yukon_init(struct skge_hw *hw, int port); |
97 | static void yukon_reset(struct skge_hw *hw, int port); | ||
98 | static void genesis_mac_init(struct skge_hw *hw, int port); | 99 | static void genesis_mac_init(struct skge_hw *hw, int port); |
99 | static void genesis_reset(struct skge_hw *hw, int port); | ||
100 | static void genesis_link_up(struct skge_port *skge); | 100 | static void genesis_link_up(struct skge_port *skge); |
101 | 101 | ||
102 | /* Avoid conditionals by using array */ | 102 | /* Avoid conditionals by using array */ |
@@ -276,10 +276,9 @@ static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
276 | skge->autoneg = ecmd->autoneg; | 276 | skge->autoneg = ecmd->autoneg; |
277 | skge->advertising = ecmd->advertising; | 277 | skge->advertising = ecmd->advertising; |
278 | 278 | ||
279 | if (netif_running(dev)) { | 279 | if (netif_running(dev)) |
280 | skge_down(dev); | 280 | skge_phy_reset(skge); |
281 | skge_up(dev); | 281 | |
282 | } | ||
283 | return (0); | 282 | return (0); |
284 | } | 283 | } |
285 | 284 | ||
@@ -399,6 +398,7 @@ static int skge_set_ring_param(struct net_device *dev, | |||
399 | struct ethtool_ringparam *p) | 398 | struct ethtool_ringparam *p) |
400 | { | 399 | { |
401 | struct skge_port *skge = netdev_priv(dev); | 400 | struct skge_port *skge = netdev_priv(dev); |
401 | int err; | ||
402 | 402 | ||
403 | if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || | 403 | if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || |
404 | p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE) | 404 | p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE) |
@@ -409,7 +409,9 @@ static int skge_set_ring_param(struct net_device *dev, | |||
409 | 409 | ||
410 | if (netif_running(dev)) { | 410 | if (netif_running(dev)) { |
411 | skge_down(dev); | 411 | skge_down(dev); |
412 | skge_up(dev); | 412 | err = skge_up(dev); |
413 | if (err) | ||
414 | dev_close(dev); | ||
413 | } | 415 | } |
414 | 416 | ||
415 | return 0; | 417 | return 0; |
@@ -430,21 +432,11 @@ static void skge_set_msglevel(struct net_device *netdev, u32 value) | |||
430 | static int skge_nway_reset(struct net_device *dev) | 432 | static int skge_nway_reset(struct net_device *dev) |
431 | { | 433 | { |
432 | struct skge_port *skge = netdev_priv(dev); | 434 | struct skge_port *skge = netdev_priv(dev); |
433 | struct skge_hw *hw = skge->hw; | ||
434 | int port = skge->port; | ||
435 | 435 | ||
436 | if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev)) | 436 | if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev)) |
437 | return -EINVAL; | 437 | return -EINVAL; |
438 | 438 | ||
439 | spin_lock_bh(&hw->phy_lock); | 439 | skge_phy_reset(skge); |
440 | if (hw->chip_id == CHIP_ID_GENESIS) { | ||
441 | genesis_reset(hw, port); | ||
442 | genesis_mac_init(hw, port); | ||
443 | } else { | ||
444 | yukon_reset(hw, port); | ||
445 | yukon_init(hw, port); | ||
446 | } | ||
447 | spin_unlock_bh(&hw->phy_lock); | ||
448 | return 0; | 440 | return 0; |
449 | } | 441 | } |
450 | 442 | ||
@@ -516,10 +508,8 @@ static int skge_set_pauseparam(struct net_device *dev, | |||
516 | else | 508 | else |
517 | skge->flow_control = FLOW_MODE_NONE; | 509 | skge->flow_control = FLOW_MODE_NONE; |
518 | 510 | ||
519 | if (netif_running(dev)) { | 511 | if (netif_running(dev)) |
520 | skge_down(dev); | 512 | skge_phy_reset(skge); |
521 | skge_up(dev); | ||
522 | } | ||
523 | return 0; | 513 | return 0; |
524 | } | 514 | } |
525 | 515 | ||
@@ -2019,6 +2009,25 @@ static void yukon_phy_intr(struct skge_port *skge) | |||
2019 | /* XXX restart autonegotiation? */ | 2009 | /* XXX restart autonegotiation? */ |
2020 | } | 2010 | } |
2021 | 2011 | ||
2012 | static void skge_phy_reset(struct skge_port *skge) | ||
2013 | { | ||
2014 | struct skge_hw *hw = skge->hw; | ||
2015 | int port = skge->port; | ||
2016 | |||
2017 | netif_stop_queue(skge->netdev); | ||
2018 | netif_carrier_off(skge->netdev); | ||
2019 | |||
2020 | spin_lock_bh(&hw->phy_lock); | ||
2021 | if (hw->chip_id == CHIP_ID_GENESIS) { | ||
2022 | genesis_reset(hw, port); | ||
2023 | genesis_mac_init(hw, port); | ||
2024 | } else { | ||
2025 | yukon_reset(hw, port); | ||
2026 | yukon_init(hw, port); | ||
2027 | } | ||
2028 | spin_unlock_bh(&hw->phy_lock); | ||
2029 | } | ||
2030 | |||
2022 | /* Basic MII support */ | 2031 | /* Basic MII support */ |
2023 | static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 2032 | static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
2024 | { | 2033 | { |
@@ -2187,6 +2196,7 @@ static int skge_up(struct net_device *dev) | |||
2187 | kfree(skge->rx_ring.start); | 2196 | kfree(skge->rx_ring.start); |
2188 | free_pci_mem: | 2197 | free_pci_mem: |
2189 | pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); | 2198 | pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); |
2199 | skge->mem = NULL; | ||
2190 | 2200 | ||
2191 | return err; | 2201 | return err; |
2192 | } | 2202 | } |
@@ -2197,6 +2207,9 @@ static int skge_down(struct net_device *dev) | |||
2197 | struct skge_hw *hw = skge->hw; | 2207 | struct skge_hw *hw = skge->hw; |
2198 | int port = skge->port; | 2208 | int port = skge->port; |
2199 | 2209 | ||
2210 | if (skge->mem == NULL) | ||
2211 | return 0; | ||
2212 | |||
2200 | if (netif_msg_ifdown(skge)) | 2213 | if (netif_msg_ifdown(skge)) |
2201 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); | 2214 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); |
2202 | 2215 | ||
@@ -2253,6 +2266,7 @@ static int skge_down(struct net_device *dev) | |||
2253 | kfree(skge->rx_ring.start); | 2266 | kfree(skge->rx_ring.start); |
2254 | kfree(skge->tx_ring.start); | 2267 | kfree(skge->tx_ring.start); |
2255 | pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); | 2268 | pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); |
2269 | skge->mem = NULL; | ||
2256 | return 0; | 2270 | return 0; |
2257 | } | 2271 | } |
2258 | 2272 | ||
@@ -2413,18 +2427,23 @@ static void skge_tx_timeout(struct net_device *dev) | |||
2413 | 2427 | ||
2414 | static int skge_change_mtu(struct net_device *dev, int new_mtu) | 2428 | static int skge_change_mtu(struct net_device *dev, int new_mtu) |
2415 | { | 2429 | { |
2416 | int err = 0; | 2430 | int err; |
2417 | int running = netif_running(dev); | ||
2418 | 2431 | ||
2419 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) | 2432 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) |
2420 | return -EINVAL; | 2433 | return -EINVAL; |
2421 | 2434 | ||
2435 | if (!netif_running(dev)) { | ||
2436 | dev->mtu = new_mtu; | ||
2437 | return 0; | ||
2438 | } | ||
2439 | |||
2440 | skge_down(dev); | ||
2422 | 2441 | ||
2423 | if (running) | ||
2424 | skge_down(dev); | ||
2425 | dev->mtu = new_mtu; | 2442 | dev->mtu = new_mtu; |
2426 | if (running) | 2443 | |
2427 | skge_up(dev); | 2444 | err = skge_up(dev); |
2445 | if (err) | ||
2446 | dev_close(dev); | ||
2428 | 2447 | ||
2429 | return err; | 2448 | return err; |
2430 | } | 2449 | } |
@@ -3398,8 +3417,8 @@ static int skge_resume(struct pci_dev *pdev) | |||
3398 | struct net_device *dev = hw->dev[i]; | 3417 | struct net_device *dev = hw->dev[i]; |
3399 | if (dev) { | 3418 | if (dev) { |
3400 | netif_device_attach(dev); | 3419 | netif_device_attach(dev); |
3401 | if (netif_running(dev)) | 3420 | if (netif_running(dev) && skge_up(dev)) |
3402 | skge_up(dev); | 3421 | dev_close(dev); |
3403 | } | 3422 | } |
3404 | } | 3423 | } |
3405 | return 0; | 3424 | return 0; |