diff options
author | Aparna Das <aparnad@nvidia.com> | 2018-09-11 20:11:44 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-09-27 18:04:47 -0400 |
commit | 78e3d22da3c2513d425c8c2560468ce854a982dd (patch) | |
tree | 87ce6d1c47357c868cb58608e893afb4c14cfa69 /drivers/gpu/nvgpu/vgpu | |
parent | 8789cafcfb0d1e16ad0b2c61b047d275f2d684b4 (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')
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/clk_vgpu.c | 174 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/gp10b/vgpu_hal_gp10b.c | 16 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/gv11b/vgpu_hal_gv11b.c | 16 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/vgpu/vgpu.c | 8 |
4 files changed, 199 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 | ||
29 | static unsigned long | ||
30 | vgpu_freq_table[TEGRA_VGPU_GPU_FREQ_TABLE_SIZE]; | ||
31 | |||
32 | static unsigned long vgpu_clk_get_rate(struct gk20a *g, u32 api_domain) | 30 | static 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 | ||
96 | static unsigned long vgpu_clk_get_maxrate(struct gk20a *g, u32 api_domain) | 94 | static 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 | |||
119 | static 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 | |||
139 | static 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 | |||
165 | static 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 | ||
103 | void vgpu_init_clk_support(struct gk20a *g) | 209 | void 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 | ||
110 | int vgpu_clk_get_freqs(struct gk20a *g, unsigned long **freqs, int *num_freqs) | 219 | int 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 | |||
274 | done: | ||
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 | ||
141 | int vgpu_clk_cap_rate(struct gk20a *g, unsigned long rate) | 285 | int 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 = { | |||
558 | int vgpu_gp10b_init_hal(struct gk20a *g) | 568 | int 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 = { | |||
627 | int vgpu_gv11b_init_hal(struct gk20a *g) | 637 | int 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 | ||
240 | void vgpu_detect_chip(struct gk20a *g) | 248 | void vgpu_detect_chip(struct gk20a *g) |