]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ice: check ICE_VSI_DOWN under rtnl_lock when preparing for reset
authorLarysa Zaremba <larysa.zaremba@intel.com>
Fri, 23 Aug 2024 09:59:29 +0000 (11:59 +0200)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Tue, 3 Sep 2024 16:01:08 +0000 (09:01 -0700)
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>
drivers/net/ethernet/intel/ice/ice_lib.c

index 3dccfaba024c8e04fd35182d171503870a15456c..737c00b02dd0e139fa9b5215bb2121e5ef10be07 100644 (file)
@@ -2672,8 +2672,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);
 
@@ -2681,15 +2680,16 @@ 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) {
+       } else if (vsi->type == ICE_VSI_CTRL && !already_down) {
                ice_vsi_close(vsi);
        }
 }