aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAyyappan Veeraiyan <ayyappan.veeraiyan@intel.com>2008-02-01 18:58:41 -0500
committerJeff Garzik <jeff@garzik.org>2008-02-05 13:31:31 -0500
commitd4f80882ee7bdc721230b9ac209ddd3a837e4545 (patch)
treeec7a096ac3c39c0d5cc5f32e88f8c7bf2f089e4c /drivers
parent06f7525be463ef95bfdba001484bda04d00ec74e (diff)
ixgbe: remove obsolete irq_sem, add driver state checking code
After testing we confirmed that the irq_sem can safely be removed from ixgbe. Add strict state checking code to various ethtool parts to properly protect against races between various driver reset paths. Signed-off-by: Ayyappan Veeraiyan <ayyappan.veeraiyan@intel.com> Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ixgbe/ixgbe.h2
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c29
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c60
3 files changed, 49 insertions, 42 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index a021a6e72641..7dd9a03650d3 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -174,7 +174,6 @@ struct ixgbe_adapter {
174 struct vlan_group *vlgrp; 174 struct vlan_group *vlgrp;
175 u16 bd_number; 175 u16 bd_number;
176 u16 rx_buf_len; 176 u16 rx_buf_len;
177 atomic_t irq_sem;
178 struct work_struct reset_task; 177 struct work_struct reset_task;
179 178
180 /* TX */ 179 /* TX */
@@ -244,6 +243,7 @@ extern const char ixgbe_driver_version[];
244 243
245extern int ixgbe_up(struct ixgbe_adapter *adapter); 244extern int ixgbe_up(struct ixgbe_adapter *adapter);
246extern void ixgbe_down(struct ixgbe_adapter *adapter); 245extern void ixgbe_down(struct ixgbe_adapter *adapter);
246extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
247extern void ixgbe_reset(struct ixgbe_adapter *adapter); 247extern void ixgbe_reset(struct ixgbe_adapter *adapter);
248extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); 248extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
249extern void ixgbe_set_ethtool_ops(struct net_device *netdev); 249extern void ixgbe_set_ethtool_ops(struct net_device *netdev);
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 36353447716d..9f3cdb873001 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -179,12 +179,10 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
179 179
180 hw->fc.original_type = hw->fc.type; 180 hw->fc.original_type = hw->fc.type;
181 181
182 if (netif_running(adapter->netdev)) { 182 if (netif_running(netdev))
183 ixgbe_down(adapter); 183 ixgbe_reinit_locked(adapter);
184 ixgbe_up(adapter); 184 else
185 } else {
186 ixgbe_reset(adapter); 185 ixgbe_reset(adapter);
187 }
188 186
189 return 0; 187 return 0;
190} 188}
@@ -203,12 +201,10 @@ static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data)
203 else 201 else
204 adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; 202 adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
205 203
206 if (netif_running(netdev)) { 204 if (netif_running(netdev))
207 ixgbe_down(adapter); 205 ixgbe_reinit_locked(adapter);
208 ixgbe_up(adapter); 206 else
209 } else {
210 ixgbe_reset(adapter); 207 ixgbe_reset(adapter);
211 }
212 208
213 return 0; 209 return 0;
214} 210}
@@ -662,7 +658,10 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
662 return 0; 658 return 0;
663 } 659 }
664 660
665 if (netif_running(adapter->netdev)) 661 while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
662 msleep(1);
663
664 if (netif_running(netdev))
666 ixgbe_down(adapter); 665 ixgbe_down(adapter);
667 666
668 /* 667 /*
@@ -733,6 +732,7 @@ err_setup:
733 if (netif_running(adapter->netdev)) 732 if (netif_running(adapter->netdev))
734 ixgbe_up(adapter); 733 ixgbe_up(adapter);
735 734
735 clear_bit(__IXGBE_RESETTING, &adapter->state);
736 return err; 736 return err;
737} 737}
738 738
@@ -820,11 +820,8 @@ static int ixgbe_nway_reset(struct net_device *netdev)
820{ 820{
821 struct ixgbe_adapter *adapter = netdev_priv(netdev); 821 struct ixgbe_adapter *adapter = netdev_priv(netdev);
822 822
823 if (netif_running(netdev)) { 823 if (netif_running(netdev))
824 ixgbe_down(adapter); 824 ixgbe_reinit_locked(adapter);
825 ixgbe_reset(adapter);
826 ixgbe_up(adapter);
827 }
828 825
829 return 0; 826 return 0;
830} 827}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 3732dd6c4b2a..28bb20330de7 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -535,7 +535,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
535 if (!test_bit(__IXGBE_DOWN, &adapter->state)) 535 if (!test_bit(__IXGBE_DOWN, &adapter->state))
536 mod_timer(&adapter->watchdog_timer, jiffies); 536 mod_timer(&adapter->watchdog_timer, jiffies);
537 } 537 }
538 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); 538
539 if (!test_bit(__IXGBE_DOWN, &adapter->state))
540 IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
539 541
540 return IRQ_HANDLED; 542 return IRQ_HANDLED;
541} 543}
@@ -713,7 +715,6 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
713 if (netif_rx_schedule_prep(netdev, &adapter->napi)) { 715 if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
714 /* Disable interrupts and register for poll. The flush of the 716 /* Disable interrupts and register for poll. The flush of the
715 * posted write is intentionally left out. */ 717 * posted write is intentionally left out. */
716 atomic_inc(&adapter->irq_sem);
717 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); 718 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
718 __netif_rx_schedule(netdev, &adapter->napi); 719 __netif_rx_schedule(netdev, &adapter->napi);
719 } 720 }
@@ -801,7 +802,6 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
801 **/ 802 **/
802static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) 803static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
803{ 804{
804 atomic_inc(&adapter->irq_sem);
805 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); 805 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
806 IXGBE_WRITE_FLUSH(&adapter->hw); 806 IXGBE_WRITE_FLUSH(&adapter->hw);
807 synchronize_irq(adapter->pdev->irq); 807 synchronize_irq(adapter->pdev->irq);
@@ -813,15 +813,13 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
813 **/ 813 **/
814static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) 814static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
815{ 815{
816 if (atomic_dec_and_test(&adapter->irq_sem)) { 816 if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
817 if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) 817 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC,
818 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, 818 (IXGBE_EIMS_ENABLE_MASK &
819 (IXGBE_EIMS_ENABLE_MASK & 819 ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC)));
820 ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC))); 820 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
821 IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, 821 IXGBE_EIMS_ENABLE_MASK);
822 IXGBE_EIMS_ENABLE_MASK); 822 IXGBE_WRITE_FLUSH(&adapter->hw);
823 IXGBE_WRITE_FLUSH(&adapter->hw);
824 }
825} 823}
826 824
827/** 825/**
@@ -1040,7 +1038,8 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
1040 struct ixgbe_adapter *adapter = netdev_priv(netdev); 1038 struct ixgbe_adapter *adapter = netdev_priv(netdev);
1041 u32 ctrl; 1039 u32 ctrl;
1042 1040
1043 ixgbe_irq_disable(adapter); 1041 if (!test_bit(__IXGBE_DOWN, &adapter->state))
1042 ixgbe_irq_disable(adapter);
1044 adapter->vlgrp = grp; 1043 adapter->vlgrp = grp;
1045 1044
1046 if (grp) { 1045 if (grp) {
@@ -1051,7 +1050,8 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
1051 IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); 1050 IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl);
1052 } 1051 }
1053 1052
1054 ixgbe_irq_enable(adapter); 1053 if (!test_bit(__IXGBE_DOWN, &adapter->state))
1054 ixgbe_irq_enable(adapter);
1055} 1055}
1056 1056
1057static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) 1057static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
@@ -1066,9 +1066,13 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
1066{ 1066{
1067 struct ixgbe_adapter *adapter = netdev_priv(netdev); 1067 struct ixgbe_adapter *adapter = netdev_priv(netdev);
1068 1068
1069 ixgbe_irq_disable(adapter); 1069 if (!test_bit(__IXGBE_DOWN, &adapter->state))
1070 ixgbe_irq_disable(adapter);
1071
1070 vlan_group_set_device(adapter->vlgrp, vid, NULL); 1072 vlan_group_set_device(adapter->vlgrp, vid, NULL);
1071 ixgbe_irq_enable(adapter); 1073
1074 if (!test_bit(__IXGBE_DOWN, &adapter->state))
1075 ixgbe_irq_enable(adapter);
1072 1076
1073 /* remove VID from filter table */ 1077 /* remove VID from filter table */
1074 ixgbe_set_vfta(&adapter->hw, vid, 0, false); 1078 ixgbe_set_vfta(&adapter->hw, vid, 0, false);
@@ -1224,6 +1228,16 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
1224 return 0; 1228 return 0;
1225} 1229}
1226 1230
1231void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
1232{
1233 WARN_ON(in_interrupt());
1234 while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
1235 msleep(1);
1236 ixgbe_down(adapter);
1237 ixgbe_up(adapter);
1238 clear_bit(__IXGBE_RESETTING, &adapter->state);
1239}
1240
1227int ixgbe_up(struct ixgbe_adapter *adapter) 1241int ixgbe_up(struct ixgbe_adapter *adapter)
1228{ 1242{
1229 /* hardware has been reset, we need to reload some things */ 1243 /* hardware has been reset, we need to reload some things */
@@ -1408,7 +1422,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
1408 msleep(10); 1422 msleep(10);
1409 1423
1410 napi_disable(&adapter->napi); 1424 napi_disable(&adapter->napi);
1411 atomic_set(&adapter->irq_sem, 0);
1412 1425
1413 ixgbe_irq_disable(adapter); 1426 ixgbe_irq_disable(adapter);
1414 1427
@@ -1481,7 +1494,8 @@ static int ixgbe_clean(struct napi_struct *napi, int budget)
1481 /* If budget not fully consumed, exit the polling mode */ 1494 /* If budget not fully consumed, exit the polling mode */
1482 if (work_done < budget) { 1495 if (work_done < budget) {
1483 netif_rx_complete(netdev, napi); 1496 netif_rx_complete(netdev, napi);
1484 ixgbe_irq_enable(adapter); 1497 if (!test_bit(__IXGBE_DOWN, &adapter->state))
1498 ixgbe_irq_enable(adapter);
1485 } 1499 }
1486 1500
1487 return work_done; 1501 return work_done;
@@ -1506,8 +1520,7 @@ static void ixgbe_reset_task(struct work_struct *work)
1506 1520
1507 adapter->tx_timeout_count++; 1521 adapter->tx_timeout_count++;
1508 1522
1509 ixgbe_down(adapter); 1523 ixgbe_reinit_locked(adapter);
1510 ixgbe_up(adapter);
1511} 1524}
1512 1525
1513/** 1526/**
@@ -1590,7 +1603,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
1590 return -ENOMEM; 1603 return -ENOMEM;
1591 } 1604 }
1592 1605
1593 atomic_set(&adapter->irq_sem, 1);
1594 set_bit(__IXGBE_DOWN, &adapter->state); 1606 set_bit(__IXGBE_DOWN, &adapter->state);
1595 1607
1596 return 0; 1608 return 0;
@@ -1828,10 +1840,8 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
1828 1840
1829 netdev->mtu = new_mtu; 1841 netdev->mtu = new_mtu;
1830 1842
1831 if (netif_running(netdev)) { 1843 if (netif_running(netdev))
1832 ixgbe_down(adapter); 1844 ixgbe_reinit_locked(adapter);
1833 ixgbe_up(adapter);
1834 }
1835 1845
1836 return 0; 1846 return 0;
1837} 1847}