[v2,20/22] clk: add nvkm_clk_reclock function

Submitted by Karol Herbst on March 21, 2016, 4:16 p.m.

Details

Message ID 1458577000-6615-21-git-send-email-nouveau@karolherbst.de
State New
Headers show
Series "Volting/Clocking improvements for Fermi and newer" ( rev: 2 ) in Nouveau

Not browsing as part of any series.

Commit Message

Karol Herbst March 21, 2016, 4:16 p.m.
this function just forces a reclock. This makes sense if some cstates get (un)available and we have to adjust to that.

This can happen for various reasons:
 * temperature changes
 * user changes boost mode

Signed-off-by: Karol Herbst <nouveau@karolherbst.de>
---
 drm/nouveau/include/nvkm/subdev/clk.h |  1 +
 drm/nouveau/nvkm/subdev/clk/base.c    | 23 ++++++++++++++++-------
 2 files changed, 17 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/include/nvkm/subdev/clk.h b/drm/nouveau/include/nvkm/subdev/clk.h
index 61d99fd..de164a3 100644
--- a/drm/nouveau/include/nvkm/subdev/clk.h
+++ b/drm/nouveau/include/nvkm/subdev/clk.h
@@ -120,6 +120,7 @@  int nvkm_clk_ustate(struct nvkm_clk *, int req, int pwr);
 int nvkm_clk_astate(struct nvkm_clk *, int req, int rel, bool wait);
 int nvkm_clk_dstate(struct nvkm_clk *, int req, int rel);
 int nvkm_clk_tstate(struct nvkm_clk *, int req, int rel);
+int nvkm_clk_reclock(struct nvkm_clk *);
 
 int nv04_clk_new(struct nvkm_device *, int, struct nvkm_clk **);
 int nv40_clk_new(struct nvkm_device *, int, struct nvkm_clk **);
diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c
index 2d16e9c..7a8451e 100644
--- a/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drm/nouveau/nvkm/subdev/clk/base.c
@@ -264,6 +264,9 @@  nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
 	struct nvkm_pstate *pstate;
 	int ret, idx = 0;
 
+	if (pstatei == -1)
+		return 0;
+
 	list_for_each_entry(pstate, &clk->states, head) {
 		if (idx++ == pstatei)
 			break;
@@ -292,7 +295,7 @@  nvkm_pstate_work(struct work_struct *work)
 {
 	struct nvkm_clk *clk = container_of(work, typeof(*clk), work);
 	struct nvkm_subdev *subdev = &clk->subdev;
-	int pstate;
+	int pstate, ret;
 
 	if (!atomic_xchg(&clk->waiting, 0))
 		return;
@@ -312,12 +315,10 @@  nvkm_pstate_work(struct work_struct *work)
 	}
 
 	nvkm_trace(subdev, "-> %d\n", pstate);
-	if (pstate != clk->pstate) {
-		int ret = nvkm_pstate_prog(clk, pstate);
-		if (ret) {
-			nvkm_error(subdev, "error setting pstate %d: %d\n",
-				   pstate, ret);
-		}
+	ret = nvkm_pstate_prog(clk, pstate);
+	if (ret) {
+		nvkm_error(subdev, "error setting pstate %d: %d\n",
+			   pstate, ret);
 	}
 
 	wake_up_all(&clk->wait);
@@ -560,6 +561,14 @@  nvkm_clk_pwrsrc(struct nvkm_notify *notify)
 	return NVKM_NOTIFY_DROP;
 }
 
+int
+nvkm_clk_reclock(struct nvkm_clk *clk)
+{
+	if (clk->allow_reclock)
+		return nvkm_pstate_calc(clk, true);
+	return -ENODEV;
+}
+
 /******************************************************************************
  * subdev base class implementation
  *****************************************************************************/

Comments

On 21/03/16 18:16, Karol Herbst wrote:
> this function just forces a reclock. This makes sense if some cstates get (un)available and we have to adjust to that.
>
> This can happen for various reasons:
>   * temperature changes
>   * user changes boost mode
>
> Signed-off-by: Karol Herbst <nouveau@karolherbst.de>
You can also add one event:
  * The load changes

In the end, the dyn. reclocking will generate a target pstate/cstate 
which will be applied as well as possible. With this in mind, we could 
rename this function nvkm_clk_update(<no param>). Reclock is a weird 
name, but so is update.

Pick whatever you want!