gpu: nvgpu: support gk20a virtualization
[linux-3.10.git] / drivers / gpu / nvgpu / vgpu / vgpu.c
1 /*
2  * Virtualized GPU
3  *
4  * Copyright (c) 2014 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
16 #include <linux/kthread.h>
17 #include <linux/delay.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/pm_runtime.h>
20 #include "vgpu/vgpu.h"
21 #include "gk20a/debug_gk20a.h"
22 #include "gk20a/hal_gk20a.h"
23 #include "gk20a/hw_mc_gk20a.h"
24
25 static inline int vgpu_comm_init(struct platform_device *pdev)
26 {
27         size_t queue_sizes[] = { TEGRA_VGPU_QUEUE_SIZES };
28
29         return tegra_gr_comm_init(pdev, TEGRA_GR_COMM_CTX_CLIENT, 3,
30                                 queue_sizes, TEGRA_VGPU_QUEUE_CMD,
31                                 ARRAY_SIZE(queue_sizes));
32 }
33
34 static inline void vgpu_comm_deinit(void)
35 {
36         size_t queue_sizes[] = { TEGRA_VGPU_QUEUE_SIZES };
37
38         tegra_gr_comm_deinit(TEGRA_GR_COMM_CTX_CLIENT, TEGRA_VGPU_QUEUE_CMD,
39                         ARRAY_SIZE(queue_sizes));
40 }
41
42 int vgpu_comm_sendrecv(struct tegra_vgpu_cmd_msg *msg, size_t size_in,
43                 size_t size_out)
44 {
45         void *handle;
46         size_t size = size_in;
47         void *data = msg;
48         int err;
49
50         err = tegra_gr_comm_sendrecv(TEGRA_GR_COMM_CTX_CLIENT,
51                                 tegra_gr_comm_get_server_vmid(),
52                                 TEGRA_VGPU_QUEUE_CMD, &handle, &data, &size);
53         if (!err) {
54                 WARN_ON(size < size_out);
55                 memcpy(msg, data, size_out);
56                 tegra_gr_comm_release(handle);
57         }
58
59         return err;
60 }
61
62 static u64 vgpu_connect(void)
63 {
64         struct tegra_vgpu_cmd_msg msg;
65         struct tegra_vgpu_connect_params *p = &msg.params.connect;
66         int err;
67
68         msg.cmd = TEGRA_VGPU_CMD_CONNECT;
69         p->module = TEGRA_VGPU_MODULE_GPU;
70         err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
71
72         return (err || msg.ret) ? 0 : p->handle;
73 }
74
75 int vgpu_get_attribute(u64 handle, u32 attrib, u32 *value)
76 {
77         struct tegra_vgpu_cmd_msg msg;
78         struct tegra_vgpu_attrib_params *p = &msg.params.attrib;
79         int err;
80
81         msg.cmd = TEGRA_VGPU_CMD_GET_ATTRIBUTE;
82         msg.handle = handle;
83         p->attrib = attrib;
84         err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
85
86         if (err || msg.ret)
87                 return -1;
88
89         *value = p->value;
90         return 0;
91 }
92
93 static int vgpu_intr_thread(void *dev_id)
94 {
95         struct gk20a *g = dev_id;
96
97         while (true) {
98                 struct tegra_vgpu_intr_msg *msg;
99                 u32 sender;
100                 void *handle;
101                 size_t size;
102                 int err;
103
104                 err = tegra_gr_comm_recv(TEGRA_GR_COMM_CTX_CLIENT,
105                                         TEGRA_VGPU_QUEUE_INTR, &handle,
106                                         (void **)&msg, &size, &sender);
107                 if (WARN_ON(err))
108                         continue;
109
110                 if (msg->event == TEGRA_VGPU_EVENT_ABORT) {
111                         tegra_gr_comm_release(handle);
112                         break;
113                 }
114
115                 if (msg->unit == TEGRA_VGPU_INTR_GR)
116                         vgpu_gr_isr(g, &msg->info.gr_intr);
117
118                 tegra_gr_comm_release(handle);
119         }
120
121         while (!kthread_should_stop())
122                 msleep(10);
123         return 0;
124 }
125
126 static void vgpu_remove_support(struct platform_device *dev)
127 {
128         struct gk20a *g = get_gk20a(dev);
129         struct gk20a_platform *platform = gk20a_get_platform(dev);
130         struct tegra_vgpu_intr_msg msg;
131         int err;
132
133         if (g->pmu.remove_support)
134                 g->pmu.remove_support(&g->pmu);
135
136         if (g->gr.remove_support)
137                 g->gr.remove_support(&g->gr);
138
139         if (g->fifo.remove_support)
140                 g->fifo.remove_support(&g->fifo);
141
142         if (g->mm.remove_support)
143                 g->mm.remove_support(&g->mm);
144
145         msg.event = TEGRA_VGPU_EVENT_ABORT;
146         err = tegra_gr_comm_send(TEGRA_GR_COMM_CTX_CLIENT,
147                                 TEGRA_GR_COMM_ID_SELF, TEGRA_VGPU_QUEUE_INTR,
148                                 &msg, sizeof(msg));
149         WARN_ON(err);
150         kthread_stop(platform->intr_handler);
151
152         /* free mappings to registers, etc*/
153
154         if (g->bar1) {
155                 iounmap(g->bar1);
156                 g->bar1 = 0;
157         }
158 }
159
160 static int vgpu_init_support(struct platform_device *dev)
161 {
162         struct resource *r = platform_get_resource(dev, IORESOURCE_MEM, 0);
163         struct gk20a *g = get_gk20a(dev);
164         int err = 0;
165
166         if (!r) {
167                 dev_err(dev_from_gk20a(g), "faield to get gk20a bar1\n");
168                 err = -ENXIO;
169                 goto fail;
170         }
171
172         g->bar1 = devm_request_and_ioremap(&dev->dev, r);
173         if (!g->bar1) {
174                 dev_err(dev_from_gk20a(g), "failed to remap gk20a bar1\n");
175                 err = -ENXIO;
176                 goto fail;
177         }
178
179         mutex_init(&g->dbg_sessions_lock);
180         mutex_init(&g->client_lock);
181
182         g->remove_support = vgpu_remove_support;
183         return 0;
184
185  fail:
186         vgpu_remove_support(dev);
187         return err;
188 }
189
190 int vgpu_pm_prepare_poweroff(struct device *dev)
191 {
192         struct platform_device *pdev = to_platform_device(dev);
193         struct gk20a *g = get_gk20a(pdev);
194         int ret = 0;
195
196         gk20a_dbg_fn("");
197
198         if (!g->power_on)
199                 return 0;
200
201         ret = gk20a_channel_suspend(g);
202         if (ret)
203                 return ret;
204
205         g->power_on = false;
206
207         return ret;
208 }
209
210 static void vgpu_detect_chip(struct gk20a *g)
211 {
212         struct nvhost_gpu_characteristics *gpu = &g->gpu_characteristics;
213         struct gk20a_platform *platform = gk20a_get_platform(g->dev);
214
215         u32 mc_boot_0_value;
216
217         if (vgpu_get_attribute(platform->virt_handle,
218                         TEGRA_VGPU_ATTRIB_PMC_BOOT_0,
219                         &mc_boot_0_value)) {
220                 gk20a_err(dev_from_gk20a(g), "failed to detect chip");
221                 return;
222         }
223
224         gpu->arch = mc_boot_0_architecture_v(mc_boot_0_value) <<
225                 NVHOST_GPU_ARCHITECTURE_SHIFT;
226         gpu->impl = mc_boot_0_implementation_v(mc_boot_0_value);
227         gpu->rev =
228                 (mc_boot_0_major_revision_v(mc_boot_0_value) << 4) |
229                 mc_boot_0_minor_revision_v(mc_boot_0_value);
230
231         gk20a_dbg_info("arch: %x, impl: %x, rev: %x\n",
232                         g->gpu_characteristics.arch,
233                         g->gpu_characteristics.impl,
234                         g->gpu_characteristics.rev);
235 }
236
237 static int vgpu_init_hal(struct gk20a *g)
238 {
239         u32 ver = g->gpu_characteristics.arch + g->gpu_characteristics.impl;
240
241         switch (ver) {
242         case GK20A_GPUID_GK20A:
243                 gk20a_dbg_info("gk20a detected");
244                 /* init gk20a ops then override with virt extensions */
245                 gk20a_init_hal(&g->ops);
246                 vgpu_init_fifo_ops(&g->ops);
247                 vgpu_init_gr_ops(&g->ops);
248                 vgpu_init_ltc_ops(&g->ops);
249                 vgpu_init_mm_ops(&g->ops);
250                 break;
251         default:
252                 gk20a_err(&g->dev->dev, "no support for %x", ver);
253                 return -ENODEV;
254         }
255
256         return 0;
257 }
258
259 int vgpu_pm_finalize_poweron(struct device *dev)
260 {
261         struct platform_device *pdev = to_platform_device(dev);
262         struct gk20a *g = get_gk20a(pdev);
263         int err;
264
265         gk20a_dbg_fn("");
266
267         if (g->power_on)
268                 return 0;
269
270         g->power_on = true;
271
272         vgpu_detect_chip(g);
273         err = vgpu_init_hal(g);
274         if (err)
275                 goto done;
276
277         err = vgpu_init_mm_support(g);
278         if (err) {
279                 gk20a_err(dev, "failed to init gk20a mm");
280                 goto done;
281         }
282
283         err = vgpu_init_fifo_support(g);
284         if (err) {
285                 gk20a_err(dev, "failed to init gk20a fifo");
286                 goto done;
287         }
288
289         err = vgpu_init_gr_support(g);
290         if (err) {
291                 gk20a_err(dev, "failed to init gk20a gr");
292                 goto done;
293         }
294
295         err = gk20a_init_gpu_characteristics(g);
296         if (err) {
297                 gk20a_err(dev, "failed to init gk20a gpu characteristics");
298                 goto done;
299         }
300
301         gk20a_channel_resume(g);
302
303 done:
304         return err;
305 }
306
307 static int vgpu_pm_init(struct platform_device *dev)
308 {
309         int err = 0;
310
311         gk20a_dbg_fn("");
312
313         pm_runtime_enable(&dev->dev);
314         return err;
315 }
316
317 int vgpu_probe(struct platform_device *dev)
318 {
319         struct gk20a *gk20a;
320         int err;
321         struct gk20a_platform *platform = gk20a_get_platform(dev);
322
323         if (!platform) {
324                 dev_err(&dev->dev, "no platform data\n");
325                 return -ENODATA;
326         }
327
328         gk20a_dbg_fn("");
329
330         gk20a = kzalloc(sizeof(struct gk20a), GFP_KERNEL);
331         if (!gk20a) {
332                 dev_err(&dev->dev, "couldn't allocate gk20a support");
333                 return -ENOMEM;
334         }
335
336         platform->g = gk20a;
337         gk20a->dev = dev;
338
339         err = gk20a_user_init(dev);
340         if (err)
341                 return err;
342
343         vgpu_init_support(dev);
344
345         init_rwsem(&gk20a->busy_lock);
346
347         spin_lock_init(&gk20a->mc_enable_lock);
348
349         /* Initialize the platform interface. */
350         err = platform->probe(dev);
351         if (err) {
352                 dev_err(&dev->dev, "platform probe failed");
353                 return err;
354         }
355
356         err = vgpu_pm_init(dev);
357         if (err) {
358                 dev_err(&dev->dev, "pm init failed");
359                 return err;
360         }
361
362         if (platform->late_probe) {
363                 err = platform->late_probe(dev);
364                 if (err) {
365                         dev_err(&dev->dev, "late probe failed");
366                         return err;
367                 }
368         }
369
370         err = vgpu_comm_init(dev);
371         if (err) {
372                 dev_err(&dev->dev, "failed to init comm interface\n");
373                 return -ENOSYS;
374         }
375
376         platform->virt_handle = vgpu_connect();
377         if (!platform->virt_handle) {
378                 dev_err(&dev->dev, "failed to connect to server node\n");
379                 vgpu_comm_deinit();
380                 return -ENOSYS;
381         }
382
383         platform->intr_handler = kthread_run(vgpu_intr_thread, gk20a, "gk20a");
384         if (IS_ERR(platform->intr_handler))
385                 return -ENOMEM;
386
387         gk20a_debug_init(dev);
388
389         /* Set DMA parameters to allow larger sgt lists */
390         dev->dev.dma_parms = &gk20a->dma_parms;
391         dma_set_max_seg_size(&dev->dev, UINT_MAX);
392
393         gk20a->gr_idle_timeout_default =
394                         CONFIG_GK20A_DEFAULT_TIMEOUT;
395         gk20a->timeouts_enabled = true;
396
397         gk20a_create_sysfs(dev);
398         gk20a_init_gr(gk20a);
399
400         return 0;
401 }
402
403 int vgpu_remove(struct platform_device *dev)
404 {
405         struct gk20a *g = get_gk20a(dev);
406         gk20a_dbg_fn("");
407
408         if (g->remove_support)
409                 g->remove_support(dev);
410
411         vgpu_comm_deinit();
412         gk20a_user_deinit(dev);
413         gk20a_get_platform(dev)->g = NULL;
414         kfree(g);
415         return 0;
416 }