All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT
@ 2021-08-11 20:14 Valentin Schneider
  2021-08-11 20:14 ` [PATCH v3 1/2] cpu_pm: Make notifier chain use a raw_spinlock_t Valentin Schneider
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Valentin Schneider @ 2021-08-11 20:14 UTC (permalink / raw)
  To: linux-kernel, linux-rt-users, linux-pm
  Cc: Thomas Gleixner, Peter Zijlstra, Sebastian Andrzej Siewior,
	Daniel Bristot de Oliveira, Ingo Molnar, Rafael J. Wysocki

Hi folks,

This is v3 of:

  http://lore.kernel.org/r/20210811131405.1731576-1-valentin.schneider@arm.com

which addresses cpu_pm's notifier chain not playing nice with PREEMPT_RT.

Revisions
=========

v1 -> v2
++++++++

o Reword changelog; clarify comments (Sebastian)
o Delete atomic_notifier_call_chain_robust() (Sebastian)

Valentin Schneider (2):
  cpu_pm: Make notifier chain use a raw_spinlock_t
  notifier: Remove atomic_notifier_call_chain_robust()

 include/linux/notifier.h |  2 --
 kernel/cpu_pm.c          | 50 ++++++++++++++++++++++++++++++----------
 kernel/notifier.c        | 19 ---------------
 3 files changed, 38 insertions(+), 33 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v3 1/2] cpu_pm: Make notifier chain use a raw_spinlock_t
  2021-08-11 20:14 [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT Valentin Schneider
@ 2021-08-11 20:14 ` Valentin Schneider
  2021-08-11 20:14 ` [PATCH v3 2/2] notifier: Remove atomic_notifier_call_chain_robust() Valentin Schneider
  2021-08-12  7:13 ` [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT Sebastian Andrzej Siewior
  2 siblings, 0 replies; 5+ messages in thread
From: Valentin Schneider @ 2021-08-11 20:14 UTC (permalink / raw)
  To: linux-kernel, linux-rt-users, linux-pm
  Cc: Thomas Gleixner, Peter Zijlstra, Sebastian Andrzej Siewior,
	Daniel Bristot de Oliveira, Ingo Molnar, Rafael J. Wysocki

Invoking atomic_notifier_chain_notify() requires acquiring a spinlock_t,
which can block under CONFIG_PREEMPT_RT. Notifications for members of the
cpu_pm notification chain will be issued by the idle task, which can never
block.

Making *all* atomic_notifiers use a raw_spinlock is too big of a hammer, as
only notifications issued by the idle task are problematic.

Special-case cpu_pm_notifier_chain by kludging a raw_notifier and
raw_spinlock_t together, matching the atomic_notifier behavior with a
raw_spinlock_t.

Fixes: 70d932985757 ("notifier: Fix broken error handling pattern")
Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
---
 kernel/cpu_pm.c | 50 +++++++++++++++++++++++++++++++++++++------------
 1 file changed, 38 insertions(+), 12 deletions(-)

diff --git a/kernel/cpu_pm.c b/kernel/cpu_pm.c
index f7e1d0eccdbc..246efc74e3f3 100644
--- a/kernel/cpu_pm.c
+++ b/kernel/cpu_pm.c
@@ -13,19 +13,32 @@
 #include <linux/spinlock.h>
 #include <linux/syscore_ops.h>
 
-static ATOMIC_NOTIFIER_HEAD(cpu_pm_notifier_chain);
+/*
+ * atomic_notifiers use a spinlock_t, which can block under PREEMPT_RT.
+ * Notifications for cpu_pm will be issued by the idle task itself, which can
+ * never block, IOW it requires using a raw_spinlock_t.
+ */
+static struct {
+	struct raw_notifier_head chain;
+	raw_spinlock_t lock;
+} cpu_pm_notifier = {
+	.chain = RAW_NOTIFIER_INIT(cpu_pm_notifier.chain),
+	.lock  = __RAW_SPIN_LOCK_UNLOCKED(cpu_pm_notifier.lock),
+};
 
 static int cpu_pm_notify(enum cpu_pm_event event)
 {
 	int ret;
 
 	/*
-	 * atomic_notifier_call_chain has a RCU read critical section, which
-	 * could be disfunctional in cpu idle. Copy RCU_NONIDLE code to let
-	 * RCU know this.
+	 * This introduces a RCU read critical section, which could be
+	 * disfunctional in cpu idle. Copy RCU_NONIDLE code to let RCU know
+	 * this.
 	 */
 	rcu_irq_enter_irqson();
-	ret = atomic_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL);
+	rcu_read_lock();
+	ret = raw_notifier_call_chain(&cpu_pm_notifier.chain, event, NULL);
+	rcu_read_unlock();
 	rcu_irq_exit_irqson();
 
 	return notifier_to_errno(ret);
@@ -33,10 +46,13 @@ static int cpu_pm_notify(enum cpu_pm_event event)
 
 static int cpu_pm_notify_robust(enum cpu_pm_event event_up, enum cpu_pm_event event_down)
 {
+	unsigned long flags;
 	int ret;
 
 	rcu_irq_enter_irqson();
-	ret = atomic_notifier_call_chain_robust(&cpu_pm_notifier_chain, event_up, event_down, NULL);
+	raw_spin_lock_irqsave(&cpu_pm_notifier.lock, flags);
+	ret = raw_notifier_call_chain_robust(&cpu_pm_notifier.chain, event_up, event_down, NULL);
+	raw_spin_unlock_irqrestore(&cpu_pm_notifier.lock, flags);
 	rcu_irq_exit_irqson();
 
 	return notifier_to_errno(ret);
@@ -49,12 +65,17 @@ static int cpu_pm_notify_robust(enum cpu_pm_event event_up, enum cpu_pm_event ev
  * Add a driver to a list of drivers that are notified about
  * CPU and CPU cluster low power entry and exit.
  *
- * This function may sleep, and has the same return conditions as
- * raw_notifier_chain_register.
+ * This function has the same return conditions as raw_notifier_chain_register.
  */
 int cpu_pm_register_notifier(struct notifier_block *nb)
 {
-	return atomic_notifier_chain_register(&cpu_pm_notifier_chain, nb);
+	unsigned long flags;
+	int ret;
+
+	raw_spin_lock_irqsave(&cpu_pm_notifier.lock, flags);
+	ret = raw_notifier_chain_register(&cpu_pm_notifier.chain, nb);
+	raw_spin_unlock_irqrestore(&cpu_pm_notifier.lock, flags);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);
 
@@ -64,12 +85,17 @@ EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);
  *
  * Remove a driver from the CPU PM notifier list.
  *
- * This function may sleep, and has the same return conditions as
- * raw_notifier_chain_unregister.
+ * This function has the same return conditions as raw_notifier_chain_unregister.
  */
 int cpu_pm_unregister_notifier(struct notifier_block *nb)
 {
-	return atomic_notifier_chain_unregister(&cpu_pm_notifier_chain, nb);
+	unsigned long flags;
+	int ret;
+
+	raw_spin_lock_irqsave(&cpu_pm_notifier.lock, flags);
+	ret = raw_notifier_chain_unregister(&cpu_pm_notifier.chain, nb);
+	raw_spin_unlock_irqrestore(&cpu_pm_notifier.lock, flags);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v3 2/2] notifier: Remove atomic_notifier_call_chain_robust()
  2021-08-11 20:14 [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT Valentin Schneider
  2021-08-11 20:14 ` [PATCH v3 1/2] cpu_pm: Make notifier chain use a raw_spinlock_t Valentin Schneider
@ 2021-08-11 20:14 ` Valentin Schneider
  2021-08-12  7:13 ` [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT Sebastian Andrzej Siewior
  2 siblings, 0 replies; 5+ messages in thread
From: Valentin Schneider @ 2021-08-11 20:14 UTC (permalink / raw)
  To: linux-kernel, linux-rt-users, linux-pm
  Cc: Sebastian Andrzej Siewior, Thomas Gleixner, Peter Zijlstra,
	Daniel Bristot de Oliveira, Ingo Molnar, Rafael J. Wysocki

This now has no more users, remove it.

Suggested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
---
 include/linux/notifier.h |  2 --
 kernel/notifier.c        | 19 -------------------
 2 files changed, 21 deletions(-)

diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 2fb373a5c1ed..87069b8459af 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -168,8 +168,6 @@ extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
 extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
 		unsigned long val, void *v);
 
-extern int atomic_notifier_call_chain_robust(struct atomic_notifier_head *nh,
-		unsigned long val_up, unsigned long val_down, void *v);
 extern int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh,
 		unsigned long val_up, unsigned long val_down, void *v);
 extern int raw_notifier_call_chain_robust(struct raw_notifier_head *nh,
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 1b019cbca594..b8251dc0bc0f 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -172,25 +172,6 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
 }
 EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
 
-int atomic_notifier_call_chain_robust(struct atomic_notifier_head *nh,
-		unsigned long val_up, unsigned long val_down, void *v)
-{
-	unsigned long flags;
-	int ret;
-
-	/*
-	 * Musn't use RCU; because then the notifier list can
-	 * change between the up and down traversal.
-	 */
-	spin_lock_irqsave(&nh->lock, flags);
-	ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v);
-	spin_unlock_irqrestore(&nh->lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(atomic_notifier_call_chain_robust);
-NOKPROBE_SYMBOL(atomic_notifier_call_chain_robust);
-
 /**
  *	atomic_notifier_call_chain - Call functions in an atomic notifier chain
  *	@nh: Pointer to head of the atomic notifier chain
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT
  2021-08-11 20:14 [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT Valentin Schneider
  2021-08-11 20:14 ` [PATCH v3 1/2] cpu_pm: Make notifier chain use a raw_spinlock_t Valentin Schneider
  2021-08-11 20:14 ` [PATCH v3 2/2] notifier: Remove atomic_notifier_call_chain_robust() Valentin Schneider
@ 2021-08-12  7:13 ` Sebastian Andrzej Siewior
  2021-08-16 16:56   ` Rafael J. Wysocki
  2 siblings, 1 reply; 5+ messages in thread
From: Sebastian Andrzej Siewior @ 2021-08-12  7:13 UTC (permalink / raw)
  To: Valentin Schneider
  Cc: linux-kernel, linux-rt-users, linux-pm, Thomas Gleixner,
	Peter Zijlstra, Daniel Bristot de Oliveira, Ingo Molnar,
	Rafael J. Wysocki

On 2021-08-11 21:14:30 [+0100], Valentin Schneider wrote:
> Hi folks,
> 
> This is v3 of:
> 
>   http://lore.kernel.org/r/20210811131405.1731576-1-valentin.schneider@arm.com
> 
> which addresses cpu_pm's notifier chain not playing nice with PREEMPT_RT.

Thank you.
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Sebastian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT
  2021-08-12  7:13 ` [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT Sebastian Andrzej Siewior
@ 2021-08-16 16:56   ` Rafael J. Wysocki
  0 siblings, 0 replies; 5+ messages in thread
From: Rafael J. Wysocki @ 2021-08-16 16:56 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, Valentin Schneider
  Cc: Linux Kernel Mailing List, linux-rt-users, Linux PM,
	Thomas Gleixner, Peter Zijlstra, Daniel Bristot de Oliveira,
	Ingo Molnar, Rafael J. Wysocki

On Thu, Aug 12, 2021 at 9:13 AM Sebastian Andrzej Siewior
<bigeasy@linutronix.de> wrote:
>
> On 2021-08-11 21:14:30 [+0100], Valentin Schneider wrote:
> > Hi folks,
> >
> > This is v3 of:
> >
> >   http://lore.kernel.org/r/20210811131405.1731576-1-valentin.schneider@arm.com
> >
> > which addresses cpu_pm's notifier chain not playing nice with PREEMPT_RT.
>
> Thank you.
> Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Both patches applied as 5.15 material, thanks!

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-08-16 16:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-11 20:14 [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT Valentin Schneider
2021-08-11 20:14 ` [PATCH v3 1/2] cpu_pm: Make notifier chain use a raw_spinlock_t Valentin Schneider
2021-08-11 20:14 ` [PATCH v3 2/2] notifier: Remove atomic_notifier_call_chain_robust() Valentin Schneider
2021-08-12  7:13 ` [PATCH v3 0/2] cpu_pm: cpu_pm_notifier_chain vs PREEMPT_RT Sebastian Andrzej Siewior
2021-08-16 16:56   ` Rafael J. Wysocki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.