Commit 91089033 authored by Mitch Williams's avatar Mitch Williams Committed by Jeff Kirsher

i40e: lock service task correctly

The service task lock was being set in the scheduling function, not the
actual service task. This would potentially leave the bit set for a long
time before the task actually ran. Furthermore, if the service task
takes too long, it calls the schedule function to reschedule itself -
which would fail to take the lock and do nothing.

Instead, set and clear the lock bit in the service task itself. In the
process, get rid of the i40e_service_event_complete() function, which is
really just two lines of code that can be put right in the service task
itself.

Change-ID: I83155e682b686121e2897f4429eb7d3f7c669168
Signed-off-by: default avatarMitch Williams <mitch.a.williams@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent f62ba914
......@@ -288,8 +288,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
void i40e_service_event_schedule(struct i40e_pf *pf)
{
if (!test_bit(__I40E_DOWN, &pf->state) &&
!test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) &&
!test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
!test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
queue_work(i40e_wq, &pf->service_task);
}
......@@ -5954,19 +5953,6 @@ static void i40e_handle_lan_overflow_event(struct i40e_pf *pf,
}
}
/**
* i40e_service_event_complete - Finish up the service event
* @pf: board private structure
**/
static void i40e_service_event_complete(struct i40e_pf *pf)
{
WARN_ON(!test_bit(__I40E_SERVICE_SCHED, &pf->state));
/* flush memory to make sure state is correct before next watchog */
smp_mb__before_atomic();
clear_bit(__I40E_SERVICE_SCHED, &pf->state);
}
/**
* i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
* @pf: board private structure
......@@ -7276,10 +7262,12 @@ static void i40e_service_task(struct work_struct *work)
/* don't bother with service tasks if a reset is in progress */
if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) {
i40e_service_event_complete(pf);
return;
}
if (test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
return;
i40e_detect_recover_hung(pf);
i40e_sync_filters_subtask(pf);
i40e_reset_subtask(pf);
......@@ -7292,7 +7280,9 @@ static void i40e_service_task(struct work_struct *work)
i40e_sync_udp_filters_subtask(pf);
i40e_clean_adminq_subtask(pf);
i40e_service_event_complete(pf);
/* flush memory to make sure state is correct before next watchdog */
smp_mb__before_atomic();
clear_bit(__I40E_SERVICE_SCHED, &pf->state);
/* If the tasks have taken longer than one timer cycle or there
* is more work to be done, reschedule the service task now
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment