Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / net / ixgb / ixgb_main.c
index 6738b4d..c68b182 100644 (file)
@@ -67,7 +67,7 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
 /* Local Function Prototypes */
 
 int ixgb_up(struct ixgb_adapter *adapter);
-void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
+void ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog);
 void ixgb_reset(struct ixgb_adapter *adapter);
 int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
 int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
@@ -94,14 +94,14 @@ static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
 static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
 static int ixgb_set_mac(struct net_device *netdev, void *p);
 static irqreturn_t ixgb_intr(int irq, void *data);
-static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+static bool ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
 
 #ifdef CONFIG_IXGB_NAPI
 static int ixgb_clean(struct napi_struct *napi, int budget);
-static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
-                                  int *work_done, int work_to_do);
+static bool ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
+                             int *work_done, int work_to_do);
 #else
-static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
+static bool ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
 #endif
 static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
 static void ixgb_tx_timeout(struct net_device *dev);
@@ -197,7 +197,6 @@ module_exit(ixgb_exit_module);
 static void
 ixgb_irq_disable(struct ixgb_adapter *adapter)
 {
-       atomic_inc(&adapter->irq_sem);
        IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
        IXGB_WRITE_FLUSH(&adapter->hw);
        synchronize_irq(adapter->pdev->irq);
@@ -211,14 +210,12 @@ ixgb_irq_disable(struct ixgb_adapter *adapter)
 static void
 ixgb_irq_enable(struct ixgb_adapter *adapter)
 {
-       if(atomic_dec_and_test(&adapter->irq_sem)) {
-               u32 val = IXGB_INT_RXT0 | IXGB_INT_RXDMT0 |
-                         IXGB_INT_TXDW | IXGB_INT_LSC;
-               if (adapter->hw.subsystem_vendor_id == SUN_SUBVENDOR_ID)
-                       val |= IXGB_INT_GPI0;
-               IXGB_WRITE_REG(&adapter->hw, IMS, val);
-               IXGB_WRITE_FLUSH(&adapter->hw);
-       }
+       u32 val = IXGB_INT_RXT0 | IXGB_INT_RXDMT0 |
+                 IXGB_INT_TXDW | IXGB_INT_LSC;
+       if (adapter->hw.subsystem_vendor_id == SUN_SUBVENDOR_ID)
+               val |= IXGB_INT_GPI0;
+       IXGB_WRITE_REG(&adapter->hw, IMS, val);
+       IXGB_WRITE_FLUSH(&adapter->hw);
 }
 
 int
@@ -283,26 +280,30 @@ 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;
 }
 
 void
-ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
+ixgb_down(struct ixgb_adapter *adapter, bool 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);
 
@@ -589,9 +590,9 @@ ixgb_sw_init(struct ixgb_adapter *adapter)
        /* enable flow control to be programmed */
        hw->fc.send_xon = 1;
 
-       atomic_set(&adapter->irq_sem, 1);
        spin_lock_init(&adapter->tx_lock);
 
+       set_bit(__IXGB_DOWN, &adapter->flags);
        return 0;
 }
 
@@ -656,7 +657,7 @@ ixgb_close(struct net_device *netdev)
 {
        struct ixgb_adapter *adapter = netdev_priv(netdev);
 
-       ixgb_down(adapter, TRUE);
+       ixgb_down(adapter, true);
 
        ixgb_free_tx_resources(adapter);
        ixgb_free_rx_resources(adapter);
@@ -881,7 +882,7 @@ ixgb_configure_rx(struct ixgb_adapter *adapter)
        IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
 
        /* Enable Receive Checksum Offload for TCP and UDP */
-       if(adapter->rx_csum == TRUE) {
+       if (adapter->rx_csum) {
                rxcsum = IXGB_READ_REG(hw, RXCSUM);
                rxcsum |= IXGB_RXCSUM_TUOFL;
                IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
@@ -1164,7 +1165,7 @@ ixgb_watchdog(unsigned long data)
        }
 
        /* Force detection of hung controller every watchdog period */
-       adapter->detect_tx_hung = TRUE;
+       adapter->detect_tx_hung = true;
 
        /* generate an interrupt to force clean up of any stragglers */
        IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);
@@ -1243,7 +1244,7 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
        return 0;
 }
 
-static boolean_t
+static bool
 ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
        struct ixgb_context_desc *context_desc;
@@ -1275,10 +1276,10 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
                if(++i == adapter->tx_ring.count) i = 0;
                adapter->tx_ring.next_to_use = i;
 
-               return TRUE;
+               return true;
        }
 
-       return FALSE;
+       return false;
 }
 
 #define IXGB_MAX_TXD_PWR       14
@@ -1464,14 +1465,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;
@@ -1548,7 +1553,7 @@ ixgb_tx_timeout_task(struct work_struct *work)
                container_of(work, struct ixgb_adapter, tx_timeout_task);
 
        adapter->tx_timeout_count++;
-       ixgb_down(adapter, TRUE);
+       ixgb_down(adapter, true);
        ixgb_up(adapter);
 }
 
@@ -1595,7 +1600,7 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
        netdev->mtu = new_mtu;
 
        if ((old_max_frame != max_frame) && netif_running(netdev)) {
-               ixgb_down(adapter, TRUE);
+               ixgb_down(adapter, true);
                ixgb_up(adapter);
        }
 
@@ -1753,9 +1758,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)) {
@@ -1764,7 +1769,6 @@ ixgb_intr(int irq, void *data)
                  of the posted write is intentionally left out.
                */
 
-               atomic_inc(&adapter->irq_sem);
                IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
                __netif_rx_schedule(netdev, &adapter->napi);
        }
@@ -1812,7 +1816,7 @@ ixgb_clean(struct napi_struct *napi, int budget)
  * @adapter: board private structure
  **/
 
-static boolean_t
+static bool
 ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
 {
        struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
@@ -1820,7 +1824,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
        struct ixgb_tx_desc *tx_desc, *eop_desc;
        struct ixgb_buffer *buffer_info;
        unsigned int i, eop;
-       boolean_t cleaned = FALSE;
+       bool cleaned = false;
 
        i = tx_ring->next_to_clean;
        eop = tx_ring->buffer_info[i].next_to_watch;
@@ -1828,7 +1832,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
 
        while(eop_desc->status & IXGB_TX_DESC_STATUS_DD) {
 
-               for(cleaned = FALSE; !cleaned; ) {
+               for (cleaned = false; !cleaned; ) {
                        tx_desc = IXGB_TX_DESC(*tx_ring, i);
                        buffer_info = &tx_ring->buffer_info[i];
 
@@ -1862,7 +1866,7 @@ ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
        if(adapter->detect_tx_hung) {
                /* detect a transmit hang in hardware, this serializes the
                 * check with the clearing of time_stamp and movement of i */
-               adapter->detect_tx_hung = FALSE;
+               adapter->detect_tx_hung = false;
                if (tx_ring->buffer_info[eop].dma &&
                   time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ)
                   && !(IXGB_READ_REG(&adapter->hw, STATUS) &
@@ -1932,7 +1936,7 @@ ixgb_rx_checksum(struct ixgb_adapter *adapter,
  * @adapter: board private structure
  **/
 
-static boolean_t
+static bool
 #ifdef CONFIG_IXGB_NAPI
 ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do)
 #else
@@ -1946,7 +1950,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
        struct ixgb_buffer *buffer_info, *next_buffer, *next2_buffer;
        uint32_t length;
        unsigned int i, j;
-       boolean_t cleaned = FALSE;
+       bool cleaned = false;
 
        i = rx_ring->next_to_clean;
        rx_desc = IXGB_RX_DESC(*rx_ring, i);
@@ -1980,7 +1984,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
                next_skb = next_buffer->skb;
                prefetch(next_skb);
 
-               cleaned = TRUE;
+               cleaned = true;
 
                pci_unmap_single(pdev,
                                 buffer_info->dma,
@@ -2193,7 +2197,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
@@ -2220,9 +2226,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);
@@ -2277,7 +2285,7 @@ static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
        struct ixgb_adapter *adapter = netdev_priv(netdev);
 
        if(netif_running(netdev))
-               ixgb_down(adapter, TRUE);
+               ixgb_down(adapter, true);
 
        pci_disable_device(pdev);