ixgbe: Use private workqueue to avoid certain possible hangs
[deliverable/linux.git] / drivers / net / ethernet / intel / ixgbe / ixgbe_main.c
index 47395ff5d908c43174a4c6afc4a8a089ae948c70..0918e32012c215d55cf430a40b99dbad01e8c69b 100644 (file)
@@ -65,9 +65,6 @@
 #include "ixgbe_common.h"
 #include "ixgbe_dcb_82599.h"
 #include "ixgbe_sriov.h"
-#ifdef CONFIG_IXGBE_VXLAN
-#include <net/vxlan.h>
-#endif
 
 char ixgbe_driver_name[] = "ixgbe";
 static const char ixgbe_driver_string[] =
@@ -175,6 +172,8 @@ MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+static struct workqueue_struct *ixgbe_wq;
+
 static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev);
 
 static int ixgbe_read_pci_cfg_word_parent(struct ixgbe_adapter *adapter,
@@ -316,7 +315,7 @@ static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
        if (!test_bit(__IXGBE_DOWN, &adapter->state) &&
            !test_bit(__IXGBE_REMOVING, &adapter->state) &&
            !test_and_set_bit(__IXGBE_SERVICE_SCHED, &adapter->state))
-               schedule_work(&adapter->service_task);
+               queue_work(ixgbe_wq, &adapter->service_task);
 }
 
 static void ixgbe_remove_adapter(struct ixgbe_hw *hw)
@@ -1659,6 +1658,7 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
 static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector,
                         struct sk_buff *skb)
 {
+       skb_mark_napi_id(skb, &q_vector->napi);
        if (ixgbe_qv_busy_polling(q_vector))
                netif_receive_skb(skb);
        else
@@ -2123,7 +2123,6 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                }
 
 #endif /* IXGBE_FCOE */
-               skb_mark_napi_id(skb, &q_vector->napi);
                ixgbe_rx_skb(q_vector, skb);
 
                /* update budget accounting */
@@ -2757,7 +2756,7 @@ static irqreturn_t ixgbe_msix_clean_rings(int irq, void *data)
        /* EIAM disabled interrupts (on this vector) for us */
 
        if (q_vector->rx.ring || q_vector->tx.ring)
-               napi_schedule(&q_vector->napi);
+               napi_schedule_irqoff(&q_vector->napi);
 
        return IRQ_HANDLED;
 }
@@ -2786,7 +2785,8 @@ int ixgbe_poll(struct napi_struct *napi, int budget)
        ixgbe_for_each_ring(ring, q_vector->tx)
                clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring);
 
-       if (!ixgbe_qv_lock_napi(q_vector))
+       /* Exit if we are called by netpoll or busy polling is active */
+       if ((budget <= 0) || !ixgbe_qv_lock_napi(q_vector))
                return budget;
 
        /* attempt to distribute budget to each queue fairly, but don't allow
@@ -2950,7 +2950,7 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
                ixgbe_ptp_check_pps_event(adapter, eicr);
 
        /* would disable interrupts here but EIAM disabled it */
-       napi_schedule(&q_vector->napi);
+       napi_schedule_irqoff(&q_vector->napi);
 
        /*
         * re-enable link(maybe) and non-queue interrupts, no flush.
@@ -3315,8 +3315,7 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
 }
 
 /**
- * Return a number of entries in the RSS indirection table
- *
+ * ixgbe_rss_indir_tbl_entries - Return RSS indirection table entries
  * @adapter: device handle
  *
  *  - 82598/82599/X540:     128
@@ -3334,8 +3333,7 @@ u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter)
 }
 
 /**
- * Write the RETA table to HW
- *
+ * ixgbe_store_reta - Write the RETA table to HW
  * @adapter: device handle
  *
  * Write the RSS redirection table stored in adapter.rss_indir_tbl[] to HW.
@@ -3374,8 +3372,7 @@ void ixgbe_store_reta(struct ixgbe_adapter *adapter)
 }
 
 /**
- * Write the RETA table to HW (for x550 devices in SRIOV mode)
- *
+ * ixgbe_store_vfreta - Write the RETA table to HW (x550 devices in SRIOV mode)
  * @adapter: device handle
  *
  * Write the RSS redirection table stored in adapter.rss_indir_tbl[] to HW.
@@ -9325,6 +9322,12 @@ static int __init ixgbe_init_module(void)
        pr_info("%s - version %s\n", ixgbe_driver_string, ixgbe_driver_version);
        pr_info("%s\n", ixgbe_copyright);
 
+       ixgbe_wq = create_singlethread_workqueue(ixgbe_driver_name);
+       if (!ixgbe_wq) {
+               pr_err("%s: Failed to create workqueue\n", ixgbe_driver_name);
+               return -ENOMEM;
+       }
+
        ixgbe_dbg_init();
 
        ret = pci_register_driver(&ixgbe_driver);
@@ -9356,6 +9359,10 @@ static void __exit ixgbe_exit_module(void)
        pci_unregister_driver(&ixgbe_driver);
 
        ixgbe_dbg_exit();
+       if (ixgbe_wq) {
+               destroy_workqueue(ixgbe_wq);
+               ixgbe_wq = NULL;
+       }
 }
 
 #ifdef CONFIG_IXGBE_DCA
This page took 0.04248 seconds and 5 git commands to generate.