aboutsummaryrefslogtreecommitdiffstats
path: root/include/gk20a/ce2_gk20a.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/gk20a/ce2_gk20a.c')
-rw-r--r--include/gk20a/ce2_gk20a.c576
1 files changed, 576 insertions, 0 deletions
diff --git a/include/gk20a/ce2_gk20a.c b/include/gk20a/ce2_gk20a.c
new file mode 100644
index 0000000..2a40b08
--- /dev/null
+++ b/include/gk20a/ce2_gk20a.c
@@ -0,0 +1,576 @@
1/*
2 * GK20A Graphics Copy Engine (gr host)
3 *
4 * Copyright (c) 2011-2019, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <nvgpu/kmem.h>
26#include <nvgpu/dma.h>
27#include <nvgpu/os_sched.h>
28#include <nvgpu/log.h>
29#include <nvgpu/enabled.h>
30#include <nvgpu/io.h>
31#include <nvgpu/utils.h>
32#include <nvgpu/channel.h>
33#include <nvgpu/power_features/cg.h>
34
35#include "gk20a.h"
36#include "gk20a/fence_gk20a.h"
37
38#include <nvgpu/hw/gk20a/hw_ce2_gk20a.h>
39#include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h>
40#include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h>
41#include <nvgpu/hw/gk20a/hw_ram_gk20a.h>
42#include <nvgpu/hw/gk20a/hw_top_gk20a.h>
43#include <nvgpu/hw/gk20a/hw_gr_gk20a.h>
44#include <nvgpu/barrier.h>
45
46/*
47 * Copy engine defines line size in pixels
48 */
49#define MAX_CE_SHIFT 31 /* 4Gpixels -1 */
50#define MAX_CE_MASK ((u32) (~(~0U << MAX_CE_SHIFT)))
51#define MAX_CE_ALIGN(a) (a & MAX_CE_MASK)
52
53
54static u32 ce2_nonblockpipe_isr(struct gk20a *g, u32 fifo_intr)
55{
56 nvgpu_log(g, gpu_dbg_intr, "ce2 non-blocking pipe interrupt\n");
57
58 return ce2_intr_status_nonblockpipe_pending_f();
59}
60
61static u32 ce2_blockpipe_isr(struct gk20a *g, u32 fifo_intr)
62{
63 nvgpu_log(g, gpu_dbg_intr, "ce2 blocking pipe interrupt\n");
64
65 return ce2_intr_status_blockpipe_pending_f();
66}
67
68static u32 ce2_launcherr_isr(struct gk20a *g, u32 fifo_intr)
69{
70 nvgpu_log(g, gpu_dbg_intr, "ce2 launch error interrupt\n");
71
72 return ce2_intr_status_launcherr_pending_f();
73}
74
75void gk20a_ce2_isr(struct gk20a *g, u32 inst_id, u32 pri_base)
76{
77 u32 ce2_intr = gk20a_readl(g, ce2_intr_status_r());
78 u32 clear_intr = 0;
79
80 nvgpu_log(g, gpu_dbg_intr, "ce2 isr %08x\n", ce2_intr);
81
82 /* clear blocking interrupts: they exibit broken behavior */
83 if (ce2_intr & ce2_intr_status_blockpipe_pending_f()) {
84 clear_intr |= ce2_blockpipe_isr(g, ce2_intr);
85 }
86
87 if (ce2_intr & ce2_intr_status_launcherr_pending_f()) {
88 clear_intr |= ce2_launcherr_isr(g, ce2_intr);
89 }
90
91 gk20a_writel(g, ce2_intr_status_r(), clear_intr);
92 return;
93}
94
95u32 gk20a_ce2_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base)
96{
97 u32 ops = 0;
98 u32 ce2_intr = gk20a_readl(g, ce2_intr_status_r());
99
100 nvgpu_log(g, gpu_dbg_intr, "ce2 nonstall isr %08x\n", ce2_intr);
101
102 if (ce2_intr & ce2_intr_status_nonblockpipe_pending_f()) {
103 gk20a_writel(g, ce2_intr_status_r(),
104 ce2_nonblockpipe_isr(g, ce2_intr));
105 ops |= (GK20A_NONSTALL_OPS_WAKEUP_SEMAPHORE |
106 GK20A_NONSTALL_OPS_POST_EVENTS);
107 }
108 return ops;
109}
110
111/* static CE app api */
112static void gk20a_ce_put_fences(struct gk20a_gpu_ctx *ce_ctx)
113{
114 u32 i;
115
116 for (i = 0; i < NVGPU_CE_MAX_INFLIGHT_JOBS; i++) {
117 struct gk20a_fence **fence = &ce_ctx->postfences[i];
118 if (*fence) {
119 gk20a_fence_put(*fence);
120 }
121 *fence = NULL;
122 }
123}
124
125/* assume this api should need to call under nvgpu_mutex_acquire(&ce_app->app_mutex) */
126static void gk20a_ce_delete_gpu_context(struct gk20a_gpu_ctx *ce_ctx)
127{
128 struct nvgpu_list_node *list = &ce_ctx->list;
129
130 ce_ctx->gpu_ctx_state = NVGPU_CE_GPU_CTX_DELETED;
131
132 nvgpu_mutex_acquire(&ce_ctx->gpu_ctx_mutex);
133
134 if (nvgpu_mem_is_valid(&ce_ctx->cmd_buf_mem)) {
135 gk20a_ce_put_fences(ce_ctx);
136 nvgpu_dma_unmap_free(ce_ctx->vm, &ce_ctx->cmd_buf_mem);
137 }
138
139 /*
140 * free the channel
141 * gk20a_channel_close() will also unbind the channel from TSG
142 */
143 gk20a_channel_close(ce_ctx->ch);
144 nvgpu_ref_put(&ce_ctx->tsg->refcount, gk20a_tsg_release);
145
146 /* housekeeping on app */
147 if (list->prev && list->next) {
148 nvgpu_list_del(list);
149 }
150
151 nvgpu_mutex_release(&ce_ctx->gpu_ctx_mutex);
152 nvgpu_mutex_destroy(&ce_ctx->gpu_ctx_mutex);
153
154 nvgpu_kfree(ce_ctx->g, ce_ctx);
155}
156
157static inline unsigned int gk20a_ce_get_method_size(int request_operation,
158 u64 size)
159{
160 /* failure size */
161 unsigned int methodsize = UINT_MAX;
162 unsigned int iterations = 0;
163 u32 shift;
164 u64 chunk = size;
165 u32 height, width;
166
167 while (chunk) {
168 iterations++;
169
170 shift = MAX_CE_ALIGN(chunk) ? __ffs(MAX_CE_ALIGN(chunk)) :
171 MAX_CE_SHIFT;
172 width = chunk >> shift;
173 height = 1 << shift;
174 width = MAX_CE_ALIGN(width);
175
176 chunk -= (u64) height * width;
177 }
178
179 if (request_operation & NVGPU_CE_PHYS_MODE_TRANSFER) {
180 methodsize = (2 + (16 * iterations)) * sizeof(u32);
181 } else if (request_operation & NVGPU_CE_MEMSET) {
182 methodsize = (2 + (15 * iterations)) * sizeof(u32);
183 }
184
185 return methodsize;
186}
187
188int gk20a_ce_prepare_submit(u64 src_buf,
189 u64 dst_buf,
190 u64 size,
191 u32 *cmd_buf_cpu_va,
192 u32 max_cmd_buf_size,
193 unsigned int payload,
194 int launch_flags,
195 int request_operation,
196 u32 dma_copy_class)
197{
198 u32 launch = 0;
199 u32 methodSize = 0;
200 u64 offset = 0;
201 u64 chunk_size = 0;
202 u64 chunk = size;
203
204 /* failure case handling */
205 if ((gk20a_ce_get_method_size(request_operation, size) >
206 max_cmd_buf_size) || (!size) ||
207 (request_operation > NVGPU_CE_MEMSET)) {
208 return 0;
209 }
210
211 /* set the channel object */
212 cmd_buf_cpu_va[methodSize++] = 0x20018000;
213 cmd_buf_cpu_va[methodSize++] = dma_copy_class;
214
215 /*
216 * The purpose clear the memory in 2D rectangles. We get the ffs to
217 * determine the number of lines to copy. The only constraint is that
218 * maximum number of pixels per line is 4Gpix - 1, which is awkward for
219 * calculation, so we settle to 2Gpix per line to make calculatione
220 * more agreable
221 */
222
223 /* The copy engine in 2D mode can have (2^32 - 1) x (2^32 - 1) pixels in
224 * a single submit, we are going to try to clear a range of up to 2Gpix
225 * multiple lines.