ice: check ICE_VSI_DOWN under rtnl_lock when preparing for reset

BugLink: https://bugs.launchpad.net/bugs/2085849

[ Upstream commit d8c40b9d3a6cef61eb5a0c58c34a3090ea938d89 ]

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: 0f9d5027a7 ("ice: Refactor VSI allocation, deletion and rebuild flow")
Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Chandan Kumar Rout <chandanx.rout@intel.com>
Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com>
Signed-off-by: Roxana Nicolescu <roxana.nicolescu@canonical.com>
This commit is contained in:
Larysa Zaremba
2024-08-23 11:59:29 +02:00
committed by Mehmet Basaran
parent afbadb6dcf
commit c860cf56a0
+7 -7
View File
@@ -2690,8 +2690,7 @@ int ice_ena_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))
return;
bool already_down = test_bit(ICE_VSI_DOWN, vsi->state);
set_bit(ICE_VSI_NEEDS_RESTART, vsi->state);
@@ -2699,16 +2698,17 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
if (netif_running(vsi->netdev)) {
if (!locked)
rtnl_lock();
ice_vsi_close(vsi);
already_down = test_bit(ICE_VSI_DOWN, vsi->state);
if (!already_down)
ice_vsi_close(vsi);
if (!locked)
rtnl_unlock();
} else {
} else if (!already_down) {
ice_vsi_close(vsi);
}
} else if (vsi->type == ICE_VSI_CTRL ||
vsi->type == ICE_VSI_SWITCHDEV_CTRL) {
} else if ((vsi->type == ICE_VSI_CTRL ||
vsi->type == ICE_VSI_SWITCHDEV_CTRL) && !already_down) {
ice_vsi_close(vsi);
}
}