|
@@ -1613,6 +1613,14 @@ static int __noreturn rcu_gp_kthread(void *arg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void rsp_wakeup(struct irq_work *work)
|
|
|
+{
|
|
|
+ struct rcu_state *rsp = container_of(work, struct rcu_state, wakeup_work);
|
|
|
+
|
|
|
+ /* Wake up rcu_gp_kthread() to start the grace period. */
|
|
|
+ wake_up(&rsp->gp_wq);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Start a new RCU grace period if warranted, re-initializing the hierarchy
|
|
|
* in preparation for detecting the next grace period. The caller must hold
|
|
@@ -1637,8 +1645,12 @@ rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
|
|
|
}
|
|
|
rsp->gp_flags = RCU_GP_FLAG_INIT;
|
|
|
|
|
|
- /* Wake up rcu_gp_kthread() to start the grace period. */
|
|
|
- wake_up(&rsp->gp_wq);
|
|
|
+ /*
|
|
|
+ * We can't do wakeups while holding the rnp->lock, as that
|
|
|
+ * could cause possible deadlocks with the rq->lock. Deter
|
|
|
+ * the wakeup to interrupt context.
|
|
|
+ */
|
|
|
+ irq_work_queue(&rsp->wakeup_work);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -3235,6 +3247,7 @@ static void __init rcu_init_one(struct rcu_state *rsp,
|
|
|
|
|
|
rsp->rda = rda;
|
|
|
init_waitqueue_head(&rsp->gp_wq);
|
|
|
+ init_irq_work(&rsp->wakeup_work, rsp_wakeup);
|
|
|
rnp = rsp->level[rcu_num_lvls - 1];
|
|
|
for_each_possible_cpu(i) {
|
|
|
while (i > rnp->grphi)
|