summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVinod G <vinodg@nvidia.com>2018-06-18 15:04:13 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-06-20 02:40:49 -0400
commit06ceff1240902c7f4cdb01dcbc9c988fc5fd9495 (patch)
tree3dd1b088f7df458119cc8e7f00f75466a04f2d33
parent52f1ab0372af3907364dea8b9ff3d25eaa4cbd7f (diff)
gpu: nvgpu: PG refcount check moved to a wrapper function.
Moved PG refcount checking to a wrapper function, this function manages the refcount and decides whether to call dbg_set_powergate function. Instead of checking the dbg_s->is_pg_disabled variable, code is checking g->dbg_powergating_disabled_refcount variable to know if powergate is disabled or not. Updating hwpm ctxsw mode without disabling powergate will result in priv errors. Bug 200410871 Bug 2109765 Change-Id: I33c9022cb04cd39249c78e72584dfe6afb7212d0 Signed-off-by: Vinod G <vinodg@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1753550 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: Richard Zhao <rizhao@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.c142
-rw-r--r--drivers/gpu/nvgpu/gk20a/dbg_gpu_gk20a.h2
-rw-r--r--drivers/gpu/nvgpu/os/linux/ioctl_dbg.c30
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
172u32 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
172int dbg_set_powergate(struct dbg_session_gk20a *dbg_s, bool disable_powergate) 202int 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);
133int gk20a_perfbuf_disable_locked(struct gk20a *g); 133int gk20a_perfbuf_disable_locked(struct gk20a *g);
134 134
135void nvgpu_dbg_session_post_event(struct dbg_session_gk20a *dbg_s); 135void nvgpu_dbg_session_post_event(struct dbg_session_gk20a *dbg_s);
136u32 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);
978pg_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;