aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarol Herbst <karolherbst@gmail.com>2016-07-16 09:26:25 -0400
committerBen Skeggs <bskeggs@redhat.com>2016-10-12 03:29:24 -0400
commit1f7f3d91ad38afc706f838fb5a642b21d28e4485 (patch)
tree2e9b734e2d52c66b5d91687416d6d6db2c01fc1e
parent0d6f81003e9ecc2d6552be92d3d894c916097552 (diff)
drm/nouveau/clk: Respect voltage limits in nvkm_cstate_prog
We should never allow to select a cstate which current voltage (depending on the temperature) is higher than 1. the max volt entries in the voltage map table. 2. what tha gpu actually can volt to. v3: Use find_best for all cstates before actually trying. Add nvkm_cstate_get function to get cstate by index. v5: Cstates with voltages lower then min_uv are valid. Move nvkm_cstate_get into the previous commit. Signed-off-by: Karol Herbst <karolherbst@gmail.com> Reviewed-by: Martin Peres <martin.peres@free.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c52
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c2
3 files changed, 54 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
index 6fd933df763e..441f6e7079d2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
@@ -27,6 +27,7 @@ struct nvkm_volt {
27 u8 max2_id; 27 u8 max2_id;
28}; 28};
29 29
30int nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temperature);
30int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id); 31int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id);
31int nvkm_volt_get(struct nvkm_volt *); 32int nvkm_volt_get(struct nvkm_volt *);
32int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, u8 temp, 33int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, u8 temp,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
index 688c908908d8..60392b2edcbb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
@@ -74,6 +74,57 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bool adjust,
74/****************************************************************************** 74/******************************************************************************
75 * C-States 75 * C-States
76 *****************************************************************************/ 76 *****************************************************************************/
77static bool
78nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate,
79 u32 max_volt, int temp)
80{
81 struct nvkm_volt *volt = clk->subdev.device->volt;
82 int voltage;
83
84 if (!volt)
85 return true;
86
87 voltage = nvkm_volt_map(volt, cstate->voltage, temp);
88 if (voltage < 0)
89 return false;
90 return voltage <= min(max_volt, volt->max_uv);
91}
92
93static struct nvkm_cstate *
94nvkm_cstate_find_best(struct nvkm_clk *clk, struct nvkm_pstate *pstate,
95 struct nvkm_cstate *start)
96{
97 struct nvkm_device *device = clk->subdev.device;
98 struct nvkm_volt *volt = device->volt;
99 struct nvkm_cstate *cstate;
100 int max_volt;
101
102 if (!pstate || !start)
103 return NULL;
104
105 if (!volt)
106 return start;
107
108 max_volt = volt->max_uv;
109 if (volt->max0_id != 0xff)
110 max_volt = min(max_volt,
111 nvkm_volt_map(volt, volt->max0_id, clk->temp));
112 if (volt->max1_id != 0xff)
113 max_volt = min(max_volt,
114 nvkm_volt_map(volt, volt->max1_id, clk->temp));
115 if (volt->max2_id != 0xff)
116 max_volt = min(max_volt,
117 nvkm_volt_map(volt, volt->max2_id, clk->temp));
118
119 for (cstate = start; &cstate->head != &pstate->list;
120 cstate = list_entry(cstate->head.prev, typeof(*cstate), head)) {
121 if (nvkm_cstate_valid(clk, cstate, max_volt, clk->temp))
122 break;
123 }
124
125 return cstate;
126}
127
77static struct nvkm_cstate * 128static struct nvkm_cstate *
78nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei) 129nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
79{ 130{
@@ -101,6 +152,7 @@ nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
101 152
102 if (!list_empty(&pstate->list)) { 153 if (!list_empty(&pstate->list)) {
103 cstate = nvkm_cstate_get(clk, pstate, cstatei); 154 cstate = nvkm_cstate_get(clk, pstate, cstatei);
155 cstate = nvkm_cstate_find_best(clk, pstate, cstate);
104 } else { 156 } else {
105 cstate = &pstate->base; 157 cstate = &pstate->base;
106 } 158 }
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
index 40ba088a5c81..5e07bd3aaccc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
@@ -88,7 +88,7 @@ nvkm_volt_map_min(struct nvkm_volt *volt, u8 id)
88 return id ? id * 10000 : -ENODEV; 88 return id ? id * 10000 : -ENODEV;
89} 89}
90 90
91static int 91int
92nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp) 92nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp)
93{ 93{
94 struct nvkm_bios *bios = volt->subdev.device->bios; 94 struct nvkm_bios *bios = volt->subdev.device->bios;