diff options
Diffstat (limited to 'drivers')
29 files changed, 791 insertions, 237 deletions
diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 2857cd5a..9e60e6a5 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile | |||
@@ -80,7 +80,8 @@ nvgpu-y := \ | |||
80 | gm206/hal_gm206.o \ | 80 | gm206/hal_gm206.o \ |
81 | gm206/gr_gm206.o \ | 81 | gm206/gr_gm206.o \ |
82 | gm206/acr_gm206.o \ | 82 | gm206/acr_gm206.o \ |
83 | gm206/pmu_gm206.o | 83 | gm206/pmu_gm206.o \ |
84 | gm206/ce_gm206.o | ||
84 | 85 | ||
85 | nvgpu-$(CONFIG_TEGRA_GK20A) += gk20a/platform_gk20a_tegra.o | 86 | nvgpu-$(CONFIG_TEGRA_GK20A) += gk20a/platform_gk20a_tegra.o |
86 | nvgpu-$(CONFIG_SYNC) += gk20a/sync_gk20a.o | 87 | nvgpu-$(CONFIG_SYNC) += gk20a/sync_gk20a.o |
diff --git a/drivers/gpu/nvgpu/gk20a/ce2_gk20a.c b/drivers/gpu/nvgpu/gk20a/ce2_gk20a.c index 00635c4d..96d38b11 100644 --- a/drivers/gpu/nvgpu/gk20a/ce2_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ce2_gk20a.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GK20A Graphics Copy Engine (gr host) | 2 | * GK20A Graphics Copy Engine (gr host) |
3 | * | 3 | * |
4 | * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 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, | 7 | * under the terms and conditions of the GNU General Public License, |
@@ -57,7 +57,7 @@ static u32 ce2_launcherr_isr(struct gk20a *g, u32 fifo_intr) | |||
57 | return ce2_intr_status_launcherr_pending_f(); | 57 | return ce2_intr_status_launcherr_pending_f(); |
58 | } | 58 | } |
59 | 59 | ||
60 | void gk20a_ce2_isr(struct gk20a *g) | 60 | void gk20a_ce2_isr(struct gk20a *g, u32 inst_id, u32 pri_base) |
61 | { | 61 | { |
62 | u32 ce2_intr = gk20a_readl(g, ce2_intr_status_r()); | 62 | u32 ce2_intr = gk20a_readl(g, ce2_intr_status_r()); |
63 | u32 clear_intr = 0; | 63 | u32 clear_intr = 0; |
@@ -75,7 +75,7 @@ void gk20a_ce2_isr(struct gk20a *g) | |||
75 | return; | 75 | return; |
76 | } | 76 | } |
77 | 77 | ||
78 | void gk20a_ce2_nonstall_isr(struct gk20a *g) | 78 | void gk20a_ce2_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base) |
79 | { | 79 | { |
80 | u32 ce2_intr = gk20a_readl(g, ce2_intr_status_r()); | 80 | u32 ce2_intr = gk20a_readl(g, ce2_intr_status_r()); |
81 | 81 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/ce2_gk20a.h b/drivers/gpu/nvgpu/gk20a/ce2_gk20a.h index bf4e3066..5ceb69e1 100644 --- a/drivers/gpu/nvgpu/gk20a/ce2_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/ce2_gk20a.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * GK20A graphics copy engine (gr host) | 4 | * GK20A graphics copy engine (gr host) |
5 | * | 5 | * |
6 | * Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved. | 6 | * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms and conditions of the GNU General Public License, | 9 | * under the terms and conditions of the GNU General Public License, |
@@ -25,7 +25,7 @@ | |||
25 | #include "tsg_gk20a.h" | 25 | #include "tsg_gk20a.h" |
26 | 26 | ||
27 | void gk20a_init_ce2(struct gpu_ops *gops); | 27 | void gk20a_init_ce2(struct gpu_ops *gops); |
28 | void gk20a_ce2_isr(struct gk20a *g); | 28 | void gk20a_ce2_isr(struct gk20a *g, u32 inst_id, u32 pri_base); |
29 | void gk20a_ce2_nonstall_isr(struct gk20a *g); | 29 | void gk20a_ce2_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base); |
30 | 30 | ||
31 | #endif /*__CE2_GK20A_H__*/ | 31 | #endif /*__CE2_GK20A_H__*/ |
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 3159f026..a5243834 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -329,11 +329,17 @@ static void channel_gk20a_bind(struct channel_gk20a *c) | |||
329 | { | 329 | { |
330 | struct gk20a *g = c->g; | 330 | struct gk20a *g = c->g; |
331 | struct fifo_gk20a *f = &g->fifo; | 331 | struct fifo_gk20a *f = &g->fifo; |
332 | struct fifo_engine_info_gk20a *engine_info = | 332 | u32 engine_id; |
333 | f->engine_info + ENGINE_GR_GK20A; | 333 | struct fifo_engine_info_gk20a *engine_info = NULL; |
334 | u32 inst_ptr = gk20a_mm_inst_block_addr(g, &c->inst_block) | 334 | u32 inst_ptr = gk20a_mm_inst_block_addr(g, &c->inst_block) |
335 | >> ram_in_base_shift_v(); | 335 | >> ram_in_base_shift_v(); |
336 | 336 | ||
337 | /* TODO:Need to handle non GR engine channel bind path */ | ||
338 | engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
339 | |||
340 | /* Consider 1st available GR engine */ | ||
341 | engine_info = (f->engine_info + engine_id); | ||
342 | |||
337 | gk20a_dbg_info("bind channel %d inst ptr 0x%08x", | 343 | gk20a_dbg_info("bind channel %d inst ptr 0x%08x", |
338 | c->hw_chid, inst_ptr); | 344 | c->hw_chid, inst_ptr); |
339 | 345 | ||
@@ -1716,7 +1722,7 @@ static void gk20a_channel_timeout_handler(struct work_struct *work) | |||
1716 | /* Get failing engine data */ | 1722 | /* Get failing engine data */ |
1717 | engine_id = gk20a_fifo_get_failing_engine_data(g, &id, &is_tsg); | 1723 | engine_id = gk20a_fifo_get_failing_engine_data(g, &id, &is_tsg); |
1718 | 1724 | ||
1719 | if (engine_id >= g->fifo.max_engines) { | 1725 | if (!gk20a_fifo_is_valid_engine_id(g, engine_id)) { |
1720 | /* If no failing engine, abort the channels */ | 1726 | /* If no failing engine, abort the channels */ |
1721 | if (gk20a_is_channel_marked_as_tsg(ch)) { | 1727 | if (gk20a_is_channel_marked_as_tsg(ch)) { |
1722 | struct tsg_gk20a *tsg = &g->fifo.tsg[ch->tsgid]; | 1728 | struct tsg_gk20a *tsg = &g->fifo.tsg[ch->tsgid]; |
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c index 6b9238e9..5e57502e 100644 --- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | |||
@@ -1102,11 +1102,10 @@ static int dbg_set_powergate(struct dbg_session_gk20a *dbg_s, | |||
1102 | false); | 1102 | false); |
1103 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, | 1103 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, |
1104 | false); | 1104 | false); |
1105 | gr_gk20a_init_blcg_mode(g, BLCG_RUN, ENGINE_GR_GK20A); | ||
1106 | 1105 | ||
1106 | gr_gk20a_init_cg_mode(g, BLCG_MODE, BLCG_RUN); | ||
1107 | g->elcg_enabled = false; | 1107 | g->elcg_enabled = false; |
1108 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A); | 1108 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); |
1109 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A); | ||
1110 | 1109 | ||
1111 | } | 1110 | } |
1112 | 1111 | ||
@@ -1126,9 +1125,8 @@ static int dbg_set_powergate(struct dbg_session_gk20a *dbg_s, | |||
1126 | --g->dbg_powergating_disabled_refcount == 0) { | 1125 | --g->dbg_powergating_disabled_refcount == 0) { |
1127 | 1126 | ||
1128 | g->elcg_enabled = true; | 1127 | g->elcg_enabled = true; |
1129 | gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_CE2_GK20A); | 1128 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO); |
1130 | gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_GR_GK20A); | 1129 | gr_gk20a_init_cg_mode(g, BLCG_MODE, BLCG_AUTO); |
1131 | gr_gk20a_init_blcg_mode(g, BLCG_AUTO, ENGINE_GR_GK20A); | ||
1132 | 1130 | ||
1133 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, | 1131 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, |
1134 | g->slcg_enabled); | 1132 | g->slcg_enabled); |
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 17efe5ca..766ea749 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | |||
@@ -40,6 +40,131 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, | |||
40 | u32 hw_chid, bool add, | 40 | u32 hw_chid, bool add, |
41 | bool wait_for_finish); | 41 | bool wait_for_finish); |
42 | 42 | ||
43 | u32 gk20a_fifo_get_engine_ids(struct gk20a *g, | ||
44 | u32 engine_id[], u32 engine_id_sz, | ||
45 | u32 engine_enum) | ||
46 | { | ||
47 | struct fifo_gk20a *f = NULL; | ||
48 | u32 instance_cnt = 0; | ||
49 | u32 engine_id_idx; | ||
50 | u32 active_engine_id = 0; | ||
51 | struct fifo_engine_info_gk20a *info = NULL; | ||
52 | |||
53 | if (g && engine_id_sz && (engine_enum < ENGINE_INVAL_GK20A)) { | ||
54 | f = &g->fifo; | ||
55 | for (engine_id_idx = 0; engine_id_idx < f->num_engines; ++engine_id_idx) { | ||
56 | active_engine_id = f->active_engines_list[engine_id_idx]; | ||
57 | info = &f->engine_info[active_engine_id]; | ||
58 | |||
59 | if (info->engine_enum == engine_enum) { | ||
60 | if (instance_cnt < engine_id_sz) { | ||
61 | engine_id[instance_cnt] = active_engine_id; | ||
62 | ++instance_cnt; | ||
63 | } else { | ||
64 | gk20a_dbg_info("warning engine_id table sz is small %d", | ||
65 | engine_id_sz); | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | return instance_cnt; | ||
71 | } | ||
72 | |||
73 | struct fifo_engine_info_gk20a *gk20a_fifo_get_engine_info(struct gk20a *g, u32 engine_id) | ||
74 | { | ||
75 | struct fifo_gk20a *f = NULL; | ||
76 | u32 engine_id_idx; | ||
77 | struct fifo_engine_info_gk20a *info = NULL; | ||
78 | |||
79 | if (!g) | ||
80 | return info; | ||
81 | |||
82 | f = &g->fifo; | ||
83 | |||
84 | if (engine_id < f->max_engines) { | ||
85 | for (engine_id_idx = 0; engine_id_idx < f->num_engines; ++engine_id_idx) { | ||
86 | if (engine_id == f->active_engines_list[engine_id_idx]) { | ||
87 | info = &f->engine_info[engine_id]; | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | if (!info) | ||
94 | gk20a_err(g->dev, "engine_id is not in active list/invalid %d", engine_id); | ||
95 | |||
96 | return info; | ||
97 | } | ||
98 | |||
99 | bool gk20a_fifo_is_valid_engine_id(struct gk20a *g, u32 engine_id) | ||
100 | { | ||
101 | struct fifo_gk20a *f = NULL; | ||
102 | u32 engine_id_idx; | ||
103 | bool valid = false; | ||
104 | |||
105 | if (!g) | ||
106 | return valid; | ||
107 | |||
108 | f = &g->fifo; | ||
109 | |||
110 | if (engine_id < f->max_engines) { | ||
111 | for (engine_id_idx = 0; engine_id_idx < f->num_engines; ++engine_id_idx) { | ||
112 | if (engine_id == f->active_engines_list[engine_id_idx]) { | ||
113 | valid = true; | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | if (!valid) | ||
120 | gk20a_err(g->dev, "engine_id is not in active list/invalid %d", engine_id); | ||
121 | |||
122 | return valid; | ||
123 | } | ||
124 | |||
125 | u32 gk20a_fifo_get_gr_engine_id(struct gk20a *g) | ||
126 | { | ||
127 | u32 gr_engine_cnt = 0; | ||
128 | u32 gr_engine_id = FIFO_INVAL_ENGINE_ID; | ||
129 | |||
130 | /* Consider 1st available GR engine */ | ||
131 | gr_engine_cnt = gk20a_fifo_get_engine_ids(g, &gr_engine_id, | ||
132 | 1, ENGINE_GR_GK20A); | ||
133 | |||
134 | if (!gr_engine_cnt) { | ||
135 | gk20a_err(dev_from_gk20a(g), "No GR engine available on this device!\n"); | ||
136 | } | ||
137 | |||
138 | return gr_engine_id; | ||
139 | } | ||
140 | |||
141 | u32 gk20a_fifo_get_all_ce_engine_reset_mask(struct gk20a *g) | ||
142 | { | ||
143 | u32 reset_mask = 0; | ||
144 | u32 engine_enum = ENGINE_INVAL_GK20A; | ||
145 | struct fifo_gk20a *f = NULL; | ||
146 | u32 engine_id_idx; | ||
147 | struct fifo_engine_info_gk20a *engine_info; | ||
148 | u32 active_engine_id = 0; | ||
149 | |||
150 | if (!g) | ||
151 | return reset_mask; | ||
152 | |||
153 | f = &g->fifo; | ||
154 | |||
155 | for (engine_id_idx = 0; engine_id_idx < f->num_engines; ++engine_id_idx) { | ||
156 | active_engine_id = f->active_engines_list[engine_id_idx]; | ||
157 | engine_info = &f->engine_info[active_engine_id]; | ||
158 | engine_enum = engine_info->engine_enum; | ||
159 | |||
160 | if ((engine_enum == ENGINE_GRCE_GK20A) || | ||
161 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) | ||
162 | reset_mask |= engine_info->reset_mask; | ||
163 | } | ||
164 | |||
165 | return reset_mask; | ||
166 | } | ||
167 | |||
43 | /* | 168 | /* |
44 | * Link engine IDs to MMU IDs and vice versa. | 169 | * Link engine IDs to MMU IDs and vice versa. |
45 | */ | 170 | */ |
@@ -47,12 +172,14 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, | |||
47 | static inline u32 gk20a_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id) | 172 | static inline u32 gk20a_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id) |
48 | { | 173 | { |
49 | u32 fault_id = ~0; | 174 | u32 fault_id = ~0; |
175 | struct fifo_engine_info_gk20a *engine_info; | ||
50 | 176 | ||
51 | if (engine_id < ENGINE_INVAL_GK20A) { | 177 | engine_info = gk20a_fifo_get_engine_info(g, engine_id); |
52 | struct fifo_engine_info_gk20a *info = | ||
53 | &g->fifo.engine_info[engine_id]; | ||
54 | 178 | ||
55 | fault_id = info->fault_id; | 179 | if (engine_info) { |
180 | fault_id = engine_info->fault_id; | ||
181 | } else { | ||
182 | gk20a_err(g->dev, "engine_id is not in active list/invalid %d", engine_id); | ||
56 | } | 183 | } |
57 | return fault_id; | 184 | return fault_id; |
58 | } | 185 | } |
@@ -60,18 +187,19 @@ static inline u32 gk20a_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id) | |||
60 | static inline u32 gk20a_mmu_id_to_engine_id(struct gk20a *g, u32 fault_id) | 187 | static inline u32 gk20a_mmu_id_to_engine_id(struct gk20a *g, u32 fault_id) |
61 | { | 188 | { |
62 | u32 engine_id; | 189 | u32 engine_id; |
63 | u32 return_engine_id = ~0; | 190 | u32 active_engine_id; |
191 | struct fifo_engine_info_gk20a *engine_info; | ||
192 | struct fifo_gk20a *f = &g->fifo; | ||
64 | 193 | ||
65 | for (engine_id = 0; engine_id < ENGINE_INVAL_GK20A; engine_id++) { | 194 | for (engine_id = 0; engine_id < f->num_engines; engine_id++) { |
66 | struct fifo_engine_info_gk20a *info = | 195 | active_engine_id = f->active_engines_list[engine_id]; |
67 | &g->fifo.engine_info[engine_id]; | 196 | engine_info = &g->fifo.engine_info[active_engine_id]; |
68 | 197 | ||
69 | if (info->fault_id == fault_id) { | 198 | if (engine_info->fault_id == fault_id) |
70 | return_engine_id = engine_id; | ||
71 | break; | 199 | break; |
72 | } | 200 | active_engine_id = FIFO_INVAL_ENGINE_ID; |
73 | } | 201 | } |
74 | return return_engine_id; | 202 | return active_engine_id; |
75 | } | 203 | } |
76 | 204 | ||
77 | int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, | 205 | int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, |
@@ -82,10 +210,15 @@ int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, | |||
82 | gk20a_dbg_info("engine type %d", engine_type); | 210 | gk20a_dbg_info("engine type %d", engine_type); |
83 | if (engine_type == top_device_info_type_enum_graphics_v()) | 211 | if (engine_type == top_device_info_type_enum_graphics_v()) |
84 | ret = ENGINE_GR_GK20A; | 212 | ret = ENGINE_GR_GK20A; |
85 | else if (engine_type == top_device_info_type_enum_copy2_v()) { | 213 | else if ((engine_type >= top_device_info_type_enum_copy0_v()) && |
86 | ret = ENGINE_CE2_GK20A; | 214 | (engine_type <= top_device_info_type_enum_copy2_v())) { |
215 | /* Lets consider all the CE engine have separate runlist at this point | ||
216 | * We can identify the ENGINE_GRCE_GK20A type CE using runlist_id | ||
217 | * comparsion logic with GR runlist_id in init_engine_info() */ | ||
218 | ret = ENGINE_ASYNC_CE_GK20A; | ||
219 | /* inst_id starts from CE0 to CE2 */ | ||
87 | if (inst_id) | 220 | if (inst_id) |
88 | *inst_id = 0x2; | 221 | *inst_id = (engine_type - top_device_info_type_enum_copy0_v()); |
89 | } | 222 | } |
90 | else | 223 | else |
91 | gk20a_err(g->dev, "unknown engine %d", engine_type); | 224 | gk20a_err(g->dev, "unknown engine %d", engine_type); |
@@ -108,12 +241,11 @@ static int init_engine_info(struct fifo_gk20a *f) | |||
108 | u32 inst_id = 0; | 241 | u32 inst_id = 0; |
109 | u32 pri_base = 0; | 242 | u32 pri_base = 0; |
110 | u32 fault_id = 0; | 243 | u32 fault_id = 0; |
244 | u32 gr_runlist_id = ~0; | ||
111 | 245 | ||
112 | gk20a_dbg_fn(""); | 246 | gk20a_dbg_fn(""); |
113 | 247 | ||
114 | /* all we really care about finding is the graphics entry */ | 248 | f->num_engines = 0; |
115 | /* especially early on in sim it probably thinks it has more */ | ||
116 | f->num_engines = 2; | ||
117 | 249 | ||
118 | for (i = 0; i < max_info_entries; i++) { | 250 | for (i = 0; i < max_info_entries; i++) { |
119 | u32 table_entry = gk20a_readl(f->g, top_device_info_r(i)); | 251 | u32 table_entry = gk20a_readl(f->g, top_device_info_r(i)); |
@@ -168,8 +300,7 @@ static int init_engine_info(struct fifo_gk20a *f) | |||
168 | g->ops.fifo.engine_enum_from_type(g, | 300 | g->ops.fifo.engine_enum_from_type(g, |
169 | engine_type, &inst_id); | 301 | engine_type, &inst_id); |
170 | } else if (entry == top_device_info_entry_data_v()) { | 302 | } else if (entry == top_device_info_entry_data_v()) { |
171 | /* gk20a don't support device_info_data | 303 | /* gk20a doesn't support device_info_data packet parsing */ |
172 | packet parsing */ | ||
173 | if (g->ops.fifo.device_info_data_parse) | 304 | if (g->ops.fifo.device_info_data_parse) |
174 | g->ops.fifo.device_info_data_parse(g, | 305 | g->ops.fifo.device_info_data_parse(g, |
175 | table_entry, &inst_id, &pri_base, | 306 | table_entry, &inst_id, &pri_base, |
@@ -179,7 +310,7 @@ static int init_engine_info(struct fifo_gk20a *f) | |||
179 | if (!top_device_info_chain_v(table_entry)) { | 310 | if (!top_device_info_chain_v(table_entry)) { |
180 | if (engine_enum < ENGINE_INVAL_GK20A) { | 311 | if (engine_enum < ENGINE_INVAL_GK20A) { |
181 | struct fifo_engine_info_gk20a *info = | 312 | struct fifo_engine_info_gk20a *info = |
182 | &g->fifo.engine_info[engine_enum]; | 313 | &g->fifo.engine_info[engine_id]; |
183 | 314 | ||
184 | info->intr_mask |= BIT(intr_id); | 315 | info->intr_mask |= BIT(intr_id); |
185 | info->reset_mask |= BIT(reset_id); | 316 | info->reset_mask |= BIT(reset_id); |
@@ -188,11 +319,25 @@ static int init_engine_info(struct fifo_gk20a *f) | |||
188 | info->inst_id = inst_id; | 319 | info->inst_id = inst_id; |
189 | info->pri_base = pri_base; | 320 | info->pri_base = pri_base; |
190 | 321 | ||
191 | if (!fault_id && | 322 | if (engine_enum == ENGINE_GR_GK20A) |
192 | (engine_enum == ENGINE_CE2_GK20A)) | 323 | gr_runlist_id = runlist_id; |
324 | |||
325 | /* GR and GR_COPY shares same runlist_id */ | ||
326 | if ((engine_enum == ENGINE_ASYNC_CE_GK20A) && | ||
327 | (gr_runlist_id == runlist_id)) | ||
328 | engine_enum = ENGINE_GRCE_GK20A; | ||
329 | |||
330 | info->engine_enum = engine_enum; | ||
331 | |||
332 | if (!fault_id && (engine_enum == ENGINE_GRCE_GK20A)) | ||
193 | fault_id = 0x1b; | 333 | fault_id = 0x1b; |
194 | info->fault_id = fault_id; | 334 | info->fault_id = fault_id; |
195 | 335 | ||
336 | /* engine_id starts from 0 to NV_HOST_NUM_ENGINES */ | ||
337 | f->active_engines_list[f->num_engines] = engine_id; | ||
338 | |||
339 | ++f->num_engines; | ||
340 | |||
196 | engine_enum = ENGINE_INVAL_GK20A; | 341 | engine_enum = ENGINE_INVAL_GK20A; |
197 | } | 342 | } |
198 | } | 343 | } |
@@ -204,13 +349,19 @@ static int init_engine_info(struct fifo_gk20a *f) | |||
204 | u32 gk20a_fifo_engine_interrupt_mask(struct gk20a *g) | 349 | u32 gk20a_fifo_engine_interrupt_mask(struct gk20a *g) |
205 | { | 350 | { |
206 | u32 eng_intr_mask = 0; | 351 | u32 eng_intr_mask = 0; |
207 | int i = 0; | 352 | int i; |
353 | u32 active_engine_id = 0; | ||
354 | u32 engine_enum = ENGINE_INVAL_GK20A; | ||
208 | 355 | ||
209 | for (i = 0; i < g->fifo.max_engines; i++) { | 356 | for (i = 0; i < g->fifo.num_engines; i++) { |
210 | u32 intr_mask = g->fifo.engine_info[i].intr_mask; | 357 | u32 intr_mask; |
211 | if (i == ENGINE_CE2_GK20A && | 358 | active_engine_id = g->fifo.active_engines_list[i]; |
359 | intr_mask = g->fifo.engine_info[active_engine_id].intr_mask; | ||
360 | engine_enum = g->fifo.engine_info[active_engine_id].engine_enum; | ||
361 | if (((engine_enum == ENGINE_GRCE_GK20A) || | ||
362 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) && | ||
212 | (!g->ops.ce2.isr_stall || !g->ops.ce2.isr_nonstall)) | 363 | (!g->ops.ce2.isr_stall || !g->ops.ce2.isr_nonstall)) |
213 | continue; | 364 | continue; |
214 | 365 | ||
215 | eng_intr_mask |= intr_mask; | 366 | eng_intr_mask |= intr_mask; |
216 | } | 367 | } |
@@ -218,13 +369,44 @@ u32 gk20a_fifo_engine_interrupt_mask(struct gk20a *g) | |||
218 | return eng_intr_mask; | 369 | return eng_intr_mask; |
219 | } | 370 | } |
220 | 371 | ||
372 | void gk20a_fifo_delete_runlist(struct fifo_gk20a *f) | ||
373 | { | ||
374 | u32 i; | ||
375 | u32 runlist_id; | ||
376 | struct fifo_runlist_info_gk20a *runlist; | ||
377 | struct gk20a *g = NULL; | ||
378 | |||
379 | if (!f || !f->runlist_info) | ||
380 | return; | ||
381 | |||
382 | g = f->g; | ||
383 | |||
384 | for (runlist_id = 0; runlist_id < f->max_runlists; runlist_id++) { | ||
385 | runlist = &f->runlist_info[runlist_id]; | ||
386 | for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) { | ||
387 | gk20a_gmmu_free(g, &runlist->mem[i]); | ||
388 | } | ||
389 | |||
390 | kfree(runlist->active_channels); | ||
391 | runlist->active_channels = NULL; | ||
392 | |||
393 | kfree(runlist->active_tsgs); | ||
394 | runlist->active_tsgs = NULL; | ||
395 | |||
396 | mutex_destroy(&runlist->mutex); | ||
397 | |||
398 | } | ||
399 | memset(f->runlist_info, 0, (sizeof(struct fifo_runlist_info_gk20a) * | ||
400 | f->max_runlists)); | ||
401 | |||
402 | kfree(f->runlist_info); | ||
403 | f->runlist_info = NULL; | ||
404 | f->max_runlists = 0; | ||
405 | } | ||
406 | |||
221 | static void gk20a_remove_fifo_support(struct fifo_gk20a *f) | 407 | static void gk20a_remove_fifo_support(struct fifo_gk20a *f) |
222 | { | 408 | { |
223 | struct gk20a *g = f->g; | 409 | struct gk20a *g = f->g; |
224 | struct fifo_engine_info_gk20a *engine_info; | ||
225 | struct fifo_runlist_info_gk20a *runlist; | ||
226 | u32 runlist_id; | ||
227 | u32 i; | ||
228 | 410 | ||
229 | gk20a_dbg_fn(""); | 411 | gk20a_dbg_fn(""); |
230 | 412 | ||
@@ -232,19 +414,14 @@ static void gk20a_remove_fifo_support(struct fifo_gk20a *f) | |||
232 | vfree(f->tsg); | 414 | vfree(f->tsg); |
233 | gk20a_gmmu_unmap_free(&g->mm.bar1.vm, &f->userd); | 415 | gk20a_gmmu_unmap_free(&g->mm.bar1.vm, &f->userd); |
234 | 416 | ||
235 | engine_info = f->engine_info + ENGINE_GR_GK20A; | 417 | gk20a_fifo_delete_runlist(f); |
236 | runlist_id = engine_info->runlist_id; | ||
237 | runlist = &f->runlist_info[runlist_id]; | ||
238 | |||
239 | for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) | ||
240 | gk20a_gmmu_free(g, &runlist->mem[i]); | ||
241 | 418 | ||
242 | kfree(runlist->active_channels); | ||
243 | kfree(runlist->active_tsgs); | ||
244 | |||
245 | kfree(f->runlist_info); | ||
246 | kfree(f->pbdma_map); | 419 | kfree(f->pbdma_map); |
420 | f->pbdma_map = NULL; | ||
247 | kfree(f->engine_info); | 421 | kfree(f->engine_info); |
422 | f->engine_info = NULL; | ||
423 | kfree(f->active_engines_list); | ||
424 | f->active_engines_list = NULL; | ||
248 | } | 425 | } |
249 | 426 | ||
250 | /* reads info from hardware and fills in pbmda exception info record */ | 427 | /* reads info from hardware and fills in pbmda exception info record */ |
@@ -327,69 +504,58 @@ static void fifo_engine_exception_status(struct gk20a *g, | |||
327 | 504 | ||
328 | static int init_runlist(struct gk20a *g, struct fifo_gk20a *f) | 505 | static int init_runlist(struct gk20a *g, struct fifo_gk20a *f) |
329 | { | 506 | { |
330 | struct fifo_engine_info_gk20a *engine_info; | ||
331 | struct fifo_runlist_info_gk20a *runlist; | 507 | struct fifo_runlist_info_gk20a *runlist; |
332 | struct device *d = dev_from_gk20a(g); | 508 | struct device *d = dev_from_gk20a(g); |
333 | u32 runlist_id; | 509 | s32 runlist_id = -1; |
334 | u32 i; | 510 | u32 i; |
335 | u64 runlist_size; | 511 | u64 runlist_size; |
336 | 512 | ||
337 | gk20a_dbg_fn(""); | 513 | gk20a_dbg_fn(""); |
338 | 514 | ||
339 | f->max_runlists = fifo_eng_runlist_base__size_1_v(); | 515 | f->max_runlists = g->ops.fifo.eng_runlist_base_size(); |
340 | f->runlist_info = kzalloc(sizeof(struct fifo_runlist_info_gk20a) * | 516 | f->runlist_info = kzalloc(sizeof(struct fifo_runlist_info_gk20a) * |
341 | f->max_runlists, GFP_KERNEL); | 517 | f->max_runlists, GFP_KERNEL); |
342 | if (!f->runlist_info) | 518 | if (!f->runlist_info) |
343 | goto clean_up; | 519 | goto clean_up_runlist; |
344 | 520 | ||
345 | engine_info = f->engine_info + ENGINE_GR_GK20A; | 521 | memset(f->runlist_info, 0, (sizeof(struct fifo_runlist_info_gk20a) * |
346 | runlist_id = engine_info->runlist_id; | 522 | f->max_runlists)); |
347 | runlist = &f->runlist_info[runlist_id]; | ||
348 | 523 | ||
349 | runlist->active_channels = | 524 | for (runlist_id = 0; runlist_id < f->max_runlists; runlist_id++) { |
350 | kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE), | 525 | runlist = &f->runlist_info[runlist_id]; |
351 | GFP_KERNEL); | 526 | |
352 | if (!runlist->active_channels) | 527 | runlist->active_channels = |
353 | goto clean_up_runlist_info; | 528 | kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE), |
354 | 529 | GFP_KERNEL); | |
355 | runlist->active_tsgs = | 530 | if (!runlist->active_channels) |
356 | kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE), | ||
357 | GFP_KERNEL); | ||
358 | if (!runlist->active_tsgs) | ||
359 | goto clean_up_runlist_info; | ||
360 | |||
361 | runlist_size = ram_rl_entry_size_v() * f->num_runlist_entries; | ||
362 | for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) { | ||
363 | int err = gk20a_gmmu_alloc(g, runlist_size, &runlist->mem[i]); | ||
364 | if (err) { | ||
365 | dev_err(d, "memory allocation failed\n"); | ||
366 | goto clean_up_runlist; | 531 | goto clean_up_runlist; |
532 | |||
533 | runlist->active_tsgs = | ||
534 | kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE), | ||
535 | GFP_KERNEL); | ||
536 | if (!runlist->active_tsgs) | ||
537 | goto clean_up_runlist; | ||
538 | |||
539 | runlist_size = ram_rl_entry_size_v() * f->num_runlist_entries; | ||
540 | for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) { | ||
541 | int err = gk20a_gmmu_alloc(g, runlist_size, &runlist->mem[i]); | ||
542 | if (err) { | ||
543 | dev_err(d, "memory allocation failed\n"); | ||
544 | goto clean_up_runlist; | ||
545 | } | ||
367 | } | 546 | } |
368 | } | 547 | mutex_init(&runlist->mutex); |
369 | mutex_init(&runlist->mutex); | ||
370 | 548 | ||
371 | /* None of buffers is pinned if this value doesn't change. | 549 | /* None of buffers is pinned if this value doesn't change. |
372 | Otherwise, one of them (cur_buffer) must have been pinned. */ | 550 | Otherwise, one of them (cur_buffer) must have been pinned. */ |
373 | runlist->cur_buffer = MAX_RUNLIST_BUFFERS; | 551 | runlist->cur_buffer = MAX_RUNLIST_BUFFERS; |
552 | } | ||
374 | 553 | ||
375 | gk20a_dbg_fn("done"); | 554 | gk20a_dbg_fn("done"); |
376 | return 0; | 555 | return 0; |
377 | 556 | ||
378 | clean_up_runlist: | 557 | clean_up_runlist: |
379 | for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) | 558 | gk20a_fifo_delete_runlist(f); |
380 | gk20a_gmmu_free(g, &runlist->mem[i]); | ||
381 | |||
382 | clean_up_runlist_info: | ||
383 | kfree(runlist->active_channels); | ||
384 | runlist->active_channels = NULL; | ||
385 | |||
386 | kfree(runlist->active_tsgs); | ||
387 | runlist->active_tsgs = NULL; | ||
388 | |||
389 | kfree(f->runlist_info); | ||
390 | f->runlist_info = NULL; | ||
391 | |||
392 | clean_up: | ||
393 | gk20a_dbg_fn("fail"); | 559 | gk20a_dbg_fn("fail"); |
394 | return -ENOMEM; | 560 | return -ENOMEM; |
395 | } | 561 | } |
@@ -543,7 +709,7 @@ static int gk20a_init_fifo_setup_sw(struct gk20a *g) | |||
543 | f->num_channels = g->ops.fifo.get_num_fifos(g); | 709 | f->num_channels = g->ops.fifo.get_num_fifos(g); |
544 | f->num_runlist_entries = fifo_eng_runlist_length_max_v(); | 710 | f->num_runlist_entries = fifo_eng_runlist_length_max_v(); |
545 | f->num_pbdma = nvgpu_get_litter_value(g, GPU_LIT_HOST_NUM_PBDMA); | 711 | f->num_pbdma = nvgpu_get_litter_value(g, GPU_LIT_HOST_NUM_PBDMA); |
546 | f->max_engines = ENGINE_INVAL_GK20A; | 712 | f->max_engines = nvgpu_get_litter_value(g, GPU_LIT_HOST_NUM_ENGINES); |
547 | 713 | ||
548 | f->userd_entry_size = 1 << ram_userd_base_shift_v(); | 714 | f->userd_entry_size = 1 << ram_userd_base_shift_v(); |
549 | 715 | ||
@@ -563,11 +729,15 @@ static int gk20a_init_fifo_setup_sw(struct gk20a *g) | |||
563 | GFP_KERNEL); | 729 | GFP_KERNEL); |
564 | f->engine_info = kzalloc(f->max_engines * sizeof(*f->engine_info), | 730 | f->engine_info = kzalloc(f->max_engines * sizeof(*f->engine_info), |
565 | GFP_KERNEL); | 731 | GFP_KERNEL); |
732 | f->active_engines_list = kzalloc(f->max_engines * sizeof(u32), | ||
733 | GFP_KERNEL); | ||
566 | 734 | ||
567 | if (!(f->channel && f->pbdma_map && f->engine_info)) { | 735 | if (!(f->channel && f->pbdma_map && f->engine_info && |
736 | f->active_engines_list)) { | ||
568 | err = -ENOMEM; | 737 | err = -ENOMEM; |
569 | goto clean_up; | 738 | goto clean_up; |
570 | } | 739 | } |
740 | memset(f->active_engines_list, 0xff, (f->max_engines * sizeof(u32))); | ||
571 | 741 | ||
572 | /* pbdma map needs to be in place before calling engine info init */ | 742 | /* pbdma map needs to be in place before calling engine info init */ |
573 | for (i = 0; i < f->num_pbdma; ++i) | 743 | for (i = 0; i < f->num_pbdma; ++i) |
@@ -614,6 +784,8 @@ clean_up: | |||
614 | f->pbdma_map = NULL; | 784 | f->pbdma_map = NULL; |
615 | kfree(f->engine_info); | 785 | kfree(f->engine_info); |
616 | f->engine_info = NULL; | 786 | f->engine_info = NULL; |
787 | kfree(f->active_engines_list); | ||
788 | f->active_engines_list = NULL; | ||
617 | 789 | ||
618 | return err; | 790 | return err; |
619 | } | 791 | } |
@@ -829,9 +1001,29 @@ static inline void get_exception_mmu_fault_info( | |||
829 | 1001 | ||
830 | void gk20a_fifo_reset_engine(struct gk20a *g, u32 engine_id) | 1002 | void gk20a_fifo_reset_engine(struct gk20a *g, u32 engine_id) |
831 | { | 1003 | { |
1004 | struct fifo_gk20a *f = NULL; | ||
1005 | u32 engine_enum = ENGINE_INVAL_GK20A; | ||
1006 | u32 inst_id = 0; | ||
1007 | struct fifo_engine_info_gk20a *engine_info; | ||
1008 | |||
832 | gk20a_dbg_fn(""); | 1009 | gk20a_dbg_fn(""); |
833 | 1010 | ||
834 | if (engine_id == ENGINE_GR_GK20A) { | 1011 | if (!g) |
1012 | return; | ||
1013 | |||
1014 | f = &g->fifo; | ||
1015 | |||
1016 | engine_info = gk20a_fifo_get_engine_info(g, engine_id); | ||
1017 | |||
1018 | if (engine_info) { | ||
1019 | engine_enum = engine_info->engine_enum; | ||
1020 | inst_id = engine_info->inst_id; | ||
1021 | } | ||
1022 | |||
1023 | if (engine_enum == ENGINE_INVAL_GK20A) | ||
1024 | gk20a_err(dev_from_gk20a(g), "unsupported engine_id %d", engine_id); | ||
1025 | |||
1026 | if (engine_enum == ENGINE_GR_GK20A) { | ||
835 | if (support_gk20a_pmu(g->dev) && g->elpg_enabled) | 1027 | if (support_gk20a_pmu(g->dev) && g->elpg_enabled) |
836 | gk20a_pmu_disable_elpg(g); | 1028 | gk20a_pmu_disable_elpg(g); |
837 | /* resetting engine will alter read/write index. | 1029 | /* resetting engine will alter read/write index. |
@@ -848,8 +1040,10 @@ void gk20a_fifo_reset_engine(struct gk20a *g, u32 engine_id) | |||
848 | if (support_gk20a_pmu(g->dev) && g->elpg_enabled) | 1040 | if (support_gk20a_pmu(g->dev) && g->elpg_enabled) |
849 | gk20a_pmu_enable_elpg(g); | 1041 | gk20a_pmu_enable_elpg(g); |
850 | } | 1042 | } |
851 | if (engine_id == ENGINE_CE2_GK20A) | 1043 | if ((engine_enum == ENGINE_GRCE_GK20A) || |
852 | gk20a_reset(g, mc_enable_ce2_m()); | 1044 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) { |
1045 | gk20a_reset(g, engine_info->reset_mask); | ||
1046 | } | ||
853 | } | 1047 | } |
854 | 1048 | ||
855 | static void gk20a_fifo_handle_chsw_fault(struct gk20a *g) | 1049 | static void gk20a_fifo_handle_chsw_fault(struct gk20a *g) |
@@ -872,6 +1066,24 @@ static void gk20a_fifo_handle_dropped_mmu_fault(struct gk20a *g) | |||
872 | static bool gk20a_fifo_should_defer_engine_reset(struct gk20a *g, u32 engine_id, | 1066 | static bool gk20a_fifo_should_defer_engine_reset(struct gk20a *g, u32 engine_id, |
873 | struct fifo_mmu_fault_info_gk20a *f, bool fake_fault) | 1067 | struct fifo_mmu_fault_info_gk20a *f, bool fake_fault) |
874 | { | 1068 | { |
1069 | u32 engine_enum = ENGINE_INVAL_GK20A; | ||
1070 | struct fifo_gk20a *fifo = NULL; | ||
1071 | struct fifo_engine_info_gk20a *engine_info; | ||
1072 | |||
1073 | if (!g || !f) | ||
1074 | return false; | ||
1075 | |||
1076 | fifo = &g->fifo; | ||
1077 | |||
1078 | engine_info = gk20a_fifo_get_engine_info(g, engine_id); | ||
1079 | |||
1080 | if (engine_info) { | ||
1081 | engine_enum = engine_info->engine_enum; | ||
1082 | } | ||
1083 | |||
1084 | if (engine_enum == ENGINE_INVAL_GK20A) | ||
1085 | return false; | ||
1086 | |||
875 | /* channel recovery is only deferred if an sm debugger | 1087 | /* channel recovery is only deferred if an sm debugger |
876 | is attached and has MMU debug mode is enabled */ | 1088 | is attached and has MMU debug mode is enabled */ |
877 | if (!gk20a_gr_sm_debugger_attached(g) || | 1089 | if (!gk20a_gr_sm_debugger_attached(g) || |
@@ -882,7 +1094,7 @@ static bool gk20a_fifo_should_defer_engine_reset(struct gk20a *g, u32 engine_id, | |||
882 | if (fake_fault) | 1094 | if (fake_fault) |
883 | return false; | 1095 | return false; |
884 | 1096 | ||
885 | if (engine_id != ENGINE_GR_GK20A || | 1097 | if (engine_enum != ENGINE_GR_GK20A || |
886 | f->engine_subid_v != fifo_intr_mmu_fault_info_engine_subid_gpc_v()) | 1098 | f->engine_subid_v != fifo_intr_mmu_fault_info_engine_subid_gpc_v()) |
887 | return false; | 1099 | return false; |
888 | 1100 | ||
@@ -1001,8 +1213,8 @@ static bool gk20a_fifo_handle_mmu_fault( | |||
1001 | false); | 1213 | false); |
1002 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, | 1214 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, |
1003 | false); | 1215 | false); |
1004 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A); | 1216 | |
1005 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A); | 1217 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); |
1006 | 1218 | ||
1007 | /* Disable fifo access */ | 1219 | /* Disable fifo access */ |
1008 | grfifo_ctl = gk20a_readl(g, gr_gpfifo_ctl_r()); | 1220 | grfifo_ctl = gk20a_readl(g, gr_gpfifo_ctl_r()); |
@@ -1219,7 +1431,7 @@ static void gk20a_fifo_trigger_mmu_fault(struct gk20a *g, | |||
1219 | 1431 | ||
1220 | /* trigger faults for all bad engines */ | 1432 | /* trigger faults for all bad engines */ |
1221 | for_each_set_bit(engine_id, &engine_ids, 32) { | 1433 | for_each_set_bit(engine_id, &engine_ids, 32) { |
1222 | if (engine_id > g->fifo.max_engines) { | 1434 | if (!gk20a_fifo_is_valid_engine_id(g, engine_id)) { |
1223 | WARN_ON(true); | 1435 | WARN_ON(true); |
1224 | break; | 1436 | break; |
1225 | } | 1437 | } |
@@ -1257,8 +1469,9 @@ static u32 gk20a_fifo_engines_on_id(struct gk20a *g, u32 id, bool is_tsg) | |||
1257 | int i; | 1469 | int i; |
1258 | u32 engines = 0; | 1470 | u32 engines = 0; |
1259 | 1471 | ||
1260 | for (i = 0; i < g->fifo.max_engines; i++) { | 1472 | for (i = 0; i < g->fifo.num_engines; i++) { |
1261 | u32 status = gk20a_readl(g, fifo_engine_status_r(i)); | 1473 | u32 active_engine_id = g->fifo.active_engines_list[i]; |
1474 | u32 status = gk20a_readl(g, fifo_engine_status_r(active_engine_id)); | ||
1262 | u32 ctx_status = | 1475 | u32 ctx_status = |
1263 | fifo_engine_status_ctx_status_v(status); | 1476 | fifo_engine_status_ctx_status_v(status); |
1264 | u32 ctx_id = (ctx_status == | 1477 | u32 ctx_id = (ctx_status == |
@@ -1276,7 +1489,7 @@ static u32 gk20a_fifo_engines_on_id(struct gk20a *g, u32 id, bool is_tsg) | |||
1276 | fifo_engine_status_id_type_tsgid_v()) || | 1489 | fifo_engine_status_id_type_tsgid_v()) || |
1277 | (!is_tsg && type == | 1490 | (!is_tsg && type == |
1278 | fifo_engine_status_id_type_chid_v())) | 1491 | fifo_engine_status_id_type_chid_v())) |
1279 | engines |= BIT(i); | 1492 | engines |= BIT(active_engine_id); |
1280 | } | 1493 | } |
1281 | } | 1494 | } |
1282 | 1495 | ||
@@ -1382,15 +1595,16 @@ void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids, | |||
1382 | ref_id_is_tsg = false; | 1595 | ref_id_is_tsg = false; |
1383 | /* Reset *all* engines that use the | 1596 | /* Reset *all* engines that use the |
1384 | * same channel as faulty engine */ | 1597 | * same channel as faulty engine */ |
1385 | for (i = 0; i < g->fifo.max_engines; i++) { | 1598 | for (i = 0; i < g->fifo.num_engines; i++) { |
1599 | u32 active_engine_id = g->fifo.active_engines_list[i]; | ||
1386 | u32 type; | 1600 | u32 type; |
1387 | u32 id; | 1601 | u32 id; |
1388 | 1602 | ||
1389 | gk20a_fifo_get_faulty_id_type(g, i, &id, &type); | 1603 | gk20a_fifo_get_faulty_id_type(g, active_engine_id, &id, &type); |
1390 | if (ref_type == type && ref_id == id) { | 1604 | if (ref_type == type && ref_id == id) { |
1391 | engine_ids |= BIT(i); | 1605 | engine_ids |= BIT(active_engine_id); |
1392 | mmu_fault_engines |= | 1606 | mmu_fault_engines |= |
1393 | BIT(gk20a_engine_id_to_mmu_id(g, i)); | 1607 | BIT(gk20a_engine_id_to_mmu_id(g, active_engine_id)); |
1394 | } | 1608 | } |
1395 | } | 1609 | } |
1396 | } | 1610 | } |
@@ -1453,16 +1667,21 @@ int gk20a_fifo_force_reset_ch(struct channel_gk20a *ch, bool verbose) | |||
1453 | u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g, | 1667 | u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g, |
1454 | int *__id, bool *__is_tsg) | 1668 | int *__id, bool *__is_tsg) |
1455 | { | 1669 | { |
1456 | u32 engine_id = -1; | 1670 | u32 engine_id; |
1457 | int id = -1; | 1671 | int id = -1; |
1458 | bool is_tsg = false; | 1672 | bool is_tsg = false; |
1459 | u32 mailbox2; | 1673 | u32 mailbox2; |
1674 | u32 active_engine_id = FIFO_INVAL_ENGINE_ID; | ||
1460 | 1675 | ||
1461 | for (engine_id = 0; engine_id < g->fifo.max_engines; engine_id++) { | 1676 | for (engine_id = 0; engine_id < g->fifo.num_engines; engine_id++) { |
1462 | u32 status = gk20a_readl(g, fifo_engine_status_r(engine_id)); | 1677 | u32 status; |
1463 | u32 ctx_status = fifo_engine_status_ctx_status_v(status); | 1678 | u32 ctx_status; |
1464 | bool failing_engine; | 1679 | bool failing_engine; |
1465 | 1680 | ||
1681 | active_engine_id = g->fifo.active_engines_list[engine_id]; | ||
1682 | status = gk20a_readl(g, fifo_engine_status_r(active_engine_id)); | ||
1683 | ctx_status = fifo_engine_status_ctx_status_v(status); | ||
1684 | |||
1466 | /* we are interested in busy engines */ | 1685 | /* we are interested in busy engines */ |
1467 | failing_engine = fifo_engine_status_engine_v(status) == | 1686 | failing_engine = fifo_engine_status_engine_v(status) == |
1468 | fifo_engine_status_engine_busy_v(); | 1687 | fifo_engine_status_engine_busy_v(); |
@@ -1476,8 +1695,10 @@ u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g, | |||
1476 | || ctx_status == | 1695 | || ctx_status == |
1477 | fifo_engine_status_ctx_status_ctxsw_load_v()); | 1696 | fifo_engine_status_ctx_status_ctxsw_load_v()); |
1478 | 1697 | ||
1479 | if (!failing_engine) | 1698 | if (!failing_engine) { |
1699 | active_engine_id = FIFO_INVAL_ENGINE_ID; | ||
1480 | continue; | 1700 | continue; |
1701 | } | ||
1481 | 1702 | ||
1482 | if (ctx_status == | 1703 | if (ctx_status == |
1483 | fifo_engine_status_ctx_status_ctxsw_load_v()) { | 1704 | fifo_engine_status_ctx_status_ctxsw_load_v()) { |
@@ -1500,7 +1721,7 @@ u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g, | |||
1500 | *__id = id; | 1721 | *__id = id; |
1501 | *__is_tsg = is_tsg; | 1722 | *__is_tsg = is_tsg; |
1502 | 1723 | ||
1503 | return engine_id; | 1724 | return active_engine_id; |
1504 | } | 1725 | } |
1505 | 1726 | ||
1506 | static bool gk20a_fifo_handle_sched_error(struct gk20a *g) | 1727 | static bool gk20a_fifo_handle_sched_error(struct gk20a *g) |
@@ -1517,7 +1738,7 @@ static bool gk20a_fifo_handle_sched_error(struct gk20a *g) | |||
1517 | engine_id = gk20a_fifo_get_failing_engine_data(g, &id, &is_tsg); | 1738 | engine_id = gk20a_fifo_get_failing_engine_data(g, &id, &is_tsg); |
1518 | 1739 | ||
1519 | /* could not find the engine - should never happen */ | 1740 | /* could not find the engine - should never happen */ |
1520 | if (unlikely(engine_id >= g->fifo.max_engines)) { | 1741 | if (!gk20a_fifo_is_valid_engine_id(g, engine_id)) { |
1521 | gk20a_err(dev_from_gk20a(g), "fifo sched error : 0x%08x, failed to find engine\n", | 1742 | gk20a_err(dev_from_gk20a(g), "fifo sched error : 0x%08x, failed to find engine\n", |
1522 | sched_error); | 1743 | sched_error); |
1523 | ret = false; | 1744 | ret = false; |
@@ -1627,14 +1848,16 @@ static u32 fifo_error_isr(struct gk20a *g, u32 fifo_intr) | |||
1627 | "channel reset initiated from %s; intr=0x%08x", | 1848 | "channel reset initiated from %s; intr=0x%08x", |
1628 | __func__, fifo_intr); | 1849 | __func__, fifo_intr); |
1629 | for (engine_id = 0; | 1850 | for (engine_id = 0; |
1630 | engine_id < g->fifo.max_engines; | 1851 | engine_id < g->fifo.num_engines; |
1631 | engine_id++) { | 1852 | engine_id++) { |
1632 | gk20a_dbg_fn("enum:%d -> engine_id:%d", engine_id, | 1853 | u32 active_engine_id = g->fifo.active_engines_list[engine_id]; |
1633 | g->fifo.engine_info[engine_id].engine_id); | 1854 | u32 engine_enum = g->fifo.engine_info[active_engine_id].engine_enum; |
1634 | fifo_pbdma_exception_status(g, | 1855 | gk20a_dbg_fn("enum:%d -> engine_id:%d", engine_enum, |
1635 | &g->fifo.engine_info[engine_id]); | 1856 | active_engine_id); |
1636 | fifo_engine_exception_status(g, | 1857 | fifo_pbdma_exception_status(g, |
1637 | &g->fifo.engine_info[engine_id]); | 1858 | &g->fifo.engine_info[active_engine_id]); |
1859 | fifo_engine_exception_status(g, | ||
1860 | &g->fifo.engine_info[active_engine_id]); | ||
1638 | } | 1861 | } |
1639 | } | 1862 | } |
1640 | 1863 | ||
@@ -2057,12 +2280,13 @@ int gk20a_fifo_enable_all_engine_activity(struct gk20a *g) | |||
2057 | int i; | 2280 | int i; |
2058 | int err = 0, ret = 0; | 2281 | int err = 0, ret = 0; |
2059 | 2282 | ||
2060 | for (i = 0; i < g->fifo.max_engines; i++) { | 2283 | for (i = 0; i < g->fifo.num_engines; i++) { |
2284 | u32 active_engine_id = g->fifo.active_engines_list[i]; | ||
2061 | err = gk20a_fifo_enable_engine_activity(g, | 2285 | err = gk20a_fifo_enable_engine_activity(g, |
2062 | &g->fifo.engine_info[i]); | 2286 | &g->fifo.engine_info[active_engine_id]); |
2063 | if (err) { | 2287 | if (err) { |
2064 | gk20a_err(dev_from_gk20a(g), | 2288 | gk20a_err(dev_from_gk20a(g), |
2065 | "failed to enable engine %d activity\n", i); | 2289 | "failed to enable engine %d activity\n", active_engine_id); |
2066 | ret = err; | 2290 | ret = err; |
2067 | } | 2291 | } |
2068 | } | 2292 | } |
@@ -2149,14 +2373,16 @@ int gk20a_fifo_disable_all_engine_activity(struct gk20a *g, | |||
2149 | { | 2373 | { |
2150 | int i; | 2374 | int i; |
2151 | int err = 0, ret = 0; | 2375 | int err = 0, ret = 0; |
2376 | u32 active_engine_id; | ||
2152 | 2377 | ||
2153 | for (i = 0; i < g->fifo.max_engines; i++) { | 2378 | for (i = 0; i < g->fifo.num_engines; i++) { |
2379 | active_engine_id = g->fifo.active_engines_list[i]; | ||
2154 | err = gk20a_fifo_disable_engine_activity(g, | 2380 | err = gk20a_fifo_disable_engine_activity(g, |
2155 | &g->fifo.engine_info[i], | 2381 | &g->fifo.engine_info[active_engine_id], |
2156 | wait_for_idle); | 2382 | wait_for_idle); |
2157 | if (err) { | 2383 | if (err) { |
2158 | gk20a_err(dev_from_gk20a(g), | 2384 | gk20a_err(dev_from_gk20a(g), |
2159 | "failed to disable engine %d activity\n", i); | 2385 | "failed to disable engine %d activity\n", active_engine_id); |
2160 | ret = err; | 2386 | ret = err; |
2161 | break; | 2387 | break; |
2162 | } | 2388 | } |
@@ -2164,11 +2390,12 @@ int gk20a_fifo_disable_all_engine_activity(struct gk20a *g, | |||
2164 | 2390 | ||
2165 | if (err) { | 2391 | if (err) { |
2166 | while (--i >= 0) { | 2392 | while (--i >= 0) { |
2393 | active_engine_id = g->fifo.active_engines_list[i]; | ||
2167 | err = gk20a_fifo_enable_engine_activity(g, | 2394 | err = gk20a_fifo_enable_engine_activity(g, |
2168 | &g->fifo.engine_info[i]); | 2395 | &g->fifo.engine_info[active_engine_id]); |
2169 | if (err) | 2396 | if (err) |
2170 | gk20a_err(dev_from_gk20a(g), | 2397 | gk20a_err(dev_from_gk20a(g), |
2171 | "failed to re-enable engine %d activity\n", i); | 2398 | "failed to re-enable engine %d activity\n", active_engine_id); |
2172 | } | 2399 | } |
2173 | } | 2400 | } |
2174 | 2401 | ||
@@ -2181,14 +2408,15 @@ static void gk20a_fifo_runlist_reset_engines(struct gk20a *g, u32 runlist_id) | |||
2181 | u32 engines = 0; | 2408 | u32 engines = 0; |
2182 | int i; | 2409 | int i; |
2183 | 2410 | ||
2184 | for (i = 0; i < f->max_engines; i++) { | 2411 | for (i = 0; i < f->num_engines; i++) { |
2185 | u32 status = gk20a_readl(g, fifo_engine_status_r(i)); | 2412 | u32 active_engine_id = g->fifo.active_engines_list[i]; |
2413 | u32 status = gk20a_readl(g, fifo_engine_status_r(active_engine_id)); | ||
2186 | bool engine_busy = fifo_engine_status_engine_v(status) == | 2414 | bool engine_busy = fifo_engine_status_engine_v(status) == |
2187 | fifo_engine_status_engine_busy_v(); | 2415 | fifo_engine_status_engine_busy_v(); |
2188 | 2416 | ||
2189 | if (engine_busy && | 2417 | if (engine_busy && |
2190 | (f->engine_info[i].runlist_id == runlist_id)) | 2418 | (f->engine_info[active_engine_id].runlist_id == runlist_id)) |
2191 | engines |= BIT(i); | 2419 | engines |= BIT(active_engine_id); |
2192 | } | 2420 | } |
2193 | 2421 | ||
2194 | if (engines) | 2422 | if (engines) |
@@ -2669,8 +2897,10 @@ static int gk20a_fifo_sched_debugfs_seq_show( | |||
2669 | struct fifo_runlist_info_gk20a *runlist; | 2897 | struct fifo_runlist_info_gk20a *runlist; |
2670 | u32 runlist_id; | 2898 | u32 runlist_id; |
2671 | int ret = SEQ_SKIP; | 2899 | int ret = SEQ_SKIP; |
2900 | u32 engine_id; | ||
2672 | 2901 | ||
2673 | engine_info = f->engine_info + ENGINE_GR_GK20A; | 2902 | engine_id = gk20a_fifo_get_gr_engine_id(g); |
2903 | engine_info = (f->engine_info + engine_id); | ||
2674 | runlist_id = engine_info->runlist_id; | 2904 | runlist_id = engine_info->runlist_id; |
2675 | runlist = &f->runlist_info[runlist_id]; | 2905 | runlist = &f->runlist_info[runlist_id]; |
2676 | 2906 | ||
@@ -2772,6 +3002,7 @@ void gk20a_init_fifo(struct gpu_ops *gops) | |||
2772 | gops->fifo.set_runlist_interleave = gk20a_fifo_set_runlist_interleave; | 3002 | gops->fifo.set_runlist_interleave = gk20a_fifo_set_runlist_interleave; |
2773 | gops->fifo.force_reset_ch = gk20a_fifo_force_reset_ch; | 3003 | gops->fifo.force_reset_ch = gk20a_fifo_force_reset_ch; |
2774 | gops->fifo.engine_enum_from_type = gk20a_fifo_engine_enum_from_type; | 3004 | gops->fifo.engine_enum_from_type = gk20a_fifo_engine_enum_from_type; |
2775 | /* gk20a don't support device_info_data packet parsing */ | 3005 | /* gk20a doesn't support device_info_data packet parsing */ |
2776 | gops->fifo.device_info_data_parse = NULL; | 3006 | gops->fifo.device_info_data_parse = NULL; |
3007 | gops->fifo.eng_runlist_base_size = fifo_eng_runlist_base__size_1_v; | ||
2777 | } | 3008 | } |
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index 5fb5f550..25d2cd9f 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | |||
@@ -26,6 +26,8 @@ | |||
26 | 26 | ||
27 | #define MAX_RUNLIST_BUFFERS 2 | 27 | #define MAX_RUNLIST_BUFFERS 2 |
28 | 28 | ||
29 | #define FIFO_INVAL_ENGINE_ID ~0 | ||
30 | |||
29 | /* generally corresponds to the "pbdma" engine */ | 31 | /* generally corresponds to the "pbdma" engine */ |
30 | 32 | ||
31 | struct fifo_runlist_info_gk20a { | 33 | struct fifo_runlist_info_gk20a { |
@@ -40,10 +42,10 @@ struct fifo_runlist_info_gk20a { | |||
40 | struct mutex mutex; /* protect channel preempt and runlist upate */ | 42 | struct mutex mutex; /* protect channel preempt and runlist upate */ |
41 | }; | 43 | }; |
42 | 44 | ||
43 | /* so far gk20a has two engines: gr and ce2(gr_copy) */ | ||
44 | enum { | 45 | enum { |
45 | ENGINE_GR_GK20A = 0, | 46 | ENGINE_GR_GK20A = 0, |
46 | ENGINE_CE2_GK20A = 1, | 47 | ENGINE_GRCE_GK20A = 1, |
48 | ENGINE_ASYNC_CE_GK20A = 2, | ||
47 | ENGINE_INVAL_GK20A | 49 | ENGINE_INVAL_GK20A |
48 | }; | 50 | }; |
49 | 51 | ||
@@ -85,6 +87,7 @@ struct fifo_engine_info_gk20a { | |||
85 | u32 inst_id; | 87 | u32 inst_id; |
86 | u32 pri_base; | 88 | u32 pri_base; |
87 | u32 fault_id; | 89 | u32 fault_id; |
90 | u32 engine_enum; | ||
88 | struct fifo_pbdma_exception_info_gk20a pbdma_exception_info; | 91 | struct fifo_pbdma_exception_info_gk20a pbdma_exception_info; |
89 | struct fifo_engine_exception_info_gk20a engine_exception_info; | 92 | struct fifo_engine_exception_info_gk20a engine_exception_info; |
90 | struct fifo_mmu_fault_info_gk20a mmu_fault_info; | 93 | struct fifo_mmu_fault_info_gk20a mmu_fault_info; |
@@ -102,6 +105,7 @@ struct fifo_gk20a { | |||
102 | struct fifo_engine_info_gk20a *engine_info; | 105 | struct fifo_engine_info_gk20a *engine_info; |
103 | u32 max_engines; | 106 | u32 max_engines; |
104 | u32 num_engines; | 107 | u32 num_engines; |
108 | u32 *active_engines_list; | ||
105 | 109 | ||
106 | struct fifo_runlist_info_gk20a *runlist_info; | 110 | struct fifo_runlist_info_gk20a *runlist_info; |
107 | u32 max_runlists; | 111 | u32 max_runlists; |
@@ -228,4 +232,15 @@ const char *gk20a_fifo_interleave_level_name(u32 interleave_level); | |||
228 | int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, | 232 | int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, |
229 | u32 *inst_id); | 233 | u32 *inst_id); |
230 | 234 | ||
235 | u32 gk20a_fifo_get_engine_ids(struct gk20a *g, u32 engine_id[], u32 engine_id_sz, u32 engine_enum); | ||
236 | |||
237 | void gk20a_fifo_delete_runlist(struct fifo_gk20a *f); | ||
238 | |||
239 | struct fifo_engine_info_gk20a *gk20a_fifo_get_engine_info(struct gk20a *g, u32 engine_id); | ||
240 | |||
241 | bool gk20a_fifo_is_valid_engine_id(struct gk20a *g, u32 engine_id); | ||
242 | |||
243 | u32 gk20a_fifo_get_gr_engine_id(struct gk20a *g); | ||
244 | |||
245 | u32 gk20a_fifo_get_all_ce_engine_reset_mask(struct gk20a *g); | ||
231 | #endif /*__GR_GK20A_H__*/ | 246 | #endif /*__GR_GK20A_H__*/ |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index a817abcd..d21d0527 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -1890,7 +1890,7 @@ void gk20a_enable(struct gk20a *g, u32 units) | |||
1890 | void gk20a_reset(struct gk20a *g, u32 units) | 1890 | void gk20a_reset(struct gk20a *g, u32 units) |
1891 | { | 1891 | { |
1892 | gk20a_disable(g, units); | 1892 | gk20a_disable(g, units); |
1893 | if (units & mc_enable_ce2_enabled_f()) | 1893 | if (units & gk20a_fifo_get_all_ce_engine_reset_mask(g)) |
1894 | udelay(500); | 1894 | udelay(500); |
1895 | else | 1895 | else |
1896 | udelay(20); | 1896 | udelay(20); |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 3da19cc8..b7f3f6f1 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -90,6 +90,7 @@ enum nvgpu_litter_value { | |||
90 | GPU_LIT_ROP_BASE, | 90 | GPU_LIT_ROP_BASE, |
91 | GPU_LIT_ROP_STRIDE, | 91 | GPU_LIT_ROP_STRIDE, |
92 | GPU_LIT_ROP_SHARED_BASE, | 92 | GPU_LIT_ROP_SHARED_BASE, |
93 | GPU_LIT_HOST_NUM_ENGINES, | ||
93 | GPU_LIT_HOST_NUM_PBDMA, | 94 | GPU_LIT_HOST_NUM_PBDMA, |
94 | GPU_LIT_LTC_STRIDE, | 95 | GPU_LIT_LTC_STRIDE, |
95 | GPU_LIT_LTS_STRIDE, | 96 | GPU_LIT_LTS_STRIDE, |
@@ -120,8 +121,8 @@ struct gpu_ops { | |||
120 | void (*flush)(struct gk20a *g); | 121 | void (*flush)(struct gk20a *g); |
121 | } ltc; | 122 | } ltc; |
122 | struct { | 123 | struct { |
123 | void (*isr_stall)(struct gk20a *g); | 124 | void (*isr_stall)(struct gk20a *g, u32 inst_id, u32 pri_base); |
124 | void (*isr_nonstall)(struct gk20a *g); | 125 | void (*isr_nonstall)(struct gk20a *g, u32 inst_id, u32 pri_base); |
125 | } ce2; | 126 | } ce2; |
126 | struct { | 127 | struct { |
127 | int (*init_fs_state)(struct gk20a *g); | 128 | int (*init_fs_state)(struct gk20a *g); |
@@ -350,6 +351,7 @@ struct gpu_ops { | |||
350 | int (*tsg_bind_channel)(struct tsg_gk20a *tsg, | 351 | int (*tsg_bind_channel)(struct tsg_gk20a *tsg, |
351 | struct channel_gk20a *ch); | 352 | struct channel_gk20a *ch); |
352 | int (*tsg_unbind_channel)(struct channel_gk20a *ch); | 353 | int (*tsg_unbind_channel)(struct channel_gk20a *ch); |
354 | u32 (*eng_runlist_base_size)(void); | ||
353 | } fifo; | 355 | } fifo; |
354 | struct pmu_v { | 356 | struct pmu_v { |
355 | /*used for change of enum zbc update cmd id from ver 0 to ver1*/ | 357 | /*used for change of enum zbc update cmd id from ver 0 to ver1*/ |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c index 0c94e246..6784cd11 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a_sysfs.c | |||
@@ -50,13 +50,12 @@ static ssize_t elcg_enable_store(struct device *dev, | |||
50 | 50 | ||
51 | if (val) { | 51 | if (val) { |
52 | g->elcg_enabled = true; | 52 | g->elcg_enabled = true; |
53 | gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_GR_GK20A); | 53 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO); |
54 | gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_CE2_GK20A); | ||
55 | } else { | 54 | } else { |
56 | g->elcg_enabled = false; | 55 | g->elcg_enabled = false; |
57 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A); | 56 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); |
58 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A); | ||
59 | } | 57 | } |
58 | |||
60 | gk20a_idle(g->dev); | 59 | gk20a_idle(g->dev); |
61 | 60 | ||
62 | dev_info(dev, "ELCG is %s.\n", g->elcg_enabled ? "enabled" : | 61 | dev_info(dev, "ELCG is %s.\n", g->elcg_enabled ? "enabled" : |
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 17307b63..fb777948 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c | |||
@@ -326,9 +326,12 @@ int gr_gk20a_wait_idle(struct gk20a *g, unsigned long end_jiffies, | |||
326 | bool gr_enabled; | 326 | bool gr_enabled; |
327 | bool ctxsw_active; | 327 | bool ctxsw_active; |
328 | bool gr_busy; | 328 | bool gr_busy; |
329 | u32 gr_engine_id; | ||
329 | 330 | ||
330 | gk20a_dbg_fn(""); | 331 | gk20a_dbg_fn(""); |
331 | 332 | ||
333 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
334 | |||
332 | do { | 335 | do { |
333 | /* fmodel: host gets fifo_engine_status(gr) from gr | 336 | /* fmodel: host gets fifo_engine_status(gr) from gr |
334 | only when gr_status is read */ | 337 | only when gr_status is read */ |
@@ -338,7 +341,7 @@ int gr_gk20a_wait_idle(struct gk20a *g, unsigned long end_jiffies, | |||
338 | mc_enable_pgraph_enabled_f(); | 341 | mc_enable_pgraph_enabled_f(); |
339 | 342 | ||
340 | ctxsw_active = gk20a_readl(g, | 343 | ctxsw_active = gk20a_readl(g, |
341 | fifo_engine_status_r(ENGINE_GR_GK20A)) & | 344 | fifo_engine_status_r(gr_engine_id)) & |
342 | fifo_engine_status_ctxsw_in_progress_f(); | 345 | fifo_engine_status_ctxsw_in_progress_f(); |
343 | 346 | ||
344 | gr_busy = gk20a_readl(g, gr_engine_status_r()) & | 347 | gr_busy = gk20a_readl(g, gr_engine_status_r()) & |
@@ -3905,11 +3908,14 @@ int gr_gk20a_add_zbc_depth(struct gk20a *g, struct gr_gk20a *gr, | |||
3905 | void gr_gk20a_pmu_save_zbc(struct gk20a *g, u32 entries) | 3908 | void gr_gk20a_pmu_save_zbc(struct gk20a *g, u32 entries) |
3906 | { | 3909 | { |
3907 | struct fifo_gk20a *f = &g->fifo; | 3910 | struct fifo_gk20a *f = &g->fifo; |
3908 | struct fifo_engine_info_gk20a *gr_info = | 3911 | struct fifo_engine_info_gk20a *gr_info = NULL; |
3909 | f->engine_info + ENGINE_GR_GK20A; | ||
3910 | unsigned long end_jiffies = jiffies + | 3912 | unsigned long end_jiffies = jiffies + |
3911 | msecs_to_jiffies(gk20a_get_gr_idle_timeout(g)); | 3913 | msecs_to_jiffies(gk20a_get_gr_idle_timeout(g)); |
3912 | u32 ret; | 3914 | u32 ret; |
3915 | u32 engine_id; | ||
3916 | |||
3917 | engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
3918 | gr_info = (f->engine_info + engine_id); | ||
3913 | 3919 | ||
3914 | ret = gk20a_fifo_disable_engine_activity(g, gr_info, true); | 3920 | ret = gk20a_fifo_disable_engine_activity(g, gr_info, true); |
3915 | if (ret) { | 3921 | if (ret) { |
@@ -4187,9 +4193,13 @@ int _gk20a_gr_zbc_set_table(struct gk20a *g, struct gr_gk20a *gr, | |||
4187 | struct zbc_entry *zbc_val) | 4193 | struct zbc_entry *zbc_val) |
4188 | { | 4194 | { |
4189 | struct fifo_gk20a *f = &g->fifo; | 4195 | struct fifo_gk20a *f = &g->fifo; |
4190 | struct fifo_engine_info_gk20a *gr_info = f->engine_info + ENGINE_GR_GK20A; | 4196 | struct fifo_engine_info_gk20a *gr_info = NULL; |
4191 | unsigned long end_jiffies; | 4197 | unsigned long end_jiffies; |
4192 | int ret; | 4198 | int ret; |
4199 | u32 engine_id; | ||
4200 | |||
4201 | engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
4202 | gr_info = (f->engine_info + engine_id); | ||
4193 | 4203 | ||
4194 | ret = gk20a_fifo_disable_engine_activity(g, gr_info, true); | 4204 | ret = gk20a_fifo_disable_engine_activity(g, gr_info, true); |
4195 | if (ret) { | 4205 | if (ret) { |
@@ -4308,6 +4318,29 @@ void gr_gk20a_init_elcg_mode(struct gk20a *g, u32 mode, u32 engine) | |||
4308 | gk20a_writel(g, therm_hubmmu_idle_filter_r(), idle_filter); | 4318 | gk20a_writel(g, therm_hubmmu_idle_filter_r(), idle_filter); |
4309 | } | 4319 | } |
4310 | 4320 | ||
4321 | void gr_gk20a_init_cg_mode(struct gk20a *g, u32 cgmode, u32 mode_config) | ||
4322 | { | ||
4323 | u32 engine_idx; | ||
4324 | u32 active_engine_id = 0; | ||
4325 | struct fifo_engine_info_gk20a *engine_info = NULL; | ||
4326 | struct fifo_gk20a *f = &g->fifo; | ||
4327 | |||
4328 | for (engine_idx = 0; engine_idx < f->num_engines; ++engine_idx) { | ||
4329 | active_engine_id = f->active_engines_list[engine_idx]; | ||
4330 | engine_info = &f->engine_info[active_engine_id]; | ||
4331 | |||
4332 | /* gr_engine supports both BLCG and ELCG */ | ||
4333 | if ((cgmode == BLCG_MODE) && | ||
4334 | (engine_info->engine_enum == ENGINE_GR_GK20A)) { | ||
4335 | gr_gk20a_init_blcg_mode(g, mode_config, active_engine_id); | ||
4336 | break; | ||
4337 | } else if (cgmode == ELCG_MODE) | ||
4338 | gr_gk20a_init_elcg_mode(g, mode_config, active_engine_id); | ||
4339 | else | ||
4340 | gk20a_err(dev_from_gk20a(g), "invalid cg mode %d %d", cgmode, mode_config); | ||
4341 | } | ||
4342 | } | ||
4343 | |||
4311 | static int gr_gk20a_zcull_init_hw(struct gk20a *g, struct gr_gk20a *gr) | 4344 | static int gr_gk20a_zcull_init_hw(struct gk20a *g, struct gr_gk20a *gr) |
4312 | { | 4345 | { |
4313 | u32 gpc_index, gpc_tpc_count, gpc_zcull_count; | 4346 | u32 gpc_index, gpc_tpc_count, gpc_zcull_count; |
@@ -4710,8 +4743,9 @@ static int gk20a_init_gr_prepare(struct gk20a *g) | |||
4710 | { | 4743 | { |
4711 | u32 gpfifo_ctrl, pmc_en; | 4744 | u32 gpfifo_ctrl, pmc_en; |
4712 | u32 err = 0; | 4745 | u32 err = 0; |
4713 | struct fifo_engine_info_gk20a *ce_info = | 4746 | u32 ce_reset_mask; |
4714 | g->fifo.engine_info + ENGINE_CE2_GK20A; | 4747 | |
4748 | ce_reset_mask = gk20a_fifo_get_all_ce_engine_reset_mask(g); | ||
4715 | 4749 | ||
4716 | /* disable fifo access */ | 4750 | /* disable fifo access */ |
4717 | pmc_en = gk20a_readl(g, mc_enable_r()); | 4751 | pmc_en = gk20a_readl(g, mc_enable_r()); |
@@ -4725,12 +4759,12 @@ static int gk20a_init_gr_prepare(struct gk20a *g) | |||
4725 | gk20a_reset(g, mc_enable_pgraph_enabled_f() | 4759 | gk20a_reset(g, mc_enable_pgraph_enabled_f() |
4726 | | mc_enable_blg_enabled_f() | 4760 | | mc_enable_blg_enabled_f() |
4727 | | mc_enable_perfmon_enabled_f() | 4761 | | mc_enable_perfmon_enabled_f() |
4728 | | ce_info->reset_mask); | 4762 | | ce_reset_mask); |
4729 | 4763 | ||
4730 | gr_gk20a_load_gating_prod(g); | 4764 | gr_gk20a_load_gating_prod(g); |
4765 | |||
4731 | /* Disable elcg until it gets enabled later in the init*/ | 4766 | /* Disable elcg until it gets enabled later in the init*/ |
4732 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A); | 4767 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); |
4733 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A); | ||
4734 | 4768 | ||
4735 | /* enable fifo access */ | 4769 | /* enable fifo access */ |
4736 | gk20a_writel(g, gr_gpfifo_ctl_r(), | 4770 | gk20a_writel(g, gr_gpfifo_ctl_r(), |
@@ -5210,11 +5244,9 @@ int gk20a_enable_gr_hw(struct gk20a *g) | |||
5210 | static void gr_gk20a_enable_elcg(struct gk20a *g) | 5244 | static void gr_gk20a_enable_elcg(struct gk20a *g) |
5211 | { | 5245 | { |
5212 | if (g->elcg_enabled) { | 5246 | if (g->elcg_enabled) { |
5213 | gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_GR_GK20A); | 5247 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO); |
5214 | gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_CE2_GK20A); | ||
5215 | } else { | 5248 | } else { |
5216 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A); | 5249 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); |
5217 | gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A); | ||
5218 | } | 5250 | } |
5219 | } | 5251 | } |
5220 | 5252 | ||
@@ -6106,6 +6138,7 @@ int gk20a_gr_isr(struct gk20a *g) | |||
6106 | u32 gr_intr = gk20a_readl(g, gr_intr_r()); | 6138 | u32 gr_intr = gk20a_readl(g, gr_intr_r()); |
6107 | struct channel_gk20a *ch = NULL; | 6139 | struct channel_gk20a *ch = NULL; |
6108 | int tsgid = NVGPU_INVALID_TSG_ID; | 6140 | int tsgid = NVGPU_INVALID_TSG_ID; |
6141 | u32 gr_engine_id; | ||
6109 | 6142 | ||
6110 | gk20a_dbg_fn(""); | 6143 | gk20a_dbg_fn(""); |
6111 | gk20a_dbg(gpu_dbg_intr, "pgraph intr %08x", gr_intr); | 6144 | gk20a_dbg(gpu_dbg_intr, "pgraph intr %08x", gr_intr); |
@@ -6113,6 +6146,8 @@ int gk20a_gr_isr(struct gk20a *g) | |||
6113 | if (!gr_intr) | 6146 | if (!gr_intr) |
6114 | return 0; | 6147 | return 0; |
6115 | 6148 | ||
6149 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
6150 | |||
6116 | grfifo_ctl = gk20a_readl(g, gr_gpfifo_ctl_r()); | 6151 | grfifo_ctl = gk20a_readl(g, gr_gpfifo_ctl_r()); |
6117 | grfifo_ctl &= ~gr_gpfifo_ctl_semaphore_access_f(1); | 6152 | grfifo_ctl &= ~gr_gpfifo_ctl_semaphore_access_f(1); |
6118 | grfifo_ctl &= ~gr_gpfifo_ctl_access_f(1); | 6153 | grfifo_ctl &= ~gr_gpfifo_ctl_access_f(1); |
@@ -6283,13 +6318,13 @@ int gk20a_gr_isr(struct gk20a *g) | |||
6283 | 6318 | ||
6284 | if (need_reset) { | 6319 | if (need_reset) { |
6285 | if (tsgid != NVGPU_INVALID_TSG_ID) | 6320 | if (tsgid != NVGPU_INVALID_TSG_ID) |
6286 | gk20a_fifo_recover(g, BIT(ENGINE_GR_GK20A), | 6321 | gk20a_fifo_recover(g, BIT(gr_engine_id), |
6287 | tsgid, true, true, true); | 6322 | tsgid, true, true, true); |
6288 | else if (ch) | 6323 | else if (ch) |
6289 | gk20a_fifo_recover(g, BIT(ENGINE_GR_GK20A), | 6324 | gk20a_fifo_recover(g, BIT(gr_engine_id), |
6290 | ch->hw_chid, false, true, true); | 6325 | ch->hw_chid, false, true, true); |
6291 | else | 6326 | else |
6292 | gk20a_fifo_recover(g, BIT(ENGINE_GR_GK20A), | 6327 | gk20a_fifo_recover(g, BIT(gr_engine_id), |
6293 | 0, false, false, true); | 6328 | 0, false, false, true); |
6294 | } | 6329 | } |
6295 | 6330 | ||
@@ -8441,6 +8476,10 @@ static u32 *gr_gk20a_rop_l2_en_mask(struct gk20a *g) | |||
8441 | static int gr_gk20a_dump_gr_status_regs(struct gk20a *g, | 8476 | static int gr_gk20a_dump_gr_status_regs(struct gk20a *g, |
8442 | struct gk20a_debug_output *o) | 8477 | struct gk20a_debug_output *o) |
8443 | { | 8478 | { |
8479 | u32 gr_engine_id; | ||
8480 | |||
8481 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
8482 | |||
8444 | gk20a_debug_output(o, "NV_PGRAPH_STATUS: 0x%x\n", | 8483 | gk20a_debug_output(o, "NV_PGRAPH_STATUS: 0x%x\n", |
8445 | gk20a_readl(g, gr_status_r())); | 8484 | gk20a_readl(g, gr_status_r())); |
8446 | gk20a_debug_output(o, "NV_PGRAPH_STATUS1: 0x%x\n", | 8485 | gk20a_debug_output(o, "NV_PGRAPH_STATUS1: 0x%x\n", |
@@ -8460,7 +8499,7 @@ static int gr_gk20a_dump_gr_status_regs(struct gk20a *g, | |||
8460 | gk20a_debug_output(o, "NV_PGRAPH_FECS_INTR : 0x%x\n", | 8499 | gk20a_debug_output(o, "NV_PGRAPH_FECS_INTR : 0x%x\n", |
8461 | gk20a_readl(g, gr_fecs_intr_r())); | 8500 | gk20a_readl(g, gr_fecs_intr_r())); |
8462 | gk20a_debug_output(o, "NV_PFIFO_ENGINE_STATUS(GR) : 0x%x\n", | 8501 | gk20a_debug_output(o, "NV_PFIFO_ENGINE_STATUS(GR) : 0x%x\n", |
8463 | gk20a_readl(g, fifo_engine_status_r(ENGINE_GR_GK20A))); | 8502 | gk20a_readl(g, fifo_engine_status_r(gr_engine_id))); |
8464 | gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY0: 0x%x\n", | 8503 | gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY0: 0x%x\n", |
8465 | gk20a_readl(g, gr_activity_0_r())); | 8504 | gk20a_readl(g, gr_activity_0_r())); |
8466 | gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY1: 0x%x\n", | 8505 | gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY1: 0x%x\n", |
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index b5d97727..189994ef 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h | |||
@@ -82,6 +82,12 @@ enum { | |||
82 | }; | 82 | }; |
83 | 83 | ||
84 | enum { | 84 | enum { |
85 | ELCG_MODE = (1 << 0), | ||
86 | BLCG_MODE = (1 << 1), | ||
87 | INVALID_MODE = (1 << 2) | ||
88 | }; | ||
89 | |||
90 | enum { | ||
85 | ELCG_RUN, /* clk always run, i.e. disable elcg */ | 91 | ELCG_RUN, /* clk always run, i.e. disable elcg */ |
86 | ELCG_STOP, /* clk is stopped */ | 92 | ELCG_STOP, /* clk is stopped */ |
87 | ELCG_AUTO /* clk will run when non-idle, standard elcg mode */ | 93 | ELCG_AUTO /* clk will run when non-idle, standard elcg mode */ |
@@ -476,6 +482,8 @@ int gr_gk20a_fecs_set_reglist_virtual_addr(struct gk20a *g, u64 pmu_va); | |||
476 | void gr_gk20a_init_elcg_mode(struct gk20a *g, u32 mode, u32 engine); | 482 | void gr_gk20a_init_elcg_mode(struct gk20a *g, u32 mode, u32 engine); |
477 | void gr_gk20a_init_blcg_mode(struct gk20a *g, u32 mode, u32 engine); | 483 | void gr_gk20a_init_blcg_mode(struct gk20a *g, u32 mode, u32 engine); |
478 | 484 | ||
485 | void gr_gk20a_init_cg_mode(struct gk20a *g, u32 cgmode, u32 mode_config); | ||
486 | |||
479 | /* sm */ | 487 | /* sm */ |
480 | bool gk20a_gr_sm_debugger_attached(struct gk20a *g); | 488 | bool gk20a_gr_sm_debugger_attached(struct gk20a *g); |
481 | void gk20a_gr_clear_sm_hww(struct gk20a *g, | 489 | void gk20a_gr_clear_sm_hww(struct gk20a *g, |
diff --git a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c index 5112af55..bf58d298 100644 --- a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c | |||
@@ -99,6 +99,9 @@ static int gk20a_get_litter_value(struct gk20a *g, | |||
99 | case GPU_LIT_ROP_SHARED_BASE: | 99 | case GPU_LIT_ROP_SHARED_BASE: |
100 | ret = proj_rop_shared_base_v(); | 100 | ret = proj_rop_shared_base_v(); |
101 | break; | 101 | break; |
102 | case GPU_LIT_HOST_NUM_ENGINES: | ||
103 | ret = proj_host_num_engines_v(); | ||
104 | break; | ||
102 | case GPU_LIT_HOST_NUM_PBDMA: | 105 | case GPU_LIT_HOST_NUM_PBDMA: |
103 | ret = proj_host_num_pbdma_v(); | 106 | ret = proj_host_num_pbdma_v(); |
104 | break; | 107 | break; |
diff --git a/drivers/gpu/nvgpu/gk20a/hw_proj_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_proj_gk20a.h index ce10db35..7dce9f91 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_proj_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_proj_gk20a.h | |||
@@ -106,6 +106,10 @@ static inline u32 proj_tpc_in_gpc_shared_base_v(void) | |||
106 | { | 106 | { |
107 | return 0x00001800; | 107 | return 0x00001800; |
108 | } | 108 | } |
109 | static inline u32 proj_host_num_engines_v(void) | ||
110 | { | ||
111 | return 0x00000002; | ||
112 | } | ||
109 | static inline u32 proj_host_num_pbdma_v(void) | 113 | static inline u32 proj_host_num_pbdma_v(void) |
110 | { | 114 | { |
111 | return 0x00000001; | 115 | return 0x00000001; |
diff --git a/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h index 517cffef..d99e6135 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_top_gk20a.h | |||
@@ -118,6 +118,22 @@ static inline u32 top_device_info_type_enum_graphics_f(void) | |||
118 | { | 118 | { |
119 | return 0x0; | 119 | return 0x0; |
120 | } | 120 | } |
121 | static inline u32 top_device_info_type_enum_copy0_v(void) | ||
122 | { | ||
123 | return 0x00000001; | ||
124 | } | ||
125 | static inline u32 top_device_info_type_enum_copy0_f(void) | ||
126 | { | ||
127 | return 0x4; | ||
128 | } | ||
129 | static inline u32 top_device_info_type_enum_copy1_v(void) | ||
130 | { | ||
131 | return 0x00000002; | ||
132 | } | ||
133 | static inline u32 top_device_info_type_enum_copy1_f(void) | ||
134 | { | ||
135 | return 0x8; | ||
136 | } | ||
121 | static inline u32 top_device_info_type_enum_copy2_v(void) | 137 | static inline u32 top_device_info_type_enum_copy2_v(void) |
122 | { | 138 | { |
123 | return 0x00000003; | 139 | return 0x00000003; |
diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c index 70da7a02..57368235 100644 --- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c | |||
@@ -74,6 +74,9 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) | |||
74 | { | 74 | { |
75 | u32 mc_intr_0; | 75 | u32 mc_intr_0; |
76 | int hw_irq_count; | 76 | int hw_irq_count; |
77 | u32 engine_id_idx; | ||
78 | u32 active_engine_id = 0; | ||
79 | u32 engine_enum = ENGINE_INVAL_GK20A; | ||
77 | 80 | ||
78 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); | 81 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); |
79 | 82 | ||
@@ -84,11 +87,26 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) | |||
84 | 87 | ||
85 | gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0); | 88 | gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0); |
86 | 89 | ||
87 | if (mc_intr_0 & g->fifo.engine_info[ENGINE_GR_GK20A].intr_mask) | 90 | for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; engine_id_idx++) { |
88 | gr_gk20a_elpg_protected_call(g, gk20a_gr_isr(g)); | 91 | active_engine_id = g->fifo.active_engines_list[engine_id_idx]; |
89 | if (mc_intr_0 & g->fifo.engine_info[ENGINE_CE2_GK20A].intr_mask | 92 | |
90 | && g->ops.ce2.isr_stall) | 93 | if (mc_intr_0 & g->fifo.engine_info[active_engine_id].intr_mask) { |
91 | g->ops.ce2.isr_stall(g); | 94 | engine_enum = g->fifo.engine_info[active_engine_id].engine_enum; |
95 | /* GR Engine */ | ||
96 | if (engine_enum == ENGINE_GR_GK20A) { | ||
97 | gr_gk20a_elpg_protected_call(g, gk20a_gr_isr(g)); | ||
98 | } | ||
99 | |||
100 | /* CE Engine */ | ||
101 | if (((engine_enum == ENGINE_GRCE_GK20A) || | ||
102 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) && | ||
103 | g->ops.ce2.isr_stall){ | ||
104 | g->ops.ce2.isr_stall(g, | ||
105 | g->fifo.engine_info[active_engine_id].inst_id, | ||
106 | g->fifo.engine_info[active_engine_id].pri_base); | ||
107 | } | ||
108 | } | ||
109 | } | ||
92 | if (mc_intr_0 & mc_intr_0_pfifo_pending_f()) | 110 | if (mc_intr_0 & mc_intr_0_pfifo_pending_f()) |
93 | gk20a_fifo_isr(g); | 111 | gk20a_fifo_isr(g); |
94 | if (mc_intr_0 & mc_intr_0_pmu_pending_f()) | 112 | if (mc_intr_0 & mc_intr_0_pmu_pending_f()) |
@@ -120,6 +138,9 @@ irqreturn_t mc_gk20a_intr_thread_nonstall(struct gk20a *g) | |||
120 | { | 138 | { |
121 | u32 mc_intr_1; | 139 | u32 mc_intr_1; |
122 | int hw_irq_count; | 140 | int hw_irq_count; |
141 | u32 engine_id_idx; | ||
142 | u32 active_engine_id = 0; | ||
143 | u32 engine_enum = ENGINE_INVAL_GK20A; | ||
123 | 144 | ||
124 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); | 145 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); |
125 | 146 | ||
@@ -132,11 +153,27 @@ irqreturn_t mc_gk20a_intr_thread_nonstall(struct gk20a *g) | |||
132 | gk20a_fifo_nonstall_isr(g); | 153 | gk20a_fifo_nonstall_isr(g); |
133 | if (mc_intr_1 & mc_intr_0_priv_ring_pending_f()) | 154 | if (mc_intr_1 & mc_intr_0_priv_ring_pending_f()) |
134 | gk20a_priv_ring_isr(g); | 155 | gk20a_priv_ring_isr(g); |
135 | if (mc_intr_1 & g->fifo.engine_info[ENGINE_GR_GK20A].intr_mask) | 156 | |
136 | gk20a_gr_nonstall_isr(g); | 157 | for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; engine_id_idx++) { |
137 | if (mc_intr_1 & g->fifo.engine_info[ENGINE_CE2_GK20A].intr_mask | 158 | active_engine_id = g->fifo.active_engines_list[engine_id_idx]; |
138 | && g->ops.ce2.isr_nonstall) | 159 | |
139 | g->ops.ce2.isr_nonstall(g); | 160 | if (mc_intr_1 & g->fifo.engine_info[active_engine_id].intr_mask) { |
161 | engine_enum = g->fifo.engine_info[active_engine_id].engine_enum; | ||
162 | /* GR Engine */ | ||
163 | if (engine_enum == ENGINE_GR_GK20A) { | ||
164 | gk20a_gr_nonstall_isr(g); | ||
165 | } | ||
166 | |||
167 | /* CE Engine */ | ||
168 | if (((engine_enum == ENGINE_GRCE_GK20A) || | ||
169 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) && | ||
170 | g->ops.ce2.isr_nonstall) { | ||
171 | g->ops.ce2.isr_nonstall(g, | ||
172 | g->fifo.engine_info[active_engine_id].inst_id, | ||
173 | g->fifo.engine_info[active_engine_id].pri_base); | ||
174 | } | ||
175 | } | ||
176 | } | ||
140 | 177 | ||
141 | /* sync handled irq counter before re-enabling interrupts */ | 178 | /* sync handled irq counter before re-enabling interrupts */ |
142 | atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count); | 179 | atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count); |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index bca57585..f6e2df00 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | |||
@@ -3061,8 +3061,12 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g) | |||
3061 | struct pmu_cmd cmd; | 3061 | struct pmu_cmd cmd; |
3062 | u32 desc; | 3062 | u32 desc; |
3063 | int err = 0; | 3063 | int err = 0; |
3064 | u32 gr_engine_id; | ||
3065 | |||
3064 | gk20a_dbg_fn(""); | 3066 | gk20a_dbg_fn(""); |
3065 | 3067 | ||
3068 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
3069 | |||
3066 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | 3070 | memset(&cmd, 0, sizeof(struct pmu_cmd)); |
3067 | cmd.hdr.unit_id = PMU_UNIT_PG; | 3071 | cmd.hdr.unit_id = PMU_UNIT_PG; |
3068 | cmd.hdr.size = PMU_CMD_HDR_SIZE + | 3072 | cmd.hdr.size = PMU_CMD_HDR_SIZE + |
@@ -3070,7 +3074,7 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g) | |||
3070 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_cmd_type(&cmd.cmd.pg, | 3074 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_cmd_type(&cmd.cmd.pg, |
3071 | PMU_PG_CMD_ID_ENG_BUF_LOAD); | 3075 | PMU_PG_CMD_ID_ENG_BUF_LOAD); |
3072 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_engine_id(&cmd.cmd.pg, | 3076 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_engine_id(&cmd.cmd.pg, |
3073 | ENGINE_GR_GK20A); | 3077 | gr_engine_id); |
3074 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_idx(&cmd.cmd.pg, | 3078 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_idx(&cmd.cmd.pg, |
3075 | PMU_PGENG_GR_BUFFER_IDX_FECS); | 3079 | PMU_PGENG_GR_BUFFER_IDX_FECS); |
3076 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_size(&cmd.cmd.pg, | 3080 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_size(&cmd.cmd.pg, |
@@ -3095,6 +3099,9 @@ static void pmu_setup_hw_load_zbc(struct gk20a *g) | |||
3095 | struct pmu_gk20a *pmu = &g->pmu; | 3099 | struct pmu_gk20a *pmu = &g->pmu; |
3096 | struct pmu_cmd cmd; | 3100 | struct pmu_cmd cmd; |
3097 | u32 desc; | 3101 | u32 desc; |
3102 | u32 gr_engine_id; | ||
3103 | |||
3104 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
3098 | 3105 | ||
3099 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | 3106 | memset(&cmd, 0, sizeof(struct pmu_cmd)); |
3100 | cmd.hdr.unit_id = PMU_UNIT_PG; | 3107 | cmd.hdr.unit_id = PMU_UNIT_PG; |
@@ -3103,7 +3110,7 @@ static void pmu_setup_hw_load_zbc(struct gk20a *g) | |||
3103 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_cmd_type(&cmd.cmd.pg, | 3110 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_cmd_type(&cmd.cmd.pg, |
3104 | PMU_PG_CMD_ID_ENG_BUF_LOAD); | 3111 | PMU_PG_CMD_ID_ENG_BUF_LOAD); |
3105 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_engine_id(&cmd.cmd.pg, | 3112 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_engine_id(&cmd.cmd.pg, |
3106 | ENGINE_GR_GK20A); | 3113 | gr_engine_id); |
3107 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_idx(&cmd.cmd.pg, | 3114 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_idx(&cmd.cmd.pg, |
3108 | PMU_PGENG_GR_BUFFER_IDX_ZBC); | 3115 | PMU_PGENG_GR_BUFFER_IDX_ZBC); |
3109 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_size(&cmd.cmd.pg, | 3116 | g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_size(&cmd.cmd.pg, |
@@ -3288,20 +3295,23 @@ static int pmu_init_powergating(struct gk20a *g) | |||
3288 | struct pmu_gk20a *pmu = &g->pmu; | 3295 | struct pmu_gk20a *pmu = &g->pmu; |
3289 | struct pmu_cmd cmd; | 3296 | struct pmu_cmd cmd; |
3290 | u32 seq; | 3297 | u32 seq; |
3298 | u32 gr_engine_id; | ||
3291 | 3299 | ||
3292 | gk20a_dbg_fn(""); | 3300 | gk20a_dbg_fn(""); |
3293 | 3301 | ||
3302 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
3303 | |||
3294 | if (tegra_cpu_is_asim()) { | 3304 | if (tegra_cpu_is_asim()) { |
3295 | /* TBD: calculate threshold for silicon */ | 3305 | /* TBD: calculate threshold for silicon */ |
3296 | gk20a_writel(g, pwr_pmu_pg_idlefilth_r(ENGINE_GR_GK20A), | 3306 | gk20a_writel(g, pwr_pmu_pg_idlefilth_r(gr_engine_id), |
3297 | PMU_PG_IDLE_THRESHOLD_SIM); | 3307 | PMU_PG_IDLE_THRESHOLD_SIM); |
3298 | gk20a_writel(g, pwr_pmu_pg_ppuidlefilth_r(ENGINE_GR_GK20A), | 3308 | gk20a_writel(g, pwr_pmu_pg_ppuidlefilth_r(gr_engine_id), |
3299 | PMU_PG_POST_POWERUP_IDLE_THRESHOLD_SIM); | 3309 | PMU_PG_POST_POWERUP_IDLE_THRESHOLD_SIM); |
3300 | } else { | 3310 | } else { |
3301 | /* TBD: calculate threshold for silicon */ | 3311 | /* TBD: calculate threshold for silicon */ |
3302 | gk20a_writel(g, pwr_pmu_pg_idlefilth_r(ENGINE_GR_GK20A), | 3312 | gk20a_writel(g, pwr_pmu_pg_idlefilth_r(gr_engine_id), |
3303 | PMU_PG_IDLE_THRESHOLD); | 3313 | PMU_PG_IDLE_THRESHOLD); |
3304 | gk20a_writel(g, pwr_pmu_pg_ppuidlefilth_r(ENGINE_GR_GK20A), | 3314 | gk20a_writel(g, pwr_pmu_pg_ppuidlefilth_r(gr_engine_id), |
3305 | PMU_PG_POST_POWERUP_IDLE_THRESHOLD); | 3315 | PMU_PG_POST_POWERUP_IDLE_THRESHOLD); |
3306 | } | 3316 | } |
3307 | 3317 | ||
@@ -3316,7 +3326,7 @@ static int pmu_init_powergating(struct gk20a *g) | |||
3316 | cmd.hdr.unit_id = PMU_UNIT_PG; | 3326 | cmd.hdr.unit_id = PMU_UNIT_PG; |
3317 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); | 3327 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); |
3318 | cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD; | 3328 | cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD; |
3319 | cmd.cmd.pg.elpg_cmd.engine_id = ENGINE_GR_GK20A; | 3329 | cmd.cmd.pg.elpg_cmd.engine_id = gr_engine_id; |
3320 | cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_INIT; | 3330 | cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_INIT; |
3321 | 3331 | ||
3322 | gk20a_dbg_pmu("cmd post PMU_PG_ELPG_CMD_INIT"); | 3332 | gk20a_dbg_pmu("cmd post PMU_PG_ELPG_CMD_INIT"); |
@@ -3329,7 +3339,7 @@ static int pmu_init_powergating(struct gk20a *g) | |||
3329 | cmd.hdr.unit_id = PMU_UNIT_PG; | 3339 | cmd.hdr.unit_id = PMU_UNIT_PG; |
3330 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_stat); | 3340 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_stat); |
3331 | cmd.cmd.pg.stat.cmd_type = PMU_PG_CMD_ID_PG_STAT; | 3341 | cmd.cmd.pg.stat.cmd_type = PMU_PG_CMD_ID_PG_STAT; |
3332 | cmd.cmd.pg.stat.engine_id = ENGINE_GR_GK20A; | 3342 | cmd.cmd.pg.stat.engine_id = gr_engine_id; |
3333 | cmd.cmd.pg.stat.sub_cmd_id = PMU_PG_STAT_CMD_ALLOC_DMEM; | 3343 | cmd.cmd.pg.stat.sub_cmd_id = PMU_PG_STAT_CMD_ALLOC_DMEM; |
3334 | cmd.cmd.pg.stat.data = 0; | 3344 | cmd.cmd.pg.stat.data = 0; |
3335 | 3345 | ||
@@ -3344,7 +3354,7 @@ static int pmu_init_powergating(struct gk20a *g) | |||
3344 | cmd.hdr.unit_id = PMU_UNIT_PG; | 3354 | cmd.hdr.unit_id = PMU_UNIT_PG; |
3345 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); | 3355 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); |
3346 | cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD; | 3356 | cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD; |
3347 | cmd.cmd.pg.elpg_cmd.engine_id = ENGINE_GR_GK20A; | 3357 | cmd.cmd.pg.elpg_cmd.engine_id = gr_engine_id; |
3348 | cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_DISALLOW; | 3358 | cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_DISALLOW; |
3349 | 3359 | ||
3350 | gk20a_dbg_pmu("cmd post PMU_PG_ELPG_CMD_DISALLOW"); | 3360 | gk20a_dbg_pmu("cmd post PMU_PG_ELPG_CMD_DISALLOW"); |
@@ -4429,14 +4439,17 @@ static int gk20a_pmu_enable_elpg_locked(struct gk20a *g) | |||
4429 | struct pmu_gk20a *pmu = &g->pmu; | 4439 | struct pmu_gk20a *pmu = &g->pmu; |
4430 | struct pmu_cmd cmd; | 4440 | struct pmu_cmd cmd; |
4431 | u32 seq, status; | 4441 | u32 seq, status; |
4442 | u32 gr_engine_id; | ||
4432 | 4443 | ||
4433 | gk20a_dbg_fn(""); | 4444 | gk20a_dbg_fn(""); |
4434 | 4445 | ||
4446 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
4447 | |||
4435 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | 4448 | memset(&cmd, 0, sizeof(struct pmu_cmd)); |
4436 | cmd.hdr.unit_id = PMU_UNIT_PG; | 4449 | cmd.hdr.unit_id = PMU_UNIT_PG; |
4437 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); | 4450 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); |
4438 | cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD; | 4451 | cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD; |
4439 | cmd.cmd.pg.elpg_cmd.engine_id = ENGINE_GR_GK20A; | 4452 | cmd.cmd.pg.elpg_cmd.engine_id = gr_engine_id; |
4440 | cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_ALLOW; | 4453 | cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_ALLOW; |
4441 | 4454 | ||
4442 | /* no need to wait ack for ELPG enable but set pending to sync | 4455 | /* no need to wait ack for ELPG enable but set pending to sync |
@@ -4503,9 +4516,12 @@ int gk20a_pmu_disable_elpg(struct gk20a *g) | |||
4503 | struct pmu_cmd cmd; | 4516 | struct pmu_cmd cmd; |
4504 | u32 seq; | 4517 | u32 seq; |
4505 | int ret = 0; | 4518 | int ret = 0; |
4519 | u32 gr_engine_id; | ||
4506 | 4520 | ||
4507 | gk20a_dbg_fn(""); | 4521 | gk20a_dbg_fn(""); |
4508 | 4522 | ||
4523 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
4524 | |||
4509 | if (!support_gk20a_pmu(g->dev)) | 4525 | if (!support_gk20a_pmu(g->dev)) |
4510 | return ret; | 4526 | return ret; |
4511 | 4527 | ||
@@ -4553,7 +4569,7 @@ int gk20a_pmu_disable_elpg(struct gk20a *g) | |||
4553 | cmd.hdr.unit_id = PMU_UNIT_PG; | 4569 | cmd.hdr.unit_id = PMU_UNIT_PG; |
4554 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); | 4570 | cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd); |
4555 | cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD; | 4571 | cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD; |
4556 | cmd.cmd.pg.elpg_cmd.engine_id = ENGINE_GR_GK20A; | 4572 | cmd.cmd.pg.elpg_cmd.engine_id = gr_engine_id; |
4557 | cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_DISALLOW; | 4573 | cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_DISALLOW; |
4558 | 4574 | ||
4559 | pmu->elpg_stat = PMU_ELPG_STAT_OFF_PENDING; | 4575 | pmu->elpg_stat = PMU_ELPG_STAT_OFF_PENDING; |
diff --git a/drivers/gpu/nvgpu/gm206/ce_gm206.c b/drivers/gpu/nvgpu/gm206/ce_gm206.c new file mode 100644 index 00000000..9ec42831 --- /dev/null +++ b/drivers/gpu/nvgpu/gm206/ce_gm206.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * GM206 Copy Engine. | ||
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 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program. | ||
17 | */ | ||
18 | |||
19 | /*TODO: remove uncecessary */ | ||
20 | #include "gk20a/gk20a.h" | ||
21 | #include "ce_gm206.h" | ||
22 | |||
23 | /*TODO: remove uncecessary */ | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/scatterlist.h> | ||
27 | #include <trace/events/gk20a.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/nvhost.h> | ||
30 | |||
31 | #include "gk20a/debug_gk20a.h" | ||
32 | #include "gk20a/semaphore_gk20a.h" | ||
33 | #include "hw_ce2_gm206.h" | ||
34 | #include "hw_pbdma_gm206.h" | ||
35 | #include "hw_ccsr_gm206.h" | ||
36 | #include "hw_ram_gm206.h" | ||
37 | #include "hw_top_gm206.h" | ||
38 | #include "hw_mc_gm206.h" | ||
39 | #include "hw_gr_gm206.h" | ||
40 | |||
41 | /* TODO: We need generic way for query the intr_status register offset. | ||
42 | * As of now, there is no way to query this information from dev_ceN_pri.h */ | ||
43 | #define COP_INTR_STATUS_OFFSET 0x908 | ||
44 | |||
45 | static u32 ce_nonblockpipe_isr(struct gk20a *g, u32 fifo_intr, u32 inst_id) | ||
46 | { | ||
47 | gk20a_dbg(gpu_dbg_intr, "ce non-blocking pipe interrupt\n"); | ||
48 | |||
49 | return ce2_intr_status_nonblockpipe_pending_f(); | ||
50 | } | ||
51 | |||
52 | static u32 ce_blockpipe_isr(struct gk20a *g, u32 fifo_intr, u32 inst_id) | ||
53 | { | ||
54 | gk20a_dbg(gpu_dbg_intr, "ce blocking pipe interrupt\n"); | ||
55 | |||
56 | return ce2_intr_status_blockpipe_pending_f(); | ||
57 | } | ||
58 | |||
59 | static u32 ce_launcherr_isr(struct gk20a *g, u32 fifo_intr, u32 inst_id) | ||
60 | { | ||
61 | gk20a_dbg(gpu_dbg_intr, "ce launch error interrupt\n"); | ||
62 | |||
63 | return ce2_intr_status_launcherr_pending_f(); | ||
64 | } | ||
65 | |||
66 | void gm206_ce_isr(struct gk20a *g, u32 inst_id, u32 pri_base) | ||
67 | { | ||
68 | u32 ce_intr_status_reg = (pri_base + COP_INTR_STATUS_OFFSET); | ||
69 | u32 ce_intr = gk20a_readl(g, ce_intr_status_reg); | ||
70 | u32 clear_intr = 0; | ||
71 | |||
72 | gk20a_dbg(gpu_dbg_intr, "ce isr %08x %08x\n", ce_intr, inst_id); | ||
73 | |||
74 | /* clear blocking interrupts: they exibit broken behavior */ | ||
75 | if (ce_intr & ce2_intr_status_blockpipe_pending_f()) | ||
76 | clear_intr |= ce_blockpipe_isr(g, ce_intr, inst_id); | ||
77 | |||
78 | if (ce_intr & ce2_intr_status_launcherr_pending_f()) | ||
79 | clear_intr |= ce_launcherr_isr(g, ce_intr, inst_id); | ||
80 | |||
81 | gk20a_writel(g, ce_intr_status_reg, clear_intr); | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | void gm206_ce_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base) | ||
86 | { | ||
87 | u32 ce_intr_status_reg = (pri_base + COP_INTR_STATUS_OFFSET); | ||
88 | u32 ce_intr = gk20a_readl(g, ce_intr_status_reg); | ||
89 | |||
90 | gk20a_dbg(gpu_dbg_intr, "ce nonstall isr %08x %08x\n", ce_intr, inst_id); | ||
91 | |||
92 | if (ce_intr & ce2_intr_status_nonblockpipe_pending_f()) { | ||
93 | gk20a_writel(g, ce_intr_status_reg, | ||
94 | ce_nonblockpipe_isr(g, ce_intr, inst_id)); | ||
95 | |||
96 | /* wake threads waiting in this channel */ | ||
97 | gk20a_channel_semaphore_wakeup(g, true); | ||
98 | } | ||
99 | |||
100 | return; | ||
101 | } | ||
102 | |||
103 | void gm206_init_ce(struct gpu_ops *gops) | ||
104 | { | ||
105 | gops->ce2.isr_stall = gm206_ce_isr; | ||
106 | gops->ce2.isr_nonstall = gm206_ce_nonstall_isr; | ||
107 | } | ||
diff --git a/drivers/gpu/nvgpu/gm206/ce_gm206.h b/drivers/gpu/nvgpu/gm206/ce_gm206.h new file mode 100644 index 00000000..c2fb1586 --- /dev/null +++ b/drivers/gpu/nvgpu/gm206/ce_gm206.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * GM206 copy engine. | ||
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 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program. | ||
17 | */ | ||
18 | #ifndef __CE_GM206_H__ | ||
19 | #define __CE_GM206_H__ | ||
20 | |||
21 | #include "gk20a/channel_gk20a.h" | ||
22 | #include "gk20a/tsg_gk20a.h" | ||
23 | |||
24 | void gm206_init_ce(struct gpu_ops *gops); | ||
25 | |||
26 | #endif /*__CE2_GM20B_H__*/ | ||
diff --git a/drivers/gpu/nvgpu/gm206/fifo_gm206.c b/drivers/gpu/nvgpu/gm206/fifo_gm206.c index c78f256c..6caf30f4 100644 --- a/drivers/gpu/nvgpu/gm206/fifo_gm206.c +++ b/drivers/gpu/nvgpu/gm206/fifo_gm206.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "gm20b/fifo_gm20b.h" | 18 | #include "gm20b/fifo_gm20b.h" |
19 | #include "fifo_gm206.h" | 19 | #include "fifo_gm206.h" |
20 | #include "hw_ccsr_gm206.h" | 20 | #include "hw_ccsr_gm206.h" |
21 | #include "hw_fifo_gm206.h" | ||
21 | 22 | ||
22 | static u32 gm206_fifo_get_num_fifos(struct gk20a *g) | 23 | static u32 gm206_fifo_get_num_fifos(struct gk20a *g) |
23 | { | 24 | { |
@@ -28,4 +29,5 @@ void gm206_init_fifo(struct gpu_ops *gops) | |||
28 | { | 29 | { |
29 | gm20b_init_fifo(gops); | 30 | gm20b_init_fifo(gops); |
30 | gops->fifo.get_num_fifos = gm206_fifo_get_num_fifos; | 31 | gops->fifo.get_num_fifos = gm206_fifo_get_num_fifos; |
32 | gops->fifo.eng_runlist_base_size = fifo_eng_runlist_base__size_1_v; | ||
31 | } | 33 | } |
diff --git a/drivers/gpu/nvgpu/gm206/hal_gm206.c b/drivers/gpu/nvgpu/gm206/hal_gm206.c index 048a109f..6b5c70e2 100644 --- a/drivers/gpu/nvgpu/gm206/hal_gm206.c +++ b/drivers/gpu/nvgpu/gm206/hal_gm206.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include "gm20b/mc_gm20b.h" | 21 | #include "gm20b/mc_gm20b.h" |
22 | #include "gm20b/ltc_gm20b.h" | 22 | #include "gm20b/ltc_gm20b.h" |
23 | #include "gm20b/mm_gm20b.h" | 23 | #include "gm20b/mm_gm20b.h" |
24 | #include "gm20b/ce2_gm20b.h" | 24 | #include "ce_gm206.h" |
25 | #include "gm20b/fb_gm20b.h" | 25 | #include "gm20b/fb_gm20b.h" |
26 | #include "gm20b/pmu_gm20b.h" | 26 | #include "gm20b/pmu_gm20b.h" |
27 | #include "gm20b/gr_gm20b.h" | 27 | #include "gm20b/gr_gm20b.h" |
@@ -142,6 +142,9 @@ static int gm206_get_litter_value(struct gk20a *g, | |||
142 | case GPU_LIT_ROP_SHARED_BASE: | 142 | case GPU_LIT_ROP_SHARED_BASE: |
143 | ret = proj_rop_shared_base_v(); | 143 | ret = proj_rop_shared_base_v(); |
144 | break; | 144 | break; |
145 | case GPU_LIT_HOST_NUM_ENGINES: | ||
146 | ret = proj_host_num_engines_v(); | ||
147 | break; | ||
145 | case GPU_LIT_HOST_NUM_PBDMA: | 148 | case GPU_LIT_HOST_NUM_PBDMA: |
146 | ret = proj_host_num_pbdma_v(); | 149 | ret = proj_host_num_pbdma_v(); |
147 | break; | 150 | break; |
@@ -183,7 +186,7 @@ int gm206_init_hal(struct gk20a *g) | |||
183 | gm20b_init_fb(gops); | 186 | gm20b_init_fb(gops); |
184 | g->ops.fb.set_use_full_comp_tag_line = NULL; | 187 | g->ops.fb.set_use_full_comp_tag_line = NULL; |
185 | gm206_init_fifo(gops); | 188 | gm206_init_fifo(gops); |
186 | gm20b_init_ce2(gops); | 189 | gm206_init_ce(gops); |
187 | gm20b_init_gr_ctx(gops); | 190 | gm20b_init_gr_ctx(gops); |
188 | gm20b_init_mm(gops); | 191 | gm20b_init_mm(gops); |
189 | gm206_init_pmu_ops(gops); | 192 | gm206_init_pmu_ops(gops); |
diff --git a/drivers/gpu/nvgpu/gm206/hw_proj_gm206.h b/drivers/gpu/nvgpu/gm206/hw_proj_gm206.h index 2f4187d0..6c21b39a 100644 --- a/drivers/gpu/nvgpu/gm206/hw_proj_gm206.h +++ b/drivers/gpu/nvgpu/gm206/hw_proj_gm206.h | |||
@@ -106,6 +106,10 @@ static inline u32 proj_tpc_in_gpc_shared_base_v(void) | |||
106 | { | 106 | { |
107 | return 0x00001800; | 107 | return 0x00001800; |
108 | } | 108 | } |
109 | static inline u32 proj_host_num_engines_v(void) | ||
110 | { | ||
111 | return 0x00000008; | ||
112 | } | ||
109 | static inline u32 proj_host_num_pbdma_v(void) | 113 | static inline u32 proj_host_num_pbdma_v(void) |
110 | { | 114 | { |
111 | return 0x00000003; | 115 | return 0x00000003; |
diff --git a/drivers/gpu/nvgpu/gm206/hw_top_gm206.h b/drivers/gpu/nvgpu/gm206/hw_top_gm206.h index e6ec1d27..988f24ea 100644 --- a/drivers/gpu/nvgpu/gm206/hw_top_gm206.h +++ b/drivers/gpu/nvgpu/gm206/hw_top_gm206.h | |||
@@ -146,6 +146,22 @@ static inline u32 top_device_info_type_enum_copy0_f(void) | |||
146 | { | 146 | { |
147 | return 0x4; | 147 | return 0x4; |
148 | } | 148 | } |
149 | static inline u32 top_device_info_type_enum_copy1_v(void) | ||
150 | { | ||
151 | return 0x00000002; | ||
152 | } | ||
153 | static inline u32 top_device_info_type_enum_copy1_f(void) | ||
154 | { | ||
155 | return 0x8; | ||
156 | } | ||
157 | static inline u32 top_device_info_type_enum_copy2_v(void) | ||
158 | { | ||
159 | return 0x00000003; | ||
160 | } | ||
161 | static inline u32 top_device_info_type_enum_copy2_f(void) | ||
162 | { | ||
163 | return 0xc; | ||
164 | } | ||
149 | static inline u32 top_device_info_entry_v(u32 r) | 165 | static inline u32 top_device_info_entry_v(u32 r) |
150 | { | 166 | { |
151 | return (r >> 0) & 0x3; | 167 | return (r >> 0) & 0x3; |
diff --git a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c index bb873bcc..031c5bae 100644 --- a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c | |||
@@ -49,12 +49,14 @@ static void channel_gm20b_bind(struct channel_gk20a *c) | |||
49 | static inline u32 gm20b_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id) | 49 | static inline u32 gm20b_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id) |
50 | { | 50 | { |
51 | u32 fault_id = ~0; | 51 | u32 fault_id = ~0; |
52 | struct fifo_engine_info_gk20a *engine_info; | ||
52 | 53 | ||
53 | if (engine_id < ENGINE_INVAL_GK20A) { | 54 | engine_info = gk20a_fifo_get_engine_info(g, engine_id); |
54 | struct fifo_engine_info_gk20a *info = | ||
55 | &g->fifo.engine_info[engine_id]; | ||
56 | 55 | ||
57 | fault_id = info->fault_id; | 56 | if (engine_info) { |
57 | fault_id = engine_info->fault_id; | ||
58 | } else { | ||
59 | gk20a_err(g->dev, "engine_id is not in active list/invalid %d", engine_id); | ||
58 | } | 60 | } |
59 | return fault_id; | 61 | return fault_id; |
60 | } | 62 | } |
@@ -72,7 +74,7 @@ static void gm20b_fifo_trigger_mmu_fault(struct gk20a *g, | |||
72 | for_each_set_bit(engine_id, &engine_ids, 32) { | 74 | for_each_set_bit(engine_id, &engine_ids, 32) { |
73 | u32 engine_mmu_fault_id; | 75 | u32 engine_mmu_fault_id; |
74 | 76 | ||
75 | if (engine_id > g->fifo.max_engines) { | 77 | if (!gk20a_fifo_is_valid_engine_id(g, engine_id)) { |
76 | gk20a_err(dev_from_gk20a(g), | 78 | gk20a_err(dev_from_gk20a(g), |
77 | "faulting unknown engine %ld", engine_id); | 79 | "faulting unknown engine %ld", engine_id); |
78 | } else { | 80 | } else { |
@@ -109,7 +111,7 @@ static u32 gm20b_fifo_get_num_fifos(struct gk20a *g) | |||
109 | return ccsr_channel__size_1_v(); | 111 | return ccsr_channel__size_1_v(); |
110 | } | 112 | } |
111 | 113 | ||
112 | void gm20b_device_info_data_parse(struct gk20a *g, | 114 | static void gm20b_device_info_data_parse(struct gk20a *g, |
113 | u32 table_entry, u32 *inst_id, | 115 | u32 table_entry, u32 *inst_id, |
114 | u32 *pri_base, u32 *fault_id) | 116 | u32 *pri_base, u32 *fault_id) |
115 | { | 117 | { |
@@ -152,4 +154,5 @@ void gm20b_init_fifo(struct gpu_ops *gops) | |||
152 | gops->fifo.force_reset_ch = gk20a_fifo_force_reset_ch; | 154 | gops->fifo.force_reset_ch = gk20a_fifo_force_reset_ch; |
153 | gops->fifo.engine_enum_from_type = gk20a_fifo_engine_enum_from_type; | 155 | gops->fifo.engine_enum_from_type = gk20a_fifo_engine_enum_from_type; |
154 | gops->fifo.device_info_data_parse = gm20b_device_info_data_parse; | 156 | gops->fifo.device_info_data_parse = gm20b_device_info_data_parse; |
157 | gops->fifo.eng_runlist_base_size = fifo_eng_runlist_base__size_1_v; | ||
155 | } | 158 | } |
diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c index d5131b7a..cc709c78 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c | |||
@@ -855,6 +855,9 @@ static int gr_gm20b_dump_gr_status_regs(struct gk20a *g, | |||
855 | struct gk20a_debug_output *o) | 855 | struct gk20a_debug_output *o) |
856 | { | 856 | { |
857 | struct gr_gk20a *gr = &g->gr; | 857 | struct gr_gk20a *gr = &g->gr; |
858 | u32 gr_engine_id; | ||
859 | |||
860 | gr_engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
858 | 861 | ||
859 | gk20a_debug_output(o, "NV_PGRAPH_STATUS: 0x%x\n", | 862 | gk20a_debug_output(o, "NV_PGRAPH_STATUS: 0x%x\n", |
860 | gk20a_readl(g, gr_status_r())); | 863 | gk20a_readl(g, gr_status_r())); |
@@ -875,7 +878,7 @@ static int gr_gm20b_dump_gr_status_regs(struct gk20a *g, | |||
875 | gk20a_debug_output(o, "NV_PGRAPH_FECS_INTR : 0x%x\n", | 878 | gk20a_debug_output(o, "NV_PGRAPH_FECS_INTR : 0x%x\n", |
876 | gk20a_readl(g, gr_fecs_intr_r())); | 879 | gk20a_readl(g, gr_fecs_intr_r())); |
877 | gk20a_debug_output(o, "NV_PFIFO_ENGINE_STATUS(GR) : 0x%x\n", | 880 | gk20a_debug_output(o, "NV_PFIFO_ENGINE_STATUS(GR) : 0x%x\n", |
878 | gk20a_readl(g, fifo_engine_status_r(ENGINE_GR_GK20A))); | 881 | gk20a_readl(g, fifo_engine_status_r(gr_engine_id))); |
879 | gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY0: 0x%x\n", | 882 | gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY0: 0x%x\n", |
880 | gk20a_readl(g, gr_activity_0_r())); | 883 | gk20a_readl(g, gr_activity_0_r())); |
881 | gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY1: 0x%x\n", | 884 | gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY1: 0x%x\n", |
diff --git a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c index c0113498..cbd3f50b 100644 --- a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c | |||
@@ -140,6 +140,9 @@ static int gm20b_get_litter_value(struct gk20a *g, | |||
140 | case GPU_LIT_ROP_SHARED_BASE: | 140 | case GPU_LIT_ROP_SHARED_BASE: |
141 | ret = proj_rop_shared_base_v(); | 141 | ret = proj_rop_shared_base_v(); |
142 | break; | 142 | break; |
143 | case GPU_LIT_HOST_NUM_ENGINES: | ||
144 | ret = proj_host_num_engines_v(); | ||
145 | break; | ||
143 | case GPU_LIT_HOST_NUM_PBDMA: | 146 | case GPU_LIT_HOST_NUM_PBDMA: |
144 | ret = proj_host_num_pbdma_v(); | 147 | ret = proj_host_num_pbdma_v(); |
145 | break; | 148 | break; |
diff --git a/drivers/gpu/nvgpu/gm20b/hw_proj_gm20b.h b/drivers/gpu/nvgpu/gm20b/hw_proj_gm20b.h index b837918c..d4d412e1 100644 --- a/drivers/gpu/nvgpu/gm20b/hw_proj_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/hw_proj_gm20b.h | |||
@@ -106,6 +106,10 @@ static inline u32 proj_tpc_in_gpc_shared_base_v(void) | |||
106 | { | 106 | { |
107 | return 0x00001800; | 107 | return 0x00001800; |
108 | } | 108 | } |
109 | static inline u32 proj_host_num_engines_v(void) | ||
110 | { | ||
111 | return 0x00000002; | ||
112 | } | ||
109 | static inline u32 proj_host_num_pbdma_v(void) | 113 | static inline u32 proj_host_num_pbdma_v(void) |
110 | { | 114 | { |
111 | return 0x00000001; | 115 | return 0x00000001; |
diff --git a/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h b/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h index c70f388c..cca37294 100644 --- a/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/hw_top_gm20b.h | |||
@@ -138,6 +138,22 @@ static inline u32 top_device_info_type_enum_graphics_f(void) | |||
138 | { | 138 | { |
139 | return 0x0; | 139 | return 0x0; |
140 | } | 140 | } |
141 | static inline u32 top_device_info_type_enum_copy0_v(void) | ||
142 | { | ||
143 | return 0x00000001; | ||
144 | } | ||
145 | static inline u32 top_device_info_type_enum_copy0_f(void) | ||
146 | { | ||
147 | return 0x4; | ||
148 | } | ||
149 | static inline u32 top_device_info_type_enum_copy1_v(void) | ||
150 | { | ||
151 | return 0x00000002; | ||
152 | } | ||
153 | static inline u32 top_device_info_type_enum_copy1_f(void) | ||
154 | { | ||
155 | return 0x8; | ||
156 | } | ||
141 | static inline u32 top_device_info_type_enum_copy2_v(void) | 157 | static inline u32 top_device_info_type_enum_copy2_v(void) |
142 | { | 158 | { |
143 | return 0x00000003; | 159 | return 0x00000003; |
diff --git a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c index 0895b757..3e89e81f 100644 --- a/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c +++ b/drivers/gpu/nvgpu/vgpu/fifo_vgpu.c | |||
@@ -163,60 +163,52 @@ static int init_engine_info(struct fifo_gk20a *f) | |||
163 | 163 | ||
164 | static int init_runlist(struct gk20a *g, struct fifo_gk20a *f) | 164 | static int init_runlist(struct gk20a *g, struct fifo_gk20a *f) |
165 | { | 165 | { |
166 | struct fifo_engine_info_gk20a *engine_info; | ||
167 | struct fifo_runlist_info_gk20a *runlist; | 166 | struct fifo_runlist_info_gk20a *runlist; |
168 | struct device *d = dev_from_gk20a(g); | 167 | struct device *d = dev_from_gk20a(g); |
169 | u32 runlist_id; | 168 | s32 runlist_id = -1; |
170 | u32 i; | 169 | u32 i; |
171 | u64 runlist_size; | 170 | u64 runlist_size; |
172 | 171 | ||
173 | gk20a_dbg_fn(""); | 172 | gk20a_dbg_fn(""); |
174 | 173 | ||
175 | f->max_runlists = fifo_eng_runlist_base__size_1_v(); | 174 | f->max_runlists = g->ops.fifo.eng_runlist_base_size(); |
176 | f->runlist_info = kzalloc(sizeof(struct fifo_runlist_info_gk20a) * | 175 | f->runlist_info = kzalloc(sizeof(struct fifo_runlist_info_gk20a) * |
177 | f->max_runlists, GFP_KERNEL); | 176 | f->max_runlists, GFP_KERNEL); |
178 | if (!f->runlist_info) | 177 | if (!f->runlist_info) |
179 | goto clean_up; | 178 | goto clean_up_runlist; |
180 | 179 | ||
181 | engine_info = f->engine_info + ENGINE_GR_GK20A; | 180 | memset(f->runlist_info, 0, (sizeof(struct fifo_runlist_info_gk20a) * |
182 | runlist_id = engine_info->runlist_id; | 181 | f->max_runlists)); |
183 | runlist = &f->runlist_info[runlist_id]; | 182 | |
183 | for (runlist_id = 0; runlist_id < f->max_runlists; runlist_id++) { | ||
184 | runlist = &f->runlist_info[runlist_id]; | ||
184 | 185 | ||
185 | runlist->active_channels = | 186 | runlist->active_channels = |
186 | kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE), | 187 | kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE), |
187 | GFP_KERNEL); | 188 | GFP_KERNEL); |
188 | if (!runlist->active_channels) | 189 | if (!runlist->active_channels) |
189 | goto clean_up_runlist_info; | ||
190 | |||
191 | runlist_size = sizeof(u16) * f->num_channels; | ||
192 | for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) { | ||
193 | int err = gk20a_gmmu_alloc(g, runlist_size, &runlist->mem[i]); | ||
194 | if (err) { | ||
195 | dev_err(d, "memory allocation failed\n"); | ||
196 | goto clean_up_runlist; | 190 | goto clean_up_runlist; |
197 | } | ||
198 | } | ||
199 | mutex_init(&runlist->mutex); | ||
200 | 191 | ||
201 | /* None of buffers is pinned if this value doesn't change. | 192 | runlist_size = sizeof(u16) * f->num_channels; |
202 | Otherwise, one of them (cur_buffer) must have been pinned. */ | 193 | for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) { |
203 | runlist->cur_buffer = MAX_RUNLIST_BUFFERS; | 194 | int err = gk20a_gmmu_alloc(g, runlist_size, &runlist->mem[i]); |
195 | if (err) { | ||
196 | dev_err(d, "memory allocation failed\n"); | ||
197 | goto clean_up_runlist; | ||
198 | } | ||
199 | } | ||
200 | mutex_init(&runlist->mutex); | ||
201 | |||
202 | /* None of buffers is pinned if this value doesn't change. | ||
203 | Otherwise, one of them (cur_buffer) must have been pinned. */ | ||
204 | runlist->cur_buffer = MAX_RUNLIST_BUFFERS; | ||
205 | } | ||
204 | 206 | ||
205 | gk20a_dbg_fn("done"); | 207 | gk20a_dbg_fn("done"); |
206 | return 0; | 208 | return 0; |
207 | 209 | ||
208 | clean_up_runlist: | 210 | clean_up_runlist: |
209 | for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) | 211 | gk20a_fifo_delete_runlist(f); |
210 | gk20a_gmmu_free(g, &runlist->mem[i]); | ||
211 | |||
212 | clean_up_runlist_info: | ||
213 | kfree(runlist->active_channels); | ||
214 | runlist->active_channels = NULL; | ||
215 | |||
216 | kfree(f->runlist_info); | ||
217 | f->runlist_info = NULL; | ||
218 | |||
219 | clean_up: | ||
220 | gk20a_dbg_fn("fail"); | 212 | gk20a_dbg_fn("fail"); |
221 | return -ENOMEM; | 213 | return -ENOMEM; |
222 | } | 214 | } |
@@ -243,7 +235,7 @@ static int vgpu_init_fifo_setup_sw(struct gk20a *g) | |||
243 | if (err) | 235 | if (err) |
244 | return -ENXIO; | 236 | return -ENXIO; |
245 | 237 | ||
246 | f->max_engines = ENGINE_INVAL_GK20A; | 238 | f->max_engines = nvgpu_get_litter_value(g, GPU_LIT_HOST_NUM_ENGINES); |
247 | 239 | ||
248 | f->userd_entry_size = 1 << ram_userd_base_shift_v(); | 240 | f->userd_entry_size = 1 << ram_userd_base_shift_v(); |
249 | 241 | ||