aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2005-06-24 23:20:04 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-24 23:20:04 -0400
commitbbe832c09233738c100145fd535b6b8fc97640f6 (patch)
treea4c9b8ec06c768a5808018d1b9a1b919c223199c /drivers/net
parentf47c11eeccc8820010992eb32dbe7370a08f8bd3 (diff)
[TG3]: Refinements to new locking strategy.
1. Move tp->irq_sync = 0 to before the interrupt mailbox IO in tg3_enable_ints() so that the interrupt handler will always see irq_sync == 0 when interrupts are enabled. 2. Remove the tg3_enable_ints() call in tg3_reset_hw(). Interrupts are always enabled explicitly or through tg3_netif_start(). This is to prevent interrupts being enabled while poll is disabled. 3. Update trans_start with jiffies in tg3_netif_stop() to prevent false NETDEV WATCHDOG. 4. Pass in the proper irq_sync parameter to tg3_full_lock() depending on netif_running() in some of the ethtool set calls. Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/tg3.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 8b8aa2ad578b..04e747aa1a86 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -430,12 +430,14 @@ static inline void tg3_cond_int(struct tg3 *tp)
430 430
431static void tg3_enable_ints(struct tg3 *tp) 431static void tg3_enable_ints(struct tg3 *tp)
432{ 432{
433 tp->irq_sync = 0;
434 wmb();
435
433 tw32(TG3PCI_MISC_HOST_CTRL, 436 tw32(TG3PCI_MISC_HOST_CTRL,
434 (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT)); 437 (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
435 tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 438 tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
436 (tp->last_tag << 24)); 439 (tp->last_tag << 24));
437 tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW); 440 tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
438 tp->irq_sync = 0;
439 tg3_cond_int(tp); 441 tg3_cond_int(tp);
440} 442}
441 443
@@ -484,6 +486,7 @@ static void tg3_restart_ints(struct tg3 *tp)
484 486
485static inline void tg3_netif_stop(struct tg3 *tp) 487static inline void tg3_netif_stop(struct tg3 *tp)
486{ 488{
489 tp->dev->trans_start = jiffies; /* prevent tx timeout */
487 netif_poll_disable(tp->dev); 490 netif_poll_disable(tp->dev);
488 netif_tx_disable(tp->dev); 491 netif_tx_disable(tp->dev);
489} 492}
@@ -5724,9 +5727,6 @@ static int tg3_reset_hw(struct tg3 *tp)
5724 5727
5725 tg3_write_sig_post_reset(tp, RESET_KIND_INIT); 5728 tg3_write_sig_post_reset(tp, RESET_KIND_INIT);
5726 5729
5727 if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)
5728 tg3_enable_ints(tp);
5729
5730 return 0; 5730 return 0;
5731} 5731}
5732 5732
@@ -7076,16 +7076,19 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
7076static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) 7076static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
7077{ 7077{
7078 struct tg3 *tp = netdev_priv(dev); 7078 struct tg3 *tp = netdev_priv(dev);
7079 int irq_sync = 0;
7079 7080
7080 if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || 7081 if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
7081 (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || 7082 (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
7082 (ering->tx_pending > TG3_TX_RING_SIZE - 1)) 7083 (ering->tx_pending > TG3_TX_RING_SIZE - 1))
7083 return -EINVAL; 7084 return -EINVAL;
7084 7085
7085 if (netif_running(dev)) 7086 if (netif_running(dev)) {
7086 tg3_netif_stop(tp); 7087 tg3_netif_stop(tp);
7088 irq_sync = 1;
7089 }
7087 7090
7088 tg3_full_lock(tp, 0); 7091 tg3_full_lock(tp, irq_sync);
7089 7092
7090 tp->rx_pending = ering->rx_pending; 7093 tp->rx_pending = ering->rx_pending;
7091 7094
@@ -7118,11 +7121,14 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
7118static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause) 7121static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
7119{ 7122{
7120 struct tg3 *tp = netdev_priv(dev); 7123 struct tg3 *tp = netdev_priv(dev);
7124 int irq_sync = 0;
7121 7125
7122 if (netif_running(dev)) 7126 if (netif_running(dev)) {
7123 tg3_netif_stop(tp); 7127 tg3_netif_stop(tp);
7128 irq_sync = 1;
7129 }
7124 7130
7125 tg3_full_lock(tp, 1); 7131 tg3_full_lock(tp, irq_sync);
7126 7132
7127 if (epause->autoneg) 7133 if (epause->autoneg)
7128 tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; 7134 tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
@@ -7578,8 +7584,6 @@ static int tg3_test_loopback(struct tg3 *tp)
7578 7584
7579 tg3_abort_hw(tp, 1); 7585 tg3_abort_hw(tp, 1);
7580 7586
7581 /* Clearing this flag to keep interrupts disabled */
7582 tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
7583 tg3_reset_hw(tp); 7587 tg3_reset_hw(tp);
7584 7588
7585 mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | 7589 mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
@@ -7688,10 +7692,14 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
7688 data[1] = 1; 7692 data[1] = 1;
7689 } 7693 }
7690 if (etest->flags & ETH_TEST_FL_OFFLINE) { 7694 if (etest->flags & ETH_TEST_FL_OFFLINE) {
7691 if (netif_running(dev)) 7695 int irq_sync = 0;
7696
7697 if (netif_running(dev)) {
7692 tg3_netif_stop(tp); 7698 tg3_netif_stop(tp);
7699 irq_sync = 1;
7700 }
7693 7701
7694 tg3_full_lock(tp, 1); 7702 tg3_full_lock(tp, irq_sync);
7695 7703
7696 tg3_halt(tp, RESET_KIND_SUSPEND, 1); 7704 tg3_halt(tp, RESET_KIND_SUSPEND, 1);
7697 tg3_nvram_lock(tp); 7705 tg3_nvram_lock(tp);
@@ -10184,8 +10192,6 @@ static int tg3_resume(struct pci_dev *pdev)
10184 tp->timer.expires = jiffies + tp->timer_offset; 10192 tp->timer.expires = jiffies + tp->timer_offset;
10185 add_timer(&tp->timer); 10193 add_timer(&tp->timer);
10186 10194
10187 tg3_enable_ints(tp);
10188
10189 tg3_netif_start(tp); 10195 tg3_netif_start(tp);
10190 10196
10191 tg3_full_unlock(tp); 10197 tg3_full_unlock(tp);