Commit d8c40b9d authored by Larysa Zaremba's avatar Larysa Zaremba Committed by Tony Nguyen

ice: check ICE_VSI_DOWN under rtnl_lock when preparing for reset

Consider the following scenario:

.ndo_bpf()		| ice_prepare_for_reset()		|
________________________|_______________________________________|
rtnl_lock()		|					|
ice_down()		|					|
			| test_bit(ICE_VSI_DOWN) - true		|
			| ice_dis_vsi() returns			|
ice_up()		|					|
			| proceeds to rebuild a running VSI	|

.ndo_bpf() is not the only rtnl-locked callback that toggles the interface
to apply new configuration. Another example is .set_channels().

To avoid the race condition above, act only after reading ICE_VSI_DOWN
under rtnl_lock.

Fixes: 0f9d5027 ("ice: Refactor VSI allocation, deletion and rebuild flow")
Reviewed-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Tested-by: default avatarChandan Kumar Rout <chandanx.rout@intel.com>
Signed-off-by: default avatarLarysa Zaremba <larysa.zaremba@intel.com>
Reviewed-by: default avatarMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent f50c6876
...@@ -2672,8 +2672,7 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked) ...@@ -2672,8 +2672,7 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked)
*/ */
void ice_dis_vsi(struct ice_vsi *vsi, bool locked) void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
{ {
if (test_bit(ICE_VSI_DOWN, vsi->state)) bool already_down = test_bit(ICE_VSI_DOWN, vsi->state);
return;
set_bit(ICE_VSI_NEEDS_RESTART, vsi->state); set_bit(ICE_VSI_NEEDS_RESTART, vsi->state);
...@@ -2681,15 +2680,16 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked) ...@@ -2681,15 +2680,16 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
if (netif_running(vsi->netdev)) { if (netif_running(vsi->netdev)) {
if (!locked) if (!locked)
rtnl_lock(); rtnl_lock();
already_down = test_bit(ICE_VSI_DOWN, vsi->state);
ice_vsi_close(vsi); if (!already_down)
ice_vsi_close(vsi);
if (!locked) if (!locked)
rtnl_unlock(); rtnl_unlock();
} else { } else if (!already_down) {
ice_vsi_close(vsi); ice_vsi_close(vsi);
} }
} else if (vsi->type == ICE_VSI_CTRL) { } else if (vsi->type == ICE_VSI_CTRL && !already_down) {
ice_vsi_close(vsi); ice_vsi_close(vsi);
} }
} }
......
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