summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c
diff options
context:
space:
mode:
authorRichard Zhao <rizhao@nvidia.com>2018-01-29 18:43:50 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2018-02-27 17:30:32 -0500
commit8202be50ce80e7fc2cf851a1ec4ad8f9378e3306 (patch)
treee0b5d6fcd4a9a71c01569cc5a23e67cb2e751628 /drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c
parent28abb3d2cd3a9efe413be3c2f8e897ccd72f6b93 (diff)
gpu: nvgpu: vgpu: split vgpu.c into vgpu.c and vgpu_linux.c
vgpu.c will keep common code whil vgpu_linux.c is linux specific. Jira EVLR-2364 Change-Id: Ice9782fa96c256f1b70320886d3720ab0db26244 Signed-off-by: Richard Zhao <rizhao@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1649943 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c463
1 files changed, 463 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c b/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c
new file mode 100644
index 00000000..69bf22ee
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/vgpu/vgpu_linux.c
@@ -0,0 +1,463 @@
1/*
2 * Virtualized GPU for Linux
3 *
4 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/mm.h>
20#include <linux/dma-mapping.h>
21#include <linux/pm_runtime.h>
22#include <linux/pm_qos.h>
23#include <linux/platform_device.h>
24#include <soc/tegra/chip-id.h>
25#include <uapi/linux/nvgpu.h>
26
27#include <nvgpu/kmem.h>
28#include <nvgpu/bug.h>
29#include <nvgpu/enabled.h>
30#include <nvgpu/debug.h>
31#include <nvgpu/bus.h>
32#include <nvgpu/soc.h>
33#include <nvgpu/ctxsw_trace.h>
34#include <nvgpu/defaults.h>
35
36#include "vgpu.h"
37#include "vgpu_linux.h"
38#include "fecs_trace_vgpu.h"
39#include "clk_vgpu.h"
40#include "gk20a/tsg_gk20a.h"
41#include "gk20a/channel_gk20a.h"
42#include "gk20a/regops_gk20a.h"
43#include "gm20b/hal_gm20b.h"
44
45#include "common/linux/module.h"
46#include "common/linux/os_linux.h"
47#include "common/linux/ioctl.h"
48#include "common/linux/scale.h"
49#include "common/linux/driver_common.h"
50#include "common/linux/platform_gk20a.h"
51
52#include <nvgpu/hw/gk20a/hw_mc_gk20a.h>
53
54struct vgpu_priv_data *vgpu_get_priv_data(struct gk20a *g)
55{
56 struct gk20a_platform *plat = gk20a_get_platform(dev_from_gk20a(g));
57
58 return (struct vgpu_priv_data *)plat->vgpu_priv;
59}
60
61static void vgpu_remove_support(struct gk20a *g)
62{
63 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
64
65 vgpu_remove_support_common(g);
66
67 /* free mappings to registers, etc*/
68
69 if (l->bar1) {
70 iounmap(l->bar1);
71 l->bar1 = NULL;
72 }
73}
74
75static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform)
76{
77 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
78
79 nvgpu_mutex_init(&g->poweron_lock);
80 nvgpu_mutex_init(&g->poweroff_lock);
81 l->regs_saved = l->regs;
82 l->bar1_saved = l->bar1;
83
84 nvgpu_init_list_node(&g->pending_sema_waits);
85 nvgpu_raw_spinlock_init(&g->pending_sema_waits_lock);
86
87 g->aggressive_sync_destroy = platform->aggressive_sync_destroy;
88 g->aggressive_sync_destroy_thresh = platform->aggressive_sync_destroy_thresh;
89 g->has_syncpoints = platform->has_syncpoints;
90 g->ptimer_src_freq = platform->ptimer_src_freq;
91 g->can_railgate = platform->can_railgate_init;
92 g->railgate_delay = platform->railgate_delay_init;
93
94 __nvgpu_set_enabled(g, NVGPU_MM_UNIFY_ADDRESS_SPACES,
95 platform->unify_address_spaces);
96}
97
98static int vgpu_init_support(struct platform_device *pdev)
99{
100 struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
101 struct gk20a *g = get_gk20a(&pdev->dev);
102 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
103 void __iomem *regs;
104 int err = 0;
105
106 if (!r) {
107 nvgpu_err(g, "failed to get gk20a bar1");
108 err = -ENXIO;
109 goto fail;
110 }
111
112 if (r->name && !strcmp(r->name, "/vgpu")) {
113 regs = devm_ioremap_resource(&pdev->dev, r);
114 if (IS_ERR(regs)) {
115 nvgpu_err(g, "failed to remap gk20a bar1");
116 err = PTR_ERR(regs);
117 goto fail;
118 }
119 l->bar1 = regs;
120 l->bar1_mem = r;
121 }
122
123 nvgpu_mutex_init(&g->dbg_sessions_lock);
124 nvgpu_mutex_init(&g->client_lock);
125
126 nvgpu_init_list_node(&g->profiler_objects);
127
128 g->dbg_regops_tmp_buf = nvgpu_kzalloc(g, SZ_4K);
129 if (!g->dbg_regops_tmp_buf) {
130 nvgpu_err(g, "couldn't allocate regops tmp buf");
131 return -ENOMEM;
132 }
133 g->dbg_regops_tmp_buf_ops =
134 SZ_4K / sizeof(g->dbg_regops_tmp_buf[0]);
135
136 g->remove_support = vgpu_remove_support;
137 return 0;
138
139 fail:
140 vgpu_remove_support(g);
141 return err;
142}
143
144int vgpu_pm_prepare_poweroff(struct device *dev)
145{
146 struct gk20a *g = get_gk20a(dev);
147 int ret = 0;
148
149 gk20a_dbg_fn("");
150
151 if (!g->power_on)
152 return 0;
153
154 ret = gk20a_channel_suspend(g);
155 if (ret)
156 return ret;
157
158 g->power_on = false;
159
160 return ret;
161}
162
163int vgpu_pm_finalize_poweron(struct device *dev)
164{
165 struct gk20a *g = get_gk20a(dev);
166 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
167 int err;
168
169 gk20a_dbg_fn("");
170
171 if (g->power_on)
172 return 0;
173
174 g->power_on = true;
175
176 vgpu_detect_chip(g);
177 err = vgpu_init_hal(g);
178 if (err)
179 goto done;
180
181 if (g->ops.ltc.init_fs_state)
182 g->ops.ltc.init_fs_state(g);
183
184 err = vgpu_init_mm_support(g);
185 if (err) {
186 nvgpu_err(g, "failed to init gk20a mm");
187 goto done;
188 }
189
190 err = vgpu_init_fifo_support(g);
191 if (err) {
192 nvgpu_err(g, "failed to init gk20a fifo");
193 goto done;
194 }
195
196 err = vgpu_init_gr_support(g);
197 if (err) {
198 nvgpu_err(g, "failed to init gk20a gr");
199 goto done;
200 }
201
202 err = g->ops.chip_init_gpu_characteristics(g);
203 if (err) {
204 nvgpu_err(g, "failed to init gk20a gpu characteristics");
205 goto done;
206 }
207
208 err = nvgpu_finalize_poweron_linux(l);
209 if (err)
210 goto done;
211
212#ifdef CONFIG_GK20A_CTXSW_TRACE
213 gk20a_ctxsw_trace_init(g);
214#endif
215 gk20a_sched_ctrl_init(g);
216 gk20a_channel_resume(g);
217
218 g->sw_ready = true;
219
220done:
221 return err;
222}
223
224static int vgpu_qos_notify(struct notifier_block *nb,
225 unsigned long n, void *data)
226{
227 struct gk20a_scale_profile *profile =
228 container_of(nb, struct gk20a_scale_profile,
229 qos_notify_block);
230 struct gk20a *g = get_gk20a(profile->dev);
231 u32 max_freq;
232 int err;
233
234 gk20a_dbg_fn("");
235
236 max_freq = (u32)pm_qos_read_max_bound(PM_QOS_GPU_FREQ_BOUNDS);
237 err = vgpu_clk_cap_rate(profile->dev, max_freq);
238 if (err)
239 nvgpu_err(g, "%s failed, err=%d", __func__, err);
240
241 return NOTIFY_OK; /* need notify call further */
242}
243
244static int vgpu_pm_qos_init(struct device *dev)
245{
246 struct gk20a *g = get_gk20a(dev);
247 struct gk20a_scale_profile *profile = g->scale_profile;
248
249 if (IS_ENABLED(CONFIG_GK20A_DEVFREQ)) {
250 if (!profile)
251 return -EINVAL;
252 } else {
253 profile = nvgpu_kzalloc(g, sizeof(*profile));
254 if (!profile)
255 return -ENOMEM;
256 g->scale_profile = profile;
257 }
258
259 profile->dev = dev;
260 profile->qos_notify_block.notifier_call = vgpu_qos_notify;
261 pm_qos_add_max_notifier(PM_QOS_GPU_FREQ_BOUNDS,
262 &profile->qos_notify_block);
263 return 0;
264}
265
266static void vgpu_pm_qos_remove(struct device *dev)
267{
268 struct gk20a *g = get_gk20a(dev);
269
270 pm_qos_remove_max_notifier(PM_QOS_GPU_FREQ_BOUNDS,
271 &g->scale_profile->qos_notify_block);
272 nvgpu_kfree(g, g->scale_profile);
273 g->scale_profile = NULL;
274}
275
276static int vgpu_pm_init(struct device *dev)
277{
278 struct gk20a *g = get_gk20a(dev);
279 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
280 unsigned long *freqs;
281 int num_freqs;
282 int err = 0;
283
284 gk20a_dbg_fn("");
285
286 if (nvgpu_platform_is_simulation(g))
287 return 0;
288
289 __pm_runtime_disable(dev, false);
290
291 if (IS_ENABLED(CONFIG_GK20A_DEVFREQ))
292 gk20a_scale_init(dev);
293
294 if (l->devfreq) {
295 /* set min/max frequency based on frequency table */
296 err = vgpu_clk_get_freqs(dev, &freqs, &num_freqs);
297 if (err)
298 return err;
299
300 if (num_freqs < 1)
301 return -EINVAL;
302
303 l->devfreq->min_freq = freqs[0];
304 l->devfreq->max_freq = freqs[num_freqs - 1];
305 }
306
307 err = vgpu_pm_qos_init(dev);
308 if (err)
309 return err;
310
311 return err;
312}
313
314int vgpu_probe(struct platform_device *pdev)
315{
316 struct nvgpu_os_linux *l;
317 struct gk20a *gk20a;
318 int err;
319 struct device *dev = &pdev->dev;
320 struct gk20a_platform *platform = gk20a_get_platform(dev);
321 struct vgpu_priv_data *priv;
322
323 if (!platform) {
324 dev_err(dev, "no platform data\n");
325 return -ENODATA;
326 }
327
328 gk20a_dbg_fn("");
329
330 l = kzalloc(sizeof(*l), GFP_KERNEL);
331 if (!l) {
332 dev_err(dev, "couldn't allocate gk20a support");
333 return -ENOMEM;
334 }
335 gk20a = &l->g;
336 nvgpu_init_gk20a(gk20a);
337
338 nvgpu_kmem_init(gk20a);
339
340 err = nvgpu_init_enabled_flags(gk20a);
341 if (err) {
342 kfree(gk20a);
343 return err;
344 }
345
346 l->dev = dev;
347 if (tegra_platform_is_vdk())
348 __nvgpu_set_enabled(gk20a, NVGPU_IS_FMODEL, true);
349
350 gk20a->is_virtual = true;
351
352 priv = nvgpu_kzalloc(gk20a, sizeof(*priv));
353 if (!priv) {
354 kfree(gk20a);
355 return -ENOMEM;
356 }
357
358 platform->g = gk20a;
359 platform->vgpu_priv = priv;
360
361 err = gk20a_user_init(dev, INTERFACE_NAME, &nvgpu_class);
362 if (err)
363 return err;
364
365 vgpu_init_support(pdev);
366
367 vgpu_init_vars(gk20a, platform);
368
369 init_rwsem(&l->busy_lock);
370
371 nvgpu_spinlock_init(&gk20a->mc_enable_lock);
372
373 gk20a->ch_wdt_timeout_ms = platform->ch_wdt_timeout_ms;
374
375 /* Initialize the platform interface. */
376 err = platform->probe(dev);
377 if (err) {
378 if (err == -EPROBE_DEFER)
379 nvgpu_info(gk20a, "platform probe failed");
380 else
381 nvgpu_err(gk20a, "platform probe failed");
382 return err;
383 }
384
385 if (platform->late_probe) {
386 err = platform->late_probe(dev);
387 if (err) {
388 nvgpu_err(gk20a, "late probe failed");
389 return err;
390 }
391 }
392
393 err = vgpu_comm_init(gk20a);
394 if (err) {
395 nvgpu_err(gk20a, "failed to init comm interface");
396 return -ENOSYS;
397 }
398
399 priv->virt_handle = vgpu_connect();
400 if (!priv->virt_handle) {
401 nvgpu_err(gk20a, "failed to connect to server node");
402 vgpu_comm_deinit();
403 return -ENOSYS;
404 }
405
406 err = vgpu_get_constants(gk20a);
407 if (err) {
408 vgpu_comm_deinit();
409 return err;
410 }
411
412 err = vgpu_pm_init(dev);
413 if (err) {
414 nvgpu_err(gk20a, "pm init failed");
415 return err;
416 }
417
418 err = nvgpu_thread_create(&priv->intr_handler, gk20a,
419 vgpu_intr_thread, "gk20a");
420 if (err)
421 return err;
422
423 gk20a_debug_init(gk20a, "gpu.0");
424
425 /* Set DMA parameters to allow larger sgt lists */
426 dev->dma_parms = &l->dma_parms;
427 dma_set_max_seg_size(dev, UINT_MAX);
428
429 gk20a->gr_idle_timeout_default = NVGPU_DEFAULT_GR_IDLE_TIMEOUT;
430 gk20a->timeouts_enabled = true;
431
432 vgpu_create_sysfs(dev);
433 gk20a_init_gr(gk20a);
434
435 gk20a_dbg_info("total ram pages : %lu", totalram_pages);
436 gk20a->gr.max_comptag_mem = totalram_pages
437 >> (10 - (PAGE_SHIFT - 10));
438
439 nvgpu_ref_init(&gk20a->refcount);
440
441 return 0;
442}
443
444int vgpu_remove(struct platform_device *pdev)
445{
446 struct device *dev = &pdev->dev;
447 struct gk20a *g = get_gk20a(dev);
448
449 gk20a_dbg_fn("");
450
451 vgpu_pm_qos_remove(dev);
452 if (g->remove_support)
453 g->remove_support(g);
454
455 vgpu_comm_deinit();
456 gk20a_sched_ctrl_cleanup(g);
457 gk20a_user_deinit(dev, &nvgpu_class);
458 vgpu_remove_sysfs(dev);
459 gk20a_get_platform(dev)->g = NULL;
460 gk20a_put(g);
461
462 return 0;
463}