Hi!
The Tegra20 requires an enabled VDE power domain during startup. As the VDE is currently not used, it is disabled during runtime. Since 8f0c714ad9be, there is a workaround for the "normal restart path" which enables the VDE before doing PMC's warm reboot. This workaround is not executed in the "emergency restart path", leading to a hang-up during start.
This series implements and registers a new pmic-based restart handler for boards with tps6586x. This cold reboot ensures that the VDE power domain is enabled during startup on tegra20-based boards.
Since bae1d3a05a8b, i2c transfers are non-atomic while preemption is disabled (which is e.g. done during panic()). This could lead to warnings ("Voluntary context switch within RCU") in i2c-based restart handlers during emergency restart. The state of preemption should be detected by i2c_in_atomic_xfer_mode() to use atomic i2c xfer when required. Beside the new system_state check, the check is the same as the one pre v5.2.
v5: https://lore.kernel.org/r/20230327-tegra-pmic-reboot-v5-0-ab090e03284d@skida...
v6: - drop 4/6 to abort restart on unexpected failure (suggested by Dmitry) - 4,5: fix comments in handlers (suggested by Lee) - 4,5: same delay for both handlers (suggested by Lee)
v5: - introduce new 3 & 4, therefore 3 -> 5, 4 -> 6 - 3: provide dev to sys_off handler, if it is known - 4: return NOTIFY_DONE from sys_off_notify, to avoid skipping - 5: drop Reviewed-by from Dmitry, add poweroff timeout - 5,6: return notifier value instead of direct errno from handler - 5,6: use new dev field instead of passing dev as cb_data - 5,6: increase timeout values based on error observations - 6: skip unsupported reboot modes in restart handler
--- Benjamin Bara (5): kernel/reboot: emergency_restart: set correct system_state i2c: core: run atomic i2c xfer when !preemptible kernel/reboot: add device to sys_off_handler mfd: tps6586x: use devm-based power off handler mfd: tps6586x: register restart handler
drivers/i2c/i2c-core.h | 2 +- drivers/mfd/tps6586x.c | 55 ++++++++++++++++++++++++++++++++++++++++++-------- include/linux/reboot.h | 3 +++ kernel/reboot.c | 4 ++++ 4 files changed, 55 insertions(+), 9 deletions(-) --- base-commit: 197b6b60ae7bc51dd0814953c562833143b292aa change-id: 20230327-tegra-pmic-reboot-4175ff814a4b
Best regards,
From: Benjamin Bara benjamin.bara@skidata.com
As the emergency restart does not call kernel_restart_prepare(), the system_state stays in SYSTEM_RUNNING.
Since bae1d3a05a8b, this hinders i2c_in_atomic_xfer_mode() from becoming active, and therefore might lead to avoidable warnings in the restart handlers, e.g.:
[ 12.667612] WARNING: CPU: 1 PID: 1 at kernel/rcu/tree_plugin.h:318 rcu_note_context_switch+0x33c/0x6b0 [ 12.676926] Voluntary context switch within RCU read-side critical section! ... [ 12.742376] schedule_timeout from wait_for_completion_timeout+0x90/0x114 [ 12.749179] wait_for_completion_timeout from tegra_i2c_wait_completion+0x40/0x70 ... [ 12.994527] atomic_notifier_call_chain from machine_restart+0x34/0x58 [ 13.001050] machine_restart from panic+0x2a8/0x32c
Avoid these by setting the correct system_state.
Fixes: bae1d3a05a8b ("i2c: core: remove use of in_atomic()") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Benjamin Bara benjamin.bara@skidata.com --- kernel/reboot.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/reboot.c b/kernel/reboot.c index 3bba88c7ffc6..6ebef11c8876 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -74,6 +74,7 @@ void __weak (*pm_power_off)(void); void emergency_restart(void) { kmsg_dump(KMSG_DUMP_EMERG); + system_state = SYSTEM_RESTART; machine_emergency_restart(); } EXPORT_SYMBOL_GPL(emergency_restart);
On 5/9/23 22:02, Benjamin Bara wrote:
From: Benjamin Bara benjamin.bara@skidata.com
As the emergency restart does not call kernel_restart_prepare(), the system_state stays in SYSTEM_RUNNING.
Since bae1d3a05a8b, this hinders i2c_in_atomic_xfer_mode() from becoming active, and therefore might lead to avoidable warnings in the restart handlers, e.g.:
[ 12.667612] WARNING: CPU: 1 PID: 1 at kernel/rcu/tree_plugin.h:318 rcu_note_context_switch+0x33c/0x6b0 [ 12.676926] Voluntary context switch within RCU read-side critical section! ... [ 12.742376] schedule_timeout from wait_for_completion_timeout+0x90/0x114 [ 12.749179] wait_for_completion_timeout from tegra_i2c_wait_completion+0x40/0x70 ... [ 12.994527] atomic_notifier_call_chain from machine_restart+0x34/0x58 [ 13.001050] machine_restart from panic+0x2a8/0x32c
Avoid these by setting the correct system_state.
Fixes: bae1d3a05a8b ("i2c: core: remove use of in_atomic()") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Benjamin Bara benjamin.bara@skidata.com
kernel/reboot.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/reboot.c b/kernel/reboot.c index 3bba88c7ffc6..6ebef11c8876 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -74,6 +74,7 @@ void __weak (*pm_power_off)(void); void emergency_restart(void) { kmsg_dump(KMSG_DUMP_EMERG);
- system_state = SYSTEM_RESTART; machine_emergency_restart();
} EXPORT_SYMBOL_GPL(emergency_restart);
Reviewed-by: Dmitry Osipenko dmitry.osipenko@collabora.com
On 21:02-20230509, Benjamin Bara wrote:
From: Benjamin Bara benjamin.bara@skidata.com
As the emergency restart does not call kernel_restart_prepare(), the system_state stays in SYSTEM_RUNNING.
Since bae1d3a05a8b, this hinders i2c_in_atomic_xfer_mode() from becoming active, and therefore might lead to avoidable warnings in the restart handlers, e.g.:
[ 12.667612] WARNING: CPU: 1 PID: 1 at kernel/rcu/tree_plugin.h:318 rcu_note_context_switch+0x33c/0x6b0 [ 12.676926] Voluntary context switch within RCU read-side critical section! ... [ 12.742376] schedule_timeout from wait_for_completion_timeout+0x90/0x114 [ 12.749179] wait_for_completion_timeout from tegra_i2c_wait_completion+0x40/0x70 ... [ 12.994527] atomic_notifier_call_chain from machine_restart+0x34/0x58 [ 13.001050] machine_restart from panic+0x2a8/0x32c
Avoid these by setting the correct system_state.
Fixes: bae1d3a05a8b ("i2c: core: remove use of in_atomic()") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Benjamin Bara benjamin.bara@skidata.com
kernel/reboot.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/reboot.c b/kernel/reboot.c index 3bba88c7ffc6..6ebef11c8876 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -74,6 +74,7 @@ void __weak (*pm_power_off)(void); void emergency_restart(void) { kmsg_dump(KMSG_DUMP_EMERG);
- system_state = SYSTEM_RESTART; machine_emergency_restart();
} EXPORT_SYMBOL_GPL(emergency_restart);
-- 2.34.1
Tested-by: Nishanth Menon nm@ti.com
This in addition to a deeper bug in our driver seems to have helped resolve a report we had been looking at. Tested on beagleplay platform
https://lore.kernel.org/all/ZGeHMjlnob2GFyHF@francesco-nb.int.toradex.com/
Hello Nishanth,
On Wed, Jun 14, 2023 at 07:06:50PM -0500, Nishanth Menon wrote:
On 21:02-20230509, Benjamin Bara wrote:
From: Benjamin Bara benjamin.bara@skidata.com
As the emergency restart does not call kernel_restart_prepare(), the system_state stays in SYSTEM_RUNNING.
Since bae1d3a05a8b, this hinders i2c_in_atomic_xfer_mode() from becoming active, and therefore might lead to avoidable warnings in the restart handlers, e.g.:
[ 12.667612] WARNING: CPU: 1 PID: 1 at kernel/rcu/tree_plugin.h:318 rcu_note_context_switch+0x33c/0x6b0 [ 12.676926] Voluntary context switch within RCU read-side critical section! ... [ 12.742376] schedule_timeout from wait_for_completion_timeout+0x90/0x114 [ 12.749179] wait_for_completion_timeout from tegra_i2c_wait_completion+0x40/0x70 ... [ 12.994527] atomic_notifier_call_chain from machine_restart+0x34/0x58 [ 13.001050] machine_restart from panic+0x2a8/0x32c
Avoid these by setting the correct system_state.
Fixes: bae1d3a05a8b ("i2c: core: remove use of in_atomic()") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Benjamin Bara benjamin.bara@skidata.com
kernel/reboot.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/kernel/reboot.c b/kernel/reboot.c index 3bba88c7ffc6..6ebef11c8876 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -74,6 +74,7 @@ void __weak (*pm_power_off)(void); void emergency_restart(void) { kmsg_dump(KMSG_DUMP_EMERG);
- system_state = SYSTEM_RESTART; machine_emergency_restart();
} EXPORT_SYMBOL_GPL(emergency_restart);
-- 2.34.1
Tested-by: Nishanth Menon nm@ti.com
This in addition to a deeper bug in our driver seems to have helped resolve a report we had been looking at. Tested on beagleplay platform
https://lore.kernel.org/all/ZGeHMjlnob2GFyHF@francesco-nb.int.toradex.com/
Is this patch going to fix the RCU warning I reported on that email or it is just part of a more complex solution?
Francesco
On 15:21-20230615, Francesco Dolcini wrote:
-- 2.34.1
Tested-by: Nishanth Menon nm@ti.com
This in addition to a deeper bug in our driver seems to have helped resolve a report we had been looking at. Tested on beagleplay platform
https://lore.kernel.org/all/ZGeHMjlnob2GFyHF@francesco-nb.int.toradex.com/
Is this patch going to fix the RCU warning I reported on that email or it is just part of a more complex solution?
From what I see, It is part of the solution. Problem happens as follows for us: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/driv...
When i2c is not that frequently used, runtime pm disables the power domain on our platform. As part of reset or power-off, when i2c is invoked, it ends up calling into the firmware handler which (no surprise), attempts to do the wrong thing (and rightly flagged by RCU).
We are in the middle of trying various combinations out to ensure we are'nt messing things up.
From: Benjamin Bara benjamin.bara@skidata.com
Since bae1d3a05a8b, i2c transfers are non-atomic if preemption is disabled. However, non-atomic i2c transfers require preemption (e.g. in wait_for_completion() while waiting for the DMA).
panic() calls preempt_disable_notrace() before calling emergency_restart(). Therefore, if an i2c device is used for the restart, the xfer should be atomic. This avoids warnings like:
[ 12.667612] WARNING: CPU: 1 PID: 1 at kernel/rcu/tree_plugin.h:318 rcu_note_context_switch+0x33c/0x6b0 [ 12.676926] Voluntary context switch within RCU read-side critical section! ... [ 12.742376] schedule_timeout from wait_for_completion_timeout+0x90/0x114 [ 12.749179] wait_for_completion_timeout from tegra_i2c_wait_completion+0x40/0x70 ... [ 12.994527] atomic_notifier_call_chain from machine_restart+0x34/0x58 [ 13.001050] machine_restart from panic+0x2a8/0x32c
Use !preemptible() instead, which is basically the same check as pre-v5.2.
Fixes: bae1d3a05a8b ("i2c: core: remove use of in_atomic()") Cc: stable@vger.kernel.org # v5.2+ Suggested-by: Dmitry Osipenko dmitry.osipenko@collabora.com Acked-by: Wolfram Sang wsa@kernel.org Signed-off-by: Benjamin Bara benjamin.bara@skidata.com --- drivers/i2c/i2c-core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 1247e6e6e975..05b8b8dfa9bd 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -29,7 +29,7 @@ int i2c_dev_irq_from_resources(const struct resource *resources, */ static inline bool i2c_in_atomic_xfer_mode(void) { - return system_state > SYSTEM_RUNNING && irqs_disabled(); + return system_state > SYSTEM_RUNNING && !preemptible(); }
static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
On 5/9/23 22:03, Benjamin Bara wrote:
From: Benjamin Bara benjamin.bara@skidata.com
Since bae1d3a05a8b, i2c transfers are non-atomic if preemption is disabled. However, non-atomic i2c transfers require preemption (e.g. in wait_for_completion() while waiting for the DMA).
panic() calls preempt_disable_notrace() before calling emergency_restart(). Therefore, if an i2c device is used for the restart, the xfer should be atomic. This avoids warnings like:
[ 12.667612] WARNING: CPU: 1 PID: 1 at kernel/rcu/tree_plugin.h:318 rcu_note_context_switch+0x33c/0x6b0 [ 12.676926] Voluntary context switch within RCU read-side critical section! ... [ 12.742376] schedule_timeout from wait_for_completion_timeout+0x90/0x114 [ 12.749179] wait_for_completion_timeout from tegra_i2c_wait_completion+0x40/0x70 ... [ 12.994527] atomic_notifier_call_chain from machine_restart+0x34/0x58 [ 13.001050] machine_restart from panic+0x2a8/0x32c
Use !preemptible() instead, which is basically the same check as pre-v5.2.
Fixes: bae1d3a05a8b ("i2c: core: remove use of in_atomic()") Cc: stable@vger.kernel.org # v5.2+ Suggested-by: Dmitry Osipenko dmitry.osipenko@collabora.com Acked-by: Wolfram Sang wsa@kernel.org Signed-off-by: Benjamin Bara benjamin.bara@skidata.com
drivers/i2c/i2c-core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 1247e6e6e975..05b8b8dfa9bd 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -29,7 +29,7 @@ int i2c_dev_irq_from_resources(const struct resource *resources, */ static inline bool i2c_in_atomic_xfer_mode(void) {
- return system_state > SYSTEM_RUNNING && irqs_disabled();
- return system_state > SYSTEM_RUNNING && !preemptible();
} static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
Reviewed-by: Dmitry Osipenko dmitry.osipenko@collabora.com
On 21:03-20230509, Benjamin Bara wrote:
From: Benjamin Bara benjamin.bara@skidata.com
Since bae1d3a05a8b, i2c transfers are non-atomic if preemption is disabled. However, non-atomic i2c transfers require preemption (e.g. in wait_for_completion() while waiting for the DMA).
panic() calls preempt_disable_notrace() before calling emergency_restart(). Therefore, if an i2c device is used for the restart, the xfer should be atomic. This avoids warnings like:
[ 12.667612] WARNING: CPU: 1 PID: 1 at kernel/rcu/tree_plugin.h:318 rcu_note_context_switch+0x33c/0x6b0 [ 12.676926] Voluntary context switch within RCU read-side critical section! ... [ 12.742376] schedule_timeout from wait_for_completion_timeout+0x90/0x114 [ 12.749179] wait_for_completion_timeout from tegra_i2c_wait_completion+0x40/0x70 ... [ 12.994527] atomic_notifier_call_chain from machine_restart+0x34/0x58 [ 13.001050] machine_restart from panic+0x2a8/0x32c
Use !preemptible() instead, which is basically the same check as pre-v5.2.
Fixes: bae1d3a05a8b ("i2c: core: remove use of in_atomic()") Cc: stable@vger.kernel.org # v5.2+ Suggested-by: Dmitry Osipenko dmitry.osipenko@collabora.com Acked-by: Wolfram Sang wsa@kernel.org Signed-off-by: Benjamin Bara benjamin.bara@skidata.com
drivers/i2c/i2c-core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 1247e6e6e975..05b8b8dfa9bd 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -29,7 +29,7 @@ int i2c_dev_irq_from_resources(const struct resource *resources, */ static inline bool i2c_in_atomic_xfer_mode(void) {
- return system_state > SYSTEM_RUNNING && irqs_disabled();
- return system_state > SYSTEM_RUNNING && !preemptible();
} static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
-- 2.34.1
Tested-by: Nishanth Menon nm@ti.com
This in addition to a deeper bug in our driver seems to have helped resolve a report we had been looking at. Tested on beagleplay platform
https://lore.kernel.org/all/ZGeHMjlnob2GFyHF@francesco-nb.int.toradex.com/
linux-stable-mirror@lists.linaro.org