diff --git a/Marlin/src/feature/bedlevel/bedlevel.cpp b/Marlin/src/feature/bedlevel/bedlevel.cpp
index 84c16f54847..262595039a9 100644
--- a/Marlin/src/feature/bedlevel/bedlevel.cpp
+++ b/Marlin/src/feature/bedlevel/bedlevel.cpp
@@ -49,7 +49,7 @@
 bool leveling_is_valid() {
   return
     #if ENABLED(MESH_BED_LEVELING)
-      mbl.has_mesh
+      mbl.has_mesh()
     #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
       !!bilinear_grid_spacing[X_AXIS]
     #elif ENABLED(AUTO_BED_LEVELING_UBL)
@@ -178,10 +178,7 @@ void reset_bed_level() {
   #endif
   set_bed_leveling_enabled(false);
   #if ENABLED(MESH_BED_LEVELING)
-    if (leveling_is_valid()) {
-      mbl.reset();
-      mbl.has_mesh = false;
-    }
+    mbl.reset();
   #elif ENABLED(AUTO_BED_LEVELING_UBL)
     ubl.reset();
   #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
index 08235b5248c..800630c6ba2 100644
--- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
+++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp
@@ -31,8 +31,6 @@
 
   mesh_bed_leveling mbl;
 
-  bool mesh_bed_leveling::has_mesh;
-
   float mesh_bed_leveling::z_offset,
         mesh_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y],
         mesh_bed_leveling::index_to_xpos[GRID_MAX_POINTS_X],
@@ -47,7 +45,6 @@
   }
 
   void mesh_bed_leveling::reset() {
-    has_mesh = false;
     z_offset = 0;
     ZERO(z_values);
   }
@@ -58,12 +55,12 @@
      * Prepare a mesh-leveled linear move in a Cartesian setup,
      * splitting the move where it crosses mesh borders.
      */
-    void mesh_line_to_destination(const float fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
+    void mesh_bed_leveling::line_to_destination(const float fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
       // Get current and destination cells for this line
-      int cx1 = mbl.cell_index_x(current_position[X_AXIS]),
-          cy1 = mbl.cell_index_y(current_position[Y_AXIS]),
-          cx2 = mbl.cell_index_x(destination[X_AXIS]),
-          cy2 = mbl.cell_index_y(destination[Y_AXIS]);
+      int cx1 = cell_index_x(current_position[X_AXIS]),
+          cy1 = cell_index_y(current_position[Y_AXIS]),
+          cx2 = cell_index_x(destination[X_AXIS]),
+          cy2 = cell_index_y(destination[Y_AXIS]);
       NOMORE(cx1, GRID_MAX_POINTS_X - 2);
       NOMORE(cy1, GRID_MAX_POINTS_Y - 2);
       NOMORE(cx2, GRID_MAX_POINTS_X - 2);
@@ -71,7 +68,7 @@
 
       // Start and end in the same cell? No split needed.
       if (cx1 == cx2 && cy1 == cy2) {
-        buffer_line_to_destination(fr_mm_s);
+        line_to_destination(fr_mm_s);
         set_current_from_destination();
         return;
       }
@@ -87,7 +84,7 @@
         // Split on the X grid line
         CBI(x_splits, gcx);
         COPY(end, destination);
-        destination[X_AXIS] = mbl.index_to_xpos[gcx];
+        destination[X_AXIS] = index_to_xpos[gcx];
         normalized_dist = (destination[X_AXIS] - current_position[X_AXIS]) / (end[X_AXIS] - current_position[X_AXIS]);
         destination[Y_AXIS] = MBL_SEGMENT_END(Y);
       }
@@ -96,14 +93,14 @@
         // Split on the Y grid line
         CBI(y_splits, gcy);
         COPY(end, destination);
-        destination[Y_AXIS] = mbl.index_to_ypos[gcy];
+        destination[Y_AXIS] = index_to_ypos[gcy];
         normalized_dist = (destination[Y_AXIS] - current_position[Y_AXIS]) / (end[Y_AXIS] - current_position[Y_AXIS]);
         destination[X_AXIS] = MBL_SEGMENT_END(X);
       }
       else {
         // Must already have been split on these border(s)
         // This should be a rare case.
-        buffer_line_to_destination(fr_mm_s);
+        line_to_destination(fr_mm_s);
         set_current_from_destination();
         return;
       }
@@ -112,21 +109,21 @@
       destination[E_AXIS] = MBL_SEGMENT_END(E);
 
       // Do the split and look for more borders
-      mesh_line_to_destination(fr_mm_s, x_splits, y_splits);
+      line_to_destination(fr_mm_s, x_splits, y_splits);
 
       // Restore destination from stack
       COPY(destination, end);
-      mesh_line_to_destination(fr_mm_s, x_splits, y_splits);
+      line_to_destination(fr_mm_s, x_splits, y_splits);
     }
 
   #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
 
-  void mbl_mesh_report() {
+  void mesh_bed_leveling::report_mesh() {
     SERIAL_PROTOCOLLNPGM("Num X,Y: " STRINGIFY(GRID_MAX_POINTS_X) "," STRINGIFY(GRID_MAX_POINTS_Y));
-    SERIAL_PROTOCOLPGM("Z offset: "); SERIAL_PROTOCOL_F(mbl.z_offset, 5);
+    SERIAL_PROTOCOLPGM("Z offset: "); SERIAL_PROTOCOL_F(z_offset, 5);
     SERIAL_PROTOCOLLNPGM("\nMeasured points:");
     print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5,
-      [](const uint8_t ix, const uint8_t iy) { return mbl.z_values[ix][iy]; }
+      [](const uint8_t ix, const uint8_t iy) { return z_values[ix][iy]; }
     );
   }
 
diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h
index f183cc7d689..45969eea376 100644
--- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h
+++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h
@@ -39,7 +39,6 @@ enum MeshLevelingState {
 
 class mesh_bed_leveling {
 public:
-  static bool has_mesh;
   static float z_offset,
                z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y],
                index_to_xpos[GRID_MAX_POINTS_X],
@@ -47,8 +46,17 @@ public:
 
   mesh_bed_leveling();
 
+  static void report_mesh();
+
   static void reset();
 
+  FORCE_INLINE static bool has_mesh() {
+    for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
+      for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
+        if (z_values[x][y]) return true;
+    return false;
+  }
+
   static void set_z(const int8_t px, const int8_t py, const float &z) { z_values[px][py] = z; }
 
   static inline void zigzag(const int8_t index, int8_t &px, int8_t &py) {
@@ -105,15 +113,13 @@ public:
       #endif
     ;
   }
+
+  // Support functions, which may be embedded in the class later
+  #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
+    void line_to_destination(const float fr_mm_s, uint8_t x_splits=0xFF, uint8_t y_splits=0xFF);
+  #endif
 };
 
 extern mesh_bed_leveling mbl;
 
-// Support functions, which may be embedded in the class later
-#if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES)
-  void mesh_line_to_destination(const float fr_mm_s, uint8_t x_splits=0xFF, uint8_t y_splits=0xFF);
-#endif
-
-void mbl_mesh_report();
-
 #endif // _MESH_BED_LEVELING_H_
diff --git a/Marlin/src/gcode/bedlevel/M420.cpp b/Marlin/src/gcode/bedlevel/M420.cpp
index 740b632544e..1af94893ede 100644
--- a/Marlin/src/gcode/bedlevel/M420.cpp
+++ b/Marlin/src/gcode/bedlevel/M420.cpp
@@ -100,7 +100,7 @@ void GcodeSuite::M420() {
           #endif
         #elif ENABLED(MESH_BED_LEVELING)
           SERIAL_ECHOLNPGM("Mesh Bed Level data:");
-          mbl_mesh_report();
+          mbl.report_mesh();
         #endif
       }
     #endif
diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp
index 881e567e474..87dcb5659f9 100644
--- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp
+++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp
@@ -81,7 +81,7 @@ void GcodeSuite::G29() {
     case MeshReport:
       if (leveling_is_valid()) {
         SERIAL_PROTOCOLLNPAIR("State: ", planner.leveling_active ? MSG_ON : MSG_OFF);
-        mbl_mesh_report();
+        mbl.report_mesh();
       }
       else
         SERIAL_PROTOCOLLNPGM("Mesh bed leveling has no data.");
@@ -136,7 +136,6 @@ void GcodeSuite::G29() {
         SERIAL_PROTOCOLLNPGM("Mesh probing done.");
         BUZZ(100, 659);
         BUZZ(100, 698);
-        mbl.has_mesh = true;
 
         gcode.home_all_axes();
         set_bed_leveling_enabled(true);
@@ -185,9 +184,6 @@ void GcodeSuite::G29() {
         SERIAL_CHAR('Z'); echo_not_entered();
         return;
       }
-
-      mbl.has_mesh = true; // set since user manually entered a mesh point
-
       break;
 
     case MeshSetZOffset:
diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp
index 9926b4d9724..f2a2c366be7 100644
--- a/Marlin/src/module/configuration_store.cpp
+++ b/Marlin/src/module/configuration_store.cpp
@@ -37,7 +37,7 @@
  */
 
 // Change EEPROM version if the structure changes
-#define EEPROM_VERSION "V48"
+#define EEPROM_VERSION "V49"
 #define EEPROM_OFFSET 100
 
 // Check the integrity of data offsets.
@@ -114,7 +114,6 @@ typedef struct SettingsDataStruct {
   //
   // MESH_BED_LEVELING
   //
-  bool mbl_has_mesh;                                    // mbl.has_mesh
   float mbl_z_offset;                                   // mbl.z_offset
   uint8_t mesh_num_x, mesh_num_y;                       // GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y
   #if ENABLED(MESH_BED_LEVELING)
@@ -297,7 +296,6 @@ void MarlinSettings::postprocess() {
 
   #if ENABLED(AUTO_BED_LEVELING_BILINEAR)
     refresh_bed_level();
-    //set_bed_leveling_enabled(leveling_is_on);
   #endif
 
   #if HAS_MOTOR_CURRENT_PWM
@@ -425,16 +423,13 @@ void MarlinSettings::postprocess() {
         "MBL Z array is the wrong size."
       );
       const uint8_t mesh_num_x = GRID_MAX_POINTS_X, mesh_num_y = GRID_MAX_POINTS_Y;
-      EEPROM_WRITE(mbl.has_mesh);
       EEPROM_WRITE(mbl.z_offset);
       EEPROM_WRITE(mesh_num_x);
       EEPROM_WRITE(mesh_num_y);
       EEPROM_WRITE(mbl.z_values);
     #else // For disabled MBL write a default mesh
-      const bool leveling_is_on = false;
       dummy = 0.0f;
       const uint8_t mesh_num_x = 3, mesh_num_y = 3;
-      EEPROM_WRITE(leveling_is_on);
       EEPROM_WRITE(dummy); // z_offset
       EEPROM_WRITE(mesh_num_x);
       EEPROM_WRITE(mesh_num_y);
@@ -925,18 +920,13 @@ void MarlinSettings::postprocess() {
       // Mesh (Manual) Bed Leveling
       //
 
-      bool leveling_is_on;
       uint8_t mesh_num_x, mesh_num_y;
-      EEPROM_READ_ALWAYS(leveling_is_on);
       EEPROM_READ(dummy);
       EEPROM_READ_ALWAYS(mesh_num_x);
       EEPROM_READ_ALWAYS(mesh_num_y);
 
       #if ENABLED(MESH_BED_LEVELING)
-        if (!validating) {
-          mbl.has_mesh = leveling_is_on;
-          mbl.z_offset = dummy;
-        }
+        if (!validating) mbl.z_offset = dummy;
         if (mesh_num_x == GRID_MAX_POINTS_X && mesh_num_y == GRID_MAX_POINTS_Y) {
           // EEPROM data fits the current mesh
           EEPROM_READ(mbl.z_values);