|
@@ -324,6 +324,54 @@ static void handle_non_critical_trips(struct thermal_zone_device *tz,
|
|
|
def_governor->throttle(tz, trip);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * thermal_emergency_poweroff_func - emergency poweroff work after a known delay
|
|
|
+ * @work: work_struct associated with the emergency poweroff function
|
|
|
+ *
|
|
|
+ * This function is called in very critical situations to force
|
|
|
+ * a kernel poweroff after a configurable timeout value.
|
|
|
+ */
|
|
|
+static void thermal_emergency_poweroff_func(struct work_struct *work)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * We have reached here after the emergency thermal shutdown
|
|
|
+ * Waiting period has expired. This means orderly_poweroff has
|
|
|
+ * not been able to shut off the system for some reason.
|
|
|
+ * Try to shut down the system immediately using kernel_power_off
|
|
|
+ * if populated
|
|
|
+ */
|
|
|
+ WARN(1, "Attempting kernel_power_off: Temperature too high\n");
|
|
|
+ kernel_power_off();
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Worst of the worst case trigger emergency restart
|
|
|
+ */
|
|
|
+ WARN(1, "Attempting emergency_restart: Temperature too high\n");
|
|
|
+ emergency_restart();
|
|
|
+}
|
|
|
+
|
|
|
+static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work,
|
|
|
+ thermal_emergency_poweroff_func);
|
|
|
+
|
|
|
+/**
|
|
|
+ * thermal_emergency_poweroff - Trigger an emergency system poweroff
|
|
|
+ *
|
|
|
+ * This may be called from any critical situation to trigger a system shutdown
|
|
|
+ * after a known period of time. By default this is not scheduled.
|
|
|
+ */
|
|
|
+void thermal_emergency_poweroff(void)
|
|
|
+{
|
|
|
+ int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;
|
|
|
+ /*
|
|
|
+ * poweroff_delay_ms must be a carefully profiled positive value.
|
|
|
+ * Its a must for thermal_emergency_poweroff_work to be scheduled
|
|
|
+ */
|
|
|
+ if (poweroff_delay_ms <= 0)
|
|
|
+ return;
|
|
|
+ schedule_delayed_work(&thermal_emergency_poweroff_work,
|
|
|
+ msecs_to_jiffies(poweroff_delay_ms));
|
|
|
+}
|
|
|
+
|
|
|
static void handle_critical_trips(struct thermal_zone_device *tz,
|
|
|
int trip, enum thermal_trip_type trip_type)
|
|
|
{
|
|
@@ -346,6 +394,11 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
|
|
|
tz->temperature / 1000);
|
|
|
mutex_lock(&poweroff_lock);
|
|
|
if (!power_off_triggered) {
|
|
|
+ /*
|
|
|
+ * Queue a backup emergency shutdown in the event of
|
|
|
+ * orderly_poweroff failure
|
|
|
+ */
|
|
|
+ thermal_emergency_poweroff();
|
|
|
orderly_poweroff(true);
|
|
|
power_off_triggered = true;
|
|
|
}
|