[v4,28/37] clk: hold information about the current cstate status

Submitted by Karol Herbst on April 18, 2016, 7:14 p.m.

Details

Message ID 1461006851-5007-29-git-send-email-nouveau@karolherbst.de
State New
Headers show
Series "Volting/Clocking improvements for Fermi and newer" ( rev: 4 ) in Nouveau

Not browsing as part of any series.

Commit Message

Karol Herbst April 18, 2016, 7:14 p.m.
Signed-off-by: Karol Herbst <nouveau@karolherbst.de>
---
 drm/nouveau/include/nvkm/subdev/clk.h |  5 +++++
 drm/nouveau/nvkm/subdev/clk/base.c    | 32 +++++++++++++++++++++++++-------
 2 files changed, 30 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 4fb2c1b..6deda96 100644
--- a/drm/nouveau/include/nvkm/subdev/clk.h
+++ b/drm/nouveau/include/nvkm/subdev/clk.h
@@ -95,6 +95,11 @@  struct nvkm_clk {
 	int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */
 	int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */
 	int astate; /* perfmon adjustment (base) */
+	struct nvkm_cstate *set_cstate;
+#define NVKM_CLK_CSTATE_DEFAULT -1
+#define NVKM_CLK_CSTATE_BASE    -2
+#define NVKM_CLK_CSTATE_HIGHEST -3
+	int exp_cstate;
 
 	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 762dfe2..23f4cfe 100644
--- a/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drm/nouveau/nvkm/subdev/clk/base.c
@@ -152,9 +152,14 @@  static struct nvkm_cstate *
 nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
 {
 	struct nvkm_cstate *cstate;
-	if (cstatei == -1)
+	switch (cstatei) {
+	case NVKM_CLK_CSTATE_HIGHEST:
 		return list_entry(pstate->list.prev, typeof(*cstate), head);
-	else {
+	case NVKM_CLK_CSTATE_BASE:
+		return &pstate->base;
+	case NVKM_CLK_CSTATE_DEFAULT:
+		return NULL;
+	default:
 		list_for_each_entry(cstate, &pstate->list, head) {
 			if (cstate->cstate == cstatei)
 				return cstate;
@@ -173,6 +178,9 @@  nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
 	struct nvkm_cstate *cstate;
 	int ret;
 
+	if (cstatei == NVKM_CLK_CSTATE_DEFAULT)
+		return 0;
+
 	if (!list_empty(&pstate->list)) {
 		cstate = nvkm_cstate_get(clk, pstate, cstatei);
 		cstate = nvkm_cstate_find_best(clk, pstate, cstate);
@@ -199,6 +207,7 @@  nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
 
 	ret = clk->func->calc(clk, cstate);
 	if (ret == 0) {
+		clk->set_cstate = cstate;
 		ret = clk->func->prog(clk);
 		clk->func->tidy(clk);
 	}
@@ -303,7 +312,7 @@  nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
 		ram->func->tidy(ram);
 	}
 
-	return nvkm_cstate_prog(clk, pstate, -1);
+	return nvkm_cstate_prog(clk, pstate, clk->exp_cstate);
 }
 
 static void
@@ -321,9 +330,9 @@  nvkm_clk_update_work(struct work_struct *work)
 		pstate = clk->pstate->pstate;
 	else
 		pstate = -1;
-	nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d\n",
+	nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d C %d\n",
 		   pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
-		   clk->astate);
+		   clk->astate, clk->exp_cstate);
 
 	pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
 	if (clk->state_nr && pstate != -1) {
@@ -541,6 +550,7 @@  nvkm_clk_ustate(struct nvkm_clk *clk, int req, int pwr)
 	if (ret >= 0) {
 		if (ret -= 2, pwr) clk->ustate_ac = ret;
 		else		   clk->ustate_dc = ret;
+		clk->exp_cstate = NVKM_CLK_CSTATE_HIGHEST;
 		return nvkm_clk_update(clk, true);
 	}
 	return ret;
@@ -553,6 +563,7 @@  nvkm_clk_astate(struct nvkm_clk *clk, int req, int rel, bool wait)
 	if ( rel) clk->astate += rel;
 	clk->astate = min(clk->astate, clk->state_nr - 1);
 	clk->astate = max(clk->astate, 0);
+	clk->exp_cstate = NVKM_CLK_CSTATE_BASE;
 	return nvkm_clk_update(clk, wait);
 }
 
@@ -614,6 +625,8 @@  nvkm_clk_init(struct nvkm_subdev *subdev)
 
 	clk->astate = clk->state_nr - 1;
 	clk->pstate = NULL;
+	clk->exp_cstate = NVKM_CLK_CSTATE_DEFAULT;
+	clk->set_cstate = NULL;
 	nvkm_clk_update(clk, true);
 	return 0;
 }
@@ -698,15 +711,20 @@  nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
 	if (mode) {
 		clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen);
 		clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
+		clk->exp_cstate = NVKM_CLK_CSTATE_HIGHEST;
 	}
 
 	mode = nvkm_stropt(device->cfgopt, "NvClkModeAC", &arglen);
-	if (mode)
+	if (mode) {
 		clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen);
+		clk->exp_cstate = NVKM_CLK_CSTATE_HIGHEST;
+	}
 
 	mode = nvkm_stropt(device->cfgopt, "NvClkModeDC", &arglen);
-	if (mode)
+	if (mode) {
 		clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
+		clk->exp_cstate = NVKM_CLK_CSTATE_HIGHEST;
+	}
 
 	return 0;
 }

Comments

On 18/04/16 22:14, Karol Herbst wrote:
> Signed-off-by: Karol Herbst <nouveau@karolherbst.de>
> ---
>   drm/nouveau/include/nvkm/subdev/clk.h |  5 +++++
>   drm/nouveau/nvkm/subdev/clk/base.c    | 32 +++++++++++++++++++++++++-------
>   2 files changed, 30 insertions(+), 7 deletions(-)
>
> diff --git a/drm/nouveau/include/nvkm/subdev/clk.h b/drm/nouveau/include/nvkm/subdev/clk.h
> index 4fb2c1b..6deda96 100644
> --- a/drm/nouveau/include/nvkm/subdev/clk.h
> +++ b/drm/nouveau/include/nvkm/subdev/clk.h
> @@ -95,6 +95,11 @@ struct nvkm_clk {
>   	int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */
>   	int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */
>   	int astate; /* perfmon adjustment (base) */
> +	struct nvkm_cstate *set_cstate;
> +#define NVKM_CLK_CSTATE_DEFAULT -1
> +#define NVKM_CLK_CSTATE_BASE    -2
> +#define NVKM_CLK_CSTATE_HIGHEST -3
> +	int exp_cstate;
>   
>   	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 762dfe2..23f4cfe 100644
> --- a/drm/nouveau/nvkm/subdev/clk/base.c
> +++ b/drm/nouveau/nvkm/subdev/clk/base.c
> @@ -152,9 +152,14 @@ static struct nvkm_cstate *
>   nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
>   {
>   	struct nvkm_cstate *cstate;
> -	if (cstatei == -1)
> +	switch (cstatei) {
> +	case NVKM_CLK_CSTATE_HIGHEST:
>   		return list_entry(pstate->list.prev, typeof(*cstate), head);
> -	else {
> +	case NVKM_CLK_CSTATE_BASE:
> +		return &pstate->base;
> +	case NVKM_CLK_CSTATE_DEFAULT:
> +		return NULL;
> +	default:
>   		list_for_each_entry(cstate, &pstate->list, head) {
>   			if (cstate->cstate == cstatei)
>   				return cstate;
> @@ -173,6 +178,9 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
>   	struct nvkm_cstate *cstate;
>   	int ret;
>   
> +	if (cstatei == NVKM_CLK_CSTATE_DEFAULT)
> +		return 0;
> +
>   	if (!list_empty(&pstate->list)) {
>   		cstate = nvkm_cstate_get(clk, pstate, cstatei);
>   		cstate = nvkm_cstate_find_best(clk, pstate, cstate);
> @@ -199,6 +207,7 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
>   
>   	ret = clk->func->calc(clk, cstate);
>   	if (ret == 0) {
> +		clk->set_cstate = cstate;
>   		ret = clk->func->prog(clk);
>   		clk->func->tidy(clk);
>   	}
> @@ -303,7 +312,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
>   		ram->func->tidy(ram);
>   	}
>   
> -	return nvkm_cstate_prog(clk, pstate, -1);
> +	return nvkm_cstate_prog(clk, pstate, clk->exp_cstate);
>   }
>   
>   static void
> @@ -321,9 +330,9 @@ nvkm_clk_update_work(struct work_struct *work)
>   		pstate = clk->pstate->pstate;
>   	else
>   		pstate = -1;
> -	nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d\n",
> +	nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d C %d\n",
>   		   pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
> -		   clk->astate);
> +		   clk->astate, clk->exp_cstate);
>   
>   	pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
>   	if (clk->state_nr && pstate != -1) {
> @@ -541,6 +550,7 @@ nvkm_clk_ustate(struct nvkm_clk *clk, int req, int pwr)
>   	if (ret >= 0) {
>   		if (ret -= 2, pwr) clk->ustate_ac = ret;
>   		else		   clk->ustate_dc = ret;
> +		clk->exp_cstate = NVKM_CLK_CSTATE_HIGHEST;

I am really not a fan of this astate. We will revisit this when we are 
done with manual reclocking!

In the mean time, this is:

Reviewed-by: Martin Peres <martin.peres@free.fr>

>   		return nvkm_clk_update(clk, true);
>   	}
>   	return ret;
> @@ -553,6 +563,7 @@ nvkm_clk_astate(struct nvkm_clk *clk, int req, int rel, bool wait)
>   	if ( rel) clk->astate += rel;
>   	clk->astate = min(clk->astate, clk->state_nr - 1);
>   	clk->astate = max(clk->astate, 0);
> +	clk->exp_cstate = NVKM_CLK_CSTATE_BASE;
>   	return nvkm_clk_update(clk, wait);
>   }
>   
> @@ -614,6 +625,8 @@ nvkm_clk_init(struct nvkm_subdev *subdev)
>   
>   	clk->astate = clk->state_nr - 1;
>   	clk->pstate = NULL;
> +	clk->exp_cstate = NVKM_CLK_CSTATE_DEFAULT;
> +	clk->set_cstate = NULL;
>   	nvkm_clk_update(clk, true);
>   	return 0;
>   }
> @@ -698,15 +711,20 @@ nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
>   	if (mode) {
>   		clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen);
>   		clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
> +		clk->exp_cstate = NVKM_CLK_CSTATE_HIGHEST;
>   	}
>   
>   	mode = nvkm_stropt(device->cfgopt, "NvClkModeAC", &arglen);
> -	if (mode)
> +	if (mode) {
>   		clk->ustate_ac = nvkm_clk_nstate(clk, mode, arglen);
> +		clk->exp_cstate = NVKM_CLK_CSTATE_HIGHEST;
> +	}
>   
>   	mode = nvkm_stropt(device->cfgopt, "NvClkModeDC", &arglen);
> -	if (mode)
> +	if (mode) {
>   		clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
> +		clk->exp_cstate = NVKM_CLK_CSTATE_HIGHEST;
> +	}
>   
>   	return 0;
>   }