diff options
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r-- | kernel/rcutree.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index d9202857d3ad..55e8f6ef8195 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -660,6 +660,8 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | |||
660 | struct rcu_node *rnp = rcu_get_root(rsp); | 660 | struct rcu_node *rnp = rcu_get_root(rsp); |
661 | 661 | ||
662 | if (!cpu_needs_another_gp(rsp, rdp) || rsp->fqs_active) { | 662 | if (!cpu_needs_another_gp(rsp, rdp) || rsp->fqs_active) { |
663 | if (cpu_needs_another_gp(rsp, rdp)) | ||
664 | rsp->fqs_need_gp = 1; | ||
663 | if (rnp->completed == rsp->completed) { | 665 | if (rnp->completed == rsp->completed) { |
664 | spin_unlock_irqrestore(&rnp->lock, flags); | 666 | spin_unlock_irqrestore(&rnp->lock, flags); |
665 | return; | 667 | return; |
@@ -1239,6 +1241,12 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1239 | break; | 1241 | break; |
1240 | } | 1242 | } |
1241 | rsp->fqs_active = 0; | 1243 | rsp->fqs_active = 0; |
1244 | if (rsp->fqs_need_gp) { | ||
1245 | spin_unlock(&rsp->fqslock); /* irqs remain disabled */ | ||
1246 | rsp->fqs_need_gp = 0; | ||
1247 | rcu_start_gp(rsp, flags); /* releases rnp->lock */ | ||
1248 | return; | ||
1249 | } | ||
1242 | spin_unlock(&rnp->lock); /* irqs remain disabled */ | 1250 | spin_unlock(&rnp->lock); /* irqs remain disabled */ |
1243 | unlock_fqs_ret: | 1251 | unlock_fqs_ret: |
1244 | spin_unlock_irqrestore(&rsp->fqslock, flags); | 1252 | spin_unlock_irqrestore(&rsp->fqslock, flags); |