int nouveau_therm_attr_set(struct nouveau_therm *therm, enum nouveau_therm_attr_type type, int value) { struct nouveau_therm_priv *priv = (void *)therm; switch (type) { case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: if (value < 0) value = 0; if (value > priv->fan->bios.max_duty) value = priv->fan->bios.max_duty; priv->fan->bios.min_duty = value; return 0; case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: if (value < 0) value = 0; if (value < priv->fan->bios.min_duty) value = priv->fan->bios.min_duty; priv->fan->bios.max_duty = value; return 0; case NOUVEAU_THERM_ATTR_FAN_MODE: return nouveau_therm_fan_mode(therm, value); case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: priv->bios_sensor.thrs_fan_boost.temp = value; priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: priv->bios_sensor.thrs_fan_boost.hysteresis = value; priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK: priv->bios_sensor.thrs_down_clock.temp = value; priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST: priv->bios_sensor.thrs_down_clock.hysteresis = value; priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_CRITICAL: priv->bios_sensor.thrs_critical.temp = value; priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST: priv->bios_sensor.thrs_critical.hysteresis = value; priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN: priv->bios_sensor.thrs_shutdown.temp = value; priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST: priv->bios_sensor.thrs_shutdown.hysteresis = value; priv->sensor.program_alarms(therm); return 0; } return -EINVAL; }
int nouveau_therm_preinit(struct nouveau_therm *therm) { nouveau_therm_sensor_ctor(therm); nouveau_therm_ic_ctor(therm); nouveau_therm_fan_ctor(therm); nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_NONE); nouveau_therm_sensor_preinit(therm); return 0; }
void nouveau_therm_sensor_event(struct nouveau_therm *therm, enum nouveau_therm_thrs thrs, enum nouveau_therm_thrs_direction dir) { struct nouveau_therm_priv *priv = (void *)therm; bool active; const char *thresolds[] = { "fanboost", "downclock", "critical", "shutdown" }; int temperature = therm->temp_get(therm); if (thrs < 0 || thrs > 3) return; if (dir == NOUVEAU_THERM_THRS_FALLING) nv_info(therm, "temperature (%i C) went below the '%s' threshold\n", temperature, thresolds[thrs]); else nv_info(therm, "temperature (%i C) hit the '%s' threshold\n", temperature, thresolds[thrs]); active = (dir == NOUVEAU_THERM_THRS_RISING); switch (thrs) { case NOUVEAU_THERM_THRS_FANBOOST: if (active) { nouveau_therm_fan_set(therm, true, 100); nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_AUTO); } break; case NOUVEAU_THERM_THRS_DOWNCLOCK: if (priv->emergency.downclock) priv->emergency.downclock(therm, active); break; case NOUVEAU_THERM_THRS_CRITICAL: if (priv->emergency.pause) priv->emergency.pause(therm, active); break; case NOUVEAU_THERM_THRS_SHUTDOWN: if (active) { struct work_struct *work; work = kmalloc(sizeof(*work), GFP_ATOMIC); if (work) { INIT_WORK(work, nv_poweroff_work); schedule_work(work); } } break; case NOUVEAU_THERM_THRS_NR: break; } }
int _nouveau_therm_init(struct nouveau_object *object) { struct nouveau_therm *therm = (void *)object; struct nouveau_therm_priv *priv = (void *)therm; int ret; ret = nouveau_subdev_init(&therm->base); if (ret) return ret; if (priv->suspend >= 0) { /* restore the pwm value only when on manual or auto mode */ if (priv->suspend > 0) nouveau_therm_fan_set(therm, true, priv->fan->percent); nouveau_therm_fan_mode(therm, priv->suspend); } nouveau_therm_sensor_init(therm); nouveau_therm_fan_init(therm); return 0; }