diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index 4047adb52b684720ed41cef582b55eb179f28848..b1754079f2235f10e3d2797e496fd4a5e5fa3c60 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -8473,17 +8473,26 @@ void quickstop_stepper() {
    * M421: Set a single Mesh Bed Leveling Z coordinate
    *
    *   M421 I<xindex> J<yindex> Z<linear>
+   *   or
+   *   M421 I<xindex> J<yindex> Q<offset>
    */
   inline void gcode_M421() {
     int8_t px = 0, py = 0;
     float z = 0;
-    bool hasI, hasJ, hasZ;
+    bool hasI, hasJ, hasZ, hasQ;
     if ((hasI = code_seen('I'))) px = code_value_linear_units();
     if ((hasJ = code_seen('J'))) py = code_value_linear_units();
     if ((hasZ = code_seen('Z'))) z = code_value_linear_units();
+    if ((hasQ = code_seen('Q'))) z = code_value_linear_units();
 
-    if (hasI && hasJ && hasZ) {
-      if (WITHIN(px, 0, GRID_MAX_POINTS_X - 1) && WITHIN(py, 0, GRID_MAX_POINTS_X - 1)) {
+    if (!hasI || !hasJ || (hasQ && hasZ) || (!hasQ && !hasZ)) {
+      SERIAL_ERROR_START;
+      SERIAL_ERRORLNPGM(MSG_ERR_M421_PARAMETERS);
+      return;
+    }
+
+    if (WITHIN(px, 0, GRID_MAX_POINTS_X - 1) && WITHIN(py, 0, GRID_MAX_POINTS_Y - 1)) {
+      if (hasZ) { // doing an absolute mesh value
         #if ENABLED(AUTO_BED_LEVELING_UBL)
           ubl.z_values[px][py] = z;
         #else
@@ -8492,18 +8501,23 @@ void quickstop_stepper() {
             bed_level_virt_interpolate();
           #endif
         #endif
-      }
-      else {
-        SERIAL_ERROR_START;
-        SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY);
+      } 
+      else { // doing an offset of a mesh value
+        #if ENABLED(AUTO_BED_LEVELING_UBL)
+          ubl.z_values[px][py] += z;
+        #else
+          z_values[px][py] += z;
+          #if ENABLED(ABL_BILINEAR_SUBDIVISION)
+            bed_level_virt_interpolate();
+          #endif
+        #endif
       }
     }
-    else {
+    else { // bad indexes were specified for the mesh point
       SERIAL_ERROR_START;
-      SERIAL_ERRORLNPGM(MSG_ERR_M421_PARAMETERS);
+      SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY);
     }
   }
-
 #endif
 
 #if HAS_M206_COMMAND
diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp
index 997922550ba2311fe7252d5d037eb8805afc6a7a..fe815af2cb22b5784e74ed50a0621822fec2c00b 100644
--- a/Marlin/configuration_store.cpp
+++ b/Marlin/configuration_store.cpp
@@ -1459,33 +1459,8 @@ void MarlinSettings::reset() {
       SERIAL_EOL;
 
       if (!forReplay) {
-        SERIAL_ECHOPGM("\nUBL is ");
-        ubl.state.active ? SERIAL_CHAR('A') : SERIAL_ECHOPGM("Ina");
-        SERIAL_ECHOLNPAIR("ctive\n\nActive Mesh Slot: ", ubl.state.eeprom_storage_slot);
+        ubl.g29_what_command();        
 
-        SERIAL_ECHOPGM("z_offset: ");
-        SERIAL_ECHO_F(ubl.state.z_offset, 6);
-        SERIAL_EOL;
-
-        SERIAL_ECHOPAIR("EEPROM can hold ", (int)((UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values)));
-        SERIAL_ECHOLNPGM(" meshes.\n");
-
-        SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_X  ", GRID_MAX_POINTS_X);
-        SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_Y  ", GRID_MAX_POINTS_Y);
-
-        SERIAL_ECHOPGM("UBL_MESH_MIN_X  " STRINGIFY(UBL_MESH_MIN_X));
-        SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_X );
-        SERIAL_ECHOPGM("UBL_MESH_MIN_Y  " STRINGIFY(UBL_MESH_MIN_Y));
-        SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_Y );
-
-        SERIAL_ECHOPGM("UBL_MESH_MAX_X  " STRINGIFY(UBL_MESH_MAX_X));
-        SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_X);
-        SERIAL_ECHOPGM("UBL_MESH_MAX_Y  " STRINGIFY(UBL_MESH_MAX_Y));
-        SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_Y);
-
-        SERIAL_ECHOLNPAIR("MESH_X_DIST  ", MESH_X_DIST);
-        SERIAL_ECHOLNPAIR("MESH_Y_DIST  ", MESH_Y_DIST);
-        SERIAL_EOL;
       }
 
     #elif HAS_ABL
diff --git a/Marlin/language.h b/Marlin/language.h
index 1294eb6b6c2fbd4091b43626b05e4b3c8f6a4448..914c0363d0c2978245594e76f7f015977a1f8735 100644
--- a/Marlin/language.h
+++ b/Marlin/language.h
@@ -155,7 +155,7 @@
 #define MSG_FILAMENT_RUNOUT_SENSOR          "filament: "
 #define MSG_ERR_MATERIAL_INDEX              "M145 S<index> out of range (0-1)"
 #define MSG_ERR_M355_NONE                   "No case light"
-#define MSG_ERR_M421_PARAMETERS             "M421 required parameters missing"
+#define MSG_ERR_M421_PARAMETERS             "M421 incorrect parameter usage"
 #define MSG_ERR_MESH_XY                     "Mesh point cannot be resolved"
 #define MSG_ERR_ARC_ARGS                    "G2/G3 bad parameters"
 #define MSG_ERR_PROTECTED_PIN               "Protected Pin"
diff --git a/Marlin/ubl.h b/Marlin/ubl.h
index a6516ba8a3036de806714969aab7b7f8a70db922..b33b5d21feec3c1e7ccce93cab111468ffd1a2e1 100644
--- a/Marlin/ubl.h
+++ b/Marlin/ubl.h
@@ -63,7 +63,6 @@
   void shift_mesh_height();
   void fine_tune_mesh(const float&, const float&, const bool);
   bool g29_parameter_parsing();
-  void g29_what_command();
   void g29_eeprom_dump();
   void g29_compare_current_mesh_to_stored_mesh();
 
diff --git a/Marlin/ubl_G29.cpp b/Marlin/ubl_G29.cpp
index 6e794a3b05c5da459ccc4ca39205ac04abc1495a..cee20f1747ee9d951753131a879475d07586195f 100644
--- a/Marlin/ubl_G29.cpp
+++ b/Marlin/ubl_G29.cpp
@@ -520,8 +520,8 @@
     // Much of the 'What?' command can be eliminated. But until we are fully debugged, it is
     // good to have the extra information. Soon... we prune this to just a few items
     //
-    if (code_seen('W')) g29_what_command();
-
+    if (code_seen('W')) ubl.g29_what_command();
+ 
     //
     // When we are fully debugged, the EEPROM dump command will get deleted also. But
     // right now, it is good to have the extra information. Soon... we prune this.
@@ -1181,7 +1181,7 @@
    * Much of the 'What?' command can be eliminated. But until we are fully debugged, it is
    * good to have the extra information. Soon... we prune this to just a few items
    */
-  void g29_what_command() {
+  void unified_bed_leveling::g29_what_command() {
     const uint16_t k = E2END - ubl.eeprom_start;
 
     say_ubl_name();
@@ -1205,82 +1205,73 @@
     SERIAL_PROTOCOLLNPAIR("UBL object count: ", (int)ubl_cnt);
 
     #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
-      SERIAL_PROTOCOLLNPAIR("planner.z_fade_height : ", planner.z_fade_height);
+      SERIAL_PROTOCOL("planner.z_fade_height : ");
+      SERIAL_PROTOCOL_F(planner.z_fade_height, 4);
+      SERIAL_EOL;
     #endif
     SERIAL_PROTOCOLPGM("zprobe_zoffset: ");
     SERIAL_PROTOCOL_F(zprobe_zoffset, 7);
     SERIAL_EOL;
 
-    SERIAL_PROTOCOLPGM("z_offset: ");
-    SERIAL_PROTOCOL_F(ubl.state.z_offset, 7);
-    SERIAL_EOL;
+    SERIAL_PROTOCOLLNPAIR("ubl.eeprom_start=", hex_address((void*)ubl.eeprom_start));
+
+    SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_X  ", GRID_MAX_POINTS_X);
+    SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_Y  ", GRID_MAX_POINTS_Y);
     safe_delay(25);
 
-    SERIAL_PROTOCOLLNPAIR("ubl.eeprom_start=", hex_address((void*)ubl.eeprom_start));
+    SERIAL_ECHOLNPAIR("MESH_X_DIST  ", MESH_X_DIST);
+    SERIAL_ECHOLNPAIR("MESH_Y_DIST  ", MESH_Y_DIST);
+    safe_delay(25);
 
     SERIAL_PROTOCOLPGM("X-Axis Mesh Points at: ");
     for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
-      SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(pgm_read_float(&ubl.mesh_index_to_xpos[i])), 1);
+      SERIAL_PROTOCOL_F(LOGICAL_X_POSITION(pgm_read_float(&ubl.mesh_index_to_xpos[i])), 3);
       SERIAL_PROTOCOLPGM("  ");
-      safe_delay(50);
+      safe_delay(25);
     }
     SERIAL_EOL;
 
     SERIAL_PROTOCOLPGM("Y-Axis Mesh Points at: ");
     for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; i++) {
-      SERIAL_PROTOCOL_F(LOGICAL_Y_POSITION(pgm_read_float(&ubl.mesh_index_to_ypos[i])), 1);
+      SERIAL_PROTOCOL_F(LOGICAL_Y_POSITION(pgm_read_float(&ubl.mesh_index_to_ypos[i])), 3);
       SERIAL_PROTOCOLPGM("  ");
-      safe_delay(50);
+      safe_delay(25);
     }
     SERIAL_EOL;
 
-    #if HAS_KILL
-      SERIAL_PROTOCOLPAIR("Kill pin on :", KILL_PIN);
-      SERIAL_PROTOCOLLNPAIR("  state:", READ(KILL_PIN));
-    #endif
-    SERIAL_EOL;
-    safe_delay(50);
-
-    SERIAL_PROTOCOLLNPAIR("ubl_state_at_invocation :", ubl_state_at_invocation);
-    SERIAL_EOL;
-    SERIAL_PROTOCOLLNPAIR("ubl_state_recursion_chk :", ubl_state_recursion_chk);
-    SERIAL_EOL;
-    safe_delay(50);
     SERIAL_PROTOCOLLNPAIR("Free EEPROM space starts at: ", hex_address((void*)ubl.eeprom_start));
+    SERIAL_PROTOCOLLNPAIR("end of EEPROM: ", hex_address((void*)E2END));
+    safe_delay(25);
 
-    SERIAL_PROTOCOLLNPAIR("end of EEPROM              : ", hex_address((void*)E2END));
-    safe_delay(50);
-
-    SERIAL_PROTOCOLLNPAIR("sizeof(ubl) :  ", (int)sizeof(ubl));
+    SERIAL_PROTOCOLPAIR("sizeof(ubl.state) : ", (int)sizeof(ubl.state));
     SERIAL_EOL;
     SERIAL_PROTOCOLLNPAIR("z_value[][] size: ", (int)sizeof(ubl.z_values));
     SERIAL_EOL;
-    safe_delay(50);
+    safe_delay(25);
 
     SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)k));
-    safe_delay(50);
+    safe_delay(25);
 
     SERIAL_PROTOCOLPAIR("EEPROM can hold ", k / sizeof(ubl.z_values));
     SERIAL_PROTOCOLLNPGM(" meshes.\n");
-    safe_delay(50);
-
-    SERIAL_PROTOCOLPAIR("sizeof(ubl.state) : ", (int)sizeof(ubl.state));
+    safe_delay(25);
 
     SERIAL_PROTOCOLPAIR("\nGRID_MAX_POINTS_X  ", GRID_MAX_POINTS_X);
     SERIAL_PROTOCOLPAIR("\nGRID_MAX_POINTS_Y  ", GRID_MAX_POINTS_Y);
-    safe_delay(50);
-    SERIAL_PROTOCOLPAIR("\nUBL_MESH_MIN_X         ", UBL_MESH_MIN_X);
-    SERIAL_PROTOCOLPAIR("\nUBL_MESH_MIN_Y         ", UBL_MESH_MIN_Y);
-    safe_delay(50);
-    SERIAL_PROTOCOLPAIR("\nUBL_MESH_MAX_X         ", UBL_MESH_MAX_X);
-    SERIAL_PROTOCOLPAIR("\nUBL_MESH_MAX_Y         ", UBL_MESH_MAX_Y);
-    safe_delay(50);
-    SERIAL_PROTOCOLPGM("\nMESH_X_DIST        ");
-    SERIAL_PROTOCOL_F(MESH_X_DIST, 6);
-    SERIAL_PROTOCOLPGM("\nMESH_Y_DIST        ");
-    SERIAL_PROTOCOL_F(MESH_Y_DIST, 6);
+    safe_delay(25);
     SERIAL_EOL;
-    safe_delay(50);
+
+    SERIAL_ECHOPGM("UBL_MESH_MIN_X  " STRINGIFY(UBL_MESH_MIN_X));
+    SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_X );
+    SERIAL_ECHOPGM("UBL_MESH_MIN_Y  " STRINGIFY(UBL_MESH_MIN_Y));
+    SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_Y );
+    safe_delay(25);
+
+    SERIAL_ECHOPGM("UBL_MESH_MAX_X  " STRINGIFY(UBL_MESH_MAX_X));
+    SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_X);
+    SERIAL_ECHOPGM("UBL_MESH_MAX_Y  " STRINGIFY(UBL_MESH_MAX_Y));
+    SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_Y);
+    safe_delay(25);
 
     if (!ubl.sanity_check()) {
       say_ubl_name();