diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | 142 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/linux/ioctl_dbg.c | 30 |
3 files changed, 97 insertions, 77 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c index 97de7138..ddf2039b 100644 --- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c | |||
@@ -169,6 +169,36 @@ int gk20a_dbg_gpu_clear_broadcast_stop_trigger(struct channel_gk20a *ch) | |||
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | ||
172 | u32 nvgpu_set_powergate_locked(struct dbg_session_gk20a *dbg_s, | ||
173 | bool mode) | ||
174 | { | ||
175 | u32 err = 0U; | ||
176 | struct gk20a *g = dbg_s->g; | ||
177 | |||
178 | if (dbg_s->is_pg_disabled != mode) { | ||
179 | if (mode == false) { | ||
180 | g->dbg_powergating_disabled_refcount--; | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Allow powergate disable or enable only if | ||
185 | * the global pg disabled refcount is zero | ||
186 | */ | ||
187 | if (g->dbg_powergating_disabled_refcount == 0) { | ||
188 | err = g->ops.dbg_session_ops.dbg_set_powergate(dbg_s, | ||
189 | mode); | ||
190 | } | ||
191 | |||
192 | if (mode) { | ||
193 | g->dbg_powergating_disabled_refcount++; | ||
194 | } | ||
195 | |||
196 | dbg_s->is_pg_disabled = mode; | ||
197 | } | ||
198 | |||
199 | return err; | ||
200 | } | ||
201 | |||
172 | int dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate) | 202 | int dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate) |
173 | { | 203 | { |
174 | int err = 0; | 204 | int err = 0; |
@@ -194,36 +224,28 @@ int dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate) | |||
194 | * clocking state changes allowed from mainline code (but they | 224 | * clocking state changes allowed from mainline code (but they |
195 | * should be saved). | 225 | * should be saved). |
196 | */ | 226 | */ |
197 | /* Allow powergate disable if the current dbg_session doesn't | ||
198 | * call a powergate disable ioctl and the global | ||
199 | * powergating_disabled_refcount is zero | ||
200 | */ | ||
201 | 227 | ||
202 | if ((dbg_s->is_pg_disabled == false) && | 228 | nvgpu_log(g, gpu_dbg_gpu_dbg | gpu_dbg_fn, |
203 | (g->dbg_powergating_disabled_refcount++ == 0)) { | 229 | "module busy"); |
204 | 230 | err = gk20a_busy(g); | |
205 | nvgpu_log(g, gpu_dbg_gpu_dbg | gpu_dbg_fn, | 231 | if (err) |
206 | "module busy"); | 232 | return err; |
207 | err = gk20a_busy(g); | 233 | |
208 | if (err) | 234 | /*do elpg disable before clock gating */ |
209 | return err; | 235 | nvgpu_pmu_pg_global_enable(g, false); |
210 | 236 | ||
211 | /*do elpg disable before clock gating */ | 237 | if (g->ops.clock_gating.slcg_gr_load_gating_prod) |
212 | nvgpu_pmu_pg_global_enable(g, false); | 238 | g->ops.clock_gating.slcg_gr_load_gating_prod(g, |
213 | 239 | false); | |
214 | if (g->ops.clock_gating.slcg_gr_load_gating_prod) | 240 | if (g->ops.clock_gating.slcg_perf_load_gating_prod) |
215 | g->ops.clock_gating.slcg_gr_load_gating_prod(g, | 241 | g->ops.clock_gating.slcg_perf_load_gating_prod(g, |
216 | false); | 242 | false); |
217 | if (g->ops.clock_gating.slcg_perf_load_gating_prod) | 243 | if (g->ops.clock_gating.slcg_ltc_load_gating_prod) |
218 | g->ops.clock_gating.slcg_perf_load_gating_prod(g, | 244 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, |
219 | false); | 245 | false); |
220 | if (g->ops.clock_gating.slcg_ltc_load_gating_prod) | 246 | |
221 | g->ops.clock_gating.slcg_ltc_load_gating_prod(g, | 247 | gr_gk20a_init_cg_mode(g, BLCG_MODE, BLCG_RUN); |
222 | false); | 248 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); |
223 | |||
224 | gr_gk20a_init_cg_mode(g, BLCG_MODE, BLCG_RUN); | ||
225 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN); | ||
226 | } | ||
227 | 249 | ||
228 | dbg_s->is_pg_disabled = true; | 250 | dbg_s->is_pg_disabled = true; |
229 | } else { | 251 | } else { |
@@ -231,42 +253,34 @@ int dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate) | |||
231 | /* release pending exceptions to fault/be handled as usual */ | 253 | /* release pending exceptions to fault/be handled as usual */ |
232 | /*TBD: ordering of these? */ | 254 | /*TBD: ordering of these? */ |
233 | 255 | ||
234 | /* Re-enabling powergate as no other sessions want | 256 | if (g->elcg_enabled) |
235 | * powergate disabled and the current dbg-sessions had | 257 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO); |
236 | * requested the powergate disable through ioctl | 258 | |
237 | */ | 259 | if (g->blcg_enabled) |
238 | if (dbg_s->is_pg_disabled && | 260 | gr_gk20a_init_cg_mode(g, BLCG_MODE, BLCG_AUTO); |
239 | --g->dbg_powergating_disabled_refcount == 0) { | 261 | |
240 | 262 | if (g->slcg_enabled) { | |
241 | if (g->elcg_enabled) | 263 | if (g->ops.clock_gating. |
242 | gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO); | 264 | slcg_ltc_load_gating_prod) |
243 | 265 | g->ops.clock_gating. | |
244 | if (g->blcg_enabled) | 266 | slcg_ltc_load_gating_prod(g, |
245 | gr_gk20a_init_cg_mode(g, BLCG_MODE, BLCG_AUTO); | 267 | g->slcg_enabled); |
246 | 268 | if (g->ops.clock_gating. | |
247 | if (g->slcg_enabled) { | 269 | slcg_perf_load_gating_prod) |
248 | if (g->ops.clock_gating. | 270 | g->ops.clock_gating. |
249 | slcg_ltc_load_gating_prod) | 271 | slcg_perf_load_gating_prod(g, |
250 | g->ops.clock_gating. | 272 | g->slcg_enabled); |
251 | slcg_ltc_load_gating_prod(g, | 273 | if (g->ops.clock_gating. |
252 | g->slcg_enabled); | 274 | slcg_gr_load_gating_prod) |
253 | if (g->ops.clock_gating. | 275 | g->ops.clock_gating. |
254 | slcg_perf_load_gating_prod) | 276 | slcg_gr_load_gating_prod(g, |
255 | g->ops.clock_gating. | 277 | g->slcg_enabled); |
256 | slcg_perf_load_gating_prod(g, | ||
257 | g->slcg_enabled); | ||
258 | if (g->ops.clock_gating. | ||
259 | slcg_gr_load_gating_prod) | ||
260 | g->ops.clock_gating. | ||
261 | slcg_gr_load_gating_prod(g, | ||
262 | g->slcg_enabled); | ||
263 | } | ||
264 | nvgpu_pmu_pg_global_enable(g, true); | ||
265 | |||
266 | nvgpu_log(g, gpu_dbg_gpu_dbg | gpu_dbg_fn, | ||
267 | "module idle"); | ||
268 | gk20a_idle(g); | ||
269 | } | 278 | } |
279 | nvgpu_pmu_pg_global_enable(g, true); | ||
280 | |||
281 | nvgpu_log(g, gpu_dbg_gpu_dbg | gpu_dbg_fn, | ||
282 | "module idle"); | ||
283 | gk20a_idle(g); | ||
270 | 284 | ||
271 | dbg_s->is_pg_disabled = false; | 285 | dbg_s->is_pg_disabled = false; |
272 | } | 286 | } |
diff --git a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h index b714a648..d9d07844 100644 --- a/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h | |||
@@ -133,4 +133,6 @@ int gk20a_perfbuf_enable_locked(struct gk20a *g, u64 offset, u32 size); | |||
133 | int gk20a_perfbuf_disable_locked(struct gk20a *g); | 133 | int gk20a_perfbuf_disable_locked(struct gk20a *g); |
134 | 134 | ||
135 | void nvgpu_dbg_session_post_event(struct dbg_session_gk20a *dbg_s); | 135 | void nvgpu_dbg_session_post_event(struct dbg_session_gk20a *dbg_s); |
136 | u32 nvgpu_set_powergate_locked(struct dbg_session_gk20a *dbg_s, | ||
137 | bool mode); | ||
136 | #endif /* DBG_GPU_GK20A_H */ | 138 | #endif /* DBG_GPU_GK20A_H */ |
diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c b/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c index 31e7e2cb..76ff25c0 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_dbg.c | |||
@@ -181,7 +181,9 @@ int gk20a_dbg_gpu_dev_release(struct inode *inode, struct file *filp) | |||
181 | * calling powergate/timeout enable ioctl | 181 | * calling powergate/timeout enable ioctl |
182 | */ | 182 | */ |
183 | nvgpu_mutex_acquire(&g->dbg_sessions_lock); | 183 | nvgpu_mutex_acquire(&g->dbg_sessions_lock); |
184 | g->ops.dbg_session_ops.dbg_set_powergate(dbg_s, false); | 184 | if (dbg_s->is_pg_disabled) { |
185 | nvgpu_set_powergate_locked(dbg_s, false); | ||
186 | } | ||
185 | nvgpu_dbg_timeout_enable(dbg_s, NVGPU_DBG_GPU_IOCTL_TIMEOUT_ENABLE); | 187 | nvgpu_dbg_timeout_enable(dbg_s, NVGPU_DBG_GPU_IOCTL_TIMEOUT_ENABLE); |
186 | 188 | ||
187 | /* If this session owned the perf buffer, release it */ | 189 | /* If this session owned the perf buffer, release it */ |
@@ -867,9 +869,10 @@ static int nvgpu_ioctl_channel_reg_ops(struct dbg_session_gk20a *dbg_s, | |||
867 | /* In the virtual case, the server will handle | 869 | /* In the virtual case, the server will handle |
868 | * disabling/enabling powergating when processing reg ops | 870 | * disabling/enabling powergating when processing reg ops |
869 | */ | 871 | */ |
870 | powergate_err = g->ops.dbg_session_ops.dbg_set_powergate(dbg_s, | 872 | powergate_err = nvgpu_set_powergate_locked(dbg_s, true); |
871 | true); | 873 | if (!powergate_err) { |
872 | is_pg_disabled = true; | 874 | is_pg_disabled = true; |
875 | } | ||
873 | } | 876 | } |
874 | 877 | ||
875 | if (!powergate_err) { | 878 | if (!powergate_err) { |
@@ -938,9 +941,8 @@ static int nvgpu_ioctl_channel_reg_ops(struct dbg_session_gk20a *dbg_s, | |||
938 | 941 | ||
939 | /* enable powergate, if previously disabled */ | 942 | /* enable powergate, if previously disabled */ |
940 | if (is_pg_disabled) { | 943 | if (is_pg_disabled) { |
941 | powergate_err = | 944 | powergate_err = nvgpu_set_powergate_locked(dbg_s, |
942 | g->ops.dbg_session_ops.dbg_set_powergate(dbg_s, | 945 | false); |
943 | false); | ||
944 | } | 946 | } |
945 | } | 947 | } |
946 | 948 | ||
@@ -964,14 +966,16 @@ static int nvgpu_ioctl_powergate_gk20a(struct dbg_session_gk20a *dbg_s, | |||
964 | g->name, args->mode); | 966 | g->name, args->mode); |
965 | 967 | ||
966 | nvgpu_mutex_acquire(&g->dbg_sessions_lock); | 968 | nvgpu_mutex_acquire(&g->dbg_sessions_lock); |
967 | if (args->mode == NVGPU_DBG_GPU_POWERGATE_MODE_DISABLE) { | 969 | if ((args->mode != NVGPU_DBG_GPU_POWERGATE_MODE_DISABLE) && |
968 | err = g->ops.dbg_session_ops.dbg_set_powergate(dbg_s, true); | 970 | (args->mode != NVGPU_DBG_GPU_POWERGATE_MODE_ENABLE)) { |
969 | } else if (args->mode == NVGPU_DBG_GPU_POWERGATE_MODE_ENABLE) { | ||
970 | err = g->ops.dbg_session_ops.dbg_set_powergate(dbg_s, false); | ||
971 | } else { | ||
972 | nvgpu_err(g, "invalid powergate mode"); | 971 | nvgpu_err(g, "invalid powergate mode"); |
973 | err = -EINVAL; | 972 | err = -EINVAL; |
973 | goto pg_err_end; | ||
974 | } | 974 | } |
975 | |||
976 | err = nvgpu_set_powergate_locked(dbg_s, | ||
977 | args->mode == NVGPU_DBG_GPU_POWERGATE_MODE_DISABLE); | ||
978 | pg_err_end: | ||
975 | nvgpu_mutex_release(&g->dbg_sessions_lock); | 979 | nvgpu_mutex_release(&g->dbg_sessions_lock); |
976 | return err; | 980 | return err; |
977 | } | 981 | } |
@@ -1053,7 +1057,7 @@ static int nvgpu_dbg_gpu_ioctl_hwpm_ctxsw_mode(struct dbg_session_gk20a *dbg_s, | |||
1053 | err = -EINVAL; | 1057 | err = -EINVAL; |
1054 | goto clean_up; | 1058 | goto clean_up; |
1055 | } | 1059 | } |
1056 | if (!dbg_s->is_pg_disabled) { | 1060 | if (g->dbg_powergating_disabled_refcount == 0) { |
1057 | nvgpu_err(g, "powergate is not disabled"); | 1061 | nvgpu_err(g, "powergate is not disabled"); |
1058 | err = -ENOSYS; | 1062 | err = -ENOSYS; |
1059 | goto clean_up; | 1063 | goto clean_up; |