[Nouveau] [RFC PATCH 27/29] clk: implement limiting pstates just like we do for cstates
Karol Herbst
karolherbst at gmail.com
Fri Sep 15 17:11:27 UTC 2017
Signed-off-by: Karol Herbst <karolherbst at gmail.com>
---
drm/nouveau/nvkm/subdev/clk/base.c | 62 ++++++++++++++++++++++++++++++++------
1 file changed, 52 insertions(+), 10 deletions(-)
diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c
index 9f44ace0..2a51c078 100644
--- a/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drm/nouveau/nvkm/subdev/clk/base.c
@@ -288,6 +288,52 @@ nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
/******************************************************************************
* P-States
*****************************************************************************/
+static struct nvkm_pstate *
+nvkm_pstate_find_best(struct nvkm_clk *clk, struct nvkm_pstate *start)
+{
+ struct nvkm_pstate *pstate;
+ u8 limit;
+
+ switch (clk->boost_mode) {
+ case NVKM_CLK_BOOST_NONE:
+ limit = clk->base_limit.pstate;
+ if (limit)
+ break;
+ case NVKM_CLK_BOOST_BIOS:
+ limit = clk->boost_limit.pstate;
+ break;
+ default:
+ limit = 0;
+ break;
+ }
+
+ if (!limit)
+ return start;
+
+ for (pstate = start; &pstate->head != &clk->states;
+ pstate = list_entry(pstate->head.prev, typeof(*pstate), head)) {
+ if (limit >= pstate->pstate)
+ break;
+ }
+ return pstate;
+}
+
+static struct nvkm_pstate *
+nvkm_pstate_get(struct nvkm_clk *clk, int pstateid)
+{
+ struct nvkm_pstate *pstate;
+ switch (pstateid) {
+ case NVKM_CLK_PSTATE_DEFAULT:
+ return NULL;
+ default:
+ list_for_each_entry(pstate, &clk->states, head) {
+ if (pstate->pstate == pstateid)
+ return pstate;
+ }
+ }
+ return NULL;
+}
+
static int
nvkm_pstate_prog(struct nvkm_clk *clk, int pstateid)
{
@@ -300,20 +346,16 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstateid)
if (pstateid == NVKM_CLK_PSTATE_DEFAULT)
return 0;
- if (clk->pstate && clk->pstate->pstate == pstateid) {
- pstate = clk->pstate;
- goto cstate;
- }
-
- list_for_each_entry(pstate, &clk->states, head) {
- if (pstate->pstate == pstateid)
- break;
- }
+ pstate = nvkm_pstate_get(clk, pstateid);
+ pstate = nvkm_pstate_find_best(clk, pstate);
if (!pstate)
return -EINVAL;
- nvkm_debug(subdev, "setting performance state %x\n", pstateid);
+ if (clk->pstate && clk->pstate == pstate)
+ goto cstate;
+
+ nvkm_debug(subdev, "setting performance state %x\n", pstate->pstate);
clk->pstate = pstate;
nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width);
--
2.14.1
More information about the Nouveau
mailing list