summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gp106/gr_gp106.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/gp106/gr_gp106.c')
-rw-r--r--drivers/gpu/nvgpu/gp106/gr_gp106.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gp106/gr_gp106.c b/drivers/gpu/nvgpu/gp106/gr_gp106.c
new file mode 100644
index 00000000..8d8376d3
--- /dev/null
+++ b/drivers/gpu/nvgpu/gp106/gr_gp106.c
@@ -0,0 +1,239 @@
1/*
2 * GP106 GPU GR
3 *
4 * Copyright (c) 2016, 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 "gk20a/gk20a.h" /* FERMI and MAXWELL classes defined here */
17
18#include "gk20a/gr_gk20a.h"
19
20#include "gm20b/gr_gm20b.h" /* for MAXWELL classes */
21#include "gp10b/gr_gp10b.h"
22#include "gr_gp106.h"
23#include "hw_gr_gp106.h"
24
25static bool gr_gp106_is_valid_class(struct gk20a *g, u32 class_num)
26{
27 bool valid = false;
28
29 switch (class_num) {
30 case PASCAL_COMPUTE_A:
31 case PASCAL_COMPUTE_B:
32 case PASCAL_A:
33 case PASCAL_B:
34 case PASCAL_DMA_COPY_A:
35 case PASCAL_DMA_COPY_B:
36 valid = true;
37 break;
38
39 case MAXWELL_COMPUTE_B:
40 case MAXWELL_B:
41 case FERMI_TWOD_A:
42 case KEPLER_DMA_COPY_A:
43 case MAXWELL_DMA_COPY_A:
44 valid = true;
45 break;
46
47 default:
48 break;
49 }
50 gk20a_dbg_info("class=0x%x valid=%d", class_num, valid);
51 return valid;
52}
53
54static u32 gr_gp106_pagepool_default_size(struct gk20a *g)
55{
56 return gr_scc_pagepool_total_pages_hwmax_value_v();
57}
58
59static void gr_gp106_set_go_idle_timeout(struct gk20a *g, u32 data)
60{
61 gk20a_writel(g, gr_fe_go_idle_timeout_r(), data);
62}
63
64static int gr_gp106_handle_sw_method(struct gk20a *g, u32 addr,
65 u32 class_num, u32 offset, u32 data)
66{
67 gk20a_dbg_fn("");
68
69 if (class_num == PASCAL_COMPUTE_B) {
70 switch (offset << 2) {
71 case NVC0C0_SET_SHADER_EXCEPTIONS:
72 gk20a_gr_set_shader_exceptions(g, data);
73 break;
74 default:
75 goto fail;
76 }
77 }
78
79 if (class_num == PASCAL_B) {
80 switch (offset << 2) {
81 case NVC097_SET_SHADER_EXCEPTIONS:
82 gk20a_gr_set_shader_exceptions(g, data);
83 break;
84 case NVC097_SET_CIRCULAR_BUFFER_SIZE:
85 g->ops.gr.set_circular_buffer_size(g, data);
86 break;
87 case NVC097_SET_ALPHA_CIRCULAR_BUFFER_SIZE:
88 g->ops.gr.set_alpha_circular_buffer_size(g, data);
89 break;
90 case NVC097_SET_GO_IDLE_TIMEOUT:
91 gr_gp106_set_go_idle_timeout(g, data);
92 break;
93 default:
94 goto fail;
95 }
96 }
97 return 0;
98
99fail:
100 return -EINVAL;
101}
102
103static void gr_gp106_cb_size_default(struct gk20a *g)
104{
105 struct gr_gk20a *gr = &g->gr;
106
107 if (!gr->attrib_cb_default_size)
108 gr->attrib_cb_default_size = 0x800;
109 gr->alpha_cb_default_size =
110 gr_gpc0_ppc0_cbm_alpha_cb_size_v_default_v();
111}
112
113static int gr_gp106_set_ctxsw_preemption_mode(struct gk20a *g,
114 struct gr_ctx_desc *gr_ctx,
115 struct vm_gk20a *vm, u32 class,
116 u32 graphics_preempt_mode,
117 u32 compute_preempt_mode)
118{
119 int err = 0;
120
121 if (class == PASCAL_B && g->gr.t18x.ctx_vars.force_preemption_gfxp)
122 graphics_preempt_mode = NVGPU_GRAPHICS_PREEMPTION_MODE_GFXP;
123
124 if (class == PASCAL_COMPUTE_B &&
125 g->gr.t18x.ctx_vars.force_preemption_cilp)
126 compute_preempt_mode = NVGPU_COMPUTE_PREEMPTION_MODE_CILP;
127
128 /* check for invalid combinations */
129 if ((graphics_preempt_mode == 0) && (compute_preempt_mode == 0))
130 return -EINVAL;
131
132 if ((graphics_preempt_mode == NVGPU_GRAPHICS_PREEMPTION_MODE_GFXP) &&
133 (compute_preempt_mode == NVGPU_COMPUTE_PREEMPTION_MODE_CILP))
134 return -EINVAL;
135
136 /* set preemption modes */
137 switch (graphics_preempt_mode) {
138 case NVGPU_GRAPHICS_PREEMPTION_MODE_GFXP:
139 {
140 u32 spill_size =
141 gr_gpc0_swdx_rm_spill_buffer_size_256b_default_v() *
142 gr_gpc0_swdx_rm_spill_buffer_size_256b_byte_granularity_v();
143 u32 pagepool_size = g->ops.gr.pagepool_default_size(g) *
144 gr_scc_pagepool_total_pages_byte_granularity_v();
145 u32 betacb_size = g->gr.attrib_cb_default_size +
146 (gr_gpc0_ppc0_cbm_beta_cb_size_v_gfxp_v() -
147 gr_gpc0_ppc0_cbm_beta_cb_size_v_default_v());
148 u32 attrib_cb_size = (betacb_size + g->gr.alpha_cb_size) *
149 gr_gpc0_ppc0_cbm_beta_cb_size_v_granularity_v() *
150 g->gr.max_tpc_count;
151 attrib_cb_size = ALIGN(attrib_cb_size, 128);
152
153 gk20a_dbg_info("gfxp context spill_size=%d", spill_size);
154 gk20a_dbg_info("gfxp context pagepool_size=%d", pagepool_size);
155 gk20a_dbg_info("gfxp context attrib_cb_size=%d",
156 attrib_cb_size);
157
158 err = gr_gp10b_alloc_buffer(vm,
159 g->gr.t18x.ctx_vars.preempt_image_size,
160 &gr_ctx->t18x.preempt_ctxsw_buffer);
161 if (err) {
162 gk20a_err(dev_from_gk20a(g),
163 "cannot allocate preempt buffer");
164 goto fail;
165 }
166
167 err = gr_gp10b_alloc_buffer(vm,
168 spill_size,
169 &gr_ctx->t18x.spill_ctxsw_buffer);
170 if (err) {
171 gk20a_err(dev_from_gk20a(g),
172 "cannot allocate spill buffer");
173 goto fail_free_preempt;
174 }
175
176 err = gr_gp10b_alloc_buffer(vm,
177 attrib_cb_size,
178 &gr_ctx->t18x.betacb_ctxsw_buffer);
179 if (err) {
180 gk20a_err(dev_from_gk20a(g),
181 "cannot allocate beta buffer");
182 goto fail_free_spill;
183 }
184
185 err = gr_gp10b_alloc_buffer(vm,
186 pagepool_size,
187 &gr_ctx->t18x.pagepool_ctxsw_buffer);
188 if (err) {
189 gk20a_err(dev_from_gk20a(g),
190 "cannot allocate page pool");
191 goto fail_free_betacb;
192 }
193
194 gr_ctx->graphics_preempt_mode = graphics_preempt_mode;
195 break;
196 }
197
198 case NVGPU_GRAPHICS_PREEMPTION_MODE_WFI:
199 gr_ctx->graphics_preempt_mode = graphics_preempt_mode;
200 break;
201
202 default:
203 break;
204 }
205
206 if (class == PASCAL_COMPUTE_B) {
207 switch (compute_preempt_mode) {
208 case NVGPU_COMPUTE_PREEMPTION_MODE_WFI:
209 case NVGPU_COMPUTE_PREEMPTION_MODE_CTA:
210 case NVGPU_COMPUTE_PREEMPTION_MODE_CILP:
211 gr_ctx->compute_preempt_mode = compute_preempt_mode;
212 break;
213 default:
214 break;
215 }
216 }
217
218 return 0;
219
220fail_free_betacb:
221 gk20a_gmmu_unmap_free(vm, &gr_ctx->t18x.betacb_ctxsw_buffer);
222fail_free_spill:
223 gk20a_gmmu_unmap_free(vm, &gr_ctx->t18x.spill_ctxsw_buffer);
224fail_free_preempt:
225 gk20a_gmmu_unmap_free(vm, &gr_ctx->t18x.preempt_ctxsw_buffer);
226fail:
227 return err;
228}
229
230void gp106_init_gr(struct gpu_ops *gops)
231{
232 gp10b_init_gr(gops);
233 gops->gr.is_valid_class = gr_gp106_is_valid_class;
234 gops->gr.pagepool_default_size = gr_gp106_pagepool_default_size;
235 gops->gr.handle_sw_method = gr_gp106_handle_sw_method;
236 gops->gr.cb_size_default = gr_gp106_cb_size_default;
237 gops->gr.init_preemption_state = NULL;
238 gops->gr.set_ctxsw_preemption_mode = gr_gp106_set_ctxsw_preemption_mode;
239}