[Nouveau] [PATCH 22/32] clk: Thermal throttling
Karol Herbst
karolherbst at gmail.com
Fri Nov 17 00:04:26 UTC 2017
v2: make message about relaxed throttling an info
rework reporting about current clk state
Signed-off-by: Karol Herbst <karolherbst at gmail.com>
Reviewed-by: Pierre Moreau <pierre.morrow at free.fr>
---
drm/nouveau/include/nvkm/subdev/clk.h | 1 +
drm/nouveau/nvkm/subdev/clk/base.c | 47 +++++++++++++++++++++++++++--------
2 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/drm/nouveau/include/nvkm/subdev/clk.h b/drm/nouveau/include/nvkm/subdev/clk.h
index 3bb2099c..32923732 100644
--- a/drm/nouveau/include/nvkm/subdev/clk.h
+++ b/drm/nouveau/include/nvkm/subdev/clk.h
@@ -110,6 +110,7 @@ struct nvkm_clk {
int temp;
int max_temp;
int relax_temp;
+ bool throttled;
bool allow_reclock;
#define NVKM_CLK_BOOST_NONE 0x0
diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c
index 4279f80a..3704475d 100644
--- a/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drm/nouveau/nvkm/subdev/clk/base.c
@@ -180,8 +180,13 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate,
return 0;
if (!list_empty(&pstate->cstates)) {
- cstate = nvkm_cstate_get(clk, pstate, cstate_id);
- cstate = nvkm_cstate_find_best(clk, pstate, cstate);
+ if (clk->throttled) {
+ cstate = list_first_entry(&pstate->cstates,
+ struct nvkm_cstate, head);
+ } else {
+ cstate = nvkm_cstate_get(clk, pstate, cstate_id);
+ cstate = nvkm_cstate_find_best(clk, pstate, cstate);
+ }
} else {
cstate = &pstate->base;
}
@@ -325,17 +330,22 @@ nvkm_clk_update_work(struct work_struct *work)
return;
clk->pwrsrc = power_supply_is_system_supplied();
- nvkm_trace(subdev, "P %x PWR %d U(AC) %d U(DC) %d A %d T %d°C\n",
- clk->pstate_id, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
- clk->astate, clk->temp);
-
pstate_id = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
- if (clk->pstates_cnt && pstate_id != NVKM_CLK_PSTATE_BOOT)
- pstate_id = (pstate_id < 0) ? clk->astate : pstate_id;
- else
+ if (clk->pstates_cnt && pstate_id != NVKM_CLK_PSTATE_BOOT) {
+ if (clk->throttled)
+ pstate_id = list_first_entry(&clk->pstates,
+ struct nvkm_pstate,
+ head)->id;
+ else
+ pstate_id = (pstate_id < 0) ? clk->astate : pstate_id;
+ } else {
pstate_id = NVKM_CLK_PSTATE_BOOT;
+ }
+
+ nvkm_trace(subdev, "PWR %d U(AC) %d U(DC) %d A %d T %d°C -> %d\n",
+ clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
+ clk->astate, clk->temp, pstate_id);
- nvkm_trace(subdev, "-> %x\n", pstate_id);
if (pstate_id != clk->pstate_id) {
int ret = nvkm_pstate_prog(clk, pstate_id);
if (ret) {
@@ -552,9 +562,25 @@ nvkm_clk_astate(struct nvkm_clk *clk, int req, int rel, bool wait)
int
nvkm_clk_tstate(struct nvkm_clk *clk, int temp)
{
+ struct nvkm_subdev *subdev = &clk->subdev;
if (clk->temp == temp)
return 0;
clk->temp = temp;
+ if (clk->max_temp && clk->relax_temp) {
+ if (!clk->throttled && temp > clk->max_temp) {
+ nvkm_warn(subdev,
+ "temperature (%d C) hit the 'downclock' "
+ "threshold\n",
+ temp);
+ clk->throttled = true;
+ } else if (clk->throttled && temp < clk->relax_temp) {
+ nvkm_info(subdev,
+ "temperature (%d C) went below the "
+ "'relax' threshold\n",
+ temp);
+ clk->throttled = false;
+ }
+ }
return nvkm_clk_update(clk, false);
}
@@ -720,6 +746,7 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
clk->domains = func->domains;
clk->ustate_ac = NVKM_CLK_PSTATE_BOOT;
clk->ustate_dc = NVKM_CLK_PSTATE_BOOT;
+ clk->throttled = false;
clk->allow_reclock = allow_reclock;
INIT_WORK(&clk->work, nvkm_clk_update_work);
--
2.15.0
More information about the Nouveau
mailing list