dt-bindings: thermal-zones: Document critical-action
Subsystems (2)
PATCH 1/4 dt-bindings: thermal-zones: Document critical-action
From: Fabio Estevam <[email protected]>
Document the critical-action property to describe the thermal action that will be taken after the critical temperature is reached.
The possible values are:
- 0 for shutdown
- 1 for reboot.
--- .../devicetree/bindings/thermal/thermal-zones.yaml | 8 ++++++++ 1 file changed, 8 insertions(+)
Documentation/devicetree/bindings/thermal/thermal-zones.yaml +8 -0
@@ -75,6 +75,14 @@ patternProperties: framework and assumes that the thermal sensors in this zone support interrupts. + critical-action: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + The action that happens after the critical temperature is reached. + Possible values are 0 for shutdown and 1 for reboot. + + enum: [ 0, 1 ] + thermal-sensors: $ref: /schemas/types.yaml#/definitions/phandle-array maxItems: 1
Signature · 1 line
2.34.1
PATCH 2/4 dt-bindings: thermal: Document the values for the 'critical-action'
From: Fabio Estevam <[email protected]>
Document the possible values for the 'critical-action' property to make it more readable in the devicetree.
--- include/dt-bindings/thermal/thermal.h | 4 ++++ 1 file changed, 4 insertions(+)
include/dt-bindings/thermal/thermal.h +4 -0
@@ -12,5 +12,9 @@/* On cooling devices upper and lower limits */ #define THERMAL_NO_LIMIT (~0) +/* Possible values for the 'critical-action' property */ +#define THERMAL_CRITICAL_ACTION_SHUTDOWN 0 +#define THERMAL_CRITICAL_ACTION_REBOOT 1 +#endif
Signature · 1 line
2.34.1
PATCH 3/4 reboot: Introduce hw_protection_reboot()
In reply to Fabio EstevamFrom: Fabio Estevam <[email protected]>
Introduce hw_protection_reboot() to trigger an emergency reboot.
It is a counterpart of hw_protection_shutdown() 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.
--- include/linux/reboot.h | 1 + kernel/reboot.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+)
include/linux/reboot.h +1 -0
@@ -174,6 +174,7 @@ void ctrl_alt_del(void);extern void orderly_poweroff (bool force);extern void orderly_reboot (void ); +void hw_protection_reboot (const char *reason,int ms_until_forced);void hw_protection_shutdown (const char *reason,int ms_until_forced);/*
kernel/reboot.c +34 -0
@@ -952,6 +952,40 @@ static void hw_failure_emergency_poweroff(int poweroff_delay_ms) msecs_to_jiffies(poweroff_delay_ms)); } +/** +* hw_protection_reboot - Trigger an emergency system reboot +* +* @reason: Reason of emergency reboot to be printed. +* @ms_until_forced: Time to wait for orderly reboot before tiggering a +* forced reboot. Negative value disables the forced +* reboot. +* +* Initiate an emergency system reboot in order to protect hardware from +* further damage. Usage examples include a thermal protection. +* +* NOTE: The request is ignored if protection reboot is already pending even +* if the previous request has given a large timeout for forced reboot. +* Can be called from any context. +*/ +void hw_protection_reboot (const char *reason,int ms_until_forced) +{ +static atomic_t allow_proceed =ATOMIC_INIT (1 ); + +pr_emerg ("HARDWARE PROTECTION reboot (%s)\n" , reason); + +/* Reboot should be initiated only once. */ +if (!atomic_dec_and_test (&allow_proceed)) +return ; + +/* +* Queue a backup emergency reboot in the event of +* orderly_reboot failure +*/ +hw_failure_emergency_poweroff (ms_until_forced); +orderly_reboot (); +} +EXPORT_SYMBOL_GPL (hw_protection_reboot); +/** * hw_protection_shutdown - Trigger an emergency system poweroff *
Signature · 1 line
2.34.1
PATCH 4/4 thermal: thermal_core: Allow rebooting after critical temp
In reply to Fabio EstevamFrom: Fabio Estevam <[email protected]>
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.
Tested on a i.MX8MM board with the following devicetre changes:
thermal-zones {
cpu-thermal {
critical-action = <THERMAL_CRITICAL_ACTION_REBOOT>;
};
};--- drivers/thermal/thermal_core.c | 8 +++++++- drivers/thermal/thermal_of.c | 17 ++++++++++++++--- include/linux/thermal.h | 6 ++++++ 3 files changed, 27 insertions(+), 4 deletions(-)
drivers/thermal/thermal_core.c +7 -1
@@ -320,11 +320,17 @@ void thermal_zone_device_critical(struct thermal_zone_device *tz)* Its a must for forced_emergency_poweroff_work to be scheduled. */ int poweroff_delay_ms =CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS ; +void (*hw_protection_action)(const char *reason,int ms_until_forced);dev_emerg (&tz->device,"%s: critical temperature reached, " "shutting down\n" , tz->type); -hw_protection_shutdown ("Temperature too high" , poweroff_delay_ms); + hw_protection_action = hw_protection_shutdown; + +if (tz->action ==THERMAL_CRITICAL_ACTION_REBOOT ) + hw_protection_action = hw_protection_reboot; + +hw_protection_action ("Temperature too high" , poweroff_delay_ms); }EXPORT_SYMBOL (thermal_zone_device_critical);
drivers/thermal/thermal_of.c +14 -3
@@ -218,7 +218,8 @@ static struct device_node *of_thermal_zone_find(struct device_node *sensor, intreturn tz; } -static int thermal_of_monitor_init (struct device_node *np,int *delay,int *pdelay) +static int thermal_of_monitor_init (struct device_node *np,int *delay, +int *pdelay,int *critical_action) {int ret;
@@ -234,6 +235,14 @@ static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdelreturn ret; } +/* +* If the "critical-action" property is not found, fall back to +* the shutdown action to keep the existing behavior. +*/ + ret =of_property_read_u32 (np,"critical-action" , critical_action); +if (ret <0 ) + *critical_action =THERMAL_CRITICAL_ACTION_SHUTDOWN ; +return 0 ; }
@@ -471,7 +480,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; -int delay, pdelay; +int delay, pdelay, critical_action;int ntrips, mask;int ret;
@@ -494,7 +503,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node * goto out_kfree_of_ops; } - ret =thermal_of_monitor_init (np, &delay, &pdelay); + ret =thermal_of_monitor_init (np, &delay, &pdelay, &critical_action);if (ret) {pr_err ("Failed to initialize monitoring delays from %pOFn\n" , np); goto out_kfree_trips;
@@ -516,6 +525,8 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node * goto out_kfree_trips; } + tz->action = critical_action; + ret =thermal_zone_device_enable (tz);if (ret) { pr_err("Failed to enabled thermal zone '%s', id=%d: %d\n",
include/linux/thermal.h +6 -0
@@ -34,6 +34,11 @@ struct thermal_cooling_device;struct thermal_instance ;struct thermal_attr ; +enum thermal_action { +THERMAL_CRITICAL_ACTION_SHUTDOWN ,/* shutdown when crit temperature is reached */ +THERMAL_CRITICAL_ACTION_REBOOT ,/* reboot when crit temperature is reached */ +}; +enum thermal_trend {THERMAL_TREND_STABLE ,/* temperature is stable */ THERMAL_TREND_RAISING ,/* temperature is raising */
@@ -185,6 +190,7 @@ struct thermal_zone_device {struct list_head node;struct delayed_work poll_queue;enum thermal_notify_event notify_event; +enum thermal_action action; };/**
Signature · 1 line
2.34.1