summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/clk_vgpu.c
diff options
context:
space:
mode:
authorAparna Das <aparnad@nvidia.com>2018-09-11 20:11:44 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-09-27 18:04:47 -0400
commit78e3d22da3c2513d425c8c2560468ce854a982dd (patch)
tree87ce6d1c47357c868cb58608e893afb4c14cfa69 /drivers/gpu/nvgpu/vgpu/clk_vgpu.c
parent8789cafcfb0d1e16ad0b2c61b047d275f2d684b4 (diff)
gpu: nvgpu: vgpu: support clk-arb
1. Implement the following vgpu functions to support clk-arb: - vgpu_clk_get_range() to return min and max freqs from supported frequencies - implement vgpu_clk_get_round_rate() which sets rounded rate to input rate. Rounding is handled in RM Server - modify vgpu_clk_get_freqs() to retrieve freq table in IVM memory instead of copying the value in array as part of cmd message. 2. Add support for clk-arb related HALs for vgpu. 3. support_clk_freq_controller is assigned true for vgpu provided guest VM has the privilege to set clock frequency. Bug 200422845 Bug 2363882 Jira EVLR-3254 Change-Id: I91fc392db381c5db1d52b19d45ec0481fdc27554 Signed-off-by: Aparna Das <aparnad@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1812379 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/vgpu/clk_vgpu.c')
-rw-r--r--drivers/gpu/nvgpu/vgpu/clk_vgpu.c174
1 files changed, 159 insertions, 15 deletions
diff --git a/drivers/gpu/nvgpu/vgpu/clk_vgpu.c b/drivers/gpu/nvgpu/vgpu/clk_vgpu.c
index efcb4fb0..6aea7c8f 100644
--- a/drivers/gpu/nvgpu/vgpu/clk_vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/clk_vgpu.c
@@ -21,14 +21,12 @@
21 */ 21 */
22 22
23#include <nvgpu/vgpu/vgpu.h> 23#include <nvgpu/vgpu/vgpu.h>
24#include <nvgpu/vgpu/vgpu_ivc.h>
24 25
25#include "gk20a/gk20a.h" 26#include "gk20a/gk20a.h"
26#include "clk_vgpu.h" 27#include "clk_vgpu.h"
27#include "ctrl/ctrlclk.h" 28#include "ctrl/ctrlclk.h"
28 29
29static unsigned long
30vgpu_freq_table[TEGRA_VGPU_GPU_FREQ_TABLE_SIZE];
31
32static unsigned long vgpu_clk_get_rate(struct gk20a *g, u32 api_domain) 30static unsigned long vgpu_clk_get_rate(struct gk20a *g, u32 api_domain)
33{ 31{
34 struct tegra_vgpu_cmd_msg msg = {}; 32 struct tegra_vgpu_cmd_msg msg = {};
@@ -95,9 +93,117 @@ static int vgpu_clk_set_rate(struct gk20a *g,
95 93
96static unsigned long vgpu_clk_get_maxrate(struct gk20a *g, u32 api_domain) 94static unsigned long vgpu_clk_get_maxrate(struct gk20a *g, u32 api_domain)
97{ 95{
98 struct vgpu_priv_data *priv = vgpu_get_priv_data(g); 96 unsigned long *freqs;
97 int num_freqs = 0;
98 int err;
99 unsigned long ret = 0;
100
101 nvgpu_log_fn(g, " ");
102
103 switch (api_domain) {
104 case CTRL_CLK_DOMAIN_GPCCLK:
105 err = vgpu_clk_get_freqs(g, &freqs, &num_freqs);
106 if (err == 0) {
107 /* return freq in Hz */
108 ret = freqs[num_freqs - 1];
109 }
110 break;
111 default:
112 nvgpu_err(g, "unknown clock: %u", api_domain);
113 break;
114 }
115
116 return ret;
117}
118
119static int vgpu_clk_get_round_rate(struct gk20a *g, u32 api_domain,
120 unsigned long rate_target, unsigned long *rounded_rate)
121{
122 int err = -EINVAL;
123
124 nvgpu_log_fn(g, " ");
99 125
100 return priv->constants.max_freq; 126 switch (api_domain) {
127 case CTRL_CLK_DOMAIN_GPCCLK:
128 *rounded_rate = rate_target;
129 err = 0;
130 break;
131 default:
132 nvgpu_err(g, "unknown clock: %u", api_domain);
133 break;
134 }
135
136 return err;
137}
138
139static int vgpu_clk_get_range(struct gk20a *g, u32 api_domain,
140 u16 *min_mhz, u16 *max_mhz)
141{
142 unsigned long *freqs;
143 int num_freqs = 0;
144 int err = -EINVAL;
145
146 nvgpu_log_fn(g, " ");
147
148 switch (api_domain) {
149 case CTRL_CLK_DOMAIN_GPCCLK:
150 err = vgpu_clk_get_freqs(g, &freqs, &num_freqs);
151 if (err == 0) {
152 /* return freq in MHz */
153 *min_mhz = (u16)(freqs[0] / 1000000);
154 *max_mhz = (u16)(freqs[num_freqs - 1] / 1000000);
155 }
156 break;
157 default:
158 nvgpu_err(g, "unknown clock: %u", api_domain);
159 break;
160 }
161
162 return err;
163}
164
165static int vgpu_clk_get_f_points(struct gk20a *g,
166 u32 api_domain, u32 *num_points, u16 *freqs_mhz)
167{
168 unsigned long *freqs;
169 int num_freqs = 0;
170 u32 i;
171 int err = -EINVAL;
172
173 nvgpu_log_fn(g, " ");
174
175 switch (api_domain) {
176 case CTRL_CLK_DOMAIN_GPCCLK:
177 err = vgpu_clk_get_freqs(g, &freqs, &num_freqs);
178 if (err) {
179 return err;
180 }
181
182 if (num_points == NULL) {
183 return -EINVAL;
184 }
185
186 if (*num_points != 0U) {
187 if (freqs == NULL || (*num_points > (u32)num_freqs)) {
188 return -EINVAL;
189 }
190 }
191
192 if (*num_points == 0) {
193 *num_points = num_freqs;
194 } else {
195 for (i = 0; i < *num_points; i++) {
196 /* return freq in MHz */
197 freqs_mhz[i] = (u16)(freqs[i] / 1000000);
198 }
199 }
200 break;
201 default:
202 nvgpu_err(g, "unknown clock: %u", api_domain);
203 break;
204 }
205
206 return err;
101} 207}
102 208
103void vgpu_init_clk_support(struct gk20a *g) 209void vgpu_init_clk_support(struct gk20a *g)
@@ -105,37 +211,75 @@ void vgpu_init_clk_support(struct gk20a *g)
105 g->ops.clk.get_rate = vgpu_clk_get_rate; 211 g->ops.clk.get_rate = vgpu_clk_get_rate;
106 g->ops.clk.set_rate = vgpu_clk_set_rate; 212 g->ops.clk.set_rate = vgpu_clk_set_rate;
107 g->ops.clk.get_maxrate = vgpu_clk_get_maxrate; 213 g->ops.clk.get_maxrate = vgpu_clk_get_maxrate;
214 g->ops.clk.clk_get_round_rate = vgpu_clk_get_round_rate;
215 g->ops.clk.get_clk_range = vgpu_clk_get_range;
216 g->ops.clk.clk_domain_get_f_points = vgpu_clk_get_f_points;
108} 217}
109 218
110int vgpu_clk_get_freqs(struct gk20a *g, unsigned long **freqs, int *num_freqs) 219int vgpu_clk_get_freqs(struct gk20a *g, unsigned long **freqs_out,
220 int *num_freqs)
111{ 221{
112 struct tegra_vgpu_cmd_msg msg = {}; 222 struct tegra_vgpu_cmd_msg msg = {};
113 struct tegra_vgpu_get_gpu_freq_table_params *p = 223 struct tegra_vgpu_get_gpu_freq_table_params *p =
114 &msg.params.get_gpu_freq_table; 224 &msg.params.get_gpu_freq_table;
225 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
226 u32 *freqs;
227 int err = 0;
228 void *handle = NULL;
229 size_t oob_size;
115 unsigned int i; 230 unsigned int i;
116 int err;
117 231
118 nvgpu_log_fn(g, " "); 232 nvgpu_log_fn(g, " ");
119 233
234 nvgpu_mutex_acquire(&priv->vgpu_clk_get_freq_lock);
235
236 if (priv->freqs != NULL) {
237 goto done;
238 }
239
120 msg.cmd = TEGRA_VGPU_CMD_GET_GPU_FREQ_TABLE; 240 msg.cmd = TEGRA_VGPU_CMD_GET_GPU_FREQ_TABLE;
121 msg.handle = vgpu_get_handle(g); 241 msg.handle = vgpu_get_handle(g);
122 242
123 p->num_freqs = TEGRA_VGPU_GPU_FREQ_TABLE_SIZE;
124 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); 243 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
125 err = err ? err : msg.ret; 244 err = err ? err : msg.ret;
126 if (err) { 245 if (err) {
127 nvgpu_err(g, "%s failed - %d", __func__, err); 246 nvgpu_err(g, "%s failed - %d", __func__, err);
128 return err; 247 goto done;
129 } 248 }
130 249
131 /* return frequency in Hz */ 250 handle = vgpu_ivc_oob_get_ptr(vgpu_ivc_get_server_vmid(),
132 for (i = 0; i < p->num_freqs; i++) 251 TEGRA_VGPU_QUEUE_CMD, (void **)&freqs, &oob_size);
133 vgpu_freq_table[i] = p->freqs[i] * 1000; 252 if (!handle) {
253 nvgpu_err(g, "failed to get ivm handle");
254 err = -EINVAL;
255 goto done;
256 }
134 257
135 *freqs = vgpu_freq_table; 258 priv->freqs = nvgpu_kzalloc(g, sizeof(*priv->freqs) * (p->num_freqs));
136 *num_freqs = p->num_freqs; 259 if (!priv->freqs) {
260 nvgpu_err(g, "failed to allocate memory");
261 vgpu_ivc_oob_put_ptr(handle);
262 err = -ENOMEM;
263 goto done;
264 }
265 priv->num_freqs = p->num_freqs;
137 266
138 return 0; 267 for (i = 0; i < priv->num_freqs; i++) {
268 /* store frequency in Hz */
269 priv->freqs[i] = (unsigned long)(freqs[i] * 1000);
270 }
271
272 vgpu_ivc_oob_put_ptr(handle);
273
274done:
275 if (err == 0) {
276 *num_freqs = priv->num_freqs;
277 *freqs_out = priv->freqs;
278 }
279
280 nvgpu_mutex_release(&priv->vgpu_clk_get_freq_lock);
281
282 return err;
139} 283}
140 284
141int vgpu_clk_cap_rate(struct gk20a *g, unsigned long rate) 285int vgpu_clk_cap_rate(struct gk20a *g, unsigned long rate)