summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/os/linux/vgpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/os/linux/vgpu')
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/clk_vgpu.c168
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/clk_vgpu.h27
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/fecs_trace_vgpu.c224
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/gv11b/platform_gv11b_vgpu_tegra.c97
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/platform_vgpu_tegra.c69
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c50
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/vgpu_ivc.c77
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/vgpu_ivm.c53
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c475
-rw-r--r--drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.h57
10 files changed, 1297 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/clk_vgpu.c b/drivers/gpu/nvgpu/os/linux/vgpu/clk_vgpu.c
new file mode 100644
index 00000000..9f6017d3
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/clk_vgpu.c
@@ -0,0 +1,168 @@
1/*
2 * Virtualized GPU Clock Interface
3 *
4 * Copyright (c) 2017-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 <nvgpu/vgpu/vgpu.h>
20
21#include "gk20a/gk20a.h"
22#include "clk_vgpu.h"
23#include "ctrl/ctrlclk.h"
24#include "os/linux/platform_gk20a.h"
25
26static unsigned long
27vgpu_freq_table[TEGRA_VGPU_GPU_FREQ_TABLE_SIZE];
28
29static unsigned long vgpu_clk_get_rate(struct gk20a *g, u32 api_domain)
30{
31 struct tegra_vgpu_cmd_msg msg = {};
32 struct tegra_vgpu_gpu_clk_rate_params *p = &msg.params.gpu_clk_rate;
33 int err;
34 unsigned long ret = 0;
35
36 nvgpu_log_fn(g, " ");
37
38 switch (api_domain) {
39 case CTRL_CLK_DOMAIN_GPCCLK:
40 msg.cmd = TEGRA_VGPU_CMD_GET_GPU_CLK_RATE;
41 msg.handle = vgpu_get_handle(g);
42 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
43 err = err ? err : msg.ret;
44 if (err)
45 nvgpu_err(g, "%s failed - %d", __func__, err);
46 else
47 /* return frequency in Hz */
48 ret = p->rate * 1000;
49 break;
50 case CTRL_CLK_DOMAIN_PWRCLK:
51 nvgpu_err(g, "unsupported clock: %u", api_domain);
52 break;
53 default:
54 nvgpu_err(g, "unknown clock: %u", api_domain);
55 break;
56 }
57
58 return ret;
59}
60
61static int vgpu_clk_set_rate(struct gk20a *g,
62 u32 api_domain, unsigned long rate)
63{
64 struct tegra_vgpu_cmd_msg msg = {};
65 struct tegra_vgpu_gpu_clk_rate_params *p = &msg.params.gpu_clk_rate;
66 int err = -EINVAL;
67
68 nvgpu_log_fn(g, " ");
69
70 switch (api_domain) {
71 case CTRL_CLK_DOMAIN_GPCCLK:
72 msg.cmd = TEGRA_VGPU_CMD_SET_GPU_CLK_RATE;
73 msg.handle = vgpu_get_handle(g);
74
75 /* server dvfs framework requires frequency in kHz */
76 p->rate = (u32)(rate / 1000);
77 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
78 err = err ? err : msg.ret;
79 if (err)
80 nvgpu_err(g, "%s failed - %d", __func__, err);
81 break;
82 case CTRL_CLK_DOMAIN_PWRCLK:
83 nvgpu_err(g, "unsupported clock: %u", api_domain);
84 break;
85 default:
86 nvgpu_err(g, "unknown clock: %u", api_domain);
87 break;
88 }
89
90 return err;
91}
92
93static unsigned long vgpu_clk_get_maxrate(struct gk20a *g, u32 api_domain)
94{
95 struct vgpu_priv_data *priv = vgpu_get_priv_data(g);
96
97 return priv->constants.max_freq;
98}
99
100void vgpu_init_clk_support(struct gk20a *g)
101{
102 g->ops.clk.get_rate = vgpu_clk_get_rate;
103 g->ops.clk.set_rate = vgpu_clk_set_rate;
104 g->ops.clk.get_maxrate = vgpu_clk_get_maxrate;
105}
106
107long vgpu_clk_round_rate(struct device *dev, unsigned long rate)
108{
109 /* server will handle frequency rounding */
110 return rate;
111}
112
113int vgpu_clk_get_freqs(struct device *dev,
114 unsigned long **freqs, int *num_freqs)
115{
116 struct gk20a_platform *platform = gk20a_get_platform(dev);
117 struct gk20a *g = platform->g;
118 struct tegra_vgpu_cmd_msg msg = {};
119 struct tegra_vgpu_get_gpu_freq_table_params *p =
120 &msg.params.get_gpu_freq_table;
121 unsigned int i;
122 int err;
123
124 nvgpu_log_fn(g, " ");
125
126 msg.cmd = TEGRA_VGPU_CMD_GET_GPU_FREQ_TABLE;
127 msg.handle = vgpu_get_handle(g);
128
129 p->num_freqs = TEGRA_VGPU_GPU_FREQ_TABLE_SIZE;
130 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
131 err = err ? err : msg.ret;
132 if (err) {
133 nvgpu_err(g, "%s failed - %d", __func__, err);
134 return err;
135 }
136
137 /* return frequency in Hz */
138 for (i = 0; i < p->num_freqs; i++)
139 vgpu_freq_table[i] = p->freqs[i] * 1000;
140
141 *freqs = vgpu_freq_table;
142 *num_freqs = p->num_freqs;
143
144 return 0;
145}
146
147int vgpu_clk_cap_rate(struct device *dev, unsigned long rate)
148{
149 struct gk20a_platform *platform = gk20a_get_platform(dev);
150 struct gk20a *g = platform->g;
151 struct tegra_vgpu_cmd_msg msg = {};
152 struct tegra_vgpu_gpu_clk_rate_params *p = &msg.params.gpu_clk_rate;
153 int err = 0;
154
155 nvgpu_log_fn(g, " ");
156
157 msg.cmd = TEGRA_VGPU_CMD_CAP_GPU_CLK_RATE;
158 msg.handle = vgpu_get_handle(g);
159 p->rate = (u32)rate;
160 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
161 err = err ? err : msg.ret;
162 if (err) {
163 nvgpu_err(g, "%s failed - %d", __func__, err);
164 return err;
165 }
166
167 return 0;
168}
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/clk_vgpu.h b/drivers/gpu/nvgpu/os/linux/vgpu/clk_vgpu.h
new file mode 100644
index 00000000..8d477643
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/clk_vgpu.h
@@ -0,0 +1,27 @@
1/*
2 * Virtualized GPU Clock Interface
3 *
4 * Copyright (c) 2017, 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#ifndef _CLK_VIRT_H_
20#define _CLK_VIRT_H_
21
22void vgpu_init_clk_support(struct gk20a *g);
23long vgpu_clk_round_rate(struct device *dev, unsigned long rate);
24int vgpu_clk_get_freqs(struct device *dev,
25 unsigned long **freqs, int *num_freqs);
26int vgpu_clk_cap_rate(struct device *dev, unsigned long rate);
27#endif
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/fecs_trace_vgpu.c b/drivers/gpu/nvgpu/os/linux/vgpu/fecs_trace_vgpu.c
new file mode 100644
index 00000000..6339aef9
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/fecs_trace_vgpu.c
@@ -0,0 +1,224 @@
1/*
2 * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <uapi/linux/nvgpu.h>
18
19#include <nvgpu/kmem.h>
20#include <nvgpu/bug.h>
21#include <nvgpu/enabled.h>
22#include <nvgpu/ctxsw_trace.h>
23#include <nvgpu/vgpu/vgpu_ivm.h>
24#include <nvgpu/vgpu/tegra_vgpu.h>
25#include <nvgpu/vgpu/vgpu.h>
26
27#include "gk20a/gk20a.h"
28#include "os/linux/os_linux.h"
29#include "vgpu/fecs_trace_vgpu.h"
30
31struct vgpu_fecs_trace {
32 struct tegra_hv_ivm_cookie *cookie;
33 struct nvgpu_ctxsw_ring_header *header;
34 struct nvgpu_ctxsw_trace_entry *entries;
35 int num_entries;
36 bool enabled;
37 void *buf;
38};
39
40int vgpu_fecs_trace_init(struct gk20a *g)
41{
42 struct device *dev = dev_from_gk20a(g);
43 struct device_node *np = dev->of_node;
44 struct of_phandle_args args;
45 struct vgpu_fecs_trace *vcst;
46 u32 mempool;
47 int err;
48
49 nvgpu_log_fn(g, " ");
50
51 vcst = nvgpu_kzalloc(g, sizeof(*vcst));
52 if (!vcst)
53 return -ENOMEM;
54
55 err = of_parse_phandle_with_fixed_args(np,
56 "mempool-fecs-trace", 1, 0, &args);
57 if (err) {
58 nvgpu_info(g, "does not support fecs trace");
59 goto fail;
60 }
61 __nvgpu_set_enabled(g, NVGPU_SUPPORT_FECS_CTXSW_TRACE, true);
62
63 mempool = args.args[0];
64 vcst->cookie = vgpu_ivm_mempool_reserve(mempool);
65 if (IS_ERR(vcst->cookie)) {
66 nvgpu_info(g,
67 "mempool %u reserve failed", mempool);
68 vcst->cookie = NULL;
69 err = -EINVAL;
70 goto fail;
71 }
72
73 vcst->buf = ioremap_cache(vgpu_ivm_get_ipa(vcst->cookie),
74 vgpu_ivm_get_size(vcst->cookie));
75 if (!vcst->buf) {
76 nvgpu_info(g, "ioremap_cache failed");
77 err = -EINVAL;
78 goto fail;
79 }
80 vcst->header = vcst->buf;
81 vcst->num_entries = vcst->header->num_ents;
82 if (unlikely(vcst->header->ent_size != sizeof(*vcst->entries))) {
83 nvgpu_err(g, "entry size mismatch");
84 goto fail;
85 }
86 vcst->entries = vcst->buf + sizeof(*vcst->header);
87 g->fecs_trace = (struct gk20a_fecs_trace *)vcst;
88
89 return 0;
90fail:
91 iounmap(vcst->buf);
92 if (vcst->cookie)
93 vgpu_ivm_mempool_unreserve(vcst->cookie);
94 nvgpu_kfree(g, vcst);
95 return err;
96}
97
98int vgpu_fecs_trace_deinit(struct gk20a *g)
99{
100 struct vgpu_fecs_trace *vcst = (struct vgpu_fecs_trace *)g->fecs_trace;
101
102 iounmap(vcst->buf);
103 vgpu_ivm_mempool_unreserve(vcst->cookie);
104 nvgpu_kfree(g, vcst);
105 return 0;
106}
107
108int vgpu_fecs_trace_enable(struct gk20a *g)
109{
110 struct vgpu_fecs_trace *vcst = (struct vgpu_fecs_trace *)g->fecs_trace;
111 struct tegra_vgpu_cmd_msg msg = {
112 .cmd = TEGRA_VGPU_CMD_FECS_TRACE_ENABLE,
113 .handle = vgpu_get_handle(g),
114 };
115 int err;
116
117 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
118 err = err ? err : msg.ret;
119 WARN_ON(err);
120 vcst->enabled = !err;
121 return err;
122}
123
124int vgpu_fecs_trace_disable(struct gk20a *g)
125{
126 struct vgpu_fecs_trace *vcst = (struct vgpu_fecs_trace *)g->fecs_trace;
127 struct tegra_vgpu_cmd_msg msg = {
128 .cmd = TEGRA_VGPU_CMD_FECS_TRACE_DISABLE,
129 .handle = vgpu_get_handle(g),
130 };
131 int err;
132
133 vcst->enabled = false;
134 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
135 err = err ? err : msg.ret;
136 WARN_ON(err);
137 return err;
138}
139
140bool vgpu_fecs_trace_is_enabled(struct gk20a *g)
141{
142 struct vgpu_fecs_trace *vcst = (struct vgpu_fecs_trace *)g->fecs_trace;
143
144 return (vcst && vcst->enabled);
145}
146
147int vgpu_fecs_trace_poll(struct gk20a *g)
148{
149 struct tegra_vgpu_cmd_msg msg = {
150 .cmd = TEGRA_VGPU_CMD_FECS_TRACE_POLL,
151 .handle = vgpu_get_handle(g),
152 };
153 int err;
154
155 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
156 err = err ? err : msg.ret;
157 WARN_ON(err);
158 return err;
159}
160
161int vgpu_alloc_user_buffer(struct gk20a *g, void **buf, size_t *size)
162{
163 struct vgpu_fecs_trace *vcst = (struct vgpu_fecs_trace *)g->fecs_trace;
164
165 *buf = vcst->buf;
166 *size = vgpu_ivm_get_size(vcst->cookie);
167 return 0;
168}
169
170int vgpu_free_user_buffer(struct gk20a *g)
171{
172 return 0;
173}
174
175int vgpu_mmap_user_buffer(struct gk20a *g, struct vm_area_struct *vma)
176{
177 struct vgpu_fecs_trace *vcst = (struct vgpu_fecs_trace *)g->fecs_trace;
178 unsigned long size = vgpu_ivm_get_size(vcst->cookie);
179 unsigned long vsize = vma->vm_end - vma->vm_start;
180
181 size = min(size, vsize);
182 size = round_up(size, PAGE_SIZE);
183
184 return remap_pfn_range(vma, vma->vm_start,
185 vgpu_ivm_get_ipa(vcst->cookie) >> PAGE_SHIFT,
186 size,
187 vma->vm_page_prot);
188}
189
190#ifdef CONFIG_GK20A_CTXSW_TRACE
191int vgpu_fecs_trace_max_entries(struct gk20a *g,
192 struct nvgpu_ctxsw_trace_filter *filter)
193{
194 struct vgpu_fecs_trace *vcst = (struct vgpu_fecs_trace *)g->fecs_trace;
195
196 return vcst->header->num_ents;
197}
198
199#if NVGPU_CTXSW_FILTER_SIZE != TEGRA_VGPU_FECS_TRACE_FILTER_SIZE
200#error "FECS trace filter size mismatch!"
201#endif
202
203int vgpu_fecs_trace_set_filter(struct gk20a *g,
204 struct nvgpu_ctxsw_trace_filter *filter)
205{
206 struct tegra_vgpu_cmd_msg msg = {
207 .cmd = TEGRA_VGPU_CMD_FECS_TRACE_SET_FILTER,
208 .handle = vgpu_get_handle(g),
209 };
210 struct tegra_vgpu_fecs_trace_filter *p = &msg.params.fecs_trace_filter;
211 int err;
212
213 memcpy(&p->tag_bits, &filter->tag_bits, sizeof(p->tag_bits));
214 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
215 err = err ? err : msg.ret;
216 WARN_ON(err);
217 return err;
218}
219
220void vgpu_fecs_trace_data_update(struct gk20a *g)
221{
222 gk20a_ctxsw_trace_wake_up(g, 0);
223}
224#endif /* CONFIG_GK20A_CTXSW_TRACE */
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/gv11b/platform_gv11b_vgpu_tegra.c b/drivers/gpu/nvgpu/os/linux/vgpu/gv11b/platform_gv11b_vgpu_tegra.c
new file mode 100644
index 00000000..66911626
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/gv11b/platform_gv11b_vgpu_tegra.c
@@ -0,0 +1,97 @@
1/*
2 * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/platform_device.h>
18
19#include <nvgpu/nvhost.h>
20
21#include "gk20a/gk20a.h"
22#include "os/linux/vgpu/clk_vgpu.h"
23#include "os/linux/platform_gk20a.h"
24#include "os/linux/os_linux.h"
25
26static int gv11b_vgpu_probe(struct device *dev)
27{
28 struct platform_device *pdev = to_platform_device(dev);
29 struct gk20a_platform *platform = dev_get_drvdata(dev);
30 struct resource *r;
31 void __iomem *regs;
32 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(platform->g);
33 struct gk20a *g = platform->g;
34 int ret;
35
36 r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usermode");
37 if (!r) {
38 nvgpu_err(g, "failed to get usermode regs");
39 return -ENXIO;
40 }
41 regs = devm_ioremap_resource(dev, r);
42 if (IS_ERR(regs)) {
43 nvgpu_err(g, "failed to map usermode regs");
44 return PTR_ERR(regs);
45 }
46 l->usermode_regs = regs;
47
48#ifdef CONFIG_TEGRA_GK20A_NVHOST
49 ret = nvgpu_get_nvhost_dev(g);
50 if (ret) {
51 l->usermode_regs = NULL;
52 return ret;
53 }
54
55 ret = nvgpu_nvhost_syncpt_unit_interface_get_aperture(g->nvhost_dev,
56 &g->syncpt_unit_base,
57 &g->syncpt_unit_size);
58 if (ret) {
59 nvgpu_err(g, "Failed to get syncpt interface");
60 return -ENOSYS;
61 }
62 g->syncpt_size = nvgpu_nvhost_syncpt_unit_interface_get_byte_offset(1);
63 nvgpu_info(g, "syncpt_unit_base %llx syncpt_unit_size %zx size %x\n",
64 g->syncpt_unit_base, g->syncpt_unit_size, g->syncpt_size);
65#endif
66 vgpu_init_clk_support(platform->g);
67
68 return 0;
69}
70
71struct gk20a_platform gv11b_vgpu_tegra_platform = {
72 .has_syncpoints = true,
73
74 /* power management configuration */
75 .can_railgate_init = false,
76 .can_elpg_init = false,
77 .enable_slcg = false,
78 .enable_blcg = false,
79 .enable_elcg = false,
80 .enable_elpg = false,
81 .enable_aelpg = false,
82 .can_slcg = false,
83 .can_blcg = false,
84 .can_elcg = false,
85
86 .ch_wdt_timeout_ms = 5000,
87
88 .probe = gv11b_vgpu_probe,
89
90 .clk_round_rate = vgpu_clk_round_rate,
91 .get_clk_freqs = vgpu_clk_get_freqs,
92
93 /* frequency scaling configuration */
94 .devfreq_governor = "userspace",
95
96 .virtual_dev = true,
97};
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/platform_vgpu_tegra.c b/drivers/gpu/nvgpu/os/linux/vgpu/platform_vgpu_tegra.c
new file mode 100644
index 00000000..e4819e7d
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/platform_vgpu_tegra.c
@@ -0,0 +1,69 @@
1/*
2 * Tegra Virtualized GPU Platform Interface
3 *
4 * Copyright (c) 2014-2017, 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 <nvgpu/nvhost.h>
20
21#include "gk20a/gk20a.h"
22#include "os/linux/platform_gk20a.h"
23#include "clk_vgpu.h"
24
25static int gk20a_tegra_probe(struct device *dev)
26{
27#ifdef CONFIG_TEGRA_GK20A_NVHOST
28 struct gk20a_platform *platform = dev_get_drvdata(dev);
29 int ret;
30
31 ret = nvgpu_get_nvhost_dev(platform->g);
32 if (ret)
33 return ret;
34
35 vgpu_init_clk_support(platform->g);
36 return 0;
37#else
38 return 0;
39#endif
40}
41
42struct gk20a_platform vgpu_tegra_platform = {
43 .has_syncpoints = true,
44 .aggressive_sync_destroy_thresh = 64,
45
46 /* power management configuration */
47 .can_railgate_init = false,
48 .can_elpg_init = false,
49 .enable_slcg = false,
50 .enable_blcg = false,
51 .enable_elcg = false,
52 .enable_elpg = false,
53 .enable_aelpg = false,
54 .can_slcg = false,
55 .can_blcg = false,
56 .can_elcg = false,
57
58 .ch_wdt_timeout_ms = 5000,
59
60 .probe = gk20a_tegra_probe,
61
62 .clk_round_rate = vgpu_clk_round_rate,
63 .get_clk_freqs = vgpu_clk_get_freqs,
64
65 /* frequency scaling configuration */
66 .devfreq_governor = "userspace",
67
68 .virtual_dev = true,
69};
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c b/drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c
new file mode 100644
index 00000000..57aad4b4
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/sysfs_vgpu.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/device.h>
18#include <nvgpu/vgpu/vgpu.h>
19
20#include "os/linux/platform_gk20a.h"
21
22static ssize_t vgpu_load_show(struct device *dev,
23 struct device_attribute *attr,
24 char *buf)
25{
26 struct gk20a *g = get_gk20a(dev);
27 struct tegra_vgpu_cmd_msg msg = {0};
28 struct tegra_vgpu_gpu_load_params *p = &msg.params.gpu_load;
29 int err;
30
31 msg.cmd = TEGRA_VGPU_CMD_GET_GPU_LOAD;
32 msg.handle = vgpu_get_handle(g);
33 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
34 if (err)
35 return err;
36
37 return snprintf(buf, PAGE_SIZE, "%u\n", p->load);
38}
39static DEVICE_ATTR(load, S_IRUGO, vgpu_load_show, NULL);
40
41void vgpu_create_sysfs(struct device *dev)
42{
43 if (device_create_file(dev, &dev_attr_load))
44 dev_err(dev, "Failed to create vgpu sysfs attributes!\n");
45}
46
47void vgpu_remove_sysfs(struct device *dev)
48{
49 device_remove_file(dev, &dev_attr_load);
50}
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_ivc.c b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_ivc.c
new file mode 100644
index 00000000..950f0d49
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_ivc.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (c) 2018, NVIDIA Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <nvgpu/types.h>
18#include <linux/tegra_gr_comm.h>
19
20#include "os/linux/os_linux.h"
21
22int vgpu_ivc_init(struct gk20a *g, u32 elems,
23 const size_t *queue_sizes, u32 queue_start, u32 num_queues)
24{
25 struct platform_device *pdev = to_platform_device(dev_from_gk20a(g));
26
27 return tegra_gr_comm_init(pdev, elems, queue_sizes, queue_start,
28 num_queues);
29}
30
31void vgpu_ivc_deinit(u32 queue_start, u32 num_queues)
32{
33 tegra_gr_comm_deinit(queue_start, num_queues);
34}
35
36void vgpu_ivc_release(void *handle)
37{
38 tegra_gr_comm_release(handle);
39}
40
41u32 vgpu_ivc_get_server_vmid(void)
42{
43 return tegra_gr_comm_get_server_vmid();
44}
45
46int vgpu_ivc_recv(u32 index, void **handle, void **data,
47 size_t *size, u32 *sender)
48{
49 return tegra_gr_comm_recv(index, handle, data, size, sender);
50}
51
52int vgpu_ivc_send(u32 peer, u32 index, void *data, size_t size)
53{
54 return tegra_gr_comm_send(peer, index, data, size);
55}
56
57int vgpu_ivc_sendrecv(u32 peer, u32 index, void **handle,
58 void **data, size_t *size)
59{
60 return tegra_gr_comm_sendrecv(peer, index, handle, data, size);
61}
62
63u32 vgpu_ivc_get_peer_self(void)
64{
65 return TEGRA_GR_COMM_ID_SELF;
66}
67
68void *vgpu_ivc_oob_get_ptr(u32 peer, u32 index, void **ptr,
69 size_t *size)
70{
71 return tegra_gr_comm_oob_get_ptr(peer, index, ptr, size);
72}
73
74void vgpu_ivc_oob_put_ptr(void *handle)
75{
76 tegra_gr_comm_oob_put_ptr(handle);
77}
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_ivm.c b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_ivm.c
new file mode 100644
index 00000000..bbd444da
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_ivm.c
@@ -0,0 +1,53 @@
1/*
2 * Copyright (c) 2018, NVIDIA Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <nvgpu/vgpu/vgpu_ivm.h>
18
19#include <linux/tegra-ivc.h>
20
21#include "os/linux/os_linux.h"
22
23struct tegra_hv_ivm_cookie *vgpu_ivm_mempool_reserve(unsigned int id)
24{
25 return tegra_hv_mempool_reserve(id);
26}
27
28int vgpu_ivm_mempool_unreserve(struct tegra_hv_ivm_cookie *cookie)
29{
30 return tegra_hv_mempool_unreserve(cookie);
31}
32
33u64 vgpu_ivm_get_ipa(struct tegra_hv_ivm_cookie *cookie)
34{
35 return cookie->ipa;
36}
37
38u64 vgpu_ivm_get_size(struct tegra_hv_ivm_cookie *cookie)
39{
40 return cookie->size;
41}
42
43void *vgpu_ivm_mempool_map(struct tegra_hv_ivm_cookie *cookie)
44{
45 return ioremap_cache(vgpu_ivm_get_ipa(cookie),
46 vgpu_ivm_get_size(cookie));
47}
48
49void vgpu_ivm_mempool_unmap(struct tegra_hv_ivm_cookie *cookie,
50 void *addr)
51{
52 iounmap(addr);
53}
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c
new file mode 100644
index 00000000..a7612e54
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.c
@@ -0,0 +1,475 @@
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
26#include <nvgpu/kmem.h>
27#include <nvgpu/bug.h>
28#include <nvgpu/enabled.h>
29#include <nvgpu/debug.h>
30#include <nvgpu/soc.h>
31#include <nvgpu/ctxsw_trace.h>
32#include <nvgpu/defaults.h>
33#include <nvgpu/ltc.h>
34
35#include "vgpu_linux.h"
36#include "vgpu/fecs_trace_vgpu.h"
37#include "clk_vgpu.h"
38#include "gk20a/tsg_gk20a.h"
39#include "gk20a/channel_gk20a.h"
40#include "gk20a/regops_gk20a.h"
41#include "gm20b/hal_gm20b.h"
42
43#include "os/linux/module.h"
44#include "os/linux/os_linux.h"
45#include "os/linux/ioctl.h"
46#include "os/linux/scale.h"
47#include "os/linux/driver_common.h"
48#include "os/linux/platform_gk20a.h"
49
50#include <nvgpu/hw/gk20a/hw_mc_gk20a.h>
51
52struct vgpu_priv_data *vgpu_get_priv_data(struct gk20a *g)
53{
54 struct gk20a_platform *plat = gk20a_get_platform(dev_from_gk20a(g));
55
56 return (struct vgpu_priv_data *)plat->vgpu_priv;
57}
58
59static void vgpu_remove_support(struct gk20a *g)
60{
61 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
62
63 vgpu_remove_support_common(g);
64
65 /* free mappings to registers, etc*/
66
67 if (l->bar1) {
68 iounmap(l->bar1);
69 l->bar1 = NULL;
70 }
71}
72
73static void vgpu_init_vars(struct gk20a *g, struct gk20a_platform *platform)
74{
75 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
76
77 nvgpu_mutex_init(&g->poweron_lock);
78 nvgpu_mutex_init(&g->poweroff_lock);
79 nvgpu_mutex_init(&g->ctxsw_disable_lock);
80 l->regs_saved = l->regs;
81 l->bar1_saved = l->bar1;
82
83 g->aggressive_sync_destroy = platform->aggressive_sync_destroy;
84 g->aggressive_sync_destroy_thresh = platform->aggressive_sync_destroy_thresh;
85 g->has_syncpoints = platform->has_syncpoints;
86 g->ptimer_src_freq = platform->ptimer_src_freq;
87 g->can_railgate = platform->can_railgate_init;
88 g->railgate_delay = platform->railgate_delay_init;
89
90 __nvgpu_set_enabled(g, NVGPU_MM_UNIFY_ADDRESS_SPACES,
91 platform->unify_address_spaces);
92}
93
94static int vgpu_init_support(struct platform_device *pdev)
95{
96 struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
97 struct gk20a *g = get_gk20a(&pdev->dev);
98 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
99 void __iomem *regs;
100 int err = 0;
101
102 if (!r) {
103 nvgpu_err(g, "failed to get gk20a bar1");
104 err = -ENXIO;
105 goto fail;
106 }
107
108 if (r->name && !strcmp(r->name, "/vgpu")) {
109 regs = devm_ioremap_resource(&pdev->dev, r);
110 if (IS_ERR(regs)) {
111 nvgpu_err(g, "failed to remap gk20a bar1");
112 err = PTR_ERR(regs);
113 goto fail;
114 }
115 l->bar1 = regs;
116 l->bar1_mem = r;
117 }
118
119 nvgpu_mutex_init(&g->dbg_sessions_lock);
120 nvgpu_mutex_init(&g->client_lock);
121
122 nvgpu_init_list_node(&g->profiler_objects);
123
124 g->dbg_regops_tmp_buf = nvgpu_kzalloc(g, SZ_4K);
125 if (!g->dbg_regops_tmp_buf) {
126 nvgpu_err(g, "couldn't allocate regops tmp buf");
127 return -ENOMEM;
128 }
129 g->dbg_regops_tmp_buf_ops =
130 SZ_4K / sizeof(g->dbg_regops_tmp_buf[0]);
131
132 g->remove_support = vgpu_remove_support;
133 return 0;
134
135 fail:
136 vgpu_remove_support(g);
137 return err;
138}
139
140int vgpu_pm_prepare_poweroff(struct device *dev)
141{
142 struct gk20a *g = get_gk20a(dev);
143 int ret = 0;
144
145 nvgpu_log_fn(g, " ");
146
147 if (!g->power_on)
148 return 0;
149
150 ret = gk20a_channel_suspend(g);
151 if (ret)
152 return ret;
153
154 g->power_on = false;
155
156 return ret;
157}
158
159int vgpu_pm_finalize_poweron(struct device *dev)
160{
161 struct gk20a *g = get_gk20a(dev);
162 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
163 int err;
164
165 nvgpu_log_fn(g, " ");
166
167 if (g->power_on)
168 return 0;
169
170 g->power_on = true;
171
172 vgpu_detect_chip(g);
173 err = vgpu_init_hal(g);
174 if (err)
175 goto done;
176
177 if (g->ops.ltc.init_fs_state)
178 g->ops.ltc.init_fs_state(g);
179
180 err = nvgpu_init_ltc_support(g);
181 if (err) {
182 nvgpu_err(g, "failed to init ltc");
183 goto done;
184 }
185
186 err = vgpu_init_mm_support(g);
187 if (err) {
188 nvgpu_err(g, "failed to init gk20a mm");
189 goto done;
190 }
191
192 err = vgpu_init_fifo_support(g);
193 if (err) {
194 nvgpu_err(g, "failed to init gk20a fifo");
195 goto done;
196 }
197
198 err = vgpu_init_gr_support(g);
199 if (err) {
200 nvgpu_err(g, "failed to init gk20a gr");
201 goto done;
202 }
203
204 err = g->ops.chip_init_gpu_characteristics(g);
205 if (err) {
206 nvgpu_err(g, "failed to init gk20a gpu characteristics");
207 goto done;
208 }
209
210 err = nvgpu_finalize_poweron_linux(l);
211 if (err)
212 goto done;
213
214#ifdef CONFIG_GK20A_CTXSW_TRACE
215 gk20a_ctxsw_trace_init(g);
216#endif
217 gk20a_sched_ctrl_init(g);
218 gk20a_channel_resume(g);
219
220 g->sw_ready = true;
221
222done:
223 return err;
224}
225
226static int vgpu_qos_notify(struct notifier_block *nb,
227 unsigned long n, void *data)
228{
229 struct gk20a_scale_profile *profile =
230 container_of(nb, struct gk20a_scale_profile,
231 qos_notify_block);
232 struct gk20a *g = get_gk20a(profile->dev);
233 u32 max_freq;
234 int err;
235
236 nvgpu_log_fn(g, " ");
237
238 max_freq = (u32)pm_qos_read_max_bound(PM_QOS_GPU_FREQ_BOUNDS);
239 err = vgpu_clk_cap_rate(profile->dev, max_freq);
240 if (err)
241 nvgpu_err(g, "%s failed, err=%d", __func__, err);
242
243 return NOTIFY_OK; /* need notify call further */
244}
245
246static int vgpu_pm_qos_init(struct device *dev)
247{
248 struct gk20a *g = get_gk20a(dev);
249 struct gk20a_scale_profile *profile = g->scale_profile;
250
251 if (IS_ENABLED(CONFIG_GK20A_DEVFREQ)) {
252 if (!profile)
253 return -EINVAL;
254 } else {
255 profile = nvgpu_kzalloc(g, sizeof(*profile));
256 if (!profile)
257 return -ENOMEM;
258 g->scale_profile = profile;
259 }
260
261 profile->dev = dev;
262 profile->qos_notify_block.notifier_call = vgpu_qos_notify;
263 pm_qos_add_max_notifier(PM_QOS_GPU_FREQ_BOUNDS,
264 &profile->qos_notify_block);
265 return 0;
266}
267
268static void vgpu_pm_qos_remove(struct device *dev)
269{
270 struct gk20a *g = get_gk20a(dev);
271
272 pm_qos_remove_max_notifier(PM_QOS_GPU_FREQ_BOUNDS,
273 &g->scale_profile->qos_notify_block);
274 nvgpu_kfree(g, g->scale_profile);
275 g->scale_profile = NULL;
276}
277
278static int vgpu_pm_init(struct device *dev)
279{
280 struct gk20a *g = get_gk20a(dev);
281 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
282 unsigned long *freqs;
283 int num_freqs;
284 int err = 0;
285
286 nvgpu_log_fn(g, " ");
287
288 if (nvgpu_platform_is_simulation(g))
289 return 0;
290
291 __pm_runtime_disable(dev, false);
292
293 if (IS_ENABLED(CONFIG_GK20A_DEVFREQ))
294 gk20a_scale_init(dev);
295
296 if (l->devfreq) {
297 /* set min/max frequency based on frequency table */
298 err = vgpu_clk_get_freqs(dev, &freqs, &num_freqs);
299 if (err)
300 return err;
301
302 if (num_freqs < 1)
303 return -EINVAL;
304
305 l->devfreq->min_freq = freqs[0];
306 l->devfreq->max_freq = freqs[num_freqs - 1];
307 }
308
309 err = vgpu_pm_qos_init(dev);
310 if (err)
311 return err;
312
313 return err;
314}
315
316int vgpu_probe(struct platform_device *pdev)
317{
318 struct nvgpu_os_linux *l;
319 struct gk20a *gk20a;
320 int err;
321 struct device *dev = &pdev->dev;
322 struct gk20a_platform *platform = gk20a_get_platform(dev);
323 struct vgpu_priv_data *priv;
324
325 if (!platform) {
326 dev_err(dev, "no platform data\n");
327 return -ENODATA;
328 }
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
337 nvgpu_log_fn(gk20a, " ");
338
339 nvgpu_init_gk20a(gk20a);
340
341 nvgpu_kmem_init(gk20a);
342
343 err = nvgpu_init_enabled_flags(gk20a);
344 if (err) {
345 kfree(gk20a);
346 return err;
347 }
348
349 l->dev = dev;
350 if (tegra_platform_is_vdk())
351 __nvgpu_set_enabled(gk20a, NVGPU_IS_FMODEL, true);
352
353 gk20a->is_virtual = true;
354
355 priv = nvgpu_kzalloc(gk20a, sizeof(*priv));
356 if (!priv) {
357 kfree(gk20a);
358 return -ENOMEM;
359 }
360
361 platform->g = gk20a;
362 platform->vgpu_priv = priv;
363
364 err = gk20a_user_init(dev, INTERFACE_NAME, &nvgpu_class);
365 if (err)
366 return err;
367
368 vgpu_init_support(pdev);
369
370 vgpu_init_vars(gk20a, platform);
371
372 init_rwsem(&l->busy_lock);
373
374 nvgpu_spinlock_init(&gk20a->mc_enable_lock);
375
376 gk20a->ch_wdt_timeout_ms = platform->ch_wdt_timeout_ms;
377
378 /* Initialize the platform interface. */
379 err = platform->probe(dev);
380 if (err) {
381 if (err == -EPROBE_DEFER)
382 nvgpu_info(gk20a, "platform probe failed");
383 else
384 nvgpu_err(gk20a, "platform probe failed");
385 return err;
386 }
387
388 if (platform->late_probe) {
389 err = platform->late_probe(dev);
390 if (err) {
391 nvgpu_err(gk20a, "late probe failed");
392 return err;
393 }
394 }
395
396 err = vgpu_comm_init(gk20a);
397 if (err) {
398 nvgpu_err(gk20a, "failed to init comm interface");
399 return -ENOSYS;
400 }
401
402 priv->virt_handle = vgpu_connect();
403 if (!priv->virt_handle) {
404 nvgpu_err(gk20a, "failed to connect to server node");
405 vgpu_comm_deinit();
406 return -ENOSYS;
407 }
408
409 err = vgpu_get_constants(gk20a);
410 if (err) {
411 vgpu_comm_deinit();
412 return err;
413 }
414
415 err = vgpu_pm_init(dev);
416 if (err) {
417 nvgpu_err(gk20a, "pm init failed");
418 return err;
419 }
420
421 err = nvgpu_thread_create(&priv->intr_handler, gk20a,
422 vgpu_intr_thread, "gk20a");
423 if (err)
424 return err;
425
426 gk20a_debug_init(gk20a, "gpu.0");
427
428 /* Set DMA parameters to allow larger sgt lists */
429 dev->dma_parms = &l->dma_parms;
430 dma_set_max_seg_size(dev, UINT_MAX);
431
432 gk20a->gr_idle_timeout_default = NVGPU_DEFAULT_GR_IDLE_TIMEOUT;
433 gk20a->timeouts_disabled_by_user = false;
434 nvgpu_atomic_set(&gk20a->timeouts_disabled_refcount, 0);
435
436 vgpu_create_sysfs(dev);
437 gk20a_init_gr(gk20a);
438
439 nvgpu_log_info(gk20a, "total ram pages : %lu", totalram_pages);
440 gk20a->gr.max_comptag_mem = totalram_pages
441 >> (10 - (PAGE_SHIFT - 10));
442
443 nvgpu_ref_init(&gk20a->refcount);
444
445 return 0;
446}
447
448int vgpu_remove(struct platform_device *pdev)
449{
450 struct device *dev = &pdev->dev;
451 struct gk20a *g = get_gk20a(dev);
452
453 nvgpu_log_fn(g, " ");
454
455 vgpu_pm_qos_remove(dev);
456 if (g->remove_support)
457 g->remove_support(g);
458
459 vgpu_comm_deinit();
460 gk20a_sched_ctrl_cleanup(g);
461 gk20a_user_deinit(dev, &nvgpu_class);
462 vgpu_remove_sysfs(dev);
463 gk20a_get_platform(dev)->g = NULL;
464 gk20a_put(g);
465
466 return 0;
467}
468
469bool vgpu_is_reduced_bar1(struct gk20a *g)
470{
471 struct fifo_gk20a *f = &g->fifo;
472 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
473
474 return resource_size(l->bar1_mem) == (resource_size_t)f->userd.size;
475}
diff --git a/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.h b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.h
new file mode 100644
index 00000000..38379cf2
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/vgpu/vgpu_linux.h
@@ -0,0 +1,57 @@
1/*
2 * Virtualized GPU Linux Interfaces
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#ifndef __VGPU_LINUX_H__
20#define __VGPU_LINUX_H__
21
22struct device;
23struct platform_device;
24
25#ifdef CONFIG_TEGRA_GR_VIRTUALIZATION
26
27#include <nvgpu/vgpu/vgpu.h>
28
29int vgpu_pm_prepare_poweroff(struct device *dev);
30int vgpu_pm_finalize_poweron(struct device *dev);
31int vgpu_probe(struct platform_device *dev);
32int vgpu_remove(struct platform_device *dev);
33
34void vgpu_create_sysfs(struct device *dev);
35void vgpu_remove_sysfs(struct device *dev);
36#else
37/* define placeholders for functions used outside of vgpu */
38
39static inline int vgpu_pm_prepare_poweroff(struct device *dev)
40{
41 return -ENOSYS;
42}
43static inline int vgpu_pm_finalize_poweron(struct device *dev)
44{
45 return -ENOSYS;
46}
47static inline int vgpu_probe(struct platform_device *dev)
48{
49 return -ENOSYS;
50}
51static inline int vgpu_remove(struct platform_device *dev)
52{
53 return -ENOSYS;
54}
55#endif
56
57#endif