aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000/e1000_ethtool.c
diff options
context:
space:
mode:
authorAuke Kok <auke-jan.h.kok@intel.com>2006-06-27 12:06:28 -0400
committerAuke Kok <juke-jan.h.kok@intel.com>2006-06-27 12:06:28 -0400
commit2db10a081c5c1082d58809a1bcf1a6073f4db160 (patch)
treef54772ef60f2c5bf5f8d602a83d6dc508158a0e0 /drivers/net/e1000/e1000_ethtool.c
parentacfbc9fde2ec7f304398f6ad7644002e07bf84bc (diff)
e1000: rework driver hardware reset locking
After studying the driver mac reset code it was found that there were multiple race conditions possible to reset the unit twice or bring it e1000_up() double. This fixes all occurences where the driver needs to reset the mac. We also remove irq requesting/releasing into _open and _close so that while the device is _up we will never touch the irq's. This fixes the double free irq bug that people saw. To make sure that the watchdog task doesn't cause another race we let it run as a non-scheduled task. Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Diffstat (limited to 'drivers/net/e1000/e1000_ethtool.c')
-rw-r--r--drivers/net/e1000/e1000_ethtool.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 845d293b2f6a..cf5c5f46341f 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -203,11 +203,9 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
203 203
204 /* reset the link */ 204 /* reset the link */
205 205
206 if (netif_running(adapter->netdev)) { 206 if (netif_running(adapter->netdev))
207 e1000_down(adapter); 207 e1000_reinit_locked(adapter);
208 e1000_reset(adapter); 208 else
209 e1000_up(adapter);
210 } else
211 e1000_reset(adapter); 209 e1000_reset(adapter);
212 210
213 return 0; 211 return 0;
@@ -254,10 +252,9 @@ e1000_set_pauseparam(struct net_device *netdev,
254 hw->original_fc = hw->fc; 252 hw->original_fc = hw->fc;
255 253
256 if (adapter->fc_autoneg == AUTONEG_ENABLE) { 254 if (adapter->fc_autoneg == AUTONEG_ENABLE) {
257 if (netif_running(adapter->netdev)) { 255 if (netif_running(adapter->netdev))
258 e1000_down(adapter); 256 e1000_reinit_locked(adapter);
259 e1000_up(adapter); 257 else
260 } else
261 e1000_reset(adapter); 258 e1000_reset(adapter);
262 } else 259 } else
263 return ((hw->media_type == e1000_media_type_fiber) ? 260 return ((hw->media_type == e1000_media_type_fiber) ?
@@ -279,10 +276,9 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
279 struct e1000_adapter *adapter = netdev_priv(netdev); 276 struct e1000_adapter *adapter = netdev_priv(netdev);
280 adapter->rx_csum = data; 277 adapter->rx_csum = data;
281 278
282 if (netif_running(netdev)) { 279 if (netif_running(netdev))
283 e1000_down(adapter); 280 e1000_reinit_locked(adapter);
284 e1000_up(adapter); 281 else
285 } else
286 e1000_reset(adapter); 282 e1000_reset(adapter);
287 return 0; 283 return 0;
288} 284}
@@ -631,6 +627,9 @@ e1000_set_ringparam(struct net_device *netdev,
631 tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues; 627 tx_ring_size = sizeof(struct e1000_tx_ring) * adapter->num_tx_queues;
632 rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues; 628 rx_ring_size = sizeof(struct e1000_rx_ring) * adapter->num_rx_queues;
633 629
630 while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
631 msleep(1);
632
634 if (netif_running(adapter->netdev)) 633 if (netif_running(adapter->netdev))
635 e1000_down(adapter); 634 e1000_down(adapter);
636 635
@@ -691,9 +690,11 @@ e1000_set_ringparam(struct net_device *netdev,
691 adapter->rx_ring = rx_new; 690 adapter->rx_ring = rx_new;
692 adapter->tx_ring = tx_new; 691 adapter->tx_ring = tx_new;
693 if ((err = e1000_up(adapter))) 692 if ((err = e1000_up(adapter)))
694 return err; 693 goto err_setup;
695 } 694 }
696 695
696 clear_bit(__E1000_RESETTING, &adapter->flags);
697
697 return 0; 698 return 0;
698err_setup_tx: 699err_setup_tx:
699 e1000_free_all_rx_resources(adapter); 700 e1000_free_all_rx_resources(adapter);
@@ -701,6 +702,8 @@ err_setup_rx:
701 adapter->rx_ring = rx_old; 702 adapter->rx_ring = rx_old;
702 adapter->tx_ring = tx_old; 703 adapter->tx_ring = tx_old;
703 e1000_up(adapter); 704 e1000_up(adapter);
705err_setup:
706 clear_bit(__E1000_RESETTING, &adapter->flags);
704 return err; 707 return err;
705} 708}
706 709
@@ -1568,6 +1571,7 @@ e1000_diag_test(struct net_device *netdev,
1568 struct e1000_adapter *adapter = netdev_priv(netdev); 1571 struct e1000_adapter *adapter = netdev_priv(netdev);
1569 boolean_t if_running = netif_running(netdev); 1572 boolean_t if_running = netif_running(netdev);
1570 1573
1574 set_bit(__E1000_DRIVER_TESTING, &adapter->flags);
1571 if (eth_test->flags == ETH_TEST_FL_OFFLINE) { 1575 if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
1572 /* Offline tests */ 1576 /* Offline tests */
1573 1577
@@ -1582,7 +1586,8 @@ e1000_diag_test(struct net_device *netdev,
1582 eth_test->flags |= ETH_TEST_FL_FAILED; 1586 eth_test->flags |= ETH_TEST_FL_FAILED;
1583 1587
1584 if (if_running) 1588 if (if_running)
1585 e1000_down(adapter); 1589 /* indicate we're in test mode */
1590 dev_close(netdev);
1586 else 1591 else
1587 e1000_reset(adapter); 1592 e1000_reset(adapter);
1588 1593
@@ -1607,8 +1612,9 @@ e1000_diag_test(struct net_device *netdev,
1607 adapter->hw.autoneg = autoneg; 1612 adapter->hw.autoneg = autoneg;
1608 1613
1609 e1000_reset(adapter); 1614 e1000_reset(adapter);
1615 clear_bit(__E1000_DRIVER_TESTING, &adapter->flags);
1610 if (if_running) 1616 if (if_running)
1611 e1000_up(adapter); 1617 dev_open(netdev);
1612 } else { 1618 } else {
1613 /* Online tests */ 1619 /* Online tests */
1614 if (e1000_link_test(adapter, &data[4])) 1620 if (e1000_link_test(adapter, &data[4]))
@@ -1619,6 +1625,8 @@ e1000_diag_test(struct net_device *netdev,
1619 data[1] = 0; 1625 data[1] = 0;
1620 data[2] = 0; 1626 data[2] = 0;
1621 data[3] = 0; 1627 data[3] = 0;
1628
1629 clear_bit(__E1000_DRIVER_TESTING, &adapter->flags);
1622 } 1630 }
1623 msleep_interruptible(4 * 1000); 1631 msleep_interruptible(4 * 1000);
1624} 1632}
@@ -1807,10 +1815,8 @@ static int
1807e1000_nway_reset(struct net_device *netdev) 1815e1000_nway_reset(struct net_device *netdev)
1808{ 1816{
1809 struct e1000_adapter *adapter = netdev_priv(netdev); 1817 struct e1000_adapter *adapter = netdev_priv(netdev);
1810 if (netif_running(netdev)) { 1818 if (netif_running(netdev))
1811 e1000_down(adapter); 1819 e1000_reinit_locked(adapter);
1812 e1000_up(adapter);
1813 }
1814 return 0; 1820 return 0;
1815} 1821}
1816 1822