suspend: fix freeze hangup which caused by insmod [1/1]
authorQiufang Dai <qiufang.dai@amlogic.com>
Thu, 26 Sep 2019 14:06:15 +0000 (22:06 +0800)
committerQiufang Dai <qiufang.dai@amlogic.com>
Sat, 12 Oct 2019 02:39:41 +0000 (19:39 -0700)
PD#TV-10472

Problem:
When system on, enter freeze mode lead to flush deferd probe.
Init.rc also run insmod in parallel, if insmod task
atomic_inc(&probe_count), and this task is freezed,
deadlock happends.

Solution:
Move flush deferd probe action before freeze task

Verify:
X32A0-T972

Change-Id: I8949db32aea14e2da37e77658a9c999af39e2c83
Signed-off-by: Qiufang Dai <qiufang.dai@amlogic.com>
drivers/base/power/main.c
kernel/power/suspend.c

index dc259d2..dc5ae60 100644 (file)
@@ -966,9 +966,10 @@ void dpm_complete(pm_message_t state)
        }
        list_splice(&list, &dpm_list);
        mutex_unlock(&dpm_list_mtx);
-
+#ifndef CONFIG_AMLOGIC_MODIFY
        /* Allow device probing and trigger re-probing of deferred devices */
        device_unblock_probing();
+#endif
        trace_suspend_resume(TPS("dpm_complete"), state.event, false);
 }
 
@@ -1632,7 +1633,7 @@ int dpm_prepare(pm_message_t state)
 
        trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
        might_sleep();
-
+#ifndef CONFIG_AMLOGIC_MODIFY
        /*
         * Give a chance for the known devices to complete their probes, before
         * disable probing of devices. This sync point is important at least
@@ -1646,7 +1647,7 @@ int dpm_prepare(pm_message_t state)
         * instead. The normal behavior will be restored in dpm_complete().
         */
        device_block_probing();
-
+#endif
        mutex_lock(&dpm_list_mtx);
        while (!list_empty(&dpm_list)) {
                struct device *dev = to_device(dpm_list.next);
index 678e8fa..71050f5 100644 (file)
@@ -33,6 +33,9 @@
 #include <linux/wakeup_reason.h>
 
 #include "power.h"
+#ifdef CONFIG_AMLOGIC_MODIFY
+#include "../../drivers/base/base.h"
+#endif
 
 const char *pm_labels[] = { "mem", "standby", "freeze", NULL };
 const char *pm_states[PM_SUSPEND_MAX];
@@ -289,6 +292,22 @@ static int suspend_prepare(suspend_state_t state)
                goto Finish;
        }
 
+#ifdef CONFIG_AMLOGIC_MODIFY
+       /*
+        * Give a chance for the known devices to complete their probes, before
+        * disable probing of devices. This sync point is important at least
+        * at boot time + hibernation restore.
+        */
+       wait_for_device_probe();
+       /*
+        * It is unsafe if probing of devices will happen during suspend or
+        * hibernation and system behavior will be unpredictable in this case.
+        * So, let's prohibit device's probing here and defer their probes
+        * instead. The normal behavior will be restored in dpm_complete().
+        */
+       device_block_probing();
+#endif
+
        trace_suspend_resume(TPS("freeze_processes"), 0, true);
        error = suspend_freeze_processes();
        trace_suspend_resume(TPS("freeze_processes"), 0, false);
@@ -500,6 +519,10 @@ int suspend_devices_and_enter(suspend_state_t state)
 static void suspend_finish(void)
 {
        suspend_thaw_processes();
+#ifdef CONFIG_AMLOGIC_MODIFY
+       /* Allow device probing and trigger re-probing of deferred devices */
+       device_unblock_probing();
+#endif
        pm_notifier_call_chain(PM_POST_SUSPEND);
        pm_restore_console();
 }