summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c
diff options
context:
space:
mode:
authorAingara Paramakuru <aparamakuru@nvidia.com>2015-08-27 14:01:45 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:52:07 -0500
commit01ba044bdbbfa831eb9f507230bac0a1ed67e4ce (patch)
treee6ae0c53d87ad237571c68dbd5cb87ffd19d137c /drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c
parent8e1c56689639917ca637875434a074fb697435e8 (diff)
gpu: nvgpu: vgpu: add gp10b support
Add support for gp10b in a virtualized environment. Bug 1677153 VFND-693 Change-Id: I919ffa44c6773940a7a3411ee8bbc403a992b7cb Signed-off-by: Aingara Paramakuru <aparamakuru@nvidia.com> Reviewed-on: http://git-master/r/792556 Reviewed-on: http://git-master/r/806193 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c')
-rw-r--r--drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c
new file mode 100644
index 00000000..0a769e94
--- /dev/null
+++ b/drivers/gpu/nvgpu/vgpu/gp10b/vgpu_mm_gp10b.c
@@ -0,0 +1,172 @@
1/*
2 * Virtualized GPU Memory Management
3 *
4 * Copyright (c) 2015, 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/dma-mapping.h>
17#include "vgpu/vgpu.h"
18#include "vgpu_mm_gp10b.h"
19#include "gk20a/semaphore_gk20a.h"
20#include "gk20a/mm_gk20a.h"
21
22static int vgpu_gp10b_init_mm_setup_hw(struct gk20a *g)
23{
24 g->mm.bypass_smmu = true;
25 g->mm.disable_bigpage = true;
26 return 0;
27}
28
29static inline int add_mem_desc(struct tegra_vgpu_mem_desc *mem_desc,
30 u64 addr, u64 size, size_t *oob_size)
31{
32 if (*oob_size < sizeof(*mem_desc))
33 return -ENOMEM;
34
35 mem_desc->addr = addr;
36 mem_desc->length = size;
37 *oob_size -= sizeof(*mem_desc);
38 return 0;
39}
40
41static u64 vgpu_gp10b_locked_gmmu_map(struct vm_gk20a *vm,
42 u64 map_offset,
43 struct sg_table *sgt,
44 u64 buffer_offset,
45 u64 size,
46 int pgsz_idx,
47 u8 kind_v,
48 u32 ctag_offset,
49 u32 flags,
50 int rw_flag,
51 bool clear_ctags,
52 bool sparse,
53 bool priv,
54 struct vm_gk20a_mapping_batch *batch)
55{
56 int err = 0;
57 struct device *d = dev_from_vm(vm);
58 struct gk20a *g = gk20a_from_vm(vm);
59 struct gk20a_platform *platform = gk20a_get_platform(g->dev);
60 struct tegra_vgpu_cmd_msg msg;
61 struct tegra_vgpu_as_map_ex_params *p = &msg.params.as_map_ex;
62 struct tegra_vgpu_mem_desc *mem_desc;
63 u32 page_size = vm->gmmu_page_sizes[pgsz_idx];
64 u64 space_to_skip = buffer_offset;
65 u64 buffer_size = 0;
66 u32 mem_desc_count = 0;
67 struct scatterlist *sgl;
68 void *handle = NULL;
69 size_t oob_size;
70 u8 prot;
71
72 gk20a_dbg_fn("");
73
74 /* FIXME: add support for sparse mappings */
75
76 if (WARN_ON(!sgt) || WARN_ON(!g->mm.bypass_smmu))
77 return -EINVAL;
78
79 if (space_to_skip & (page_size - 1))
80 return -EINVAL;
81
82 /* Allocate (or validate when map_offset != 0) the virtual address. */
83 if (!map_offset) {
84 map_offset = gk20a_vm_alloc_va(vm, size, pgsz_idx);
85 if (!map_offset) {
86 gk20a_err(d, "failed to allocate va space");
87 err = -ENOMEM;
88 goto fail;
89 }
90 }
91
92 handle = tegra_gr_comm_oob_get_ptr(TEGRA_GR_COMM_CTX_CLIENT,
93 tegra_gr_comm_get_server_vmid(),
94 TEGRA_VGPU_QUEUE_CMD,
95 (void **)&mem_desc, &oob_size);
96 if (!handle) {
97 err = -EINVAL;
98 goto fail;
99 }
100
101 sgl = sgt->sgl;
102 while (space_to_skip && sgl &&
103 (space_to_skip + page_size > sgl->length)) {
104 space_to_skip -= sgl->length;
105 sgl = sg_next(sgl);
106 }
107 WARN_ON(!sgl);
108
109 if (add_mem_desc(&mem_desc[mem_desc_count++],
110 sg_phys(sgl) + space_to_skip,
111 sgl->length - space_to_skip,
112 &oob_size)) {
113 err = -ENOMEM;
114 goto fail;
115 }
116 buffer_size += sgl->length - space_to_skip;
117
118 sgl = sg_next(sgl);
119 while (sgl && buffer_size < size) {
120 if (add_mem_desc(&mem_desc[mem_desc_count++], sg_phys(sgl),
121 sgl->length, &oob_size)) {
122 err = -ENOMEM;
123 goto fail;
124 }
125
126 buffer_size += sgl->length;
127 sgl = sg_next(sgl);
128 }
129
130 if (rw_flag == gk20a_mem_flag_read_only)
131 prot = TEGRA_VGPU_MAP_PROT_READ_ONLY;
132 else if (rw_flag == gk20a_mem_flag_write_only)
133 prot = TEGRA_VGPU_MAP_PROT_WRITE_ONLY;
134 else
135 prot = TEGRA_VGPU_MAP_PROT_NONE;
136
137 msg.cmd = TEGRA_VGPU_CMD_AS_MAP_EX;
138 msg.handle = platform->virt_handle;
139 p->handle = vm->handle;
140 p->gpu_va = map_offset;
141 p->size = size;
142 p->mem_desc_count = mem_desc_count;
143 p->pgsz_idx = pgsz_idx;
144 p->iova = 0;
145 p->kind = kind_v;
146 p->cacheable =
147 (flags & NVGPU_MAP_BUFFER_FLAGS_CACHEABLE_TRUE) ? 1 : 0;
148 p->prot = prot;
149 p->ctag_offset = ctag_offset;
150 p->clear_ctags = clear_ctags;
151 err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg));
152 if (err || msg.ret)
153 goto fail;
154
155 /* TLB invalidate handled on server side */
156
157 tegra_gr_comm_oob_put_ptr(handle);
158 return map_offset;
159fail:
160 if (handle)
161 tegra_gr_comm_oob_put_ptr(handle);
162 gk20a_err(d, "%s: failed with err=%d\n", __func__, err);
163 return 0;
164}
165
166void vgpu_gp10b_init_mm_ops(struct gpu_ops *gops)
167{
168 gk20a_dbg_fn("");
169
170 gops->mm.gmmu_map = vgpu_gp10b_locked_gmmu_map;
171 gops->mm.init_mm_setup_hw = vgpu_gp10b_init_mm_setup_hw;
172}