diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gp10b/fifo_gp10b.c')
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/fifo_gp10b.c | 320 |
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 | |||
42 | static 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 | |||
66 | int 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 | |||
94 | int 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 | |||
161 | u32 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 | |||
167 | int 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 | |||
206 | int 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 | |||
222 | void 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 | |||
246 | void 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 | |||
291 | void 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 | } | ||