0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "priv.h"
0025
0026 static void
0027 nvkm_therm_temp_set_defaults(struct nvkm_therm *therm)
0028 {
0029 therm->bios_sensor.offset_constant = 0;
0030
0031 therm->bios_sensor.thrs_fan_boost.temp = 90;
0032 therm->bios_sensor.thrs_fan_boost.hysteresis = 3;
0033
0034 therm->bios_sensor.thrs_down_clock.temp = 95;
0035 therm->bios_sensor.thrs_down_clock.hysteresis = 3;
0036
0037 therm->bios_sensor.thrs_critical.temp = 105;
0038 therm->bios_sensor.thrs_critical.hysteresis = 5;
0039
0040 therm->bios_sensor.thrs_shutdown.temp = 135;
0041 therm->bios_sensor.thrs_shutdown.hysteresis = 5;
0042 }
0043
0044 static void
0045 nvkm_therm_temp_safety_checks(struct nvkm_therm *therm)
0046 {
0047 struct nvbios_therm_sensor *s = &therm->bios_sensor;
0048
0049
0050 s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2);
0051 s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2);
0052 s->thrs_critical.hysteresis = max_t(u8, s->thrs_critical.hysteresis, 2);
0053 s->thrs_shutdown.hysteresis = max_t(u8, s->thrs_shutdown.hysteresis, 2);
0054 }
0055
0056
0057 void
0058 nvkm_therm_sensor_set_threshold_state(struct nvkm_therm *therm,
0059 enum nvkm_therm_thrs thrs,
0060 enum nvkm_therm_thrs_state st)
0061 {
0062 therm->sensor.alarm_state[thrs] = st;
0063 }
0064
0065
0066 enum nvkm_therm_thrs_state
0067 nvkm_therm_sensor_get_threshold_state(struct nvkm_therm *therm,
0068 enum nvkm_therm_thrs thrs)
0069 {
0070 return therm->sensor.alarm_state[thrs];
0071 }
0072
0073 static void
0074 nv_poweroff_work(struct work_struct *work)
0075 {
0076 orderly_poweroff(true);
0077 kfree(work);
0078 }
0079
0080 void
0081 nvkm_therm_sensor_event(struct nvkm_therm *therm, enum nvkm_therm_thrs thrs,
0082 enum nvkm_therm_thrs_direction dir)
0083 {
0084 struct nvkm_subdev *subdev = &therm->subdev;
0085 bool active;
0086 static const char * const thresholds[] = {
0087 "fanboost", "downclock", "critical", "shutdown"
0088 };
0089 int temperature = therm->func->temp_get(therm);
0090
0091 if (thrs < 0 || thrs > 3)
0092 return;
0093
0094 if (dir == NVKM_THERM_THRS_FALLING)
0095 nvkm_info(subdev,
0096 "temperature (%i C) went below the '%s' threshold\n",
0097 temperature, thresholds[thrs]);
0098 else
0099 nvkm_info(subdev, "temperature (%i C) hit the '%s' threshold\n",
0100 temperature, thresholds[thrs]);
0101
0102 active = (dir == NVKM_THERM_THRS_RISING);
0103 switch (thrs) {
0104 case NVKM_THERM_THRS_FANBOOST:
0105 if (active) {
0106 nvkm_therm_fan_set(therm, true, 100);
0107 nvkm_therm_fan_mode(therm, NVKM_THERM_CTRL_AUTO);
0108 }
0109 break;
0110 case NVKM_THERM_THRS_DOWNCLOCK:
0111 if (therm->emergency.downclock)
0112 therm->emergency.downclock(therm, active);
0113 break;
0114 case NVKM_THERM_THRS_CRITICAL:
0115 if (therm->emergency.pause)
0116 therm->emergency.pause(therm, active);
0117 break;
0118 case NVKM_THERM_THRS_SHUTDOWN:
0119 if (active) {
0120 struct work_struct *work;
0121
0122 work = kmalloc(sizeof(*work), GFP_ATOMIC);
0123 if (work) {
0124 INIT_WORK(work, nv_poweroff_work);
0125 schedule_work(work);
0126 }
0127 }
0128 break;
0129 case NVKM_THERM_THRS_NR:
0130 break;
0131 }
0132
0133 }
0134
0135
0136 static void
0137 nvkm_therm_threshold_hyst_polling(struct nvkm_therm *therm,
0138 const struct nvbios_therm_threshold *thrs,
0139 enum nvkm_therm_thrs thrs_name)
0140 {
0141 enum nvkm_therm_thrs_direction direction;
0142 enum nvkm_therm_thrs_state prev_state, new_state;
0143 int temp = therm->func->temp_get(therm);
0144
0145 prev_state = nvkm_therm_sensor_get_threshold_state(therm, thrs_name);
0146
0147 if (temp >= thrs->temp && prev_state == NVKM_THERM_THRS_LOWER) {
0148 direction = NVKM_THERM_THRS_RISING;
0149 new_state = NVKM_THERM_THRS_HIGHER;
0150 } else if (temp <= thrs->temp - thrs->hysteresis &&
0151 prev_state == NVKM_THERM_THRS_HIGHER) {
0152 direction = NVKM_THERM_THRS_FALLING;
0153 new_state = NVKM_THERM_THRS_LOWER;
0154 } else
0155 return;
0156
0157 nvkm_therm_sensor_set_threshold_state(therm, thrs_name, new_state);
0158 nvkm_therm_sensor_event(therm, thrs_name, direction);
0159 }
0160
0161 static void
0162 alarm_timer_callback(struct nvkm_alarm *alarm)
0163 {
0164 struct nvkm_therm *therm =
0165 container_of(alarm, struct nvkm_therm, sensor.therm_poll_alarm);
0166 struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
0167 struct nvkm_timer *tmr = therm->subdev.device->timer;
0168 unsigned long flags;
0169
0170 spin_lock_irqsave(&therm->sensor.alarm_program_lock, flags);
0171
0172 nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost,
0173 NVKM_THERM_THRS_FANBOOST);
0174
0175 nvkm_therm_threshold_hyst_polling(therm,
0176 &sensor->thrs_down_clock,
0177 NVKM_THERM_THRS_DOWNCLOCK);
0178
0179 nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_critical,
0180 NVKM_THERM_THRS_CRITICAL);
0181
0182 nvkm_therm_threshold_hyst_polling(therm, &sensor->thrs_shutdown,
0183 NVKM_THERM_THRS_SHUTDOWN);
0184
0185 spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags);
0186
0187
0188 if (therm->func->temp_get(therm) >= 0)
0189 nvkm_timer_alarm(tmr, 1000000000ULL, alarm);
0190 }
0191
0192 void
0193 nvkm_therm_program_alarms_polling(struct nvkm_therm *therm)
0194 {
0195 struct nvbios_therm_sensor *sensor = &therm->bios_sensor;
0196
0197 nvkm_debug(&therm->subdev,
0198 "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n",
0199 sensor->thrs_fan_boost.temp,
0200 sensor->thrs_fan_boost.hysteresis,
0201 sensor->thrs_down_clock.temp,
0202 sensor->thrs_down_clock.hysteresis,
0203 sensor->thrs_critical.temp,
0204 sensor->thrs_critical.hysteresis,
0205 sensor->thrs_shutdown.temp,
0206 sensor->thrs_shutdown.hysteresis);
0207
0208 alarm_timer_callback(&therm->sensor.therm_poll_alarm);
0209 }
0210
0211 int
0212 nvkm_therm_sensor_init(struct nvkm_therm *therm)
0213 {
0214 therm->func->program_alarms(therm);
0215 return 0;
0216 }
0217
0218 int
0219 nvkm_therm_sensor_fini(struct nvkm_therm *therm, bool suspend)
0220 {
0221 struct nvkm_timer *tmr = therm->subdev.device->timer;
0222 if (suspend)
0223 nvkm_timer_alarm(tmr, 0, &therm->sensor.therm_poll_alarm);
0224 return 0;
0225 }
0226
0227 void
0228 nvkm_therm_sensor_preinit(struct nvkm_therm *therm)
0229 {
0230 const char *sensor_avail = "yes";
0231
0232 if (therm->func->temp_get(therm) < 0)
0233 sensor_avail = "no";
0234
0235 nvkm_debug(&therm->subdev, "internal sensor: %s\n", sensor_avail);
0236 }
0237
0238 int
0239 nvkm_therm_sensor_ctor(struct nvkm_therm *therm)
0240 {
0241 struct nvkm_subdev *subdev = &therm->subdev;
0242 struct nvkm_bios *bios = subdev->device->bios;
0243
0244 nvkm_alarm_init(&therm->sensor.therm_poll_alarm, alarm_timer_callback);
0245
0246 nvkm_therm_temp_set_defaults(therm);
0247 if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE,
0248 &therm->bios_sensor))
0249 nvkm_error(subdev, "nvbios_therm_sensor_parse failed\n");
0250 nvkm_therm_temp_safety_checks(therm);
0251
0252 return 0;
0253 }