Skip to content

Commit c34743d

Browse files
azaki1anguy11
authored andcommitted
iavf: fix reset task race with iavf_remove()
The reset task is currently scheduled from the watchdog or adminq tasks. First, all direct calls to schedule the reset task are replaced with the iavf_schedule_reset(), which is modified to accept the flag showing the type of reset. To prevent the reset task from starting once iavf_remove() starts, we need to check the __IAVF_IN_REMOVE_TASK bit before we schedule it. This is now easily added to iavf_schedule_reset(). Finally, remove the check for IAVF_FLAG_RESET_NEEDED in the watchdog task. It is redundant since all callers who set the flag immediately schedules the reset task. Fixes: 3ccd54e ("iavf: Fix init state closure on remove") Fixes: 14756b2 ("iavf: Fix __IAVF_RESETTING state usage") Signed-off-by: Ahmed Zaki <[email protected]> Signed-off-by: Mateusz Palczewski <[email protected]> Tested-by: Rafal Romanowski <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent d1639a1 commit c34743d

File tree

4 files changed

+16
-29
lines changed

4 files changed

+16
-29
lines changed

drivers/net/ethernet/intel/iavf/iavf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ int iavf_up(struct iavf_adapter *adapter);
520520
void iavf_down(struct iavf_adapter *adapter);
521521
int iavf_process_config(struct iavf_adapter *adapter);
522522
int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter);
523-
void iavf_schedule_reset(struct iavf_adapter *adapter);
523+
void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags);
524524
void iavf_schedule_request_stats(struct iavf_adapter *adapter);
525525
void iavf_schedule_finish_config(struct iavf_adapter *adapter);
526526
void iavf_reset(struct iavf_adapter *adapter);

drivers/net/ethernet/intel/iavf/iavf_ethtool.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,7 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
532532
/* issue a reset to force legacy-rx change to take effect */
533533
if (changed_flags & IAVF_FLAG_LEGACY_RX) {
534534
if (netif_running(netdev)) {
535-
adapter->flags |= IAVF_FLAG_RESET_NEEDED;
536-
queue_work(adapter->wq, &adapter->reset_task);
535+
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
537536
ret = iavf_wait_for_reset(adapter);
538537
if (ret)
539538
netdev_warn(netdev, "Changing private flags timeout or interrupted waiting for reset");
@@ -676,8 +675,7 @@ static int iavf_set_ringparam(struct net_device *netdev,
676675
}
677676

678677
if (netif_running(netdev)) {
679-
adapter->flags |= IAVF_FLAG_RESET_NEEDED;
680-
queue_work(adapter->wq, &adapter->reset_task);
678+
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
681679
ret = iavf_wait_for_reset(adapter);
682680
if (ret)
683681
netdev_warn(netdev, "Changing ring parameters timeout or interrupted waiting for reset");
@@ -1860,7 +1858,7 @@ static int iavf_set_channels(struct net_device *netdev,
18601858

18611859
adapter->num_req_queues = num_req;
18621860
adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
1863-
iavf_schedule_reset(adapter);
1861+
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
18641862

18651863
ret = iavf_wait_for_reset(adapter);
18661864
if (ret)

drivers/net/ethernet/intel/iavf/iavf_main.c

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,14 @@ static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
301301
/**
302302
* iavf_schedule_reset - Set the flags and schedule a reset event
303303
* @adapter: board private structure
304+
* @flags: IAVF_FLAG_RESET_PENDING or IAVF_FLAG_RESET_NEEDED
304305
**/
305-
void iavf_schedule_reset(struct iavf_adapter *adapter)
306+
void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags)
306307
{
307-
if (!(adapter->flags &
308-
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
309-
adapter->flags |= IAVF_FLAG_RESET_NEEDED;
308+
if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
309+
!(adapter->flags &
310+
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
311+
adapter->flags |= flags;
310312
queue_work(adapter->wq, &adapter->reset_task);
311313
}
312314
}
@@ -334,7 +336,7 @@ static void iavf_tx_timeout(struct net_device *netdev, unsigned int txqueue)
334336
struct iavf_adapter *adapter = netdev_priv(netdev);
335337

336338
adapter->tx_timeout_count++;
337-
iavf_schedule_reset(adapter);
339+
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
338340
}
339341

340342
/**
@@ -2478,7 +2480,7 @@ int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter)
24782480
adapter->vsi_res->num_queue_pairs);
24792481
adapter->flags |= IAVF_FLAG_REINIT_MSIX_NEEDED;
24802482
adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
2481-
iavf_schedule_reset(adapter);
2483+
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
24822484

24832485
return -EAGAIN;
24842486
}
@@ -2775,14 +2777,6 @@ static void iavf_watchdog_task(struct work_struct *work)
27752777
if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
27762778
iavf_change_state(adapter, __IAVF_COMM_FAILED);
27772779

2778-
if (adapter->flags & IAVF_FLAG_RESET_NEEDED) {
2779-
adapter->aq_required = 0;
2780-
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
2781-
mutex_unlock(&adapter->crit_lock);
2782-
queue_work(adapter->wq, &adapter->reset_task);
2783-
return;
2784-
}
2785-
27862780
switch (adapter->state) {
27872781
case __IAVF_STARTUP:
27882782
iavf_startup(adapter);
@@ -2910,11 +2904,10 @@ static void iavf_watchdog_task(struct work_struct *work)
29102904
/* check for hw reset */
29112905
reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
29122906
if (!reg_val) {
2913-
adapter->flags |= IAVF_FLAG_RESET_PENDING;
29142907
adapter->aq_required = 0;
29152908
adapter->current_op = VIRTCHNL_OP_UNKNOWN;
29162909
dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
2917-
queue_work(adapter->wq, &adapter->reset_task);
2910+
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
29182911
mutex_unlock(&adapter->crit_lock);
29192912
queue_delayed_work(adapter->wq,
29202913
&adapter->watchdog_task, HZ * 2);
@@ -3288,9 +3281,7 @@ static void iavf_adminq_task(struct work_struct *work)
32883281
} while (pending);
32893282
mutex_unlock(&adapter->crit_lock);
32903283

3291-
if ((adapter->flags &
3292-
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
3293-
adapter->state == __IAVF_RESETTING)
3284+
if (iavf_is_reset_in_progress(adapter))
32943285
goto freedom;
32953286

32963287
/* check for error indications */
@@ -4387,8 +4378,7 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
43874378
}
43884379

43894380
if (netif_running(netdev)) {
4390-
adapter->flags |= IAVF_FLAG_RESET_NEEDED;
4391-
queue_work(adapter->wq, &adapter->reset_task);
4381+
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
43924382
ret = iavf_wait_for_reset(adapter);
43934383
if (ret < 0)
43944384
netdev_warn(netdev, "MTU change interrupted waiting for reset");

drivers/net/ethernet/intel/iavf/iavf_virtchnl.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,9 +1961,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
19611961
case VIRTCHNL_EVENT_RESET_IMPENDING:
19621962
dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n");
19631963
if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
1964-
adapter->flags |= IAVF_FLAG_RESET_PENDING;
19651964
dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
1966-
queue_work(adapter->wq, &adapter->reset_task);
1965+
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
19671966
}
19681967
break;
19691968
default:

0 commit comments

Comments
 (0)