summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Waterman <alexw@nvidia.com>2017-09-07 18:27:55 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-10-18 19:00:37 -0400
commitb3446bc0b6fca6cb992667f80a95f8503b6a652a (patch)
tree9882c36bfaef83da9d0a6eefec5e8c3564b93cea
parentbee9c830c7898ceebf8c396b40598350229a7203 (diff)
gpu: nvgpu: Move dma_buf usage from mm_gk20a.c
Move most of the dma_buf usage present in the mm_gk20a.c code out to Linux specific code and some commom/mm code. There's two primary groups of code: 1. dma_buf priv field code (for holding comptag data) 2. Comptag usage that relies on dma_buf pointers For (1) the dma_buf code was simply moved to common/linux/dmabuf.c since most of this code is clearly Linux specific. The comptag code was a bit more complicated since there is two parts to the comptag code. Firstly there's the code that manages the comptag memory. This is essentially a simple allocator. This was moved to common/mm/comptags.c since it can be shared across all chips. The second set of code is moved to common/linux/comptags.c since it is the interface between dma_bufs and the comptag memory. Two other fixes were done as well: - Add struct gk20a to the comptag allocator init so that the proper nvgpu_vzalloc() function could be used. - Add necessary includes to common/linux/vm_priv.h. JIRA NVGPU-30 JIRA NVGPU-138 Change-Id: I96c57f2763e5ebe18a2f2ee4b33e0e1a2597848c Signed-off-by: Alex Waterman <alexw@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1566628 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/Makefile.nvgpu3
-rw-r--r--drivers/gpu/nvgpu/common/linux/cde.c1
-rw-r--r--drivers/gpu/nvgpu/common/linux/comptags.c70
-rw-r--r--drivers/gpu/nvgpu/common/linux/dmabuf.c247
-rw-r--r--drivers/gpu/nvgpu/common/linux/dmabuf.h73
-rw-r--r--drivers/gpu/nvgpu/common/linux/vm.c29
-rw-r--r--drivers/gpu/nvgpu/common/linux/vm_priv.h5
-rw-r--r--drivers/gpu/nvgpu/common/mm/comptags.c95
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.c32
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.h14
-rw-r--r--drivers/gpu/nvgpu/gk20a/mm_gk20a.c298
-rw-r--r--drivers/gpu/nvgpu/gk20a/mm_gk20a.h19
-rw-r--r--drivers/gpu/nvgpu/gm20b/ltc_gm20b.c2
-rw-r--r--drivers/gpu/nvgpu/gp10b/ltc_gp10b.c2
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/comptags.h57
-rw-r--r--drivers/gpu/nvgpu/vgpu/gr_vgpu.c2
-rw-r--r--drivers/gpu/nvgpu/vgpu/ltc_vgpu.c2
17 files changed, 556 insertions, 395 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu
index 42447e0c..81b0d1b8 100644
--- a/drivers/gpu/nvgpu/Makefile.nvgpu
+++ b/drivers/gpu/nvgpu/Makefile.nvgpu
@@ -51,6 +51,8 @@ nvgpu-y := \
51 common/linux/rwsem.o \ 51 common/linux/rwsem.o \
52 common/linux/cde_gm20b.o \ 52 common/linux/cde_gm20b.o \
53 common/linux/cde_gp10b.o \ 53 common/linux/cde_gp10b.o \
54 common/linux/comptags.o \
55 common/linux/dmabuf.o \
54 common/mm/nvgpu_allocator.o \ 56 common/mm/nvgpu_allocator.o \
55 common/mm/bitmap_allocator.o \ 57 common/mm/bitmap_allocator.o \
56 common/mm/buddy_allocator.o \ 58 common/mm/buddy_allocator.o \
@@ -61,6 +63,7 @@ nvgpu-y := \
61 common/mm/vm.o \ 63 common/mm/vm.o \
62 common/mm/vm_area.o \ 64 common/mm/vm_area.o \
63 common/mm/nvgpu_mem.o \ 65 common/mm/nvgpu_mem.o \
66 common/mm/comptags.o \
64 common/bus.o \ 67 common/bus.o \
65 common/enabled.o \ 68 common/enabled.o \
66 common/pramin.o \ 69 common/pramin.o \
diff --git a/drivers/gpu/nvgpu/common/linux/cde.c b/drivers/gpu/nvgpu/common/linux/cde.c
index c3a9b770..577d86e8 100644
--- a/drivers/gpu/nvgpu/common/linux/cde.c
+++ b/drivers/gpu/nvgpu/common/linux/cde.c
@@ -39,6 +39,7 @@
39 39
40#include "cde.h" 40#include "cde.h"
41#include "os_linux.h" 41#include "os_linux.h"
42#include "dmabuf.h"
42 43
43#include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h> 44#include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h>
44#include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h> 45#include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h>
diff --git a/drivers/gpu/nvgpu/common/linux/comptags.c b/drivers/gpu/nvgpu/common/linux/comptags.c
new file mode 100644
index 00000000..517429d8
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/comptags.c
@@ -0,0 +1,70 @@
1/*
2* Copyright (c) 2017, 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/dma-buf.h>
18
19#include <nvgpu/comptags.h>
20
21#include "dmabuf.h"
22
23void gk20a_get_comptags(struct device *dev, struct dma_buf *dmabuf,
24 struct gk20a_comptags *comptags)
25{
26 struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(dmabuf, dev);
27
28 if (!comptags)
29 return;
30
31 if (!priv) {
32 memset(comptags, 0, sizeof(*comptags));
33 return;
34 }
35
36 *comptags = priv->comptags;
37}
38
39int gk20a_alloc_comptags(struct gk20a *g,
40 struct device *dev,
41 struct dma_buf *dmabuf,
42 struct gk20a_comptag_allocator *allocator,
43 u32 lines)
44{
45 struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(dmabuf, dev);
46 u32 ctaglines_allocsize;
47 u32 offset;
48 int err;
49
50 if (!priv)
51 return -ENOSYS;
52
53 if (!lines)
54 return -EINVAL;
55
56 ctaglines_allocsize = lines;
57
58 /* store the allocator so we can use it when we free the ctags */
59 priv->comptag_allocator = allocator;
60 err = gk20a_comptaglines_alloc(allocator, &offset,
61 ctaglines_allocsize);
62 if (err)
63 return err;
64
65 priv->comptags.offset = offset;
66 priv->comptags.lines = lines;
67 priv->comptags.allocated_lines = ctaglines_allocsize;
68
69 return 0;
70}
diff --git a/drivers/gpu/nvgpu/common/linux/dmabuf.c b/drivers/gpu/nvgpu/common/linux/dmabuf.c
new file mode 100644
index 00000000..0b07b255
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/dmabuf.c
@@ -0,0 +1,247 @@
1/*
2* Copyright (c) 2017, 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 <linux/dma-buf.h>
19#include <linux/scatterlist.h>
20
21#include <nvgpu/comptags.h>
22#include <nvgpu/enabled.h>
23
24#include <nvgpu/linux/vidmem.h>
25
26#include "gk20a/gk20a.h"
27#include "gk20a/platform_gk20a.h"
28
29#include "dmabuf.h"
30#include "vm_priv.h"
31#include "os_linux.h"
32
33static void gk20a_mm_delete_priv(void *_priv)
34{
35 struct gk20a_buffer_state *s, *s_tmp;
36 struct gk20a_dmabuf_priv *priv = _priv;
37 struct gk20a *g;
38
39 if (!priv)
40 return;
41
42 g = priv->g;
43
44 if (priv->comptags.lines) {
45 BUG_ON(!priv->comptag_allocator);
46 gk20a_comptaglines_free(priv->comptag_allocator,
47 priv->comptags.offset,
48 priv->comptags.allocated_lines);
49 }
50
51 /* Free buffer states */
52 nvgpu_list_for_each_entry_safe(s, s_tmp, &priv->states,
53 gk20a_buffer_state, list) {
54 gk20a_fence_put(s->fence);
55 nvgpu_list_del(&s->list);
56 nvgpu_kfree(g, s);
57 }
58
59 nvgpu_kfree(g, priv);
60}
61
62enum nvgpu_aperture gk20a_dmabuf_aperture(struct gk20a *g,
63 struct dma_buf *dmabuf)
64{
65 struct gk20a *buf_owner = nvgpu_vidmem_buf_owner(dmabuf);
66 bool unified_memory = nvgpu_is_enabled(g, NVGPU_MM_UNIFIED_MEMORY);
67
68 if (buf_owner == NULL) {
69 /* Not nvgpu-allocated, assume system memory */
70 return APERTURE_SYSMEM;
71 } else if (WARN_ON(buf_owner == g && unified_memory)) {
72 /* Looks like our video memory, but this gpu doesn't support
73 * it. Warn about a bug and bail out */
74 nvgpu_warn(g,
75 "dmabuf is our vidmem but we don't have local vidmem");
76 return APERTURE_INVALID;
77 } else if (buf_owner != g) {
78 /* Someone else's vidmem */
79 return APERTURE_INVALID;
80 } else {
81 /* Yay, buf_owner == g */
82 return APERTURE_VIDMEM;
83 }
84}
85
86struct sg_table *gk20a_mm_pin(struct device *dev, struct dma_buf *dmabuf)
87{
88 struct gk20a_dmabuf_priv *priv;
89
90 priv = dma_buf_get_drvdata(dmabuf, dev);
91 if (WARN_ON(!priv))
92 return ERR_PTR(-EINVAL);
93
94 nvgpu_mutex_acquire(&priv->lock);
95
96 if (priv->pin_count == 0) {
97 priv->attach = dma_buf_attach(dmabuf, dev);
98 if (IS_ERR(priv->attach)) {
99 nvgpu_mutex_release(&priv->lock);
100 return (struct sg_table *)priv->attach;
101 }
102
103 priv->sgt = dma_buf_map_attachment(priv->attach,
104 DMA_BIDIRECTIONAL);
105 if (IS_ERR(priv->sgt)) {
106 dma_buf_detach(dmabuf, priv->attach);
107 nvgpu_mutex_release(&priv->lock);
108 return priv->sgt;
109 }
110 }
111
112 priv->pin_count++;
113 nvgpu_mutex_release(&priv->lock);
114 return priv->sgt;
115}
116
117void gk20a_mm_unpin(struct device *dev, struct dma_buf *dmabuf,
118 struct sg_table *sgt)
119{
120 struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(dmabuf, dev);
121 dma_addr_t dma_addr;
122
123 if (IS_ERR(priv) || !priv)
124 return;
125
126 nvgpu_mutex_acquire(&priv->lock);
127 WARN_ON(priv->sgt != sgt);
128 priv->pin_count--;
129 WARN_ON(priv->pin_count < 0);
130 dma_addr = sg_dma_address(priv->sgt->sgl);
131 if (priv->pin_count == 0) {
132 dma_buf_unmap_attachment(priv->attach, priv->sgt,
133 DMA_BIDIRECTIONAL);
134 dma_buf_detach(dmabuf, priv->attach);
135 }
136 nvgpu_mutex_release(&priv->lock);
137}
138
139int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev)
140{
141 struct gk20a *g = gk20a_get_platform(dev)->g;
142 struct gk20a_dmabuf_priv *priv;
143 static u64 priv_count = 0;
144
145 priv = dma_buf_get_drvdata(dmabuf, dev);
146 if (likely(priv))
147 return 0;
148
149 nvgpu_mutex_acquire(&g->mm.priv_lock);
150 priv = dma_buf_get_drvdata(dmabuf, dev);
151 if (priv)
152 goto priv_exist_or_err;
153
154 priv = nvgpu_kzalloc(g, sizeof(*priv));
155 if (!priv) {
156 priv = ERR_PTR(-ENOMEM);
157 goto priv_exist_or_err;
158 }
159
160 nvgpu_mutex_init(&priv->lock);
161 nvgpu_init_list_node(&priv->states);
162 priv->buffer_id = ++priv_count;
163 priv->g = g;
164 dma_buf_set_drvdata(dmabuf, dev, priv, gk20a_mm_delete_priv);
165
166priv_exist_or_err:
167 nvgpu_mutex_release(&g->mm.priv_lock);
168 if (IS_ERR(priv))
169 return -ENOMEM;
170
171 return 0;
172}
173
174int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct gk20a *g,
175 u64 offset, struct gk20a_buffer_state **state)
176{
177 int err = 0;
178 struct gk20a_dmabuf_priv *priv;
179 struct gk20a_buffer_state *s;
180 struct device *dev = dev_from_gk20a(g);
181
182 if (WARN_ON(offset >= (u64)dmabuf->size))
183 return -EINVAL;
184
185 err = gk20a_dmabuf_alloc_drvdata(dmabuf, dev);
186 if (err)
187 return err;
188
189 priv = dma_buf_get_drvdata(dmabuf, dev);
190 if (WARN_ON(!priv))
191 return -ENOSYS;
192
193 nvgpu_mutex_acquire(&priv->lock);
194
195 nvgpu_list_for_each_entry(s, &priv->states, gk20a_buffer_state, list)
196 if (s->offset == offset)
197 goto out;
198
199 /* State not found, create state. */
200 s = nvgpu_kzalloc(g, sizeof(*s));
201 if (!s) {
202 err = -ENOMEM;
203 goto out;
204 }
205
206 s->offset = offset;
207 nvgpu_init_list_node(&s->list);
208 nvgpu_mutex_init(&s->lock);
209 nvgpu_list_add_tail(&s->list, &priv->states);
210
211out:
212 nvgpu_mutex_release(&priv->lock);
213 if (!err)
214 *state = s;
215 return err;
216}
217
218int gk20a_mm_get_buffer_info(struct device *dev, int dmabuf_fd,
219 u64 *buffer_id, u64 *buffer_len)
220{
221 struct dma_buf *dmabuf;
222 struct gk20a_dmabuf_priv *priv;
223 int err = 0;
224
225 dmabuf = dma_buf_get(dmabuf_fd);
226 if (IS_ERR(dmabuf)) {
227 dev_warn(dev, "%s: fd %d is not a dmabuf", __func__, dmabuf_fd);
228 return PTR_ERR(dmabuf);
229 }
230
231 err = gk20a_dmabuf_alloc_drvdata(dmabuf, dev);
232 if (err) {
233 dev_warn(dev, "Failed to allocate dmabuf drvdata (err = %d)",
234 err);
235 goto clean_up;
236 }
237
238 priv = dma_buf_get_drvdata(dmabuf, dev);
239 if (likely(priv)) {
240 *buffer_id = priv->buffer_id;
241 *buffer_len = dmabuf->size;
242 }
243
244clean_up:
245 dma_buf_put(dmabuf);
246 return err;
247}
diff --git a/drivers/gpu/nvgpu/common/linux/dmabuf.h b/drivers/gpu/nvgpu/common/linux/dmabuf.h
new file mode 100644
index 00000000..718386c5
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/dmabuf.h
@@ -0,0 +1,73 @@
1/*
2* Copyright (c) 2017, 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#ifndef __COMMON_LINUX_DMABUF_H__
18#define __COMMON_LINUX_DMABUF_H__
19
20#include <nvgpu/comptags.h>
21#include <nvgpu/list.h>
22#include <nvgpu/lock.h>
23#include <nvgpu/gmmu.h>
24
25struct sg_table;
26struct dma_buf;
27struct dma_buf_attachment;
28struct device;
29
30struct gk20a;
31struct gk20a_buffer_state;
32
33struct gk20a_dmabuf_priv {
34 struct nvgpu_mutex lock;
35
36 struct gk20a *g;
37
38 struct gk20a_comptag_allocator *comptag_allocator;
39 struct gk20a_comptags comptags;
40
41 struct dma_buf_attachment *attach;
42 struct sg_table *sgt;
43
44 int pin_count;
45
46 struct nvgpu_list_node states;
47
48 u64 buffer_id;
49};
50
51/*
52 * These are implemented in common/linux/comptags.c - these are dmabuf related
53 * functions though so they are defined here. They cannot be defined in
54 * <nvgpu/comptags.h> since that file must be OS agnostic.
55 */
56int gk20a_alloc_comptags(struct gk20a *g,
57 struct device *dev,
58 struct dma_buf *dmabuf,
59 struct gk20a_comptag_allocator *allocator,
60 u32 lines);
61void gk20a_get_comptags(struct device *dev, struct dma_buf *dmabuf,
62 struct gk20a_comptags *comptags);
63
64struct sg_table *gk20a_mm_pin(struct device *dev, struct dma_buf *dmabuf);
65void gk20a_mm_unpin(struct device *dev, struct dma_buf *dmabuf,
66 struct sg_table *sgt);
67
68int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev);
69
70int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct gk20a *g,
71 u64 offset, struct gk20a_buffer_state **state);
72
73#endif
diff --git a/drivers/gpu/nvgpu/common/linux/vm.c b/drivers/gpu/nvgpu/common/linux/vm.c
index 45058321..b686d616 100644
--- a/drivers/gpu/nvgpu/common/linux/vm.c
+++ b/drivers/gpu/nvgpu/common/linux/vm.c
@@ -24,7 +24,6 @@
24#include <nvgpu/nvgpu_mem.h> 24#include <nvgpu/nvgpu_mem.h>
25#include <nvgpu/page_allocator.h> 25#include <nvgpu/page_allocator.h>
26#include <nvgpu/vidmem.h> 26#include <nvgpu/vidmem.h>
27#include <nvgpu/enabled.h>
28 27
29#include <nvgpu/linux/vidmem.h> 28#include <nvgpu/linux/vidmem.h>
30#include <nvgpu/linux/nvgpu_mem.h> 29#include <nvgpu/linux/nvgpu_mem.h>
@@ -36,33 +35,7 @@
36 35
37#include "vm_priv.h" 36#include "vm_priv.h"
38#include "os_linux.h" 37#include "os_linux.h"
39 38#include "dmabuf.h"
40/*
41 * Temporary location for this code until a dmabuf.c file exists.
42 */
43enum nvgpu_aperture gk20a_dmabuf_aperture(struct gk20a *g,
44 struct dma_buf *dmabuf)
45{
46 struct gk20a *buf_owner = nvgpu_vidmem_buf_owner(dmabuf);
47 bool unified_memory = nvgpu_is_enabled(g, NVGPU_MM_UNIFIED_MEMORY);
48
49 if (buf_owner == NULL) {
50 /* Not nvgpu-allocated, assume system memory */
51 return APERTURE_SYSMEM;
52 } else if (WARN_ON(buf_owner == g && unified_memory)) {
53 /* Looks like our video memory, but this gpu doesn't support
54 * it. Warn about a bug and bail out */
55 nvgpu_warn(g,
56 "dmabuf is our vidmem but we don't have local vidmem");
57 return APERTURE_INVALID;
58 } else if (buf_owner != g) {
59 /* Someone else's vidmem */
60 return APERTURE_INVALID;
61 } else {
62 /* Yay, buf_owner == g */
63 return APERTURE_VIDMEM;
64 }
65}
66 39
67static struct nvgpu_mapped_buf *__nvgpu_vm_find_mapped_buf_reverse( 40static struct nvgpu_mapped_buf *__nvgpu_vm_find_mapped_buf_reverse(
68 struct vm_gk20a *vm, struct dma_buf *dmabuf, u32 kind) 41 struct vm_gk20a *vm, struct dma_buf *dmabuf, u32 kind)
diff --git a/drivers/gpu/nvgpu/common/linux/vm_priv.h b/drivers/gpu/nvgpu/common/linux/vm_priv.h
index 1eadf1d0..fa173d59 100644
--- a/drivers/gpu/nvgpu/common/linux/vm_priv.h
+++ b/drivers/gpu/nvgpu/common/linux/vm_priv.h
@@ -102,10 +102,5 @@ int setup_buffer_kind_and_compression(struct vm_gk20a *vm,
102 u32 flags, 102 u32 flags,
103 struct buffer_attrs *bfr, 103 struct buffer_attrs *bfr,
104 enum gmmu_pgsz_gk20a pgsz_idx); 104 enum gmmu_pgsz_gk20a pgsz_idx);
105int gk20a_alloc_comptags(struct gk20a *g,
106 struct device *dev,
107 struct dma_buf *dmabuf,
108 struct gk20a_comptag_allocator *allocator,
109 u32 lines);
110 105
111#endif 106#endif
diff --git a/drivers/gpu/nvgpu/common/mm/comptags.c b/drivers/gpu/nvgpu/common/mm/comptags.c
new file mode 100644
index 00000000..01ab646a
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/mm/comptags.c
@@ -0,0 +1,95 @@
1/*
2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <nvgpu/bitops.h>
24#include <nvgpu/comptags.h>
25
26#include "gk20a/gk20a.h"
27
28int gk20a_comptaglines_alloc(struct gk20a_comptag_allocator *allocator,
29 u32 *offset, u32 len)
30{
31 unsigned long addr;
32 int err = 0;
33
34 nvgpu_mutex_acquire(&allocator->lock);
35 addr = bitmap_find_next_zero_area(allocator->bitmap, allocator->size,
36 0, len, 0);
37 if (addr < allocator->size) {
38 /* number zero is reserved; bitmap base is 1 */
39 *offset = 1 + addr;
40 bitmap_set(allocator->bitmap, addr, len);
41 } else {
42 err = -ENOMEM;
43 }
44 nvgpu_mutex_release(&allocator->lock);
45
46 return err;
47}
48
49void gk20a_comptaglines_free(struct gk20a_comptag_allocator *allocator,
50 u32 offset, u32 len)
51{
52 /* number zero is reserved; bitmap base is 1 */
53 u32 addr = offset - 1;
54
55 WARN_ON(offset == 0);
56 WARN_ON(addr > allocator->size);
57 WARN_ON(addr + len > allocator->size);
58
59 nvgpu_mutex_acquire(&allocator->lock);
60 bitmap_clear(allocator->bitmap, addr, len);
61 nvgpu_mutex_release(&allocator->lock);
62}
63
64int gk20a_comptag_allocator_init(struct gk20a *g,
65 struct gk20a_comptag_allocator *allocator,
66 unsigned long size)
67{
68 nvgpu_mutex_init(&allocator->lock);
69
70 /*
71 * 0th comptag is special and is never used. The base for this bitmap
72 * is 1, and its size is one less than the size of comptag store.
73 */
74 size--;
75 allocator->bitmap = nvgpu_vzalloc(g,
76 BITS_TO_LONGS(size) * sizeof(long));
77 if (!allocator->bitmap)
78 return -ENOMEM;
79
80 allocator->size = size;
81
82 return 0;
83}
84
85void gk20a_comptag_allocator_destroy(struct gk20a *g,
86 struct gk20a_comptag_allocator *allocator)
87{
88 /*
89 * called only when exiting the driver (gk20a_remove, or unwinding the
90 * init stage); no users should be active, so taking the mutex is
91 * unnecessary here.
92 */
93 allocator->size = 0;
94 nvgpu_vfree(allocator->g, allocator->bitmap);
95}
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
index 57c1c0bc..700dcdf8 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
@@ -3044,36 +3044,6 @@ out:
3044 return err; 3044 return err;
3045} 3045}
3046 3046
3047int gk20a_comptag_allocator_init(struct gk20a_comptag_allocator *allocator,
3048 unsigned long size)
3049{
3050 nvgpu_mutex_init(&allocator->lock);
3051 /*
3052 * 0th comptag is special and is never used. The base for this bitmap
3053 * is 1, and its size is one less than the size of comptag store.
3054 */
3055 size--;
3056 allocator->bitmap = vzalloc(BITS_TO_LONGS(size) * sizeof(long));
3057 if (!allocator->bitmap)
3058 return -ENOMEM;
3059 allocator->size = size;
3060 return 0;
3061}
3062
3063void gk20a_comptag_allocator_destroy(struct gk20a_comptag_allocator *allocator)
3064{
3065 struct gr_gk20a *gr = container_of(allocator,
3066 struct gr_gk20a, comp_tags);
3067
3068 /*
3069 * called only when exiting the driver (gk20a_remove, or unwinding the
3070 * init stage); no users should be active, so taking the mutex is
3071 * unnecessary here.
3072 */
3073 allocator->size = 0;
3074 nvgpu_vfree(gr->g, allocator->bitmap);
3075}
3076
3077static void gk20a_remove_gr_support(struct gr_gk20a *gr) 3047static void gk20a_remove_gr_support(struct gr_gk20a *gr)
3078{ 3048{
3079 struct gk20a *g = gr->g; 3049 struct gk20a *g = gr->g;
@@ -3148,7 +3118,7 @@ static void gk20a_remove_gr_support(struct gr_gk20a *gr)
3148 nvgpu_big_free(g, gr->ctx_vars.hwpm_ctxsw_buffer_offset_map); 3118 nvgpu_big_free(g, gr->ctx_vars.hwpm_ctxsw_buffer_offset_map);
3149 gr->ctx_vars.hwpm_ctxsw_buffer_offset_map = NULL; 3119 gr->ctx_vars.hwpm_ctxsw_buffer_offset_map = NULL;
3150 3120
3151 gk20a_comptag_allocator_destroy(&gr->comp_tags); 3121 gk20a_comptag_allocator_destroy(g, &gr->comp_tags);
3152} 3122}
3153 3123
3154static int gr_gk20a_init_gr_config(struct gk20a *g, struct gr_gk20a *gr) 3124static int gr_gk20a_init_gr_config(struct gk20a *g, struct gr_gk20a *gr)
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h
index 5fab43ca..84eb8970 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h
@@ -36,6 +36,8 @@
36#include "gr_ctx_gk20a.h" 36#include "gr_ctx_gk20a.h"
37#include "mm_gk20a.h" 37#include "mm_gk20a.h"
38 38
39#include <nvgpu/comptags.h>
40
39#define GR_IDLE_CHECK_DEFAULT 10 /* usec */ 41#define GR_IDLE_CHECK_DEFAULT 10 /* usec */
40#define GR_IDLE_CHECK_MAX 200 /* usec */ 42#define GR_IDLE_CHECK_MAX 200 /* usec */
41#define GR_FECS_POLL_INTERVAL 5 /* usec */ 43#define GR_FECS_POLL_INTERVAL 5 /* usec */
@@ -342,13 +344,7 @@ struct gr_gk20a {
342 344
343 u32 max_comptag_mem; /* max memory size (MB) for comptag */ 345 u32 max_comptag_mem; /* max memory size (MB) for comptag */
344 struct compbit_store_desc compbit_store; 346 struct compbit_store_desc compbit_store;
345 struct gk20a_comptag_allocator { 347 struct gk20a_comptag_allocator comp_tags;
346 struct nvgpu_mutex lock;
347 /* this bitmap starts at ctag 1. 0th cannot be taken */
348 unsigned long *bitmap;
349 /* size of bitmap, not max ctags, so one less */
350 unsigned long size;
351 } comp_tags;
352 348
353 struct gr_zcull_gk20a zcull; 349 struct gr_zcull_gk20a zcull;
354 350
@@ -503,10 +499,6 @@ int gk20a_init_gr_support(struct gk20a *g);
503int gk20a_enable_gr_hw(struct gk20a *g); 499int gk20a_enable_gr_hw(struct gk20a *g);
504int gk20a_gr_reset(struct gk20a *g); 500int gk20a_gr_reset(struct gk20a *g);
505void gk20a_gr_wait_initialized(struct gk20a *g); 501void gk20a_gr_wait_initialized(struct gk20a *g);
506/* real size here, but first (ctag 0) isn't used */
507int gk20a_comptag_allocator_init(struct gk20a_comptag_allocator *allocator,
508 unsigned long size);
509void gk20a_comptag_allocator_destroy(struct gk20a_comptag_allocator *allocator);
510 502
511int gk20a_init_gr_channel(struct channel_gk20a *ch_gk20a); 503int gk20a_init_gr_channel(struct channel_gk20a *ch_gk20a);
512 504
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
index 8936cd03..69d9e983 100644
--- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c
@@ -22,7 +22,6 @@
22 * DEALINGS IN THE SOFTWARE. 22 * DEALINGS IN THE SOFTWARE.
23 */ 23 */
24 24
25#include <linux/scatterlist.h>
26#include <linux/dma-buf.h> 25#include <linux/dma-buf.h>
27#include <linux/dma-mapping.h> 26#include <linux/dma-mapping.h>
28#include <linux/dma-attrs.h> 27#include <linux/dma-attrs.h>
@@ -70,6 +69,7 @@
70 * all the common APIs no longers have Linux stuff in them. 69 * all the common APIs no longers have Linux stuff in them.
71 */ 70 */
72#include "common/linux/vm_priv.h" 71#include "common/linux/vm_priv.h"
72#include "common/linux/dmabuf.h"
73 73
74/* 74/*
75 * GPU mapping life cycle 75 * GPU mapping life cycle
@@ -108,190 +108,6 @@ static int __must_check gk20a_init_hwpm(struct mm_gk20a *mm);
108static int __must_check gk20a_init_cde_vm(struct mm_gk20a *mm); 108static int __must_check gk20a_init_cde_vm(struct mm_gk20a *mm);
109static int __must_check gk20a_init_ce_vm(struct mm_gk20a *mm); 109static int __must_check gk20a_init_ce_vm(struct mm_gk20a *mm);
110 110
111struct gk20a_dmabuf_priv {
112 struct nvgpu_mutex lock;
113
114 struct gk20a *g;
115
116 struct gk20a_comptag_allocator *comptag_allocator;
117 struct gk20a_comptags comptags;
118
119 struct dma_buf_attachment *attach;
120 struct sg_table *sgt;
121
122 int pin_count;
123
124 struct nvgpu_list_node states;
125
126 u64 buffer_id;
127};
128
129static int gk20a_comptaglines_alloc(struct gk20a_comptag_allocator *allocator,
130 u32 *offset, u32 len)
131{
132 unsigned long addr;
133 int err = 0;
134
135 nvgpu_mutex_acquire(&allocator->lock);
136 addr = bitmap_find_next_zero_area(allocator->bitmap, allocator->size,
137 0, len, 0);
138 if (addr < allocator->size) {
139 /* number zero is reserved; bitmap base is 1 */
140 *offset = 1 + addr;
141 bitmap_set(allocator->bitmap, addr, len);
142 } else {
143 err = -ENOMEM;
144 }
145 nvgpu_mutex_release(&allocator->lock);
146
147 return err;
148}
149
150static void gk20a_comptaglines_free(struct gk20a_comptag_allocator *allocator,
151 u32 offset, u32 len)
152{
153 /* number zero is reserved; bitmap base is 1 */
154 u32 addr = offset - 1;
155 WARN_ON(offset == 0);
156 WARN_ON(addr > allocator->size);
157 WARN_ON(addr + len > allocator->size);
158
159 nvgpu_mutex_acquire(&allocator->lock);
160 bitmap_clear(allocator->bitmap, addr, len);
161 nvgpu_mutex_release(&allocator->lock);
162}
163
164static void gk20a_mm_delete_priv(void *_priv)
165{
166 struct gk20a_buffer_state *s, *s_tmp;
167 struct gk20a_dmabuf_priv *priv = _priv;
168 struct gk20a *g;
169
170 if (!priv)
171 return;
172
173 g = priv->g;
174
175 if (priv->comptags.lines) {
176 BUG_ON(!priv->comptag_allocator);
177 gk20a_comptaglines_free(priv->comptag_allocator,
178 priv->comptags.offset,
179 priv->comptags.allocated_lines);
180 }
181
182 /* Free buffer states */
183 nvgpu_list_for_each_entry_safe(s, s_tmp, &priv->states,
184 gk20a_buffer_state, list) {
185 gk20a_fence_put(s->fence);
186 nvgpu_list_del(&s->list);
187 nvgpu_kfree(g, s);
188 }
189
190 nvgpu_kfree(g, priv);
191}
192
193struct sg_table *gk20a_mm_pin(struct device *dev, struct dma_buf *dmabuf)
194{
195 struct gk20a_dmabuf_priv *priv;
196
197 priv = dma_buf_get_drvdata(dmabuf, dev);
198 if (WARN_ON(!priv))
199 return ERR_PTR(-EINVAL);
200
201 nvgpu_mutex_acquire(&priv->lock);
202
203 if (priv->pin_count == 0) {
204 priv->attach = dma_buf_attach(dmabuf, dev);
205 if (IS_ERR(priv->attach)) {
206 nvgpu_mutex_release(&priv->lock);
207 return (struct sg_table *)priv->attach;
208 }
209
210 priv->sgt = dma_buf_map_attachment(priv->attach,
211 DMA_BIDIRECTIONAL);
212 if (IS_ERR(priv->sgt)) {
213 dma_buf_detach(dmabuf, priv->attach);
214 nvgpu_mutex_release(&priv->lock);
215 return priv->sgt;
216 }
217 }
218
219 priv->pin_count++;
220 nvgpu_mutex_release(&priv->lock);
221 return priv->sgt;
222}
223
224void gk20a_mm_unpin(struct device *dev, struct dma_buf *dmabuf,
225 struct sg_table *sgt)
226{
227 struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(dmabuf, dev);
228 dma_addr_t dma_addr;
229
230 if (IS_ERR(priv) || !priv)
231 return;
232
233 nvgpu_mutex_acquire(&priv->lock);
234 WARN_ON(priv->sgt != sgt);
235 priv->pin_count--;
236 WARN_ON(priv->pin_count < 0);
237 dma_addr = sg_dma_address(priv->sgt->sgl);
238 if (priv->pin_count == 0) {
239 dma_buf_unmap_attachment(priv->attach, priv->sgt,
240 DMA_BIDIRECTIONAL);
241 dma_buf_detach(dmabuf, priv->attach);
242 }
243 nvgpu_mutex_release(&priv->lock);
244}
245
246void gk20a_get_comptags(struct device *dev, struct dma_buf *dmabuf,
247 struct gk20a_comptags *comptags)
248{
249 struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(dmabuf, dev);
250
251 if (!comptags)
252 return;
253
254 if (!priv) {
255 memset(comptags, 0, sizeof(*comptags));
256 return;
257 }
258
259 *comptags = priv->comptags;
260}
261
262int gk20a_alloc_comptags(struct gk20a *g,
263 struct device *dev,
264 struct dma_buf *dmabuf,
265 struct gk20a_comptag_allocator *allocator,
266 u32 lines)
267{
268 struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(dmabuf, dev);
269 u32 ctaglines_allocsize;
270 u32 offset;
271 int err;
272
273 if (!priv)
274 return -ENOSYS;
275
276 if (!lines)
277 return -EINVAL;
278
279 ctaglines_allocsize = lines;
280
281 /* store the allocator so we can use it when we free the ctags */
282 priv->comptag_allocator = allocator;
283 err = gk20a_comptaglines_alloc(allocator, &offset,
284 ctaglines_allocsize);
285 if (err)
286 return err;
287
288 priv->comptags.offset = offset;
289 priv->comptags.lines = lines;
290 priv->comptags.allocated_lines = ctaglines_allocsize;
291
292 return 0;
293}
294
295static int gk20a_init_mm_reset_enable_hw(struct gk20a *g) 111static int gk20a_init_mm_reset_enable_hw(struct gk20a *g)
296{ 112{
297 gk20a_dbg_fn(""); 113 gk20a_dbg_fn("");
@@ -1037,87 +853,6 @@ int gk20a_vm_bind_channel(struct gk20a_as_share *as_share,
1037 return __gk20a_vm_bind_channel(as_share->vm, ch); 853 return __gk20a_vm_bind_channel(as_share->vm, ch);
1038} 854}
1039 855
1040int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev)
1041{
1042 struct gk20a *g = gk20a_get_platform(dev)->g;
1043 struct gk20a_dmabuf_priv *priv;
1044 static u64 priv_count = 0;
1045
1046 priv = dma_buf_get_drvdata(dmabuf, dev);
1047 if (likely(priv))
1048 return 0;
1049
1050 nvgpu_mutex_acquire(&g->mm.priv_lock);
1051 priv = dma_buf_get_drvdata(dmabuf, dev);
1052 if (priv)
1053 goto priv_exist_or_err;
1054
1055 priv = nvgpu_kzalloc(g, sizeof(*priv));
1056 if (!priv) {
1057 priv = ERR_PTR(-ENOMEM);
1058 goto priv_exist_or_err;
1059 }
1060
1061 nvgpu_mutex_init(&priv->lock);
1062 nvgpu_init_list_node(&priv->states);
1063 priv->buffer_id = ++priv_count;
1064 priv->g = g;
1065 dma_buf_set_drvdata(dmabuf, dev, priv, gk20a_mm_delete_priv);
1066
1067priv_exist_or_err:
1068 nvgpu_mutex_release(&g->mm.priv_lock);
1069 if (IS_ERR(priv))
1070 return -ENOMEM;
1071
1072 return 0;
1073}
1074
1075int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct gk20a *g,
1076 u64 offset, struct gk20a_buffer_state **state)
1077{
1078 int err = 0;
1079 struct gk20a_dmabuf_priv *priv;
1080 struct gk20a_buffer_state *s;
1081 struct device *dev = dev_from_gk20a(g);
1082
1083 if (WARN_ON(offset >= (u64)dmabuf->size))
1084 return -EINVAL;
1085
1086 err = gk20a_dmabuf_alloc_drvdata(dmabuf, dev);
1087 if (err)
1088 return err;
1089
1090 priv = dma_buf_get_drvdata(dmabuf, dev);
1091 if (WARN_ON(!priv))
1092 return -ENOSYS;
1093
1094 nvgpu_mutex_acquire(&priv->lock);
1095
1096 nvgpu_list_for_each_entry(s, &priv->states, gk20a_buffer_state, list)
1097 if (s->offset == offset)
1098 goto out;
1099
1100 /* State not found, create state. */
1101 s = nvgpu_kzalloc(g, sizeof(*s));
1102 if (!s) {
1103 err = -ENOMEM;
1104 goto out;
1105 }
1106
1107 s->offset = offset;
1108 nvgpu_init_list_node(&s->list);
1109 nvgpu_mutex_init(&s->lock);
1110 nvgpu_list_add_tail(&s->list, &priv->states);
1111
1112out:
1113 nvgpu_mutex_release(&priv->lock);
1114 if (!err)
1115 *state = s;
1116 return err;
1117
1118
1119}
1120
1121int nvgpu_vm_map_buffer(struct vm_gk20a *vm, 856int nvgpu_vm_map_buffer(struct vm_gk20a *vm,
1122 int dmabuf_fd, 857 int dmabuf_fd,
1123 u64 *offset_align, 858 u64 *offset_align,
@@ -1613,34 +1348,3 @@ const struct gk20a_mmu_level *gk20a_mm_get_mmu_levels(struct gk20a *g,
1613 return (big_page_size == SZ_64K) ? 1348 return (big_page_size == SZ_64K) ?
1614 gk20a_mm_levels_64k : gk20a_mm_levels_128k; 1349 gk20a_mm_levels_64k : gk20a_mm_levels_128k;
1615} 1350}
1616
1617int gk20a_mm_get_buffer_info(struct device *dev, int dmabuf_fd,
1618 u64 *buffer_id, u64 *buffer_len)
1619{
1620 struct dma_buf *dmabuf;
1621 struct gk20a_dmabuf_priv *priv;
1622 int err = 0;
1623
1624 dmabuf = dma_buf_get(dmabuf_fd);
1625 if (IS_ERR(dmabuf)) {
1626 dev_warn(dev, "%s: fd %d is not a dmabuf", __func__, dmabuf_fd);
1627 return PTR_ERR(dmabuf);
1628 }
1629
1630 err = gk20a_dmabuf_alloc_drvdata(dmabuf, dev);
1631 if (err) {
1632 dev_warn(dev, "Failed to allocate dmabuf drvdata (err = %d)",
1633 err);
1634 goto clean_up;
1635 }
1636
1637 priv = dma_buf_get_drvdata(dmabuf, dev);
1638 if (likely(priv)) {
1639 *buffer_id = priv->buffer_id;
1640 *buffer_len = dmabuf->size;
1641 }
1642
1643clean_up:
1644 dma_buf_put(dmabuf);
1645 return err;
1646}
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
index 448496f5..04034d84 100644
--- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h
@@ -117,13 +117,6 @@ gk20a_buffer_state_from_list(struct nvgpu_list_node *node)
117 ((uintptr_t)node - offsetof(struct gk20a_buffer_state, list)); 117 ((uintptr_t)node - offsetof(struct gk20a_buffer_state, list));
118}; 118};
119 119
120struct gk20a_comptags {
121 u32 offset;
122 u32 lines;
123 u32 allocated_lines;
124 bool user_mappable;
125};
126
127struct priv_cmd_queue { 120struct priv_cmd_queue {
128 struct nvgpu_mem mem; 121 struct nvgpu_mem mem;
129 u32 size; /* num of entries in words */ 122 u32 size; /* num of entries in words */
@@ -369,10 +362,6 @@ void gk20a_locked_gmmu_unmap(struct vm_gk20a *vm,
369 bool sparse, 362 bool sparse,
370 struct vm_gk20a_mapping_batch *batch); 363 struct vm_gk20a_mapping_batch *batch);
371 364
372struct sg_table *gk20a_mm_pin(struct device *dev, struct dma_buf *dmabuf);
373void gk20a_mm_unpin(struct device *dev, struct dma_buf *dmabuf,
374 struct sg_table *sgt);
375
376/* vm-as interface */ 365/* vm-as interface */
377struct nvgpu_as_alloc_space_args; 366struct nvgpu_as_alloc_space_args;
378struct nvgpu_as_free_space_args; 367struct nvgpu_as_free_space_args;
@@ -381,14 +370,6 @@ int gk20a_vm_bind_channel(struct gk20a_as_share *as_share,
381 struct channel_gk20a *ch); 370 struct channel_gk20a *ch);
382int __gk20a_vm_bind_channel(struct vm_gk20a *vm, struct channel_gk20a *ch); 371int __gk20a_vm_bind_channel(struct vm_gk20a *vm, struct channel_gk20a *ch);
383 372
384void gk20a_get_comptags(struct device *dev, struct dma_buf *dmabuf,
385 struct gk20a_comptags *comptags);
386
387int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev);
388
389int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct gk20a *g,
390 u64 offset, struct gk20a_buffer_state **state);
391
392void pde_range_from_vaddr_range(struct vm_gk20a *vm, 373void pde_range_from_vaddr_range(struct vm_gk20a *vm,
393 u64 addr_lo, u64 addr_hi, 374 u64 addr_lo, u64 addr_hi,
394 u32 *pde_lo, u32 *pde_hi); 375 u32 *pde_lo, u32 *pde_hi);
diff --git a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c
index dee46aaf..84759192 100644
--- a/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/ltc_gm20b.c
@@ -100,7 +100,7 @@ int gm20b_ltc_init_comptags(struct gk20a *g, struct gr_gk20a *gr)
100 if (err) 100 if (err)
101 return err; 101 return err;
102 102
103 err = gk20a_comptag_allocator_init(&gr->comp_tags, max_comptag_lines); 103 err = gk20a_comptag_allocator_init(g, &gr->comp_tags, max_comptag_lines);
104 if (err) 104 if (err)
105 return err; 105 return err;
106 106
diff --git a/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c b/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c
index 02cab938..9d878402 100644
--- a/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c
+++ b/drivers/gpu/nvgpu/gp10b/ltc_gp10b.c
@@ -120,7 +120,7 @@ int gp10b_ltc_init_comptags(struct gk20a *g, struct gr_gk20a *gr)
120 if (err) 120 if (err)
121 return err; 121 return err;
122 122
123 err = gk20a_comptag_allocator_init(&gr->comp_tags, max_comptag_lines); 123 err = gk20a_comptag_allocator_init(g, &gr->comp_tags, max_comptag_lines);
124 if (err) 124 if (err)
125 return err; 125 return err;
126 126
diff --git a/drivers/gpu/nvgpu/include/nvgpu/comptags.h b/drivers/gpu/nvgpu/include/nvgpu/comptags.h
new file mode 100644
index 00000000..6e3062ec
--- /dev/null
+++ b/drivers/gpu/nvgpu/include/nvgpu/comptags.h
@@ -0,0 +1,57 @@
1/*
2* Copyright (c) 2017, 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#ifndef __NVGPU_COMPTAGS__
18#define __NVGPU_COMPTAGS__
19
20#include <nvgpu/lock.h>
21
22struct gk20a;
23
24struct gk20a_comptags {
25 u32 offset;
26 u32 lines;
27 u32 allocated_lines;
28 bool user_mappable;
29};
30
31struct gk20a_comptag_allocator {
32 struct gk20a *g;
33
34 struct nvgpu_mutex lock;
35
36 /* This bitmap starts at ctag 1. 0th cannot be taken. */
37 unsigned long *bitmap;
38
39 /* Size of bitmap, not max ctags, so one less. */
40 unsigned long size;
41};
42
43/* real size here, but first (ctag 0) isn't used */
44int gk20a_comptag_allocator_init(struct gk20a *g,
45 struct gk20a_comptag_allocator *allocator,
46 unsigned long size);
47void gk20a_comptag_allocator_destroy(struct gk20a *g,
48 struct gk20a_comptag_allocator *allocator);
49
50int gk20a_comptaglines_alloc(struct gk20a_comptag_allocator *allocator,
51 u32 *offset, u32 len);
52void gk20a_comptaglines_free(struct gk20a_comptag_allocator *allocator,
53 u32 offset, u32 len);
54
55
56
57#endif
diff --git a/drivers/gpu/nvgpu/vgpu/gr_vgpu.c b/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
index 96d21c0a..b913847b 100644
--- a/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/gr_vgpu.c
@@ -844,7 +844,7 @@ static void vgpu_remove_gr_support(struct gr_gk20a *gr)
844{ 844{
845 gk20a_dbg_fn(""); 845 gk20a_dbg_fn("");
846 846
847 gk20a_comptag_allocator_destroy(&gr->comp_tags); 847 gk20a_comptag_allocator_destroy(gr->g, &gr->comp_tags);
848 848
849 nvgpu_kfree(gr->g, gr->sm_error_states); 849 nvgpu_kfree(gr->g, gr->sm_error_states);
850 gr->sm_error_states = NULL; 850 gr->sm_error_states = NULL;
diff --git a/drivers/gpu/nvgpu/vgpu/ltc_vgpu.c b/drivers/gpu/nvgpu/vgpu/ltc_vgpu.c
index a6848872..fb9558e2 100644
--- a/drivers/gpu/nvgpu/vgpu/ltc_vgpu.c
+++ b/drivers/gpu/nvgpu/vgpu/ltc_vgpu.c
@@ -50,7 +50,7 @@ int vgpu_ltc_init_comptags(struct gk20a *g, struct gr_gk20a *gr)
50 if (max_comptag_lines < 2) 50 if (max_comptag_lines < 2)
51 return -ENXIO; 51 return -ENXIO;
52 52
53 err = gk20a_comptag_allocator_init(&gr->comp_tags, max_comptag_lines); 53 err = gk20a_comptag_allocator_init(g, &gr->comp_tags, max_comptag_lines);
54 if (err) 54 if (err)
55 return err; 55 return err;
56 56