Clear ctrl_pf while holding ctrl_pf_lock for write, but release the rwsem before waiting for pre-existing RCU readers. The published NULL already prevents new readers from acquiring the retiring PF, so holding the writer lock through synchronize_rcu() only stalls sleepable users. Signed-off-by: Sergey Temerkhanov Reviewed-by: Aleksandr Loktionov --- drivers/net/ethernet/intel/ice/ice_ptp.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index 3ed37bbae161..24d4ab2197c3 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -3302,16 +3302,21 @@ static void ice_ptp_setup_adapter(struct ice_pf *pf) static void ice_ptp_cleanup_adapter(struct ice_pf *pf) { - guard(rwsem_write)(&pf->adapter->ctrl_pf_lock); + bool synchronize = false; - /* Zero out adapter->ctrl_pf pointer when the ctrl_pf itself - * is being removed to prevent any secondary PFs from accessing - * it after it is deleted. - */ - if (ice_get_ctrl_pf(pf) == pf) { - rcu_assign_pointer(pf->adapter->ctrl_pf, NULL); - synchronize_rcu(); + scoped_guard(rwsem_write, &pf->adapter->ctrl_pf_lock) { + /* Zero out adapter->ctrl_pf pointer when the ctrl_pf itself + * is being removed to prevent any secondary PFs from accessing + * it after it is deleted. + */ + if (ice_get_ctrl_pf(pf) == pf) { + rcu_assign_pointer(pf->adapter->ctrl_pf, NULL); + synchronize = true; + } } + + if (synchronize) + synchronize_rcu(); } static int ice_ptp_setup_pf(struct ice_pf *pf) -- 2.53.0