diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 1aeecc165b21..defad882b236 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "rcu.h" @@ -1628,7 +1629,7 @@ static int rcu_torture_stall(void *args) } /* Spawn CPU-stall kthread, if stall_cpu specified. */ -static int __init rcu_torture_stall_init(void) +static int rcu_torture_stall_init(void) { if (stall_cpu <= 0) return 0; @@ -2008,7 +2009,7 @@ static int rcu_torture_fwd_prog(void *args) } /* If forward-progress checking is requested and feasible, spawn the thread. */ -static int __init rcu_torture_fwd_prog_init(void) +static int rcu_torture_fwd_prog_init(void) { struct rcu_fwd *rfp; @@ -2359,7 +2360,7 @@ static void rcutorture_sync(void) cur_ops->sync(); } -static int __init +static int rcu_torture_init(void) { long i; @@ -2549,5 +2550,47 @@ rcu_torture_init(void) return firsterr; } -module_init(rcu_torture_init); -module_exit(rcu_torture_cleanup); +static int rcu_torture_notify(struct notifier_block *nb, + unsigned long mode, void *_unused) +{ + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + pr_info("Shutdodwn rcu torture.."); + rcu_torture_cleanup(); + break; + + case PM_POST_RESTORE: + pr_info("Restart rcu torture.."); + rcu_torture_init(); + break; + } + + return 0; +} + +static struct notifier_block rcu_nb = { + .notifier_call = rcu_torture_notify +}; + +static int nb_failed; + +int rcu_torture_module_init(void) +{ + nb_failed = register_pm_notifier(&rcu_nb); + if (nb_failed) + pr_warn("Failed to register PM notifier"); + + return rcu_torture_init(); +} + +void rcu_torture_module_exit(void) +{ + if (!nb_failed) + unregister_pm_notifier(&rcu_nb); + + rcu_torture_cleanup(); +} + +module_init(rcu_torture_module_init); +module_exit(rcu_torture_module_exit);