diff mbox series

[v9,1/3] dt-bindings: thermal-zones: Document critical-action

Message ID 20231001030014.1244633-1-festevam@gmail.com
State Changes Requested
Headers show
Series [v9,1/3] dt-bindings: thermal-zones: Document critical-action | expand

Checks

Context Check Description
robh/checkpatch success
robh/patch-applied success
robh/dtbs-check warning build log
robh/dt-meta-schema success

Commit Message

Fabio Estevam Oct. 1, 2023, 3 a.m. UTC
From: Fabio Estevam <festevam@denx.de>

Document the critical-action property to describe the thermal action
the OS should perform after the critical temperature is reached.

The possible values are "shutdown" and "reboot".

The motivation for introducing the critical-action property is that
different systems may need different thermal actions when the critical
temperature is reached.

For example, a desktop PC may want the OS to trigger a shutdown
when the critical temperature is reached.

However, in some embedded cases, such behavior does not suit well,
as the board may be unattended in the field and rebooting may be a
better approach.

The bootloader may also benefit from this new property as it can check
the SoC temperature and in case the temperature is above the critical
point, it can trigger a shutdown or reboot accordingly.

Signed-off-by: Fabio Estevam <festevam@denx.de>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Changes since v8:
- Go back to putting critical-action as a thermal-zone property. (Daniel)

 .../devicetree/bindings/thermal/thermal-zones.yaml       | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

Daniel Lezcano Oct. 1, 2023, 4:48 p.m. UTC | #1
On 01/10/2023 05:00, Fabio Estevam wrote:
> From: Fabio Estevam <festevam@denx.de>
> 
> Document the critical-action property to describe the thermal action
> the OS should perform after the critical temperature is reached.
> 
> The possible values are "shutdown" and "reboot".
> 
> The motivation for introducing the critical-action property is that
> different systems may need different thermal actions when the critical
> temperature is reached.
> 
> For example, a desktop PC may want the OS to trigger a shutdown
> when the critical temperature is reached.

 From my POV, 'critical' means kernel handles the action. We can not 
trust the userspace at this point.

The 'hot' trip point will result on a notification to the OS which can 
then take an last resort action before 'critical' kicks in (suspend, 
kill process, cpu hotplug, whatever)

> However, in some embedded cases, such behavior does not suit well,
> as the board may be unattended in the field and rebooting may be a
> better approach.
> 
> The bootloader may also benefit from this new property as it can check
> the SoC temperature and in case the temperature is above the critical
> point, it can trigger a shutdown or reboot accordingly.
> 
> Signed-off-by: Fabio Estevam <festevam@denx.de>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---
> Changes since v8:
> - Go back to putting critical-action as a thermal-zone property. (Daniel)
> 
>   .../devicetree/bindings/thermal/thermal-zones.yaml       | 9 +++++++++
>   1 file changed, 9 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
> index 4f3acdc4dec0..c2e4d28f885b 100644
> --- a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
> +++ b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
> @@ -75,6 +75,15 @@ patternProperties:
>             framework and assumes that the thermal sensors in this zone
>             support interrupts.
>   
> +      critical-action:
> +        $ref: /schemas/types.yaml#/definitions/string
> +        description:
> +          The action the OS should perform after the critical temperature is reached.
> +
> +        enum:
> +          - shutdown
> +          - reboot
> +
>         thermal-sensors:
>           $ref: /schemas/types.yaml#/definitions/phandle-array
>           maxItems: 1
Daniel Lezcano Oct. 1, 2023, 5:09 p.m. UTC | #2
On 01/10/2023 05:00, Fabio Estevam wrote:
> From: Fabio Estevam <festevam@denx.de>
> 
> Document the critical-action property to describe the thermal action
> the OS should perform after the critical temperature is reached.
> 
> The possible values are "shutdown" and "reboot".
> 
> The motivation for introducing the critical-action property is that
> different systems may need different thermal actions when the critical
> temperature is reached.
> 
> For example, a desktop PC may want the OS to trigger a shutdown
> when the critical temperature is reached.
> 
> However, in some embedded cases, such behavior does not suit well,
> as the board may be unattended in the field and rebooting may be a
> better approach.
> 
> The bootloader may also benefit from this new property as it can check
> the SoC temperature and in case the temperature is above the critical
> point, it can trigger a shutdown or reboot accordingly.
> 
> Signed-off-by: Fabio Estevam <festevam@denx.de>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---
> Changes since v8:
> - Go back to putting critical-action as a thermal-zone property. (Daniel)
> 
>   .../devicetree/bindings/thermal/thermal-zones.yaml       | 9 +++++++++
>   1 file changed, 9 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
> index 4f3acdc4dec0..c2e4d28f885b 100644
> --- a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
> +++ b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
> @@ -75,6 +75,15 @@ patternProperties:
>             framework and assumes that the thermal sensors in this zone
>             support interrupts.
>   
> +      critical-action:
> +        $ref: /schemas/types.yaml#/definitions/string
> +        description:
> +          The action the OS should perform after the critical temperature is reached.
> +
> +        enum:
> +          - shutdown
> +          - reboot

This option is dangerous and should be more documented.

"The action the OS should perform after the critical temperature is 
reached. By default the system will shutdown as a safe action to prevent 
to damage the hardware if the property is not set. The shutdown action 
should be always the default. Choose carefully 'reboot' as the hardware 
may be in thermal stress, thus leading to infinite reboots damaging the 
hardware. Make sure the firmware will act as the last resort and take 
over the thermal control."

[ and more info if needed ]

(written with best effort with my non native language ;)

>         thermal-sensors:
>           $ref: /schemas/types.yaml#/definitions/phandle-array
>           maxItems: 1
Daniel Lezcano Oct. 1, 2023, 5:23 p.m. UTC | #3
On 01/10/2023 05:00, Fabio Estevam wrote:
> From: Fabio Estevam <festevam@denx.de>
> 
> Introduce thermal_zone_device_critical_reboot() to trigger an
> emergency reboot.
> 
> It is a counterpart of thermal_zone_device_critical() with the
> difference that it will force a reboot instead of shutdown.
> 
> The motivation for doing this is to allow the thermal subystem
> to trigger a reboot when the temperature reaches the critical
> temperature.
> 
> Signed-off-by: Fabio Estevam <festevam@denx.de>
> ---
> Changes since v8:
> - Introduce thermal_zone_device_critical_reboot() to accomodate
> Daniel's suggestions.
> 
>   drivers/thermal/thermal_core.c | 19 +++++++++++++++++--
>   include/linux/reboot.h         | 13 ++++++++++++-
>   include/linux/thermal.h        |  1 +
>   kernel/reboot.c                | 32 +++++++++++++++++++-------------
>   4 files changed, 49 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
> index 38d393f139d8..277aafb294db 100644
> --- a/drivers/thermal/thermal_core.c
> +++ b/drivers/thermal/thermal_core.c
> @@ -313,21 +313,36 @@ static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip)
>   		       def_governor->throttle(tz, trip);
>   }
>   
> -void thermal_zone_device_critical(struct thermal_zone_device *tz)
> +static void thermal_zone_device_shutdown(struct thermal_zone_device *tz, bool shutdown)

Probably nit picking but is it possible to rename to:

static void thermal_zone_device_halt(struct thermal_zone_device *tz, 
bool shutdown)


>   {
>   	/*
>   	 * poweroff_delay_ms must be a carefully profiled positive value.
>   	 * Its a must for forced_emergency_poweroff_work to be scheduled.
>   	 */
>   	int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;
> +	static const char *msg = "Temperature too high";

Why use 'static' ?

>   	dev_emerg(&tz->device, "%s: critical temperature reached, "
>   		  "shutting down\n", tz->type);

Now the function can do 'shutdown' or 'reboot', so the message should 
reflect that.

However, the reason will be displayed in the 
hw_protection_shutdown/reboot, so having:

dev_emerg(&tz->device, "%s: critical temperature reached\n", tz->type);

> -	hw_protection_shutdown("Temperature too high", poweroff_delay_ms);
> +	if (shutdown)
> +		hw_protection_shutdown(msg, poweroff_delay_ms);
> +	else
> +		hw_protection_reboot(msg, poweroff_delay_ms);
> +}
> +
> +void thermal_zone_device_critical(struct thermal_zone_device *tz)
> +{
> +	thermal_zone_device_shutdown(tz, true);
>   }
>   EXPORT_SYMBOL(thermal_zone_device_critical);

Rename to thermal_zone_device_critical_shutdown() for consistency (in a 
separate patch).

>   
> +void thermal_zone_device_critical_reboot(struct thermal_zone_device *tz)
> +{
> +	thermal_zone_device_shutdown(tz, false);
> +}
> +EXPORT_SYMBOL(thermal_zone_device_critical_reboot);
> +
>   static void handle_critical_trips(struct thermal_zone_device *tz,
>   				  int trip, int trip_temp, enum thermal_trip_type trip_type)
>   {
> diff --git a/include/linux/reboot.h b/include/linux/reboot.h
> index c4cc3b89ced1..4683e117c753 100644
> --- a/include/linux/reboot.h
> +++ b/include/linux/reboot.h
> @@ -177,7 +177,18 @@ void ctrl_alt_del(void);
>   
>   extern void orderly_poweroff(bool force);
>   extern void orderly_reboot(void);
> -void hw_protection_shutdown(const char *reason, int ms_until_forced);
> +
> +void __hw_protection_shutdown(const char *reason, int ms_until_forced, bool shutdown);
> +
> +static inline void hw_protection_reboot(const char *reason, int ms_until_forced)
> +{
> +	__hw_protection_shutdown(reason, ms_until_forced, false);
> +}
> +
> +static inline void hw_protection_shutdown(const char *reason, int ms_until_forced)
> +{
> +	__hw_protection_shutdown(reason, ms_until_forced, true);
> +}


Those changes should be in a separate patch.

>   /*
>    * Emergency restart, callable from an interrupt handler.
> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index 6cfcae22ba12..c5ebb44ae8a6 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -353,6 +353,7 @@ int thermal_zone_get_offset(struct thermal_zone_device *tz);
>   int thermal_zone_device_enable(struct thermal_zone_device *tz);
>   int thermal_zone_device_disable(struct thermal_zone_device *tz);
>   void thermal_zone_device_critical(struct thermal_zone_device *tz);
> +void thermal_zone_device_critical_reboot(struct thermal_zone_device *tz);
>   #else
>   static inline struct thermal_zone_device *thermal_zone_device_register_with_trips(
>   					const char *type,
> diff --git a/kernel/reboot.c b/kernel/reboot.c
> index 395a0ea3c7a8..8b3010b88ed6 100644
> --- a/kernel/reboot.c
> +++ b/kernel/reboot.c
> @@ -957,21 +957,25 @@ static void hw_failure_emergency_poweroff(int poweroff_delay_ms)
>   }
>   
>   /**
> - * hw_protection_shutdown - Trigger an emergency system poweroff
> + * __hw_protection_shutdown - Trigger an emergency system shutdown or reboot
>    *
> - * @reason:		Reason of emergency shutdown to be printed.
> - * @ms_until_forced:	Time to wait for orderly shutdown before tiggering a
> - *			forced shudown. Negative value disables the forced
> - *			shutdown.
> + * @reason:		Reason of emergency shutdown or reboot to be printed.
> + * @ms_until_forced:	Time to wait for orderly shutdown or reboot before
> + *			triggering it. Negative value disables the forced
> + *			shutdown or reboot.
> + * @shutdown:		If true, indicates that a shutdown will happen
> + *			after the critical tempeature is reached.
> + *			If false, indicates that a reboot will happen
> + *			after the critical tempeature is reached.
>    *
> - * Initiate an emergency system shutdown in order to protect hardware from
> - * further damage. Usage examples include a thermal protection or a voltage or
> - * current regulator failures.
> - * NOTE: The request is ignored if protection shutdown is already pending even
> - * if the previous request has given a large timeout for forced shutdown.
> + * Initiate an emergency system shutdown or reboot in order to protect
> + * hardware from further damage. Usage examples include a thermal protection.
> + * NOTE: The request is ignored if protection shutdown or reboot is already
> + * pending even if the previous request has given a large timeout for forced
> + * shutdown/reboot.
>    * Can be called from any context.
>    */
> -void hw_protection_shutdown(const char *reason, int ms_until_forced)
> +void __hw_protection_shutdown(const char *reason, int ms_until_forced, bool shutdown)
>   {
>   	static atomic_t allow_proceed = ATOMIC_INIT(1);
>   
> @@ -986,9 +990,11 @@ void hw_protection_shutdown(const char *reason, int ms_until_forced)
>   	 * orderly_poweroff failure
>   	 */
>   	hw_failure_emergency_poweroff(ms_until_forced);
> -	orderly_poweroff(true);
> +	if (shutdown)
> +		orderly_poweroff(true);
> +	else
> +		orderly_reboot();
>   }
> -EXPORT_SYMBOL_GPL(hw_protection_shutdown);
Same comment

>   static int __init reboot_setup(char *str)
>   {
Daniel Lezcano Oct. 1, 2023, 5:25 p.m. UTC | #4
On 01/10/2023 05:00, Fabio Estevam wrote:
> From: Fabio Estevam <festevam@denx.de>
> 
> Currently, the default mechanism is to trigger a shutdown after the
> critical temperature is reached.
> 
> In some embedded cases, such behavior does not suit well, as the board may
> be unattended in the field and rebooting may be a better approach.
> 
> The bootloader may also check the temperature and only allow the boot to
> proceed when the temperature is below a certain threshold.
> 
> Introduce support for allowing a reboot to be triggered after the
> critical temperature is reached.
> 
> If the "critical-action" devicetree property is not found, fall back to
> the shutdown action to preserve the existing default behavior.
> 
> If a custom ops->critical exists, then it takes preference over
> critical-actions.
> 
> Tested on a i.MX8MM board with the following devicetree changes:
> 
> 	thermal-zones {
> 		cpu-thermal {
> 			critical-action = "reboot";
> 		};
> 	};
> 
> Signed-off-by: Fabio Estevam <festevam@denx.de>
> ---

Sounds good to me


> Changes since v8:
> - Simplify the logic for calling thermal_zone_device_critical_reboot(). (Daniel).
> 
>   drivers/thermal/thermal_of.c | 6 ++++++
>   1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c
> index 1e0655b63259..4d6c22e0ed85 100644
> --- a/drivers/thermal/thermal_of.c
> +++ b/drivers/thermal/thermal_of.c
> @@ -475,6 +475,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
>   	struct thermal_zone_params tzp = {};
>   	struct thermal_zone_device_ops *of_ops;
>   	struct device_node *np;
> +	const char *action;
>   	int delay, pdelay;
>   	int ntrips, mask;
>   	int ret;
> @@ -511,6 +512,11 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
>   
>   	mask = GENMASK_ULL((ntrips) - 1, 0);
>   
> +	ret = of_property_read_string(np, "critical-action", &action);
> +	if (!ret)
> +		if (!of_ops->critical && !strcasecmp(action, "reboot"))
> +			of_ops->critical = thermal_zone_device_critical_reboot;
> +
>   	tz = thermal_zone_device_register_with_trips(np->name, trips, ntrips,
>   						     mask, data, of_ops, &tzp,
>   						     pdelay, delay);
diff mbox series

Patch

diff --git a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
index 4f3acdc4dec0..c2e4d28f885b 100644
--- a/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
+++ b/Documentation/devicetree/bindings/thermal/thermal-zones.yaml
@@ -75,6 +75,15 @@  patternProperties:
           framework and assumes that the thermal sensors in this zone
           support interrupts.
 
+      critical-action:
+        $ref: /schemas/types.yaml#/definitions/string
+        description:
+          The action the OS should perform after the critical temperature is reached.
+
+        enum:
+          - shutdown
+          - reboot
+
       thermal-sensors:
         $ref: /schemas/types.yaml#/definitions/phandle-array
         maxItems: 1