diff options
author | Ayyappan Veeraiyan <ayyappan.veeraiyan@intel.com> | 2008-02-01 18:58:41 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-02-05 13:31:31 -0500 |
commit | d4f80882ee7bdc721230b9ac209ddd3a837e4545 (patch) | |
tree | ec7a096ac3c39c0d5cc5f32e88f8c7bf2f089e4c /drivers | |
parent | 06f7525be463ef95bfdba001484bda04d00ec74e (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.h | 2 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_ethtool.c | 29 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 60 |
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 | ||
245 | extern int ixgbe_up(struct ixgbe_adapter *adapter); | 244 | extern int ixgbe_up(struct ixgbe_adapter *adapter); |
246 | extern void ixgbe_down(struct ixgbe_adapter *adapter); | 245 | extern void ixgbe_down(struct ixgbe_adapter *adapter); |
246 | extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); | ||
247 | extern void ixgbe_reset(struct ixgbe_adapter *adapter); | 247 | extern void ixgbe_reset(struct ixgbe_adapter *adapter); |
248 | extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); | 248 | extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); |
249 | extern void ixgbe_set_ethtool_ops(struct net_device *netdev); | 249 | extern 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 | **/ |
802 | static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) | 803 | static 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 | **/ |
814 | static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) | 814 | static 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 | ||
1057 | static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) | 1057 | static 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 | ||
1231 | void 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 | |||
1227 | int ixgbe_up(struct ixgbe_adapter *adapter) | 1241 | int 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 | } |