|
@@ -378,24 +378,54 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip)
|
|
|
monitor_thermal_zone(tz);
|
|
|
}
|
|
|
|
|
|
+static int thermal_zone_get_temp(struct thermal_zone_device *tz,
|
|
|
+ unsigned long *temp)
|
|
|
+{
|
|
|
+ int ret = 0, count;
|
|
|
+ unsigned long crit_temp = -1UL;
|
|
|
+ enum thermal_trip_type type;
|
|
|
+
|
|
|
+ mutex_lock(&tz->lock);
|
|
|
+
|
|
|
+ ret = tz->ops->get_temp(tz, temp);
|
|
|
+#ifdef CONFIG_THERMAL_EMULATION
|
|
|
+ if (!tz->emul_temperature)
|
|
|
+ goto skip_emul;
|
|
|
+
|
|
|
+ for (count = 0; count < tz->trips; count++) {
|
|
|
+ ret = tz->ops->get_trip_type(tz, count, &type);
|
|
|
+ if (!ret && type == THERMAL_TRIP_CRITICAL) {
|
|
|
+ ret = tz->ops->get_trip_temp(tz, count, &crit_temp);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ret)
|
|
|
+ goto skip_emul;
|
|
|
+
|
|
|
+ if (*temp < crit_temp)
|
|
|
+ *temp = tz->emul_temperature;
|
|
|
+skip_emul:
|
|
|
+#endif
|
|
|
+ mutex_unlock(&tz->lock);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static void update_temperature(struct thermal_zone_device *tz)
|
|
|
{
|
|
|
long temp;
|
|
|
int ret;
|
|
|
|
|
|
- mutex_lock(&tz->lock);
|
|
|
-
|
|
|
- ret = tz->ops->get_temp(tz, &temp);
|
|
|
+ ret = thermal_zone_get_temp(tz, &temp);
|
|
|
if (ret) {
|
|
|
dev_warn(&tz->device, "failed to read out thermal zone %d\n",
|
|
|
tz->id);
|
|
|
- goto exit;
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
+ mutex_lock(&tz->lock);
|
|
|
tz->last_temperature = tz->temperature;
|
|
|
tz->temperature = temp;
|
|
|
-
|
|
|
-exit:
|
|
|
mutex_unlock(&tz->lock);
|
|
|
}
|
|
|
|
|
@@ -438,10 +468,7 @@ temp_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
|
long temperature;
|
|
|
int ret;
|
|
|
|
|
|
- if (!tz->ops->get_temp)
|
|
|
- return -EPERM;
|
|
|
-
|
|
|
- ret = tz->ops->get_temp(tz, &temperature);
|
|
|
+ ret = thermal_zone_get_temp(tz, &temperature);
|
|
|
|
|
|
if (ret)
|
|
|
return ret;
|
|
@@ -701,6 +728,31 @@ policy_show(struct device *dev, struct device_attribute *devattr, char *buf)
|
|
|
return sprintf(buf, "%s\n", tz->governor->name);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_THERMAL_EMULATION
|
|
|
+static ssize_t
|
|
|
+emul_temp_store(struct device *dev, struct device_attribute *attr,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
|
|
|
+ int ret = 0;
|
|
|
+ unsigned long temperature;
|
|
|
+
|
|
|
+ if (kstrtoul(buf, 10, &temperature))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (!tz->ops->set_emul_temp) {
|
|
|
+ mutex_lock(&tz->lock);
|
|
|
+ tz->emul_temperature = temperature;
|
|
|
+ mutex_unlock(&tz->lock);
|
|
|
+ } else {
|
|
|
+ ret = tz->ops->set_emul_temp(tz, temperature);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret ? ret : count;
|
|
|
+}
|
|
|
+static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store);
|
|
|
+#endif/*CONFIG_THERMAL_EMULATION*/
|
|
|
+
|
|
|
static DEVICE_ATTR(type, 0444, type_show, NULL);
|
|
|
static DEVICE_ATTR(temp, 0444, temp_show, NULL);
|
|
|
static DEVICE_ATTR(mode, 0644, mode_show, mode_store);
|
|
@@ -843,7 +895,7 @@ temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
|
temp_input);
|
|
|
struct thermal_zone_device *tz = temp->tz;
|
|
|
|
|
|
- ret = tz->ops->get_temp(tz, &temperature);
|
|
|
+ ret = thermal_zone_get_temp(tz, &temperature);
|
|
|
|
|
|
if (ret)
|
|
|
return ret;
|
|
@@ -1596,6 +1648,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type,
|
|
|
goto unregister;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_THERMAL_EMULATION
|
|
|
+ result = device_create_file(&tz->device, &dev_attr_emul_temp);
|
|
|
+ if (result)
|
|
|
+ goto unregister;
|
|
|
+#endif
|
|
|
/* Create policy attribute */
|
|
|
result = device_create_file(&tz->device, &dev_attr_policy);
|
|
|
if (result)
|