int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent) { struct nouveau_therm_priv *priv = (void *)therm; if (priv->mode != NOUVEAU_THERM_CTRL_MANUAL) return -EINVAL; return nouveau_therm_fan_set(therm, true, percent); }
int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent) { struct nouveau_therm_priv *priv = (void *)therm; if (priv->fan.mode != FAN_CONTROL_MANUAL) return -EINVAL; return nouveau_therm_fan_set(therm, percent); }
static void nouveau_therm_update(struct nouveau_therm *therm, int mode) { struct nouveau_timer *ptimer = nouveau_timer(therm); struct nouveau_therm_priv *priv = (void *)therm; unsigned long flags; bool immd = true; bool poll = true; int duty = -1; spin_lock_irqsave(&priv->lock, flags); if (mode < 0) mode = priv->mode; priv->mode = mode; switch (mode) { case NOUVEAU_THERM_CTRL_MANUAL: ptimer->alarm_cancel(ptimer, &priv->alarm); duty = nouveau_therm_fan_get(therm); if (duty < 0) duty = 100; poll = false; break; case NOUVEAU_THERM_CTRL_AUTO: switch(priv->fan->bios.fan_mode) { case NVBIOS_THERM_FAN_TRIP: duty = nouveau_therm_update_trip(therm); break; case NVBIOS_THERM_FAN_LINEAR: duty = nouveau_therm_update_linear(therm); break; case NVBIOS_THERM_FAN_OTHER: if (priv->cstate) duty = priv->cstate; poll = false; break; } immd = false; break; case NOUVEAU_THERM_CTRL_NONE: default: ptimer->alarm_cancel(ptimer, &priv->alarm); poll = false; } if (list_empty(&priv->alarm.head) && poll) ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); spin_unlock_irqrestore(&priv->lock, flags); if (duty >= 0) { nv_debug(therm, "FAN target request: %d%%\n", duty); nouveau_therm_fan_set(therm, immd, duty); } }
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; } }
static void nouveau_therm_update(struct nouveau_therm *therm, int mode) { struct nouveau_timer *ptimer = nouveau_timer(therm); struct nouveau_therm_priv *priv = (void *)therm; unsigned long flags; int duty; spin_lock_irqsave(&priv->lock, flags); nv_debug(therm, "FAN speed check\n"); if (mode < 0) mode = priv->mode; priv->mode = mode; switch (mode) { case NOUVEAU_THERM_CTRL_MANUAL: ptimer->alarm_cancel(ptimer, &priv->alarm); duty = nouveau_therm_fan_get(therm); if (duty < 0) duty = 100; break; case NOUVEAU_THERM_CTRL_AUTO: if (priv->fan->bios.nr_fan_trip) duty = nouveau_therm_update_trip(therm); else duty = nouveau_therm_update_linear(therm); break; case NOUVEAU_THERM_CTRL_NONE: default: ptimer->alarm_cancel(ptimer, &priv->alarm); goto done; } nv_debug(therm, "FAN target request: %d%%\n", duty); nouveau_therm_fan_set(therm, (mode != NOUVEAU_THERM_CTRL_AUTO), duty); done: if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); else if (!list_empty(&priv->alarm.head)) nv_debug(therm, "therm fan alarm list is not empty\n"); spin_unlock_irqrestore(&priv->lock, flags); }
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; }