diff options
| author | Emil Tantilov <emil.s.tantilov@intel.com> | 2015-01-27 22:21:34 -0500 |
|---|---|---|
| committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2015-02-05 22:58:45 -0500 |
| commit | 9ac5c5ccdbfd41c1dea802462a9b0abcfc106abc (patch) | |
| tree | 57a985688edf80ef30efa9df0a373af08e63549e | |
| parent | e66c92ad5839ffd0ffd0ac7f7afd622151ef6272 (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>
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 13 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 140 |
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 | ||
| 444 | enum ixbgevf_state_t { | 442 | enum 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 | ||
| 453 | enum ixgbevf_boards { | 452 | enum 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; | |||
| 98 | module_param(debug, int, 0); | 98 | module_param(debug, int, 0); |
| 99 | MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); | 99 | MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); |
| 100 | 100 | ||
| 101 | static 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 | |||
| 109 | static 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 */ |
| 102 | static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter); | 119 | static void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter); |
| 103 | static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector); | 120 | static 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 | ||
| 118 | static void ixgbevf_check_remove(struct ixgbe_hw *hw, u32 reg) | 135 | static 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 | ||
| 266 | static 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 | ||
| 2057 | void ixgbevf_up(struct ixgbevf_adapter *adapter) | 2080 | void 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 | whi | ||
