Index: linux-pm/include/linux/pm.h
===================================================================
--- linux-pm.orig/include/linux/pm.h
+++ linux-pm/include/linux/pm.h
@@ -574,6 +574,7 @@ struct dev_pm_info {
 	unsigned int		use_autosuspend:1;
 	unsigned int		timer_autosuspends:1;
 	unsigned int		memalloc_noio:1;
+	bool			direct_resume:1;	/* For system suspend */
 	enum rpm_request	request;
 	enum rpm_status		runtime_status;
 	int			runtime_error;
Index: linux-pm/include/linux/pm_runtime.h
===================================================================
--- linux-pm.orig/include/linux/pm_runtime.h
+++ linux-pm/include/linux/pm_runtime.h
@@ -57,6 +57,7 @@ extern unsigned long pm_runtime_autosusp
 extern void pm_runtime_update_max_time_suspended(struct device *dev,
 						 s64 delta_ns);
 extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable);
+extern void pm_set_direct_resume(struct device *dev, bool val);
 
 static inline bool pm_children_suspended(struct device *dev)
 {
@@ -116,6 +117,15 @@ static inline void pm_runtime_mark_last_
 	ACCESS_ONCE(dev->power.last_busy) = jiffies;
 }
 
+static inline void __set_direct_resume(struct device *dev, bool val)
+{
+	dev->power.direct_resume = val;
+}
+
+static inline bool pm_direct_resume_is_set(struct device *dev)
+{
+	return dev->power.direct_resume;
+}
 #else /* !CONFIG_PM_RUNTIME */
 
 static inline int __pm_runtime_idle(struct device *dev, int rpmflags)
@@ -165,6 +175,9 @@ static inline unsigned long pm_runtime_a
 				struct device *dev) { return 0; }
 static inline void pm_runtime_set_memalloc_noio(struct device *dev,
 						bool enable){}
+static inline void __set_direct_resume(struct device *dev, bool val) {}
+static inline void pm_set_direct_resume(struct device *dev, bool val) {}
+static inline bool pm_direct_resume_is_set(struct device *dev) { return false; }
 
 #endif /* !CONFIG_PM_RUNTIME */
 
Index: linux-pm/drivers/base/power/runtime.c
===================================================================
--- linux-pm.orig/drivers/base/power/runtime.c
+++ linux-pm/drivers/base/power/runtime.c
@@ -732,6 +732,7 @@ static int rpm_resume(struct device *dev
 	}
  skip_parent:
 
+	__set_direct_resume(dev, false);
 	if (dev->power.no_callbacks)
 		goto no_callback;	/* Assume success. */
 
@@ -1485,3 +1486,10 @@ out:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(pm_runtime_force_resume);
+
+void pm_set_direct_resume(struct device *dev, bool val)
+{
+	spin_lock_irq(&dev->power.lock);
+	__set_direct_resume(dev, val);
+	spin_unlock_irq(&dev->power.lock);
+}
Index: linux-pm/drivers/base/power/main.c
===================================================================
--- linux-pm.orig/drivers/base/power/main.c
+++ linux-pm/drivers/base/power/main.c
@@ -479,7 +479,7 @@ static int device_resume_noirq(struct de
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
-	if (dev->power.syscore)
+	if (dev->power.syscore || pm_direct_resume_is_set(dev))
 		goto Out;
 
 	if (!dev->power.is_noirq_suspended)
@@ -605,7 +605,7 @@ static int device_resume_early(struct de
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
-	if (dev->power.syscore)
+	if (dev->power.syscore || pm_direct_resume_is_set(dev))
 		goto Out;
 
 	if (!dev->power.is_late_suspended)
@@ -1007,7 +1007,7 @@ static int __device_suspend_noirq(struct
 		goto Complete;
 	}
 
-	if (dev->power.syscore)
+	if (dev->power.syscore || pm_direct_resume_is_set(dev))
 		goto Complete;
 
 	dpm_wait_for_children(dev, async);
@@ -1146,7 +1146,7 @@ static int __device_suspend_late(struct
 		goto Complete;
 	}
 
-	if (dev->power.syscore)
+	if (dev->power.syscore || pm_direct_resume_is_set(dev))
 		goto Complete;
 
 	dpm_wait_for_children(dev, async);
@@ -1382,10 +1382,21 @@ static int __device_suspend(struct devic
 
  End:
 	if (!error) {
+		struct device *parent = dev->parent;
+
 		dev->power.is_suspended = true;
-		if (dev->power.wakeup_path
-		    && dev->parent && !dev->parent->power.ignore_children)
-			dev->parent->power.wakeup_path = true;
+		if (parent) {
+			spin_lock_irq(&parent->power.lock);
+
+			if (dev->power.wakeup_path
+			    && !parent->power.ignore_children)
+				parent->power.wakeup_path = true;
+
+			if (!pm_direct_resume_is_set(dev))
+				__set_direct_resume(parent, false);
+
+			spin_unlock_irq(&parent->power.lock);
+		}
 	}
 
 	device_unlock(dev);
@@ -1553,6 +1564,7 @@ int dpm_prepare(pm_message_t state)
 		struct device *dev = to_device(dpm_list.next);
 
 		get_device(dev);
+		pm_set_direct_resume(dev, false);
 		mutex_unlock(&dpm_list_mtx);
 
 		error = device_prepare(dev, state);
