diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2009-08-14 18:31:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-14 18:31:25 -0400 |
commit | af18d8b89930aecc742982634adaf97dfb43ed3b (patch) | |
tree | 3492278988d8842c16c72c82bfa26a09e7d0c8c7 /drivers/net/sky2.c | |
parent | 19720737187aaee006afb20e63be5e9eddc505a8 (diff) |
sky2: cleanup restart operations
This unifies the places that bounce the device (suspend/resume
and restart). And makes the operations have the same semantics
as normal dev_open/dev_stop.
This also avoids setting the multicast addresses twice when
device is brought up.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 95 |
1 files changed, 48 insertions, 47 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3ae4b42fe4d7..301f8a6f8c08 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -1500,13 +1500,12 @@ static int sky2_up(struct net_device *dev) | |||
1500 | sky2_write32(hw, B0_IMSK, imask); | 1500 | sky2_write32(hw, B0_IMSK, imask); |
1501 | sky2_read32(hw, B0_IMSK); | 1501 | sky2_read32(hw, B0_IMSK); |
1502 | 1502 | ||
1503 | sky2_set_multicast(dev); | ||
1504 | |||
1505 | /* wake queue incase we are restarting */ | 1503 | /* wake queue incase we are restarting */ |
1506 | netif_wake_queue(dev); | 1504 | netif_wake_queue(dev); |
1507 | 1505 | ||
1508 | if (netif_msg_ifup(sky2)) | 1506 | if (netif_msg_ifup(sky2)) |
1509 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); | 1507 | printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); |
1508 | |||
1510 | return 0; | 1509 | return 0; |
1511 | 1510 | ||
1512 | err_out: | 1511 | err_out: |
@@ -3087,18 +3086,46 @@ static void sky2_reset(struct sky2_hw *hw) | |||
3087 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); | 3086 | sky2_write8(hw, STAT_ISR_TIMER_CTRL, TIM_START); |
3088 | } | 3087 | } |
3089 | 3088 | ||
3089 | /* Take device down (offline). | ||
3090 | * Equivalent to doing dev_stop() but this does not | ||
3091 | * inform upper layers of the transistion. | ||
3092 | */ | ||
3093 | static void sky2_detach(struct net_device *dev) | ||
3094 | { | ||
3095 | if (netif_running(dev)) { | ||
3096 | netif_device_detach(dev); /* stop txq */ | ||
3097 | sky2_down(dev); | ||
3098 | } | ||
3099 | } | ||
3100 | |||
3101 | /* Bring device back after doing sky2_detach */ | ||
3102 | static int sky2_reattach(struct net_device *dev) | ||
3103 | { | ||
3104 | int err = 0; | ||
3105 | |||
3106 | if (netif_running(dev)) { | ||
3107 | err = sky2_up(dev); | ||
3108 | if (err) { | ||
3109 | printk(KERN_INFO PFX "%s: could not restart %d\n", | ||
3110 | dev->name, err); | ||
3111 | dev_close(dev); | ||
3112 | } else { | ||
3113 | netif_device_attach(dev); | ||
3114 | sky2_set_multicast(dev); | ||
3115 | } | ||
3116 | } | ||
3117 | |||
3118 | return err; | ||
3119 | } | ||
3120 | |||
3090 | static void sky2_restart(struct work_struct *work) | 3121 | static void sky2_restart(struct work_struct *work) |
3091 | { | 3122 | { |
3092 | struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work); | 3123 | struct sky2_hw *hw = container_of(work, struct sky2_hw, restart_work); |
3093 | struct net_device *dev; | 3124 | int i; |
3094 | int i, err; | ||
3095 | 3125 | ||
3096 | rtnl_lock(); | 3126 | rtnl_lock(); |
3097 | for (i = 0; i < hw->ports; i++) { | 3127 | for (i = 0; i < hw->ports; i++) |
3098 | dev = hw->dev[i]; | 3128 | sky2_detach(hw->dev[i]); |
3099 | if (netif_running(dev)) | ||
3100 | sky2_down(dev); | ||
3101 | } | ||
3102 | 3129 | ||
3103 | napi_disable(&hw->napi); | 3130 | napi_disable(&hw->napi); |
3104 | sky2_write32(hw, B0_IMSK, 0); | 3131 | sky2_write32(hw, B0_IMSK, 0); |
@@ -3106,17 +3133,8 @@ static void sky2_restart(struct work_struct *work) | |||
3106 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3133 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3107 | napi_enable(&hw->napi); | 3134 | napi_enable(&hw->napi); |
3108 | 3135 | ||
3109 | for (i = 0; i < hw->ports; i++) { | 3136 | for (i = 0; i < hw->ports; i++) |
3110 | dev = hw->dev[i]; | 3137 | sky2_reattach(hw->dev[i]); |
3111 | if (netif_running(dev)) { | ||
3112 | err = sky2_up(dev); | ||
3113 | if (err) { | ||
3114 | printk(KERN_INFO PFX "%s: could not restart %d\n", | ||
3115 | dev->name, err); | ||
3116 | dev_close(dev); | ||
3117 | } | ||
3118 | } | ||
3119 | } | ||
3120 | 3138 | ||
3121 | rtnl_unlock(); | 3139 | rtnl_unlock(); |
3122 | } | 3140 | } |
@@ -3705,7 +3723,6 @@ static int sky2_set_ringparam(struct net_device *dev, | |||
3705 | struct ethtool_ringparam *ering) | 3723 | struct ethtool_ringparam *ering) |
3706 | { | 3724 | { |
3707 | struct sky2_port *sky2 = netdev_priv(dev); | 3725 | struct sky2_port *sky2 = netdev_priv(dev); |
3708 | int err = 0; | ||
3709 | 3726 | ||
3710 | if (ering->rx_pending > RX_MAX_PENDING || | 3727 | if (ering->rx_pending > RX_MAX_PENDING || |
3711 | ering->rx_pending < 8 || | 3728 | ering->rx_pending < 8 || |
@@ -3713,19 +3730,12 @@ static int sky2_set_ringparam(struct net_device *dev, | |||
3713 | ering->tx_pending > TX_RING_SIZE - 1) | 3730 | ering->tx_pending > TX_RING_SIZE - 1) |
3714 | return -EINVAL; | 3731 | return -EINVAL; |
3715 | 3732 | ||
3716 | if (netif_running(dev)) | 3733 | sky2_detach(dev); |
3717 | sky2_down(dev); | ||
3718 | 3734 | ||
3719 | sky2->rx_pending = ering->rx_pending; | 3735 | sky2->rx_pending = ering->rx_pending; |
3720 | sky2->tx_pending = ering->tx_pending; | 3736 | sky2->tx_pending = ering->tx_pending; |
3721 | 3737 | ||
3722 | if (netif_running(dev)) { | 3738 | return sky2_reattach(dev); |
3723 | err = sky2_up(dev); | ||
3724 | if (err) | ||
3725 | dev_close(dev); | ||
3726 | } | ||
3727 | |||
3728 | return err; | ||
3729 | } | 3739 | } |
3730 | 3740 | ||
3731 | static int sky2_get_regs_len(struct net_device *dev) | 3741 | static int sky2_get_regs_len(struct net_device *dev) |
@@ -4648,9 +4658,7 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4648 | struct net_device *dev = hw->dev[i]; | 4658 | struct net_device *dev = hw->dev[i]; |
4649 | struct sky2_port *sky2 = netdev_priv(dev); | 4659 | struct sky2_port *sky2 = netdev_priv(dev); |
4650 | 4660 | ||
4651 | netif_device_detach(dev); | 4661 | sky2_detach(dev); |
4652 | if (netif_running(dev)) | ||
4653 | sky2_down(dev); | ||
4654 | 4662 | ||
4655 | if (sky2->wol) | 4663 | if (sky2->wol) |
4656 | sky2_wol_init(sky2); | 4664 | sky2_wol_init(sky2); |
@@ -4698,25 +4706,18 @@ static int sky2_resume(struct pci_dev *pdev) | |||
4698 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 4706 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
4699 | napi_enable(&hw->napi); | 4707 | napi_enable(&hw->napi); |
4700 | 4708 | ||
4709 | rtnl_lock(); | ||
4701 | for (i = 0; i < hw->ports; i++) { | 4710 | for (i = 0; i < hw->ports; i++) { |
4702 | struct net_device *dev = hw->dev[i]; | 4711 | err = sky2_reattach(hw->dev[i]); |
4703 | 4712 | if (err) | |
4704 | netif_device_attach(dev); | 4713 | goto out; |
4705 | if (netif_running(dev)) { | ||
4706 | err = sky2_up(dev); | ||
4707 | if (err) { | ||
4708 | printk(KERN_ERR PFX "%s: could not up: %d\n", | ||
4709 | dev->name, err); | ||
4710 | rtnl_lock(); | ||
4711 | dev_close(dev); | ||
4712 | rtnl_unlock(); | ||
4713 | goto out; | ||
4714 | } | ||
4715 | } | ||
4716 | } | 4714 | } |
4715 | rtnl_unlock(); | ||
4717 | 4716 | ||
4718 | return 0; | 4717 | return 0; |
4719 | out: | 4718 | out: |
4719 | rtnl_unlock(); | ||
4720 | |||
4720 | dev_err(&pdev->dev, "resume failed (%d)\n", err); | 4721 | dev_err(&pdev->dev, "resume failed (%d)\n", err); |
4721 | pci_disable_device(pdev); | 4722 | pci_disable_device(pdev); |
4722 | return err; | 4723 | return err; |