ixgb: add explicit state checking
authorJesse Brandeburg <jesse.brandeburg@intel.com>
Fri, 21 Mar 2008 18:06:32 +0000 (11:06 -0700)
committerJeff Garzik <jeff@garzik.org>
Wed, 26 Mar 2008 04:17:43 +0000 (00:17 -0400)
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>
drivers/net/ixgb/ixgb.h
drivers/net/ixgb/ixgb_main.c

index 3d2e7217e9af04a9afd5beac494d67b0761255a8..0078136643f32b4c39933853a2b8f98d14894dc8 100644 (file)
@@ -195,6 +195,15 @@ struct ixgb_adapter {
        struct ixgb_hw_stats stats;
        uint32_t alloc_rx_buff_failed;
        boolean_t have_msi;
+       unsigned long flags;
+};
+
+enum ixgb_state_t {
+       /* TBD
+       __IXGB_TESTING,
+       __IXGB_RESETTING,
+       */
+       __IXGB_DOWN
 };
 
 /* Exported from other modules */
index 269e6f805f472bc7232a55cad0518a16884fdbb0..548c248093b886aeaaf699fda01d6c8a396f8e30 100644 (file)
@@ -283,13 +283,15 @@ ixgb_up(struct ixgb_adapter *adapter)
                }
        }
 
-       mod_timer(&adapter->watchdog_timer, jiffies);
+       clear_bit(__IXGB_DOWN, &adapter->flags);
 
 #ifdef CONFIG_IXGB_NAPI
        napi_enable(&adapter->napi);
 #endif
        ixgb_irq_enable(adapter);
 
+       mod_timer(&adapter->watchdog_timer, jiffies);
+
        return 0;
 }
 
@@ -298,11 +300,14 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
 {
        struct net_device *netdev = adapter->netdev;
 
+       /* prevent the interrupt handler from restarting watchdog */
+       set_bit(__IXGB_DOWN, &adapter->flags);
+
 #ifdef CONFIG_IXGB_NAPI
        napi_disable(&adapter->napi);
        atomic_set(&adapter->irq_sem, 0);
 #endif
-
+       /* waiting for NAPI to complete can re-enable interrupts */
        ixgb_irq_disable(adapter);
        free_irq(adapter->pdev->irq, netdev);
 
@@ -592,6 +597,7 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
        atomic_set(&adapter->irq_sem, 1);
        spin_lock_init(&adapter->tx_lock);
 
+       set_bit(__IXGB_DOWN, &adapter->flags);
        return 0;
 }
 
@@ -1464,14 +1470,18 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        int vlan_id = 0;
        int tso;
 
+       if (test_bit(__IXGB_DOWN, &adapter->flags)) {
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+
        if(skb->len <= 0) {
                dev_kfree_skb_any(skb);
                return 0;
        }
 
 #ifdef NETIF_F_LLTX
-       local_irq_save(flags);
-       if (!spin_trylock(&adapter->tx_lock)) {
+       if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) {
                /* Collision - tell upper layer to requeue */
                local_irq_restore(flags);
                return NETDEV_TX_LOCKED;
@@ -1753,9 +1763,9 @@ ixgb_intr(int irq, void *data)
        if(unlikely(!icr))
                return IRQ_NONE;  /* Not our interrupt */
 
-       if(unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC))) {
-               mod_timer(&adapter->watchdog_timer, jiffies);
-       }
+       if (unlikely(icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)))
+               if (!test_bit(__IXGB_DOWN, &adapter->flags))
+                       mod_timer(&adapter->watchdog_timer, jiffies);
 
 #ifdef CONFIG_IXGB_NAPI
        if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
@@ -2195,7 +2205,9 @@ ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
                IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
        }
 
-       ixgb_irq_enable(adapter);
+       /* don't enable interrupts unless we are UP */
+       if (adapter->netdev->flags & IFF_UP)
+               ixgb_irq_enable(adapter);
 }
 
 static void
@@ -2222,9 +2234,11 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
 
        vlan_group_set_device(adapter->vlgrp, vid, NULL);
 
-       ixgb_irq_enable(adapter);
+       /* don't enable interrupts unless we are UP */
+       if (adapter->netdev->flags & IFF_UP)
+               ixgb_irq_enable(adapter);
 
-       /* remove VID from filter table*/
+       /* remove VID from filter table */
 
        index = (vid >> 5) & 0x7F;
        vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);