summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gp10b/fifo_gp10b.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gp10b/fifo_gp10b.c')
-rw-r--r--drivers/gpu/nvgpu/gp10b/fifo_gp10b.c320
1 files changed, 320 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gp10b/fifo_gp10b.c b/drivers/gpu/nvgpu/gp10b/fifo_gp10b.c
new file mode 100644
index 00000000..1c9249d1
--- /dev/null
+++ b/drivers/gpu/nvgpu/gp10b/fifo_gp10b.c
@@ -0,0 +1,320 @@
1/*
2 * GP10B fifo
3 *
4 * Copyright (c) 2015-2017, 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 <uapi/linux/nvgpu.h>
26
27#include <nvgpu/dma.h>
28#include <nvgpu/bug.h>
29#include <nvgpu/log2.h>
30
31#include "fifo_gp10b.h"
32
33#include "gk20a/gk20a.h"
34#include "gm20b/fifo_gm20b.h"
35
36#include <nvgpu/hw/gp10b/hw_pbdma_gp10b.h>
37#include <nvgpu/hw/gp10b/hw_ccsr_gp10b.h>
38#include <nvgpu/hw/gp10b/hw_fifo_gp10b.h>
39#include <nvgpu/hw/gp10b/hw_ram_gp10b.h>
40#include <nvgpu/hw/gp10b/hw_top_gp10b.h>
41
42static void gp10b_set_pdb_fault_replay_flags(struct gk20a *g,
43 struct nvgpu_mem *mem)
44{
45 u32 val;
46
47 gk20a_dbg_fn("");
48
49 val = nvgpu_mem_rd32(g, mem,
50 ram_in_page_dir_base_fault_replay_tex_w());
51 val &= ~ram_in_page_dir_base_fault_replay_tex_m();
52 val |= ram_in_page_dir_base_fault_replay_tex_true_f();
53 nvgpu_mem_wr32(g, mem,
54 ram_in_page_dir_base_fault_replay_tex_w(), val);
55
56 val = nvgpu_mem_rd32(g, mem,
57 ram_in_page_dir_base_fault_replay_gcc_w());
58 val &= ~ram_in_page_dir_base_fault_replay_gcc_m();
59 val |= ram_in_page_dir_base_fault_replay_gcc_true_f();
60 nvgpu_mem_wr32(g, mem,
61 ram_in_page_dir_base_fault_replay_gcc_w(), val);
62
63 gk20a_dbg_fn("done");
64}
65
66int channel_gp10b_commit_userd(struct channel_gk20a *c)
67{
68 u32 addr_lo;
69 u32 addr_hi;
70 struct gk20a *g = c->g;
71
72 gk20a_dbg_fn("");
73
74 addr_lo = u64_lo32(c->userd_iova >> ram_userd_base_shift_v());
75 addr_hi = u64_hi32(c->userd_iova);
76
77 gk20a_dbg_info("channel %d : set ramfc userd 0x%16llx",
78 c->chid, (u64)c->userd_iova);
79
80 nvgpu_mem_wr32(g, &c->inst_block,
81 ram_in_ramfc_w() + ram_fc_userd_w(),
82 nvgpu_aperture_mask(g, &g->fifo.userd,
83 pbdma_userd_target_sys_mem_ncoh_f(),
84 pbdma_userd_target_vid_mem_f()) |
85 pbdma_userd_addr_f(addr_lo));
86
87 nvgpu_mem_wr32(g, &c->inst_block,
88 ram_in_ramfc_w() + ram_fc_userd_hi_w(),
89 pbdma_userd_hi_addr_f(addr_hi));
90
91 return 0;
92}
93
94int channel_gp10b_setup_ramfc(struct channel_gk20a *c,
95 u64 gpfifo_base, u32 gpfifo_entries,
96 unsigned long acquire_timeout, u32 flags)
97{
98 struct gk20a *g = c->g;
99 struct nvgpu_mem *mem = &c->inst_block;
100
101 gk20a_dbg_fn("");
102
103 nvgpu_memset(g, mem, 0, 0, ram_fc_size_val_v());
104
105 nvgpu_mem_wr32(g, mem, ram_fc_gp_base_w(),
106 pbdma_gp_base_offset_f(
107 u64_lo32(gpfifo_base >> pbdma_gp_base_rsvd_s())));
108
109 nvgpu_mem_wr32(g, mem, ram_fc_gp_base_hi_w(),
110 pbdma_gp_base_hi_offset_f(u64_hi32(gpfifo_base)) |
111 pbdma_gp_base_hi_limit2_f(ilog2(gpfifo_entries)));
112
113 nvgpu_mem_wr32(g, mem, ram_fc_signature_w(),
114 c->g->ops.fifo.get_pbdma_signature(c->g));
115
116 nvgpu_mem_wr32(g, mem, ram_fc_formats_w(),
117 pbdma_formats_gp_fermi0_f() |
118 pbdma_formats_pb_fermi1_f() |
119 pbdma_formats_mp_fermi0_f());
120
121 nvgpu_mem_wr32(g, mem, ram_fc_pb_header_w(),
122 pbdma_pb_header_priv_user_f() |
123 pbdma_pb_header_method_zero_f() |
124 pbdma_pb_header_subchannel_zero_f() |
125 pbdma_pb_header_level_main_f() |
126 pbdma_pb_header_first_true_f() |
127 pbdma_pb_header_type_inc_f());
128
129 nvgpu_mem_wr32(g, mem, ram_fc_subdevice_w(),
130 pbdma_subdevice_id_f(1) |
131 pbdma_subdevice_status_active_f() |
132 pbdma_subdevice_channel_dma_enable_f());
133
134 nvgpu_mem_wr32(g, mem, ram_fc_target_w(), pbdma_target_engine_sw_f());
135
136 nvgpu_mem_wr32(g, mem, ram_fc_acquire_w(),
137 g->ops.fifo.pbdma_acquire_val(acquire_timeout));
138
139 nvgpu_mem_wr32(g, mem, ram_fc_runlist_timeslice_w(),
140 pbdma_runlist_timeslice_timeout_128_f() |
141 pbdma_runlist_timeslice_timescale_3_f() |
142 pbdma_runlist_timeslice_enable_true_f());
143
144 if ( flags & NVGPU_ALLOC_GPFIFO_FLAGS_REPLAYABLE_FAULTS_ENABLE)
145 gp10b_set_pdb_fault_replay_flags(c->g, mem);
146
147
148 nvgpu_mem_wr32(g, mem, ram_fc_chid_w(), ram_fc_chid_id_f(c->chid));
149
150 if (c->is_privileged_channel) {
151 /* Set privilege level for channel */
152 nvgpu_mem_wr32(g, mem, ram_fc_config_w(),
153 pbdma_config_auth_level_privileged_f());
154
155 gk20a_fifo_setup_ramfc_for_privileged_channel(c);
156 }
157
158 return channel_gp10b_commit_userd(c);
159}
160
161u32 gp10b_fifo_get_pbdma_signature(struct gk20a *g)
162{
163 return g->ops.get_litter_value(g, GPU_LIT_GPFIFO_CLASS)
164 | pbdma_signature_sw_zero_f();
165}
166
167int gp10b_fifo_resetup_ramfc(struct channel_gk20a *c)
168{
169 u32 new_syncpt = 0, old_syncpt;
170 u32 v;
171
172 gk20a_dbg_fn("");
173
174 v = nvgpu_mem_rd32(c->g, &c->inst_block,
175 ram_fc_allowed_syncpoints_w());
176 old_syncpt = pbdma_allowed_syncpoints_0_index_v(v);
177 if (c->sync)
178 new_syncpt = c->sync->syncpt_id(c->sync);
179
180 if (new_syncpt && new_syncpt != old_syncpt) {
181 /* disable channel */
182 gk20a_disable_channel_tsg(c->g, c);
183
184 /* preempt the channel */
185 WARN_ON(gk20a_fifo_preempt(c->g, c));
186
187 v = pbdma_allowed_syncpoints_0_valid_f(1);
188
189 gk20a_dbg_info("Channel %d, syncpt id %d\n",
190 c->chid, new_syncpt);
191
192 v |= pbdma_allowed_syncpoints_0_index_f(new_syncpt);
193
194 nvgpu_mem_wr32(c->g, &c->inst_block,
195 ram_fc_allowed_syncpoints_w(), v);
196 }
197
198 /* enable channel */
199 gk20a_enable_channel_tsg(c->g, c);
200
201 gk20a_dbg_fn("done");
202
203 return 0;
204}
205
206int gp10b_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type,
207 u32 *inst_id)
208{
209 int ret = ENGINE_INVAL_GK20A;
210
211 gk20a_dbg_info("engine type %d", engine_type);
212 if (engine_type == top_device_info_type_enum_graphics_v())
213 ret = ENGINE_GR_GK20A;
214 else if (engine_type == top_device_info_type_enum_lce_v()) {
215 /* Default assumptions - all the CE engine have separate runlist */
216 ret = ENGINE_ASYNC_CE_GK20A;
217 }
218
219 return ret;
220}
221
222void gp10b_device_info_data_parse(struct gk20a *g, u32 table_entry,
223 u32 *inst_id, u32 *pri_base, u32 *fault_id)
224{
225 if (top_device_info_data_type_v(table_entry) ==
226 top_device_info_data_type_enum2_v()) {
227 if (inst_id)
228 *inst_id = top_device_info_data_inst_id_v(table_entry);
229 if (pri_base) {
230 *pri_base =
231 (top_device_info_data_pri_base_v(table_entry)
232 << top_device_info_data_pri_base_align_v());
233 gk20a_dbg_info("device info: pri_base: %d", *pri_base);
234 }
235 if (fault_id && (top_device_info_data_fault_id_v(table_entry) ==
236 top_device_info_data_fault_id_valid_v())) {
237 *fault_id =
238 g->ops.fifo.device_info_fault_id(table_entry);
239 gk20a_dbg_info("device info: fault_id: %d", *fault_id);
240 }
241 } else
242 nvgpu_err(g, "unknown device_info_data %d",
243 top_device_info_data_type_v(table_entry));
244}
245
246void gp10b_fifo_init_pbdma_intr_descs(struct fifo_gk20a *f)
247{
248 /*
249 * These are all errors which indicate something really wrong
250 * going on in the device
251 */
252 f->intr.pbdma.device_fatal_0 =
253 pbdma_intr_0_memreq_pending_f() |
254 pbdma_intr_0_memack_timeout_pending_f() |
255 pbdma_intr_0_memack_extra_pending_f() |
256 pbdma_intr_0_memdat_timeout_pending_f() |
257 pbdma_intr_0_memdat_extra_pending_f() |
258 pbdma_intr_0_memflush_pending_f() |
259 pbdma_intr_0_memop_pending_f() |
260 pbdma_intr_0_lbconnect_pending_f() |
261 pbdma_intr_0_lback_timeout_pending_f() |
262 pbdma_intr_0_lback_extra_pending_f() |
263 pbdma_intr_0_lbdat_timeout_pending_f() |
264 pbdma_intr_0_lbdat_extra_pending_f() |
265 pbdma_intr_0_pri_pending_f();
266
267 /*
268 * These are data parsing, framing errors or others which can be
269 * recovered from with intervention... or just resetting the
270 * channel
271 */
272 f->intr.pbdma.channel_fatal_0 =
273 pbdma_intr_0_gpfifo_pending_f() |
274 pbdma_intr_0_gpptr_pending_f() |
275 pbdma_intr_0_gpentry_pending_f() |
276 pbdma_intr_0_gpcrc_pending_f() |
277 pbdma_intr_0_pbptr_pending_f() |
278 pbdma_intr_0_pbentry_pending_f() |
279 pbdma_intr_0_pbcrc_pending_f() |
280 pbdma_intr_0_method_pending_f() |
281 pbdma_intr_0_methodcrc_pending_f() |
282 pbdma_intr_0_pbseg_pending_f() |
283 pbdma_intr_0_syncpoint_illegal_pending_f() |
284 pbdma_intr_0_signature_pending_f();
285
286 /* Can be used for sw-methods, or represents a recoverable timeout. */
287 f->intr.pbdma.restartable_0 =
288 pbdma_intr_0_device_pending_f();
289}
290
291void gp10b_fifo_get_mmu_fault_info(struct gk20a *g, u32 mmu_fault_id,
292 struct mmu_fault_info *mmfault)
293{
294 u32 fault_info;
295 u32 addr_lo, addr_hi;
296
297 gk20a_dbg_fn("mmu_fault_id %d", mmu_fault_id);
298
299 memset(mmfault, 0, sizeof(*mmfault));
300
301 fault_info = gk20a_readl(g,
302 fifo_intr_mmu_fault_info_r(mmu_fault_id));
303 mmfault->fault_type =
304 fifo_intr_mmu_fault_info_type_v(fault_info);
305 mmfault->access_type =
306 fifo_intr_mmu_fault_info_access_type_v(fault_info);
307 mmfault->client_type =
308 fifo_intr_mmu_fault_info_client_type_v(fault_info);
309 mmfault->client_id =
310 fifo_intr_mmu_fault_info_client_v(fault_info);
311
312 addr_lo = gk20a_readl(g, fifo_intr_mmu_fault_lo_r(mmu_fault_id));
313 addr_hi = gk20a_readl(g, fifo_intr_mmu_fault_hi_r(mmu_fault_id));
314 mmfault->fault_addr = hi32_lo32_to_u64(addr_hi, addr_lo);
315 /* note:ignoring aperture */
316 mmfault->inst_ptr = fifo_intr_mmu_fault_inst_ptr_v(
317 gk20a_readl(g, fifo_intr_mmu_fault_inst_r(mmu_fault_id)));
318 /* note: inst_ptr is a 40b phys addr. */
319 mmfault->inst_ptr <<= fifo_intr_mmu_fault_inst_ptr_align_shift_v();
320}