aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorEmil Tantilov <emil.s.tantilov@intel.com>2015-01-27 22:21:34 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2015-02-05 22:58:45 -0500
commit9ac5c5ccdbfd41c1dea802462a9b0abcfc106abc (patch)
tree57a985688edf80ef30efa9df0a373af08e63549e /drivers/net/ethernet
parente66c92ad5839ffd0ffd0ac7f7afd622151ef6272 (diff)
ixgbevf: combine all of the tasks into a single service task
This change combines the reset and watchdog tasklets into a single task. The advantage of this is that we can avoid multiple schedules of the reset task when we have a reset event needed due to either the mailbox going down or transmit packets being present on a link down. CC: Alexander Duyck <alexander.h.duyck@redhat.com> Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com> Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h13
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c140
2 files changed, 87 insertions, 66 deletions
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index a41ab370278f..3a9b356dff01 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -367,8 +367,6 @@ struct ixgbevf_adapter {
367 /* this field must be first, see ixgbevf_process_skb_fields */ 367 /* this field must be first, see ixgbevf_process_skb_fields */
368 unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; 368 unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
369 369
370 struct timer_list watchdog_timer;
371 struct work_struct reset_task;
372 struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; 370 struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
373 371
374 /* Interrupt Throttle Rate */ 372 /* Interrupt Throttle Rate */
@@ -398,8 +396,7 @@ struct ixgbevf_adapter {
398 * thus the additional *_CAPABLE flags. 396 * thus the additional *_CAPABLE flags.
399 */ 397 */
400 u32 flags; 398 u32 flags;
401#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1) 399#define IXGBEVF_FLAG_RESET_REQUESTED (u32)(1)
402
403#define IXGBEVF_FLAG_QUEUE_RESET_REQUESTED (u32)(1 << 2) 400#define IXGBEVF_FLAG_QUEUE_RESET_REQUESTED (u32)(1 << 2)
404 401
405 struct msix_entry *msix_entries; 402 struct msix_entry *msix_entries;
@@ -435,10 +432,11 @@ struct ixgbevf_adapter {
435 u32 link_speed; 432 u32 link_speed;
436 bool link_up; 433 bool link_up;
437 434
435 struct timer_list service_timer;
436 struct work_struct service_task;
437
438 spinlock_t mbx_lock; 438 spinlock_t mbx_lock;
439 unsigned long last_reset; 439 unsigned long last_reset;
440
441 struct work_struct watchdog_task;
442}; 440};
443 441
444enum ixbgevf_state_t { 442enum ixbgevf_state_t {
@@ -447,7 +445,8 @@ enum ixbgevf_state_t {
447 __IXGBEVF_DOWN, 445 __IXGBEVF_DOWN,
448 __IXGBEVF_DISABLED, 446 __IXGBEVF_DISABLED,
449 __IXGBEVF_REMOVING, 447 __IXGBEVF_REMOVING,
450 __IXGBEVF_WORK_INIT, 448 __IXGBEVF_SERVICE_SCHED,
449 __IXGBEVF_SERVICE_INITED,
451}; 450};
452 451
453enum ixgbevf_boards { 452enum ixgbevf_boards {
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index c1100654a4be..4186981e562d 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -98,6 +98,23 @@ static int debug = -1;
98module_param(debug, int, 0); 98module_param(debug, int, 0);
99MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); 99MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
100 100
101static void ixgbevf_service_event_schedule(struct ixgbevf_adapter *adapter)
102{
103 if (!test_bit(__IXGBEVF_DOWN, &adapter->state) &&
104 !test_bit(__IXGBEVF_REMOVING, &adapter->state) &&
105 !test_and_set_bit(__IXGBEVF_SERVICE_SCHED, &adapter->state))
106 schedule_work(&adapter->service_task);
107}
108
109static void ixgbevf_service_event_complete(struct ixgbevf_adapter *adapter)
110{
111 BUG_ON(!test_bit(__IXGBEVF_SERVICE_SCHED, &adapter->state));
112
113 /* flush memory to make sure state is correct before next watchdog */
114 smp_mb__before_atomic();
115 clear_bit(__IXGBEVF_SERVICE_SCHED, &adapter->state);
116}
117
101/* forward decls */ 118/* forward decls */
102static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter); 119static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter);
103static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector); 120static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector);
@@ -111,8 +128,8 @@ static void ixgbevf_remove_adapter(struct ixgbe_hw *hw)
111 return; 128 return;
112 hw->hw_addr = NULL; 129 hw->hw_addr = NULL;
113 dev_err(&adapter->pdev->dev, "Adapter removed\n"); 130 dev_err(&adapter->pdev->dev, "Adapter removed\n");
114 if (test_bit(__IXGBEVF_WORK_INIT, &adapter->state)) 131 if (test_bit(__IXGBEVF_SERVICE_INITED, &adapter->state))
115 schedule_work(&adapter->watchdog_task); 132 ixgbevf_service_event_schedule(adapter);
116} 133}
117 134
118static void ixgbevf_check_remove(struct ixgbe_hw *hw, u32 reg) 135static void ixgbevf_check_remove(struct ixgbe_hw *hw, u32 reg)
@@ -246,6 +263,15 @@ static inline bool ixgbevf_check_tx_hang(struct ixgbevf_ring *tx_ring)
246 return false; 263 return false;
247} 264}
248 265
266static void ixgbevf_tx_timeout_reset(struct ixgbevf_adapter *adapter)
267{
268 /* Do the reset outside of interrupt context */
269 if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) {
270 adapter->flags |= IXGBEVF_FLAG_RESET_REQUESTED;
271 ixgbevf_service_event_schedule(adapter);
272 }
273}
274
249/** 275/**
250 * ixgbevf_tx_timeout - Respond to a Tx Hang 276 * ixgbevf_tx_timeout - Respond to a Tx Hang
251 * @netdev: network interface device structure 277 * @netdev: network interface device structure
@@ -254,8 +280,7 @@ static void ixgbevf_tx_timeout(struct net_device *netdev)
254{ 280{
255 struct ixgbevf_adapter *adapter = netdev_priv(netdev); 281 struct ixgbevf_adapter *adapter = netdev_priv(netdev);
256 282
257 /* Do the reset outside of interrupt context */ 283 ixgbevf_tx_timeout_reset(adapter);
258 schedule_work(&adapter->reset_task);
259} 284}
260 285
261/** 286/**
@@ -387,7 +412,7 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector,
387 netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); 412 netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
388 413
389 /* schedule immediate reset if we believe we hung */ 414 /* schedule immediate reset if we believe we hung */
390 schedule_work(&adapter->reset_task); 415 ixgbevf_tx_timeout_reset(adapter);
391 416
392 return true; 417 return true;
393 } 418 }
@@ -1239,9 +1264,7 @@ static irqreturn_t ixgbevf_msix_other(int irq, void *data)
1239 1264
1240 hw->mac.get_link_status = 1; 1265 hw->mac.get_link_status = 1;
1241 1266
1242 if (!test_bit(__IXGBEVF_DOWN, &adapter->state) && 1267 ixgbevf_service_event_schedule(adapter);
1243 !test_bit(__IXGBEVF_REMOVING, &adapter->state))
1244 mod_timer(&adapter->watchdog_timer, jiffies);
1245 1268
1246 IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_other); 1269 IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_other);
1247 1270
@@ -2051,7 +2074,7 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
2051 ixgbevf_init_last_counter_stats(adapter); 2074 ixgbevf_init_last_counter_stats(adapter);
2052 2075
2053 hw->mac.get_link_status = 1; 2076 hw->mac.get_link_status = 1;
2054 mod_timer(&adapter->watchdog_timer, jiffies); 2077 mod_timer(&adapter->service_timer, jiffies);
2055} 2078}
2056 2079
2057void ixgbevf_up(struct ixgbevf_adapter *adapter) 2080void ixgbevf_up(struct ixgbevf_adapter *adapter)
@@ -2177,13 +2200,7 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter)
2177 2200
2178 ixgbevf_napi_disable_all(adapter); 2201 ixgbevf_napi_disable_all(adapter);
2179 2202
2180 del_timer_sync(&adapter->watchdog_timer); 2203 del_timer_sync(&adapter->service_timer);
2181
2182 /* can't call flush scheduled work here because it can deadlock
2183 * if linkwatch_event tries to acquire the rtnl_lock which we are
2184 * holding */
2185 while (adapter->flags & IXGBE_FLAG_IN_WATCHDOG_TASK)
2186 msleep(1);
2187 2204
2188 /* disable transmits in the hardware now that interrupts are off */ 2205 /* disable transmits in the hardware now that interrupts are off */
2189 for (i = 0; i < adapter->num_tx_queues; i++) { 2206 for (i = 0; i < adapter->num_tx_queues; i++) {
@@ -2711,22 +2728,25 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
2711} 2728}
2712 2729
2713/** 2730/**
2714 * ixgbevf_watchdog - Timer Call-back 2731 * ixgbevf_service_timer - Timer Call-back
2715 * @data: pointer to adapter cast into an unsigned long 2732 * @data: pointer to adapter cast into an unsigned long
2716 **/ 2733 **/
2717static void ixgbevf_watchdog(unsigned long data) 2734static void ixgbevf_service_timer(unsigned long data)
2718{ 2735{
2719 struct ixgbevf_adapter *adapter = (struct ixgbevf_adapter *)data; 2736 struct ixgbevf_adapter *adapter = (struct ixgbevf_adapter *)data;
2720 2737
2721 /* Do the reset outside of interrupt context */ 2738 /* Reset the timer */
2722 schedule_work(&adapter->watchdog_task); 2739 mod_timer(&adapter->service_timer, (HZ * 2) + jiffies);
2740
2741 ixgbevf_service_event_schedule(adapter);
2723} 2742}
2724 2743
2725static void ixgbevf_reset_task(struct work_struct *work) 2744static void ixgbevf_reset_subtask(struct ixgbevf_adapter *adapter)
2726{ 2745{
2727 struct ixgbevf_adapter *adapter; 2746 if (!(adapter->flags & IXGBEVF_FLAG_RESET_REQUESTED))
2747 return;
2728 2748
2729 adapter = container_of(work, struct ixgbevf_adapter, reset_task); 2749 adapter->flags &= ~IXGBEVF_FLAG_RESET_REQUESTED;
2730 2750
2731 /* If we're already down or resetting, just bail */ 2751 /* If we're already down or resetting, just bail */
2732 if (test_bit(__IXGBEVF_DOWN, &adapter->state) || 2752 if (test_bit(__IXGBEVF_DOWN, &adapter->state) ||
@@ -2766,6 +2786,7 @@ static void ixgbevf_check_hang_subtask(struct ixgbevf_adapter *adapter)
2766 /* get one bit for every active tx/rx interrupt vector */ 2786 /* get one bit for every active tx/rx interrupt vector */
2767 for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { 2787 for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
2768 struct ixgbevf_q_vector *qv = adapter->q_vector[i]; 2788 struct ixgbevf_q_vector *qv = adapter->q_vector[i];
2789
2769 if (qv->rx.ring || qv->tx.ring) 2790 if (qv->rx.ring || qv->tx.ring)
2770 eics |= 1 << i; 2791 eics |= 1 << i;
2771 } 2792 }
@@ -2793,7 +2814,7 @@ static void ixgbevf_watchdog_update_link(struct ixgbevf_adapter *adapter)
2793 2814
2794 /* if check for link returns error we will need to reset */ 2815 /* if check for link returns error we will need to reset */
2795 if (err && time_after(jiffies, adapter->last_reset + (10 * HZ))) { 2816 if (err && time_after(jiffies, adapter->last_reset + (10 * HZ))) {
2796 schedule_work(&adapter->reset_task); 2817 adapter->flags |= IXGBEVF_FLAG_RESET_REQUESTED;
2797 link_up = false; 2818 link_up = false;
2798 } 2819 }
2799 2820
@@ -2847,14 +2868,35 @@ static void ixgbevf_watchdog_link_is_down(struct ixgbevf_adapter *adapter)
2847} 2868}
2848 2869
2849/** 2870/**
2850 * ixgbevf_watchdog_task - worker thread to bring link up 2871 * ixgbevf_watchdog_subtask - worker thread to bring link up
2872 * @work: pointer to work_struct containing our data
2873 **/
2874static void ixgbevf_watchdog_subtask(struct ixgbevf_adapter *adapter)
2875{
2876 /* if interface is down do nothing */
2877 if (test_bit(__IXGBEVF_DOWN, &adapter->state) ||
2878 test_bit(__IXGBEVF_RESETTING, &adapter->state))
2879 return;
2880
2881 ixgbevf_watchdog_update_link(adapter);
2882
2883 if (adapter->link_up)
2884 ixgbevf_watchdog_link_is_up(adapter);
2885 else
2886 ixgbevf_watchdog_link_is_down(adapter);
2887
2888 ixgbevf_update_stats(adapter);
2889}
2890
2891/**
2892 * ixgbevf_service_task - manages and runs subtasks
2851 * @work: pointer to work_struct containing our data 2893 * @work: pointer to work_struct containing our data
2852 **/ 2894 **/
2853static void ixgbevf_watchdog_task(struct work_struct *work) 2895static void ixgbevf_service_task(struct work_struct *work)
2854{ 2896{
2855 struct ixgbevf_adapter *adapter = container_of(work, 2897 struct ixgbevf_adapter *adapter = container_of(work,
2856 struct ixgbevf_adapter, 2898 struct ixgbevf_adapter,
2857 watchdog_task); 2899 service_task);
2858 struct ixgbe_hw *hw = &adapter->hw; 2900 struct ixgbe_hw *hw = &adapter->hw;
2859 2901
2860 if (IXGBE_REMOVED(hw->hw_addr)) { 2902 if (IXGBE_REMOVED(hw->hw_addr)) {
@@ -2867,27 +2909,11 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
2867 } 2909 }
2868 2910
2869 ixgbevf_queue_reset_subtask(adapter); 2911 ixgbevf_queue_reset_subtask(adapter);
2870 2912 ixgbevf_reset_subtask(adapter);
2871 adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK; 2913 ixgbevf_watchdog_subtask(adapter);
2872
2873 ixgbevf_watchdog_update_link(adapter);
2874
2875 if (adapter->link_up)
2876 ixgbevf_watchdog_link_is_up(adapter);
2877 else
2878 ixgbevf_watchdog_link_is_down(adapter);
2879
2880 ixgbevf_update_stats(adapter);
2881
2882 ixgbevf_check_hang_subtask(adapter); 2914 ixgbevf_check_hang_subtask(adapter);
2883 2915
2884 /* Reset the timer */ 2916 ixgbevf_service_event_complete(adapter);
2885 if (!test_bit(__IXGBEVF_DOWN, &adapter->state) &&
2886 !test_bit(__IXGBEVF_REMOVING, &adapter->state))
2887 mod_timer(&adapter->watchdog_timer,
2888 round_jiffies(jiffies + (2 * HZ)));
2889
2890 adapter->flags &= ~IXGBE_FLAG_IN_WATCHDOG_TASK;
2891} 2917}
2892 2918
2893/** 2919/**
@@ -3994,17 +4020,17 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3994 4020
3995 netdev->priv_flags |= IFF_UNICAST_FLT; 4021 netdev->priv_flags |= IFF_UNICAST_FLT;
3996 4022
3997 init_timer(&adapter->watchdog_timer);
3998 adapter->watchdog_timer.function = ixgbevf_watchdog;
3999 adapter->watchdog_timer.data = (unsigned long)adapter;
4000
4001 if (IXGBE_REMOVED(hw->hw_addr)) { 4023 if (IXGBE_REMOVED(hw->hw_addr)) {
4002 err = -EIO; 4024 err = -EIO;
4003 goto err_sw_init; 4025 goto err_sw_init;
4004 } 4026 }
4005 INIT_WORK(&adapter->reset_task, ixgbevf_reset_task); 4027
4006 INIT_WORK(&adapter->watchdog_task, ixgbevf_watchdog_task); 4028 setup_timer(&adapter->service_timer, &ixgbevf_service_timer,
4007 set_bit(__IXGBEVF_WORK_INIT, &adapter->state); 4029 (unsigned long)adapter);
4030
4031 INIT_WORK(&adapter->service_task, ixgbevf_service_task);
4032 set_bit(__IXGBEVF_SERVICE_INITED, &adapter->state);
4033 clear_bit(__IXGBEVF_SERVICE_SCHED, &adapter->state);
4008 4034
4009 err = ixgbevf_init_interrupt_scheme(adapter); 4035 err = ixgbevf_init_interrupt_scheme(adapter);
4010 if (err) 4036 if (err)
@@ -4078,11 +4104,7 @@ static void ixgbevf_remove(struct pci_dev *pdev)
4078 adapter = netdev_priv(netdev); 4104 adapter = netdev_priv(netdev);
4079 4105
4080 set_bit(__IXGBEVF_REMOVING, &adapter->state); 4106 set_bit(__IXGBEVF_REMOVING, &adapter->state);
4081 4107 cancel_work_sync(&adapter->service_task);
4082 del_timer_sync(&adapter->watchdog_timer);
4083
4084 cancel_work_sync(&adapter->reset_task);
4085 cancel_work_sync(&adapter->watchdog_task);
4086 4108
4087 if (netdev->reg_state == NETREG_REGISTERED) 4109 if (netdev->reg_state == NETREG_REGISTERED)
4088 unregister_netdev(netdev); 4110 unregister_netdev(netdev);
@@ -4116,7 +4138,7 @@ static pci_ers_result_t ixgbevf_io_error_detected(struct pci_dev *pdev,
4116 struct net_device *netdev = pci_get_drvdata(pdev); 4138 struct net_device *netdev = pci_get_drvdata(pdev);
4117 struct ixgbevf_adapter *adapter = netdev_priv(netdev); 4139 struct ixgbevf_adapter *adapter = netdev_priv(netdev);
4118 4140
4119 if (!test_bit(__IXGBEVF_WORK_INIT, &adapter->state)) 4141 if (!test_bit(__IXGBEVF_SERVICE_INITED, &adapter->state))
4120 return PCI_ERS_RESULT_DISCONNECT; 4142 return PCI_ERS_RESULT_DISCONNECT;
4121 4143
4122 rtnl_lock(); 4144 rtnl_lock();