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: 0f9d5027a749 ("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>
  */
 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);
 
                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) {
+       } else if (vsi->type == ICE_VSI_CTRL && !already_down) {
                ice_vsi_close(vsi);
        }
 }