rcu: permit discontiguous cpu_possible_mask CPU numbering
[firefly-linux-kernel-4.4.55.git] / kernel / rcutree.c
index 3623f8e102201af97574361c1b66c85d03af244a..c60fd74e7ec91c2d538f4c5d8da34e661c855b03 100644 (file)
@@ -54,8 +54,8 @@
 
 static struct lock_class_key rcu_node_class[NUM_RCU_LVLS];
 
-#define RCU_STATE_INITIALIZER(name) { \
-       .level = { &name.node[0] }, \
+#define RCU_STATE_INITIALIZER(structname) { \
+       .level = { &structname.node[0] }, \
        .levelcnt = { \
                NUM_RCU_LVL_0,  /* root of hierarchy. */ \
                NUM_RCU_LVL_1, \
@@ -66,13 +66,14 @@ static struct lock_class_key rcu_node_class[NUM_RCU_LVLS];
        .signaled = RCU_GP_IDLE, \
        .gpnum = -300, \
        .completed = -300, \
-       .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&name.onofflock), \
+       .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&structname.onofflock), \
        .orphan_cbs_list = NULL, \
-       .orphan_cbs_tail = &name.orphan_cbs_list, \
+       .orphan_cbs_tail = &structname.orphan_cbs_list, \
        .orphan_qlen = 0, \
-       .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&name.fqslock), \
+       .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&structname.fqslock), \
        .n_force_qs = 0, \
        .n_force_qs_ngp = 0, \
+       .name = #structname, \
 }
 
 struct rcu_state rcu_sched_state = RCU_STATE_INITIALIZER(rcu_sched_state);
@@ -449,6 +450,8 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)
 
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
 
+int rcu_cpu_stall_panicking __read_mostly;
+
 static void record_gp_stall_check_time(struct rcu_state *rsp)
 {
        rsp->gp_start = jiffies;
@@ -481,7 +484,8 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
 
        /* OK, time to rat on our buddy... */
 
-       printk(KERN_ERR "INFO: RCU detected CPU stalls:");
+       printk(KERN_ERR "INFO: %s detected stalls on CPUs/tasks: {",
+              rsp->name);
        rcu_for_each_leaf_node(rsp, rnp) {
                raw_spin_lock_irqsave(&rnp->lock, flags);
                rcu_print_task_stall(rnp);
@@ -492,7 +496,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
                        if (rnp->qsmask & (1UL << cpu))
                                printk(" %d", rnp->grplo + cpu);
        }
-       printk(" (detected by %d, t=%ld jiffies)\n",
+       printk("} (detected by %d, t=%ld jiffies)\n",
               smp_processor_id(), (long)(jiffies - rsp->gp_start));
        trigger_all_cpu_backtrace();
 
@@ -508,8 +512,8 @@ static void print_cpu_stall(struct rcu_state *rsp)
        unsigned long flags;
        struct rcu_node *rnp = rcu_get_root(rsp);
 
-       printk(KERN_ERR "INFO: RCU detected CPU %d stall (t=%lu jiffies)\n",
-                       smp_processor_id(), jiffies - rsp->gp_start);
+       printk(KERN_ERR "INFO: %s detected stall on CPU %d (t=%lu jiffies)\n",
+              rsp->name, smp_processor_id(), jiffies - rsp->gp_start);
        trigger_all_cpu_backtrace();
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
@@ -526,6 +530,8 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
        long delta;
        struct rcu_node *rnp;
 
+       if (rcu_cpu_stall_panicking)
+               return;
        delta = jiffies - rsp->jiffies_stall;
        rnp = rdp->mynode;
        if ((rnp->qsmask & rdp->grpmask) && delta >= 0) {
@@ -540,6 +546,21 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
        }
 }
 
+static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
+{
+       rcu_cpu_stall_panicking = 1;
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block rcu_panic_block = {
+       .notifier_call = rcu_panic,
+};
+
+static void __init check_cpu_stall_init(void)
+{
+       atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block);
+}
+
 #else /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 static void record_gp_stall_check_time(struct rcu_state *rsp)
@@ -550,6 +571,10 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
 {
 }
 
+static void __init check_cpu_stall_init(void)
+{
+}
+
 #endif /* #else #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
 
 /*
@@ -1888,7 +1913,7 @@ static void __init rcu_init_one(struct rcu_state *rsp)
 
        rnp = rsp->level[NUM_RCU_LVLS - 1];
        for_each_possible_cpu(i) {
-               if (i > rnp->grphi)
+               while (i > rnp->grphi)
                        rnp++;
                rsp->rda[i]->mynode = rnp;
                rcu_boot_init_percpu_data(i, rsp);
@@ -1915,12 +1940,6 @@ void __init rcu_init(void)
        int cpu;
 
        rcu_bootup_announce();
-#ifdef CONFIG_RCU_CPU_STALL_DETECTOR
-       printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n");
-#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
-#if NUM_RCU_LVL_4 != 0
-       printk(KERN_INFO "Experimental four-level hierarchy is enabled.\n");
-#endif /* #if NUM_RCU_LVL_4 != 0 */
        RCU_INIT_FLAVOR(&rcu_sched_state, rcu_sched_data);
        RCU_INIT_FLAVOR(&rcu_bh_state, rcu_bh_data);
        __rcu_init_preempt();
@@ -1934,6 +1953,7 @@ void __init rcu_init(void)
        cpu_notifier(rcu_cpu_notify, 0);
        for_each_online_cpu(cpu)
                rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu);
+       check_cpu_stall_init();
 }
 
 #include "rcutree_plugin.h"