···582582This function serves as an arbitrator to set the state of a cooling583583device. It sets the cooling device to the deepest cooling state if584584possible.585585+586586+6. thermal_emergency_poweroff:587587+588588+On an event of critical trip temperature crossing. Thermal framework589589+allows the system to shutdown gracefully by calling orderly_poweroff().590590+In the event of a failure of orderly_poweroff() to shut down the system591591+we are in danger of keeping the system alive at undesirably high592592+temperatures. To mitigate this high risk scenario we program a work593593+queue to fire after a pre-determined number of seconds to start594594+an emergency shutdown of the device using the kernel_power_off()595595+function. In case kernel_power_off() fails then finally596596+emergency_restart() is called in the worst case.597597+598598+The delay should be carefully profiled so as to give adequate time for599599+orderly_poweroff(). In case of failure of an orderly_poweroff() the600600+emergency poweroff kicks in after the delay has elapsed and shuts down601601+the system.602602+603603+If set to 0 emergency poweroff will not be supported. So a carefully604604+profiled non-zero positive value is a must for emergerncy poweroff to be605605+triggered.
+17
drivers/thermal/Kconfig
···15151616if THERMAL17171818+config THERMAL_EMERGENCY_POWEROFF_DELAY_MS1919+ int "Emergency poweroff delay in milli-seconds"2020+ depends on THERMAL2121+ default 02222+ help2323+ Thermal subsystem will issue a graceful shutdown when2424+ critical temperatures are reached using orderly_poweroff(). In2525+ case of failure of an orderly_poweroff(), the thermal emergency2626+ poweroff kicks in after a delay has elapsed and shuts down the system.2727+ This config is number of milliseconds to delay before emergency2828+ poweroff kicks in. Similarly to the critical trip point,2929+ the delay should be carefully profiled so as to give adequate3030+ time for orderly_poweroff() to finish on regular execution.3131+ If set to 0 emergency poweroff will not be supported.3232+3333+ In doubt, leave as 0.3434+1835config THERMAL_HWMON1936 bool2037 prompt "Expose thermal sensors as hwmon device"
+63-1
drivers/thermal/thermal_core.c
···45454646static DEFINE_MUTEX(thermal_list_lock);4747static DEFINE_MUTEX(thermal_governor_lock);4848+static DEFINE_MUTEX(poweroff_lock);48494950static atomic_t in_suspend;5151+static bool power_off_triggered;50525153static struct thermal_governor *def_governor;5254···324322 def_governor->throttle(tz, trip);325323}326324325325+/**326326+ * thermal_emergency_poweroff_func - emergency poweroff work after a known delay327327+ * @work: work_struct associated with the emergency poweroff function328328+ *329329+ * This function is called in very critical situations to force330330+ * a kernel poweroff after a configurable timeout value.331331+ */332332+static void thermal_emergency_poweroff_func(struct work_struct *work)333333+{334334+ /*335335+ * We have reached here after the emergency thermal shutdown336336+ * Waiting period has expired. This means orderly_poweroff has337337+ * not been able to shut off the system for some reason.338338+ * Try to shut down the system immediately using kernel_power_off339339+ * if populated340340+ */341341+ WARN(1, "Attempting kernel_power_off: Temperature too high\n");342342+ kernel_power_off();343343+344344+ /*345345+ * Worst of the worst case trigger emergency restart346346+ */347347+ WARN(1, "Attempting emergency_restart: Temperature too high\n");348348+ emergency_restart();349349+}350350+351351+static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work,352352+ thermal_emergency_poweroff_func);353353+354354+/**355355+ * thermal_emergency_poweroff - Trigger an emergency system poweroff356356+ *357357+ * This may be called from any critical situation to trigger a system shutdown358358+ * after a known period of time. By default this is not scheduled.359359+ */360360+void thermal_emergency_poweroff(void)361361+{362362+ int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;363363+ /*364364+ * poweroff_delay_ms must be a carefully profiled positive value.365365+ * Its a must for thermal_emergency_poweroff_work to be scheduled366366+ */367367+ if (poweroff_delay_ms <= 0)368368+ return;369369+ schedule_delayed_work(&thermal_emergency_poweroff_work,370370+ msecs_to_jiffies(poweroff_delay_ms));371371+}372372+327373static void handle_critical_trips(struct thermal_zone_device *tz,328374 int trip, enum thermal_trip_type trip_type)329375{···392342 dev_emerg(&tz->device,393343 "critical temperature reached(%d C),shutting down\n",394344 tz->temperature / 1000);395395- orderly_poweroff(true);345345+ mutex_lock(&poweroff_lock);346346+ if (!power_off_triggered) {347347+ /*348348+ * Queue a backup emergency shutdown in the event of349349+ * orderly_poweroff failure350350+ */351351+ thermal_emergency_poweroff();352352+ orderly_poweroff(true);353353+ power_off_triggered = true;354354+ }355355+ mutex_unlock(&poweroff_lock);396356 }397357}398358···15231463{15241464 int result;1525146514661466+ mutex_init(&poweroff_lock);15261467 result = thermal_register_governors();15271468 if (result)15281469 goto error;···15581497 ida_destroy(&thermal_cdev_ida);15591498 mutex_destroy(&thermal_list_lock);15601499 mutex_destroy(&thermal_governor_lock);15001500+ mutex_destroy(&poweroff_lock);15611501 return result;15621502}15631503