aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2006-07-25 19:37:27 -0400
committerDavid S. Miller <davem@davemloft.net>2006-07-25 19:37:27 -0400
commitb9ec6c1b917e2e43a058a78198d54aeca3d71c6f (patch)
tree8dee4fc5d024525b8b32c99c123ef58eb64b4686 /drivers
parentd569f1d72f068992d07ab17f7ff9aea7f0d97cdb (diff)
[TG3]: Add tg3_restart_hw()
Add tg3_restart_hw() to handle failures when re-initializing the device. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/tg3.c80
1 files changed, 58 insertions, 22 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ce6f3be86da0..1253cec6ebdc 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -3590,6 +3590,28 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
3590static int tg3_init_hw(struct tg3 *, int); 3590static int tg3_init_hw(struct tg3 *, int);
3591static int tg3_halt(struct tg3 *, int, int); 3591static int tg3_halt(struct tg3 *, int, int);
3592 3592
3593/* Restart hardware after configuration changes, self-test, etc.
3594 * Invoked with tp->lock held.
3595 */
3596static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
3597{
3598 int err;
3599
3600 err = tg3_init_hw(tp, reset_phy);
3601 if (err) {
3602 printk(KERN_ERR PFX "%s: Failed to re-initialize device, "
3603 "aborting.\n", tp->dev->name);
3604 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
3605 tg3_full_unlock(tp);
3606 del_timer_sync(&tp->timer);
3607 tp->irq_sync = 0;
3608 netif_poll_enable(tp->dev);
3609 dev_close(tp->dev);
3610 tg3_full_lock(tp, 0);
3611 }
3612 return err;
3613}
3614
3593#ifdef CONFIG_NET_POLL_CONTROLLER 3615#ifdef CONFIG_NET_POLL_CONTROLLER
3594static void tg3_poll_controller(struct net_device *dev) 3616static void tg3_poll_controller(struct net_device *dev)
3595{ 3617{
@@ -3630,13 +3652,15 @@ static void tg3_reset_task(void *_data)
3630 } 3652 }
3631 3653
3632 tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); 3654 tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
3633 tg3_init_hw(tp, 1); 3655 if (tg3_init_hw(tp, 1))
3656 goto out;
3634 3657
3635 tg3_netif_start(tp); 3658 tg3_netif_start(tp);
3636 3659
3637 if (restart_timer) 3660 if (restart_timer)
3638 mod_timer(&tp->timer, jiffies + 1); 3661 mod_timer(&tp->timer, jiffies + 1);
3639 3662
3663out:
3640 tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; 3664 tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK;
3641 3665
3642 tg3_full_unlock(tp); 3666 tg3_full_unlock(tp);
@@ -4124,6 +4148,7 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
4124static int tg3_change_mtu(struct net_device *dev, int new_mtu) 4148static int tg3_change_mtu(struct net_device *dev, int new_mtu)
4125{ 4149{
4126 struct tg3 *tp = netdev_priv(dev); 4150 struct tg3 *tp = netdev_priv(dev);
4151 int err;
4127 4152
4128 if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp)) 4153 if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
4129 return -EINVAL; 4154 return -EINVAL;
@@ -4144,13 +4169,14 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
4144 4169
4145 tg3_set_mtu(dev, tp, new_mtu); 4170 tg3_set_mtu(dev, tp, new_mtu);
4146 4171
4147 tg3_init_hw(tp, 0); 4172 err = tg3_restart_hw(tp, 0);
4148 4173
4149 tg3_netif_start(tp); 4174 if (!err)
4175 tg3_netif_start(tp);
4150 4176
4151 tg3_full_unlock(tp); 4177 tg3_full_unlock(tp);
4152 4178
4153 return 0; 4179 return err;
4154} 4180}
4155 4181
4156/* Free up pending packets in all rx/tx rings. 4182/* Free up pending packets in all rx/tx rings.
@@ -5815,6 +5841,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
5815{ 5841{
5816 struct tg3 *tp = netdev_priv(dev); 5842 struct tg3 *tp = netdev_priv(dev);
5817 struct sockaddr *addr = p; 5843 struct sockaddr *addr = p;
5844 int err = 0;
5818 5845
5819 if (!is_valid_ether_addr(addr->sa_data)) 5846 if (!is_valid_ether_addr(addr->sa_data))
5820 return -EINVAL; 5847 return -EINVAL;
@@ -5832,9 +5859,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
5832 tg3_full_lock(tp, 1); 5859 tg3_full_lock(tp, 1);
5833 5860
5834 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); 5861 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
5835 tg3_init_hw(tp, 0); 5862 err = tg3_restart_hw(tp, 0);
5836 5863 if (!err)
5837 tg3_netif_start(tp); 5864 tg3_netif_start(tp);
5838 tg3_full_unlock(tp); 5865 tg3_full_unlock(tp);
5839 } else { 5866 } else {
5840 spin_lock_bh(&tp->lock); 5867 spin_lock_bh(&tp->lock);
@@ -5842,7 +5869,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
5842 spin_unlock_bh(&tp->lock); 5869 spin_unlock_bh(&tp->lock);
5843 } 5870 }
5844 5871
5845 return 0; 5872 return err;
5846} 5873}
5847 5874
5848/* tp->lock is held. */ 5875/* tp->lock is held. */
@@ -7956,7 +7983,7 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
7956static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) 7983static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
7957{ 7984{
7958 struct tg3 *tp = netdev_priv(dev); 7985 struct tg3 *tp = netdev_priv(dev);
7959 int irq_sync = 0; 7986 int irq_sync = 0, err = 0;
7960 7987
7961 if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || 7988 if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
7962 (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || 7989 (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
@@ -7980,13 +8007,14 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
7980 8007
7981 if (netif_running(dev)) { 8008 if (netif_running(dev)) {
7982 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); 8009 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
7983 tg3_init_hw(tp, 1); 8010 err = tg3_restart_hw(tp, 1);
7984 tg3_netif_start(tp); 8011 if (!err)
8012 tg3_netif_start(tp);
7985 } 8013 }
7986 8014
7987 tg3_full_unlock(tp); 8015 tg3_full_unlock(tp);
7988 8016
7989 return 0; 8017 return err;
7990} 8018}
7991 8019
7992static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) 8020static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
@@ -8001,7 +8029,7 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
8001static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) 8029static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
8002{ 8030{
8003 struct tg3 *tp = netdev_priv(dev); 8031 struct tg3 *tp = netdev_priv(dev);
8004 int irq_sync = 0; 8032 int irq_sync = 0, err = 0;
8005 8033
8006 if (netif_running(dev)) { 8034 if (netif_running(dev)) {
8007 tg3_netif_stop(tp); 8035 tg3_netif_stop(tp);
@@ -8025,13 +8053,14 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
8025 8053
8026 if (netif_running(dev)) { 8054 if (netif_running(dev)) {
8027 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); 8055 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
8028 tg3_init_hw(tp, 1); 8056 err = tg3_restart_hw(tp, 1);
8029 tg3_netif_start(tp); 8057 if (!err)
8058 tg3_netif_start(tp);
8030 } 8059 }
8031 8060
8032 tg3_full_unlock(tp); 8061 tg3_full_unlock(tp);
8033 8062
8034 return 0; 8063 return err;
8035} 8064}
8036 8065
8037static u32 tg3_get_rx_csum(struct net_device *dev) 8066static u32 tg3_get_rx_csum(struct net_device *dev)
@@ -8666,7 +8695,9 @@ static int tg3_test_loopback(struct tg3 *tp)
8666 if (!netif_running(tp->dev)) 8695 if (!netif_running(tp->dev))
8667 return TG3_LOOPBACK_FAILED; 8696 return TG3_LOOPBACK_FAILED;
8668 8697
8669 tg3_reset_hw(tp, 1); 8698 err = tg3_reset_hw(tp, 1);
8699 if (err)
8700 return TG3_LOOPBACK_FAILED;
8670 8701
8671 if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) 8702 if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
8672 err |= TG3_MAC_LOOPBACK_FAILED; 8703 err |= TG3_MAC_LOOPBACK_FAILED;
@@ -8740,8 +8771,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
8740 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); 8771 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
8741 if (netif_running(dev)) { 8772 if (netif_running(dev)) {
8742 tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; 8773 tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
8743 tg3_init_hw(tp, 1); 8774 if (!tg3_restart_hw(tp, 1))
8744 tg3_netif_start(tp); 8775 tg3_netif_start(tp);
8745 } 8776 }
8746 8777
8747 tg3_full_unlock(tp); 8778 tg3_full_unlock(tp);
@@ -11699,7 +11730,8 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
11699 tg3_full_lock(tp, 0); 11730 tg3_full_lock(tp, 0);
11700 11731
11701 tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; 11732 tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
11702 tg3_init_hw(tp, 1); 11733 if (tg3_restart_hw(tp, 1))
11734 goto out;
11703 11735
11704 tp->timer.expires = jiffies + tp->timer_offset; 11736 tp->timer.expires = jiffies + tp->timer_offset;
11705 add_timer(&tp->timer); 11737 add_timer(&tp->timer);
@@ -11707,6 +11739,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
11707 netif_device_attach(dev); 11739 netif_device_attach(dev);
11708 tg3_netif_start(tp); 11740 tg3_netif_start(tp);
11709 11741
11742out:
11710 tg3_full_unlock(tp); 11743 tg3_full_unlock(tp);
11711 } 11744 }
11712 11745
@@ -11733,16 +11766,19 @@ static int tg3_resume(struct pci_dev *pdev)
11733 tg3_full_lock(tp, 0); 11766 tg3_full_lock(tp, 0);
11734 11767
11735 tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; 11768 tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
11736 tg3_init_hw(tp, 1); 11769 err = tg3_restart_hw(tp, 1);
11770 if (err)
11771 goto out;
11737 11772
11738 tp->timer.expires = jiffies + tp->timer_offset; 11773 tp->timer.expires = jiffies + tp->timer_offset;
11739 add_timer(&tp->timer); 11774 add_timer(&tp->timer);
11740 11775
11741 tg3_netif_start(tp); 11776 tg3_netif_start(tp);
11742 11777
11778out:
11743 tg3_full_unlock(tp); 11779 tg3_full_unlock(tp);
11744 11780
11745 return 0; 11781 return err;
11746} 11782}
11747 11783
11748static struct pci_driver tg3_driver = { 11784static struct pci_driver tg3_driver = {