diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 6fe2303fccd9..7d23dafdffbc 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -332,8 +332,15 @@ update_connector_routing(struct drm_atomic_state *state,
 	 * about is ensuring that userspace can't do anything but shut off the
 	 * display on a connector that was destroyed after its been notified,
 	 * not before.
+	 *
+	 * Additionally, we also want to ignore connector registration when
+	 * we're trying to restore an atomic state during system resume since
+	 * there's a chance the connector may have been destroyed during the
+	 * process, but it's better to ignore that then cause
+	 * drm_atomic_helper_resume() to fail.
 	 */
-	if (drm_connector_is_unregistered(connector) && crtc_state->active) {
+	if (!state->suspend_or_resume &&
+	    drm_connector_is_unregistered(connector) && crtc_state->active) {
 		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] is not registered\n",
 				 connector->base.id, connector->name);
 		return -EINVAL;
@@ -3144,6 +3151,7 @@ EXPORT_SYMBOL(drm_atomic_helper_shutdown);
  * drm_atomic_helper_duplicate_state - duplicate an atomic state object
  * @dev: DRM device
  * @ctx: lock acquisition context
+ * @suspending: If this state is being duplicated as part of system suspend
  *
  * Makes a copy of the current atomic state by looping over all objects and
  * duplicating their respective states. This is used for example by suspend/
@@ -3166,7 +3174,8 @@ EXPORT_SYMBOL(drm_atomic_helper_shutdown);
  */
 struct drm_atomic_state *
 drm_atomic_helper_duplicate_state(struct drm_device *dev,
-				  struct drm_modeset_acquire_ctx *ctx)
+				  struct drm_modeset_acquire_ctx *ctx,
+				  bool suspending)
 {
 	struct drm_atomic_state *state;
 	struct drm_connector *conn;
@@ -3180,6 +3189,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev,
 		return ERR_PTR(-ENOMEM);
 
 	state->acquire_ctx = ctx;
+	state->suspend_or_resume = suspending;
 
 	drm_for_each_crtc(crtc, dev) {
 		struct drm_crtc_state *crtc_state;
@@ -3263,7 +3273,7 @@ struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
 
 	DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, err);
 
-	state = drm_atomic_helper_duplicate_state(dev, &ctx);
+	state = drm_atomic_helper_duplicate_state(dev, &ctx, true);
 	if (IS_ERR(state))
 		goto unlock;
 
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 8ba0e5b368da..371010f8d42e 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -3032,6 +3032,10 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
  * @port as needed. It is not OK however, to call this function and
  * drm_dp_atomic_release_vcpi_slots() in the same atomic check phase.
  *
+ * When &drm_atomic_state.suspend_or_resume is set to %true%, this function
+ * will not perform any error checking and will instead simply retrieve the
+ * previously recorded VCPI allocation that was present before system suspend.
+ *
  * See also:
  * drm_dp_atomic_release_vcpi_slots()
  * drm_dp_mst_atomic_check()
@@ -3052,9 +3056,11 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
 	if (IS_ERR(topology_state))
 		return PTR_ERR(topology_state);
 
-	port = drm_dp_mst_topology_get_port_validated(mgr, port);
-	if (port == NULL)
-		return -EINVAL;
+	if (!state->suspend_or_resume) {
+		port = drm_dp_mst_topology_get_port_validated(mgr, port);
+		if (!port)
+			return -EINVAL;
+	}
 
 	/* Find the current allocation for this port, if any */
 	list_for_each_entry(pos, &topology_state->vcpis, next) {
@@ -3062,6 +3068,19 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
 			vcpi = pos;
 			prev_slots = vcpi->vcpi;
 
+			/*
+			 * When resuming, we just want to restore the previous
+			 * VCPI without doing error checking
+			 */
+			if (state->suspend_or_resume) {
+				DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] [MST PORT:%p] restoring VCPI of %d\n",
+						 port->connector->base.id,
+						 port->connector->name,
+						 port, prev_slots);
+
+				return prev_slots;
+			}
+
 			/*
 			 * This should never happen, unless the driver tries
 			 * releasing and allocating the same VCPI allocation,
@@ -3124,6 +3143,11 @@ EXPORT_SYMBOL(drm_dp_atomic_find_vcpi_slots);
  * drm_dp_atomic_find_vcpi_slots() on the same @port in a single atomic check
  * phase.
  *
+ * When &drm_atomic_state.suspend_or_resume is set, this function will not
+ * modify the VCPI allocations in &drm_dp_mst_topology_state.vcpis, so that
+ * those VCPI allocations may be restored as-is during system resume. In this
+ * scenario, this function will always return 0.
+ *
  * See also:
  * drm_dp_atomic_find_vcpi_slots()
  * drm_dp_mst_atomic_check()
@@ -3140,6 +3164,12 @@ int drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state,
 	struct drm_dp_vcpi_allocation *pos;
 	bool found = false;
 
+	/* During suspend, just keep our VCPI allocations as-is in the atomic
+	 * state so they can be restored as-is at resume
+	 */
+	if (state->suspend_or_resume)
+		return 0;
+
 	topology_state = drm_atomic_get_mst_topology_state(state, mgr);
 	if (IS_ERR(topology_state))
 		return PTR_ERR(topology_state);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4a282532af81..4c70f1531119 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3824,7 +3824,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
 	 * Disabling the crtcs gracefully seems nicer. Also the
 	 * g33 docs say we should at least disable all the planes.
 	 */
-	state = drm_atomic_helper_duplicate_state(dev, ctx);
+	state = drm_atomic_helper_duplicate_state(dev, ctx, false);
 	if (IS_ERR(state)) {
 		ret = PTR_ERR(state);
 		DRM_ERROR("Duplicating state failed with %i\n", ret);
@@ -15043,7 +15043,7 @@ static void sanitize_watermarks(struct drm_device *dev)
 		goto fail;
 	}
 
-	state = drm_atomic_helper_duplicate_state(dev, &ctx);
+	state = drm_atomic_helper_duplicate_state(dev, &ctx, false);
 	if (WARN_ON(IS_ERR(state)))
 		goto fail;
 
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 811b4a92568f..0897f51dcd62 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -329,6 +329,17 @@ struct drm_atomic_state {
 	bool allow_modeset : 1;
 	bool legacy_cursor_update : 1;
 	bool async_update : 1;
+	/**
+	 * @suspend_or_resume:
+	 *
+	 * Indicates whether or not this atomic state is being saved or
+	 * committed as part of suspending or resuming the system
+	 * respectively. Drivers and atomic helpers hould use this to fixup
+	 * normal state inconsistencies that might arise between system
+	 * suspend and resume, so as to ensure that restoring the atomic state
+	 * at resume never fails.
+	 */
+	bool suspend_or_resume : 1;
 	struct __drm_planes_state *planes;
 	struct __drm_crtcs_state *crtcs;
 	int num_connector;
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 58214be3bf3d..359f557b6898 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -129,7 +129,8 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
 void drm_atomic_helper_shutdown(struct drm_device *dev);
 struct drm_atomic_state *
 drm_atomic_helper_duplicate_state(struct drm_device *dev,
-				  struct drm_modeset_acquire_ctx *ctx);
+				  struct drm_modeset_acquire_ctx *ctx,
+				  bool suspending);
 struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev);
 int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
 					      struct drm_modeset_acquire_ctx *ctx);
