aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2011-09-27 18:20:19 +0800
committerEric Miao <eric.miao@canonical.com>2011-11-10 07:38:44 +0800
commit55dd20b3d43a37467822677c9e0596ecae6d3dbd (patch)
tree94c7f7534a980587d3947ed87aa98f909bc0ea33 /kernel
parent9dc3a799678631d8f125b5e3c54b0b18c31f86a5 (diff)
ENGR00156637 [MX6]Reboot take long time on SMP
Add work around to the reboot issue of SMP, with SMP, all the CPUs need to do _rcu_barrier, if we enqueue an rcu callback, we need to make sure CPU tick to stay alive until we take care of those by completing the appropriate grace period. This work around only work when the reboot command issue, so it didn't impact normal kernel feature. Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcutree.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index dd4aea806f8..a28f893615f 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -47,6 +47,7 @@
#include <linux/mutex.h>
#include <linux/time.h>
#include <linux/kernel_stat.h>
+#include <linux/tick.h>
#include "rcutree.h"
@@ -1413,6 +1414,7 @@ static void rcu_process_callbacks(struct softirq_action *unused)
/* If we are last CPU on way to dyntick-idle mode, accelerate it. */
rcu_needs_cpu_flush();
}
+static atomic_t rcu_barrier_cpu_count;
static void
__call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
@@ -1440,6 +1442,14 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
*rdp->nxttail[RCU_NEXT_TAIL] = head;
rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
+ /* Work around for reboot issue, check rcu_barrier_cpu_count
+ to see whether it is in the _rcu_barrier process, do
+ tick_nohz_restart_sched_tick if yes. If we enqueue an rcu
+ callback, we need the CPU tick to stay alive until we take care
+ of those by completing the appropriate grace period. */
+ if (atomic_read(&rcu_barrier_cpu_count) != 0)
+ tick_nohz_restart_sched_tick();
+
/*
* Force the grace period if too many callbacks or too long waiting.
* Enforce hysteresis, and don't invoke force_quiescent_state()
@@ -1654,7 +1664,6 @@ static int rcu_needs_cpu_quick_check(int cpu)
}
static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
-static atomic_t rcu_barrier_cpu_count;
static DEFINE_MUTEX(rcu_barrier_mutex);
static struct completion rcu_barrier_completion;