summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h2
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu.h4
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c14
-rw-r--r--drivers/gpu/nvgpu/vgpu/clk_vgpu.c174
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c16
-rw-r--r--drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c16
-rw-r--r--drivers/gpu/nvgpu/vgpu/vgpu.c8
7 files changed, 218 insertions, 16 deletions
diff --git a/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h b/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h
index f7a58c87..5ee50b18 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/vgpu/tegra_vgpu.h
@@ -519,6 +519,7 @@ struct tegra_vgpu_constants_params {
519 u16 gpc_tpc_mask[TEGRA_VGPU_MAX_GPC_COUNT]; 519 u16 gpc_tpc_mask[TEGRA_VGPU_MAX_GPC_COUNT];
520 u32 hwpm_ctx_size; 520 u32 hwpm_ctx_size;
521 u8 force_preempt_mode; 521 u8 force_preempt_mode;
522 u8 can_set_clkrate;
522 u32 default_timeslice_us; 523 u32 default_timeslice_us;
523 u32 preempt_ctx_size; 524 u32 preempt_ctx_size;
524 u32 channel_base; 525 u32 channel_base;
@@ -578,7 +579,6 @@ struct tegra_vgpu_perfbuf_mgt_params {
578 579
579struct tegra_vgpu_get_gpu_freq_table_params { 580struct tegra_vgpu_get_gpu_freq_table_params {
580 u32 num_freqs; 581 u32 num_freqs;
581 u32 freqs[TEGRA_VGPU_GPU_FREQ_TABLE_SIZE]; /* in kHz */
582}; 582};
583 583
584struct tegra_vgpu_vsms_mapping_params { 584struct tegra_vgpu_vsms_mapping_params {
diff --git a/drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu.h b/drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu.h
index 762bc229..15ab879e 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/vgpu/vgpu.h
@@ -26,6 +26,7 @@
26#include <nvgpu/types.h> 26#include <nvgpu/types.h>
27#include <nvgpu/thread.h> 27#include <nvgpu/thread.h>
28#include <nvgpu/log.h> 28#include <nvgpu/log.h>
29#include <nvgpu/lock.h>
29#include <nvgpu/vgpu/tegra_vgpu.h> 30#include <nvgpu/vgpu/tegra_vgpu.h>
30 31
31struct device; 32struct device;
@@ -45,6 +46,9 @@ struct vgpu_priv_data {
45 struct tegra_vgpu_constants_params constants; 46 struct tegra_vgpu_constants_params constants;
46 struct vgpu_ecc_stat *ecc_stats; 47 struct vgpu_ecc_stat *ecc_stats;
47 int ecc_stats_count; 48 int ecc_stats_count;
49 u32 num_freqs;
50 unsigned long *freqs;
51 struct nvgpu_mutex vgpu_clk_get_freq_lock;
48}; 52};
49 53
50struct vgpu_priv_data *vgpu_get_priv_data(struct gk20a *g); 54struct vgpu_priv_data *vgpu_get_priv_data(struct gk20a *g);
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c
index e01178ed..aa2fa998 100644
--- a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c
@@ -33,6 +33,7 @@
33#include <nvgpu/defaults.h> 33#include <nvgpu/defaults.h>
34#include <nvgpu/ltc.h> 34#include <nvgpu/ltc.h>
35#include <nvgpu/channel.h> 35#include <nvgpu/channel.h>
36#include <nvgpu/clk_arb.h>
36 37
37#include "vgpu_linux.h" 38#include "vgpu_linux.h"
38#include "vgpu/fecs_trace_vgpu.h" 39#include "vgpu/fecs_trace_vgpu.h"
@@ -72,12 +73,19 @@ static void vgpu_remove_support(struct gk20a *g)
72static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform) 73static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform)
73{ 74{
74 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); 75 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
76 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
75 77
76 nvgpu_mutex_init(&g->power_lock); 78 nvgpu_mutex_init(&g->power_lock);
77 nvgpu_mutex_init(&g->ctxsw_disable_lock); 79 nvgpu_mutex_init(&g->ctxsw_disable_lock);
80 nvgpu_mutex_init(&g->clk_arb_enable_lock);
81
82 nvgpu_mutex_init(&priv->vgpu_clk_get_freq_lock);
83
78 l->regs_saved = l->regs; 84 l->regs_saved = l->regs;
79 l->bar1_saved = l->bar1; 85 l->bar1_saved = l->bar1;
80 86
87 nvgpu_atomic_set(&g->clk_arb_global_nr, 0);
88
81 g->aggressive_sync_destroy = platform->aggressive_sync_destroy; 89 g->aggressive_sync_destroy = platform->aggressive_sync_destroy;
82 g->aggressive_sync_destroy_thresh = platform->aggressive_sync_destroy_thresh; 90 g->aggressive_sync_destroy_thresh = platform->aggressive_sync_destroy_thresh;
83 __nvgpu_set_enabled(g, NVGPU_HAS_SYNCPOINTS, platform->has_syncpoints); 91 __nvgpu_set_enabled(g, NVGPU_HAS_SYNCPOINTS, platform->has_syncpoints);
@@ -206,6 +214,12 @@ int vgpu_pm_finalize_poweron(struct device *dev)
206 goto done; 214 goto done;
207 } 215 }
208 216
217 err = nvgpu_clk_arb_init_arbiter(g);
218 if (err) {
219 nvgpu_err(g, "failed to init clk arb");
220 goto done;
221 }
222
209 err = g->ops.chip_init_gpu_characteristics(g); 223 err = g->ops.chip_init_gpu_characteristics(g);
210 if (err) { 224 if (err) {
211 nvgpu_err(g, "failed to init gk20a gpu characteristics"); 225 nvgpu_err(g, "failed to init gk20a gpu characteristics");
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)
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c
index 78aef699..2b4b3463 100644
--- a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c
@@ -59,6 +59,7 @@
59#include "gp10b/gr_ctx_gp10b.h" 59#include "gp10b/gr_ctx_gp10b.h"
60#include "gp10b/fifo_gp10b.h" 60#include "gp10b/fifo_gp10b.h"
61#include "gp10b/regops_gp10b.h" 61#include "gp10b/regops_gp10b.h"
62#include "gp10b/clk_arb_gp10b.h"
62 63
63#include "gm20b/gr_gm20b.h" 64#include "gm20b/gr_gm20b.h"
64#include "gm20b/fifo_gm20b.h" 65#include "gm20b/fifo_gm20b.h"
@@ -450,6 +451,15 @@ static const struct gpu_ops vgpu_gp10b_ops = {
450 .reset_engine = NULL, 451 .reset_engine = NULL,
451 .is_engine_in_reset = NULL, 452 .is_engine_in_reset = NULL,
452 }, 453 },
454 .clk_arb = {
455 .get_arbiter_clk_domains = gp10b_get_arbiter_clk_domains,
456 .get_arbiter_f_points = gp10b_get_arbiter_f_points,
457 .get_arbiter_clk_range = gp10b_get_arbiter_clk_range,
458 .get_arbiter_clk_default = gp10b_get_arbiter_clk_default,
459 .arbiter_clk_init = gp10b_init_clk_arbiter,
460 .clk_arb_run_arbiter_cb = gp10b_clk_arb_run_arbiter_cb,
461 .clk_arb_cleanup = gp10b_clk_arb_cleanup,
462 },
453 .regops = { 463 .regops = {
454 .exec_regops = vgpu_exec_regops, 464 .exec_regops = vgpu_exec_regops,
455 .get_global_whitelist_ranges = 465 .get_global_whitelist_ranges =
@@ -558,6 +568,7 @@ static const struct gpu_ops vgpu_gp10b_ops = {
558int vgpu_gp10b_init_hal(struct gk20a *g) 568int vgpu_gp10b_init_hal(struct gk20a *g)
559{ 569{
560 struct gpu_ops *gops = &g->ops; 570 struct gpu_ops *gops = &g->ops;
571 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
561 572
562 gops->ltc = vgpu_gp10b_ops.ltc; 573 gops->ltc = vgpu_gp10b_ops.ltc;
563 gops->ce2 = vgpu_gp10b_ops.ce2; 574 gops->ce2 = vgpu_gp10b_ops.ce2;
@@ -573,6 +584,7 @@ int vgpu_gp10b_init_hal(struct gk20a *g)
573 gops->pramin = vgpu_gp10b_ops.pramin; 584 gops->pramin = vgpu_gp10b_ops.pramin;
574 gops->therm = vgpu_gp10b_ops.therm; 585 gops->therm = vgpu_gp10b_ops.therm;
575 gops->pmu = vgpu_gp10b_ops.pmu; 586 gops->pmu = vgpu_gp10b_ops.pmu;
587 gops->clk_arb = vgpu_gp10b_ops.clk_arb;
576 gops->regops = vgpu_gp10b_ops.regops; 588 gops->regops = vgpu_gp10b_ops.regops;
577 gops->mc = vgpu_gp10b_ops.mc; 589 gops->mc = vgpu_gp10b_ops.mc;
578 gops->debug = vgpu_gp10b_ops.debug; 590 gops->debug = vgpu_gp10b_ops.debug;
@@ -642,6 +654,10 @@ int vgpu_gp10b_init_hal(struct gk20a *g)
642 __nvgpu_set_enabled(g, NVGPU_PMU_FECS_BOOTSTRAP_DONE, false); 654 __nvgpu_set_enabled(g, NVGPU_PMU_FECS_BOOTSTRAP_DONE, false);
643 g->pmu_lsf_pmu_wpr_init_done = 0; 655 g->pmu_lsf_pmu_wpr_init_done = 0;
644 656
657 if (priv->constants.can_set_clkrate) {
658 gops->clk.support_clk_freq_controller = true;
659 }
660
645 g->name = "gp10b"; 661 g->name = "gp10b";
646 662
647 return 0; 663 return 0;
diff --git a/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c b/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c
index 1fc1b0f2..c0e1b1bb 100644
--- a/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c
+++ b/drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c
@@ -68,6 +68,7 @@
68#include <gp10b/ce_gp10b.h> 68#include <gp10b/ce_gp10b.h>
69#include "gp10b/gr_gp10b.h" 69#include "gp10b/gr_gp10b.h"
70#include <gp10b/fifo_gp10b.h> 70#include <gp10b/fifo_gp10b.h>
71#include "gp10b/clk_arb_gp10b.h"
71 72
72#include <gp106/pmu_gp106.h> 73#include <gp106/pmu_gp106.h>
73#include <gp106/acr_gp106.h> 74#include <gp106/acr_gp106.h>
@@ -522,6 +523,15 @@ static const struct gpu_ops vgpu_gv11b_ops = {
522 .pmu_pg_set_sub_feature_mask = NULL, 523 .pmu_pg_set_sub_feature_mask = NULL,
523 .is_pmu_supported = NULL, 524 .is_pmu_supported = NULL,
524 }, 525 },
526 .clk_arb = {
527 .get_arbiter_clk_domains = gp10b_get_arbiter_clk_domains,
528 .get_arbiter_f_points = gp10b_get_arbiter_f_points,
529 .get_arbiter_clk_range = gp10b_get_arbiter_clk_range,
530 .get_arbiter_clk_default = gp10b_get_arbiter_clk_default,
531 .arbiter_clk_init = gp10b_init_clk_arbiter,
532 .clk_arb_run_arbiter_cb = gp10b_clk_arb_run_arbiter_cb,
533 .clk_arb_cleanup = gp10b_clk_arb_cleanup,
534 },
525 .regops = { 535 .regops = {
526 .exec_regops = vgpu_exec_regops, 536 .exec_regops = vgpu_exec_regops,
527 .get_global_whitelist_ranges = 537 .get_global_whitelist_ranges =
@@ -627,6 +637,7 @@ static const struct gpu_ops vgpu_gv11b_ops = {
627int vgpu_gv11b_init_hal(struct gk20a *g) 637int vgpu_gv11b_init_hal(struct gk20a *g)
628{ 638{
629 struct gpu_ops *gops = &g->ops; 639 struct gpu_ops *gops = &g->ops;
640 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
630 641
631 gops->ltc = vgpu_gv11b_ops.ltc; 642 gops->ltc = vgpu_gv11b_ops.ltc;
632 gops->ce2 = vgpu_gv11b_ops.ce2; 643 gops->ce2 = vgpu_gv11b_ops.ce2;
@@ -641,6 +652,7 @@ int vgpu_gv11b_init_hal(struct gk20a *g)
641#endif 652#endif
642 gops->therm = vgpu_gv11b_ops.therm; 653 gops->therm = vgpu_gv11b_ops.therm;
643 gops->pmu = vgpu_gv11b_ops.pmu; 654 gops->pmu = vgpu_gv11b_ops.pmu;
655 gops->clk_arb = vgpu_gv11b_ops.clk_arb;
644 gops->regops = vgpu_gv11b_ops.regops; 656 gops->regops = vgpu_gv11b_ops.regops;
645 gops->mc = vgpu_gv11b_ops.mc; 657 gops->mc = vgpu_gv11b_ops.mc;
646 gops->debug = vgpu_gv11b_ops.debug; 658 gops->debug = vgpu_gv11b_ops.debug;
@@ -661,6 +673,10 @@ int vgpu_gv11b_init_hal(struct gk20a *g)
661 gops->get_litter_value = vgpu_gv11b_ops.get_litter_value; 673 gops->get_litter_value = vgpu_gv11b_ops.get_litter_value;
662 gops->semaphore_wakeup = gk20a_channel_semaphore_wakeup; 674 gops->semaphore_wakeup = gk20a_channel_semaphore_wakeup;
663 675
676 if (priv->constants.can_set_clkrate) {
677 gops->clk.support_clk_freq_controller = true;
678 }
679
664 g->name = "gv11b"; 680 g->name = "gv11b";
665 681
666 return 0; 682 return 0;
diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c
index 9ad0468e..7d7df9b3 100644
--- a/drivers/gpu/nvgpu/vgpu/vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/vgpu.c
@@ -26,6 +26,7 @@
26#include <nvgpu/vgpu/vgpu.h> 26#include <nvgpu/vgpu/vgpu.h>
27#include <nvgpu/timers.h> 27#include <nvgpu/timers.h>
28#include <nvgpu/channel.h> 28#include <nvgpu/channel.h>
29#include <nvgpu/clk_arb.h>
29 30
30#include "gk20a/gk20a.h" 31#include "gk20a/gk20a.h"
31#include "fecs_trace_vgpu.h" 32#include "fecs_trace_vgpu.h"
@@ -235,6 +236,13 @@ void vgpu_remove_support_common(struct gk20a *g)
235 &msg, sizeof(msg)); 236 &msg, sizeof(msg));
236 WARN_ON(err); 237 WARN_ON(err);
237 nvgpu_thread_stop(&priv->intr_handler); 238 nvgpu_thread_stop(&priv->intr_handler);
239
240 nvgpu_clk_arb_cleanup_arbiter(g);
241
242 nvgpu_mutex_destroy(&g->clk_arb_enable_lock);
243 nvgpu_mutex_destroy(&priv->vgpu_clk_get_freq_lock);
244
245 nvgpu_kfree(g, priv->freqs);
238} 246}
239 247
240void vgpu_detect_chip(struct gk20a *g) 248void vgpu_detect_chip(struct gk20a *g)