diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2008-03-21 14:06:32 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-03-26 00:17:43 -0400 |
commit | bab2bce7dcea9aaf9374b6c24001d6afcced4ca5 (patch) | |
tree | 07cd8982c9548337e24a26c566e20478284835da /drivers/net | |
parent | c3033b01d763aff572080db09ddcebed115b9cf5 (diff) |
ixgb: add explicit state checking
In order to remove the irq_sem code we need to implement strict
adapter state checking to prevent accidental double up or downs
or resets. This code is largely copied from e1000/e1000e.
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@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/net')
-rw-r--r-- | drivers/net/ixgb/ixgb.h | 9 | ||||
-rw-r--r-- | drivers/net/ixgb/ixgb_main.c | 34 |
2 files changed, 33 insertions, 10 deletions
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h index 3d2e7217e9af..0078136643f3 100644 --- a/drivers/net/ixgb/ixgb.h +++ b/drivers/net/ixgb/ixgb.h | |||
@@ -195,6 +195,15 @@ struct ixgb_adapter { | |||
195 | struct ixgb_hw_stats stats; | 195 | struct ixgb_hw_stats stats; |
196 | uint32_t alloc_rx_buff_failed; | 196 | uint32_t alloc_rx_buff_failed; |
197 | boolean_t have_msi; | 197 | boolean_t have_msi; |
198 | unsigned long flags; | ||
199 | }; | ||
200 | |||
201 | enum ixgb_state_t { | ||
202 | /* TBD | ||
203 | __IXGB_TESTING, | ||
204 | __IXGB_RESETTING, | ||
205 | */ | ||
206 | __IXGB_DOWN | ||
198 | }; | 207 | }; |
199 | 208 | ||
200 | /* Exported from other modules */ | 209 | /* Exported from other modules */ |
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 269e6f805f47..548c248093b8 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c | |||
@@ -283,13 +283,15 @@ ixgb_up(struct ixgb_adapter *adapter) | |||
283 | } | 283 | } |
284 | } | 284 | } |
285 | 285 | ||
286 | mod_timer(&adapter->watchdog_timer, jiffies); | 286 | clear_bit(__IXGB_DOWN, &adapter->flags); |
287 | 287 | ||
288 | #ifdef CONFIG_IXGB_NAPI | 288 | #ifdef CONFIG_IXGB_NAPI |
289 | napi_enable(&adapter->napi); | 289 | napi_enable(&adapter->napi); |
290 | #endif | 290 | #endif |
291 | ixgb_irq_enable(adapter); | 291 | ixgb_irq_enable(adapter); |
292 | 292 | ||
293 | mod_timer(&adapter->watchdog_timer, jiffies); | ||
294 | |||
293 | return 0; | 295 | return 0; |
294 | } | 296 | } |
295 | 297 | ||
@@ -298,11 +300,14 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog) | |||
298 | { | 300 | { |
299 | struct net_device *netdev = adapter->netdev; | 301 | struct net_device *netdev = adapter->netdev; |
300 | 302 | ||
303 | /* prevent the interrupt handler from restarting watchdog */ | ||
304 | set_bit(__IXGB_DOWN, &adapter->flags); | ||
305 | |||
301 | #ifdef CONFIG_IXGB_NAPI | 306 | #ifdef CONFIG_IXGB_NAPI |
302 | napi_disable(&adapter->napi); | 307 | napi_disable(&adapter->napi); |
303 | atomic_set(&adapter->irq_sem, 0); | 308 | atomic_set(&adapter->irq_sem, 0); |
304 | #endif | 309 | #endif |
305 | 310 | /* waiting for NAPI to complete can re-enable interrupts */ | |
306 | ixgb_irq_disable(adapter); | 311 | ixgb_irq_disable(adapter); |
307 | free_irq(adapter->pdev->irq, netdev); | 312 | free_irq(adapter->pdev->irq, netdev); |
308 | 313 | ||
@@ -592,6 +597,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter) | |||
592 | atomic_set(&adapter->irq_sem, 1); | 597 | atomic_set(&adapter->irq_sem, 1); |
593 | spin_lock_init(&adapter->tx_lock); | 598 | spin_lock_init(&adapter->tx_lock); |
594 | 599 | ||
600 | set_bit(__IXGB_DOWN, &adapter->flags); | ||
595 | return 0; | 601 | return 0; |
596 | } | 602 | } |
597 | 603 | ||
@@ -1464,14 +1470,18 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1464 | int vlan_id = 0; | 1470 | int vlan_id = 0; |
1465 | int tso; | 1471 | int tso; |
1466 | 1472 | ||
1473 | if (test_bit(__IXGB_DOWN, &adapter->flags)) { | ||
1474 | dev_kfree_skb(skb); | ||
1475 | return NETDEV_TX_OK; | ||
1476 | } | ||
1477 | |||
1467 | if(skb->len <= 0) { | 1478 | if(skb->len <= 0) { |
1468 | dev_kfree_skb_any(skb); | 1479 | dev_kfree_skb_any(skb); |
1469 | return 0; | 1480 | return 0; |
1470 | } | 1481 | } |
1471 | 1482 | ||
1472 | #ifdef NETIF_F_LLTX | 1483 | #ifdef NETIF_F_LLTX |
1473 | local_irq_save(flags); | 1484 | if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) { |
1474 | if (!spin_trylock(&adapter->tx_lock)) { | ||
1475 | /* Collision - tell upper layer to requeue */ | 1485 | /* Collision - tell upper layer to requeue */ |
1476 | local_irq_restore(flags); | 1486 | local_irq_restore(flags); |
1477 | return NETDEV_TX_LOCKED; | 1487 | return NETDEV_TX_LOCKED; |
@@ -1753,9 +1763,9 @@ ixgb_intr(int irq, void *data) | |||
1753 | if(unlikely(!icr)) | 1763 | if(unlikely(!icr)) |
1754 | return IRQ_NONE; /* Not our interrupt */ | 1764 | return IRQ_NONE; /* Not our interrupt */ |
1755 | 1765 | ||
1756 | if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) { | 1766 | if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) |
1757 | mod_timer(&adapter->watchdog_timer, jiffies); | 1767 | if (!test_bit(__IXGB_DOWN, &adapter->flags)) |
1758 | } | 1768 | mod_timer(&adapter->watchdog_timer, jiffies); |
1759 | 1769 | ||
1760 | #ifdef CONFIG_IXGB_NAPI | 1770 | #ifdef CONFIG_IXGB_NAPI |
1761 | if (netif_rx_schedule_prep(netdev, &adapter->napi)) { | 1771 | if (netif_rx_schedule_prep(netdev, &adapter->napi)) { |
@@ -2195,7 +2205,9 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) | |||
2195 | IXGB_WRITE_REG(&adapter->hw, RCTL, rctl); | 2205 | IXGB_WRITE_REG(&adapter->hw, RCTL, rctl); |
2196 | } | 2206 | } |
2197 | 2207 | ||
2198 | ixgb_irq_enable(adapter); | 2208 | /* don't enable interrupts unless we are UP */ |
2209 | if (adapter->netdev->flags & IFF_UP) | ||
2210 | ixgb_irq_enable(adapter); | ||
2199 | } | 2211 | } |
2200 | 2212 | ||
2201 | static void | 2213 | static void |
@@ -2222,9 +2234,11 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid) | |||
2222 | 2234 | ||
2223 | vlan_group_set_device(adapter->vlgrp, vid, NULL); | 2235 | vlan_group_set_device(adapter->vlgrp, vid, NULL); |
2224 | 2236 | ||
2225 | ixgb_irq_enable(adapter); | 2237 | /* don't enable interrupts unless we are UP */ |
2238 | if (adapter->netdev->flags & IFF_UP) | ||
2239 | ixgb_irq_enable(adapter); | ||
2226 | 2240 | ||
2227 | /* remove VID from filter table*/ | 2241 | /* remove VID from filter table */ |
2228 | 2242 | ||
2229 | index = (vid >> 5) & 0x7F; | 2243 | index = (vid >> 5) & 0x7F; |
2230 | vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index); | 2244 | vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index); |