From 1a22274b28fd47514f1463051d93028ad5f54af6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 6 Dec 2012 10:28:34 +1000 Subject: [PATCH] drm/nouveau/therm: better transitions and debug logging Signed-off-by: Ben Skeggs Signed-off-by: Martin Peres --- .../drm/nouveau/core/include/subdev/therm.h | 9 ++- .../gpu/drm/nouveau/core/subdev/therm/base.c | 56 ++++++++++--------- .../gpu/drm/nouveau/core/subdev/therm/fan.c | 14 ++++- .../gpu/drm/nouveau/core/subdev/therm/priv.h | 1 + .../gpu/drm/nouveau/core/subdev/therm/temp.c | 2 +- 5 files changed, 46 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h index 7c83eccadc61..6b17b614629f 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h @@ -4,11 +4,10 @@ #include #include -enum nouveau_therm_fan_mode { - FAN_CONTROL_NONE = 0, - FAN_CONTROL_MANUAL = 1, - FAN_CONTROL_AUTO = 2, - FAN_CONTROL_NR, +enum nouveau_therm_mode { + NOUVEAU_THERM_CTRL_NONE = 0, + NOUVEAU_THERM_CTRL_MANUAL = 1, + NOUVEAU_THERM_CTRL_AUTO = 2, }; enum nouveau_therm_attr_type { diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index f54495a0907a..b35b4a249c5f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c @@ -93,24 +93,27 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode) priv->mode = mode; switch (mode) { - case FAN_CONTROL_MANUAL: - duty = priv->fan->percent; + case NOUVEAU_THERM_CTRL_MANUAL: + duty = nouveau_therm_fan_get(therm); + if (duty < 0) + duty = 100; break; - case FAN_CONTROL_AUTO: + 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 FAN_CONTROL_NONE: + case NOUVEAU_THERM_CTRL_NONE: default: goto done; } - nouveau_therm_fan_set(therm, (mode != FAN_CONTROL_AUTO), duty); + 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 == FAN_CONTROL_AUTO)) + if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); spin_unlock_irqrestore(&priv->lock, flags); } @@ -127,28 +130,22 @@ int nouveau_therm_mode(struct nouveau_therm *therm, int mode) { struct nouveau_therm_priv *priv = (void *)therm; - - if (priv->mode == mode) - return 0; + struct nouveau_device *device = nv_device(therm); + static const char *name[] = { + "disabled", + "manual", + "automatic" + }; /* The default PDAEMON ucode interferes with fan management */ - if (nv_device(therm)->card_type >= NV_C0) + if ((mode >= ARRAY_SIZE(name)) || + (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) return -EINVAL; - switch (mode) { - case FAN_CONTROL_NONE: - nv_info(therm, "switch to no-control mode\n"); - break; - case FAN_CONTROL_MANUAL: - nv_info(therm, "switch to manual mode\n"); - break; - case FAN_CONTROL_AUTO: - nv_info(therm, "switch to automatic mode\n"); - break; - default: - return -EINVAL; - } + if (priv->mode == mode) + return 0; + nv_info(therm, "Thermal management: %s\n", name[mode]); nouveau_therm_update(therm, mode); return 0; } @@ -258,9 +255,8 @@ _nouveau_therm_init(struct nouveau_object *object) if (ret) return ret; - if (priv->fan->percent >= 0) - therm->fan_set(therm, priv->fan->percent); - + if (priv->suspend >= 0) + nouveau_therm_mode(therm, priv->mode); priv->sensor.program_alarms(therm); return 0; } @@ -271,7 +267,10 @@ _nouveau_therm_fini(struct nouveau_object *object, bool suspend) struct nouveau_therm *therm = (void *)object; struct nouveau_therm_priv *priv = (void *)therm; - priv->fan->percent = therm->fan_get(therm); + if (suspend) { + priv->suspend = priv->mode; + priv->mode = NOUVEAU_THERM_CTRL_NONE; + } return nouveau_subdev_fini(&therm->base, suspend); } @@ -299,6 +298,7 @@ nouveau_therm_create_(struct nouveau_object *parent, priv->base.fan_sense = nouveau_therm_fan_sense; priv->base.attr_get = nouveau_therm_attr_get; priv->base.attr_set = nouveau_therm_attr_set; + priv->mode = priv->suspend = -1; /* undefined */ return 0; } @@ -308,6 +308,8 @@ nouveau_therm_preinit(struct nouveau_therm *therm) nouveau_therm_ic_ctor(therm); nouveau_therm_sensor_ctor(therm); nouveau_therm_fan_ctor(therm); + + nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE); return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index 0f210f0155a8..f7d32f49f657 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -47,10 +47,17 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) target = fan->percent; target = max_t(u8, target, fan->bios.min_duty); target = min_t(u8, target, fan->bios.max_duty); - fan->percent = target; + if (fan->percent != target) { + nv_debug(therm, "FAN target: %d\n", target); + fan->percent = target; + } - /* smooth out the fanspeed increase/decrease */ + /* check that we're not already at the target duty cycle */ duty = fan->get(therm); + if (duty == target) + goto done; + + /* smooth out the fanspeed increase/decrease */ if (!immediate && duty >= 0) { /* the constant "3" is a rough approximation taken from * nvidia's behaviour. @@ -64,6 +71,7 @@ nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) duty = target; } + nv_debug(therm, "FAN update: %d\n", duty); ret = fan->set(therm, duty); if (ret) goto done; @@ -161,7 +169,7 @@ nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent) { struct nouveau_therm_priv *priv = (void *)therm; - if (priv->mode != FAN_CONTROL_MANUAL) + if (priv->mode != NOUVEAU_THERM_CTRL_MANUAL) return -EINVAL; return nouveau_therm_fan_set(therm, true, percent); diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index c2413e6aae25..06b98706b3fc 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h @@ -76,6 +76,7 @@ struct nouveau_therm_priv { spinlock_t lock; struct nouveau_therm_trip_point *last_trip; int mode; + int suspend; /* bios */ struct nvbios_therm_sensor bios_sensor; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c index d80c572de04f..820e09706578 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c @@ -108,7 +108,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm, switch (thrs) { case NOUVEAU_THERM_THRS_FANBOOST: nouveau_therm_fan_set(therm, true, 100); - nouveau_therm_mode(therm, FAN_CONTROL_AUTO); + nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO); break; case NOUVEAU_THERM_THRS_DOWNCLOCK: if (priv->emergency.downclock) -- GitLab