diff options
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 95 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | 21 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/fifo_gm20b.c | 1 |
4 files changed, 78 insertions, 43 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index b52e5310..de2c3f9e 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | |||
@@ -2441,66 +2441,82 @@ void gk20a_fifo_issue_preempt(struct gk20a *g, u32 id, bool is_tsg) | |||
2441 | fifo_preempt_type_channel_f()); | 2441 | fifo_preempt_type_channel_f()); |
2442 | } | 2442 | } |
2443 | 2443 | ||
2444 | static int __locked_fifo_preempt(struct gk20a *g, u32 id, bool is_tsg) | 2444 | int gk20a_fifo_is_preempt_pending(struct gk20a *g, u32 id, |
2445 | unsigned int id_type, unsigned int timeout_rc_type) | ||
2445 | { | 2446 | { |
2446 | struct nvgpu_timeout timeout; | 2447 | struct nvgpu_timeout timeout; |
2447 | u32 delay = GR_IDLE_CHECK_DEFAULT; | 2448 | u32 delay = GR_IDLE_CHECK_DEFAULT; |
2448 | u32 ret = 0; | 2449 | int ret = -EBUSY; |
2449 | |||
2450 | gk20a_dbg_fn("%d", id); | ||
2451 | |||
2452 | /* issue preempt */ | ||
2453 | gk20a_fifo_issue_preempt(g, id, is_tsg); | ||
2454 | 2450 | ||
2455 | gk20a_dbg_fn("%d", id); | ||
2456 | /* wait for preempt */ | ||
2457 | ret = -EBUSY; | ||
2458 | nvgpu_timeout_init(g, &timeout, gk20a_get_gr_idle_timeout(g), | 2451 | nvgpu_timeout_init(g, &timeout, gk20a_get_gr_idle_timeout(g), |
2459 | NVGPU_TIMER_CPU_TIMER); | 2452 | NVGPU_TIMER_CPU_TIMER); |
2460 | do { | 2453 | do { |
2461 | if (!(gk20a_readl(g, fifo_preempt_r()) & | 2454 | if (!(gk20a_readl(g, fifo_preempt_r()) & |
2462 | fifo_preempt_pending_true_f())) { | 2455 | fifo_preempt_pending_true_f())) { |
2463 | ret = 0; | 2456 | ret = 0; |
2464 | break; | 2457 | break; |
2465 | } | 2458 | } |
2466 | 2459 | ||
2467 | usleep_range(delay, delay * 2); | 2460 | usleep_range(delay, delay * 2); |
2468 | delay = min_t(u32, delay << 1, GR_IDLE_CHECK_MAX); | 2461 | delay = min_t(u32, delay << 1, GR_IDLE_CHECK_MAX); |
2469 | } while (!nvgpu_timeout_expired(&timeout)); | 2462 | } while (!nvgpu_timeout_expired_msg(&timeout, "preempt timeout")); |
2470 | 2463 | ||
2471 | gk20a_dbg_fn("%d", id); | 2464 | return ret; |
2472 | if (ret) { | 2465 | } |
2473 | if (is_tsg) { | ||
2474 | struct tsg_gk20a *tsg = &g->fifo.tsg[id]; | ||
2475 | struct channel_gk20a *ch = NULL; | ||
2476 | 2466 | ||
2477 | gk20a_err(dev_from_gk20a(g), | 2467 | void __locked_fifo_preempt_timeout_rc(struct gk20a *g, u32 id, |
2478 | "preempt TSG %d timeout\n", id); | 2468 | unsigned int id_type) |
2469 | { | ||
2470 | if (id_type == ID_TYPE_TSG) { | ||
2471 | struct tsg_gk20a *tsg = &g->fifo.tsg[id]; | ||
2472 | struct channel_gk20a *ch = NULL; | ||
2479 | 2473 | ||
2480 | down_read(&tsg->ch_list_lock); | 2474 | gk20a_err(dev_from_gk20a(g), |
2481 | list_for_each_entry(ch, &tsg->ch_list, ch_entry) { | 2475 | "preempt TSG %d timeout\n", id); |
2482 | if (!gk20a_channel_get(ch)) | ||
2483 | continue; | ||
2484 | gk20a_set_error_notifier(ch, | ||
2485 | NVGPU_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); | ||
2486 | gk20a_channel_put(ch); | ||
2487 | } | ||
2488 | up_read(&tsg->ch_list_lock); | ||
2489 | gk20a_fifo_recover_tsg(g, id, true); | ||
2490 | } else { | ||
2491 | struct channel_gk20a *ch = &g->fifo.channel[id]; | ||
2492 | 2476 | ||
2493 | gk20a_err(dev_from_gk20a(g), | 2477 | down_read(&tsg->ch_list_lock); |
2494 | "preempt channel %d timeout\n", id); | 2478 | list_for_each_entry(ch, &tsg->ch_list, ch_entry) { |
2479 | if (!gk20a_channel_get(ch)) | ||
2480 | continue; | ||
2481 | gk20a_set_error_notifier(ch, | ||
2482 | NVGPU_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); | ||
2483 | gk20a_channel_put(ch); | ||
2484 | } | ||
2485 | up_read(&tsg->ch_list_lock); | ||
2486 | gk20a_fifo_recover_tsg(g, id, true); | ||
2487 | } else { | ||
2488 | struct channel_gk20a *ch = &g->fifo.channel[id]; | ||
2495 | 2489 | ||
2496 | if (gk20a_channel_get(ch)) { | 2490 | gk20a_err(dev_from_gk20a(g), |
2497 | gk20a_set_error_notifier(ch, | 2491 | "preempt channel %d timeout\n", id); |
2498 | NVGPU_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); | 2492 | |
2499 | gk20a_fifo_recover_ch(g, id, true); | 2493 | if (gk20a_channel_get(ch)) { |
2500 | gk20a_channel_put(ch); | 2494 | gk20a_set_error_notifier(ch, |
2501 | } | 2495 | NVGPU_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT); |
2496 | gk20a_fifo_recover_ch(g, id, true); | ||
2497 | gk20a_channel_put(ch); | ||
2502 | } | 2498 | } |
2503 | } | 2499 | } |
2500 | } | ||
2501 | |||
2502 | int __locked_fifo_preempt(struct gk20a *g, u32 id, bool is_tsg) | ||
2503 | { | ||
2504 | int ret; | ||
2505 | unsigned int id_type; | ||
2506 | |||
2507 | gk20a_dbg_fn("%d", id); | ||
2508 | |||
2509 | /* issue preempt */ | ||
2510 | gk20a_fifo_issue_preempt(g, id, is_tsg); | ||
2511 | |||
2512 | id_type = is_tsg ? ID_TYPE_TSG : ID_TYPE_CHANNEL; | ||
2513 | |||
2514 | /* wait for preempt */ | ||
2515 | ret = g->ops.fifo.is_preempt_pending(g, id, id_type, | ||
2516 | PREEMPT_TIMEOUT_RC); | ||
2517 | |||
2518 | if (ret) | ||
2519 | __locked_fifo_preempt_timeout_rc(g, id, id_type); | ||
2504 | 2520 | ||
2505 | return ret; | 2521 | return ret; |
2506 | } | 2522 | } |
@@ -3802,4 +3818,5 @@ void gk20a_init_fifo(struct gpu_ops *gops) | |||
3802 | gops->fifo.dump_eng_status = gk20a_dump_eng_status; | 3818 | gops->fifo.dump_eng_status = gk20a_dump_eng_status; |
3803 | gops->fifo.dump_channel_status_ramfc = gk20a_dump_channel_status_ramfc; | 3819 | gops->fifo.dump_channel_status_ramfc = gk20a_dump_channel_status_ramfc; |
3804 | gops->fifo.intr_0_error_mask = gk20a_fifo_intr_0_error_mask; | 3820 | gops->fifo.intr_0_error_mask = gk20a_fifo_intr_0_error_mask; |
3821 | gops->fifo.is_preempt_pending = gk20a_fifo_is_preempt_pending; | ||
3805 | } | 3822 | } |
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index 2de5e2d6..9793f37b 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | |||
@@ -25,11 +25,18 @@ | |||
25 | #include "tsg_gk20a.h" | 25 | #include "tsg_gk20a.h" |
26 | #include "debug_gk20a.h" | 26 | #include "debug_gk20a.h" |
27 | 27 | ||
28 | #define MAX_RUNLIST_BUFFERS 2 | 28 | #define MAX_RUNLIST_BUFFERS 2 |
29 | 29 | ||
30 | #define FIFO_INVAL_ENGINE_ID ((u32)~0) | 30 | #define FIFO_INVAL_ENGINE_ID ((u32)~0) |
31 | #define FIFO_INVAL_CHANNEL_ID ((u32)~0) | 31 | #define FIFO_INVAL_CHANNEL_ID ((u32)~0) |
32 | #define FIFO_INVAL_TSG_ID ((u32)~0) | 32 | #define FIFO_INVAL_TSG_ID ((u32)~0) |
33 | |||
34 | #define ID_TYPE_CHANNEL 0 | ||
35 | #define ID_TYPE_TSG 1 | ||
36 | #define ID_TYPE_UNKNOWN ((u32)~0) | ||
37 | |||
38 | #define PREEMPT_TIMEOUT_RC 1 | ||
39 | #define PREEMPT_TIMEOUT_NORC 0 | ||
33 | 40 | ||
34 | /* | 41 | /* |
35 | * Number of entries in the kickoff latency buffer, used to calculate | 42 | * Number of entries in the kickoff latency buffer, used to calculate |
@@ -336,4 +343,10 @@ struct channel_gk20a *gk20a_refch_from_inst_ptr(struct gk20a *g, u64 inst_ptr); | |||
336 | 343 | ||
337 | u32 gk20a_fifo_intr_0_error_mask(struct gk20a *g); | 344 | u32 gk20a_fifo_intr_0_error_mask(struct gk20a *g); |
338 | 345 | ||
346 | int gk20a_fifo_is_preempt_pending(struct gk20a *g, u32 id, unsigned int id_type, | ||
347 | unsigned int timeout_rc_type); | ||
348 | int __locked_fifo_preempt(struct gk20a *g, u32 id, bool is_tsg); | ||
349 | void __locked_fifo_preempt_timeout_rc(struct gk20a *g, u32 id, | ||
350 | unsigned int id_type); | ||
351 | |||
339 | #endif /*__GR_GK20A_H__*/ | 352 | #endif /*__GR_GK20A_H__*/ |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index c1e1b564..d5757130 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -450,6 +450,10 @@ struct gpu_ops { | |||
450 | struct gk20a_debug_output *o, u32 hw_chid, | 450 | struct gk20a_debug_output *o, u32 hw_chid, |
451 | struct ch_state *ch_state); | 451 | struct ch_state *ch_state); |
452 | u32 (*intr_0_error_mask)(struct gk20a *g); | 452 | u32 (*intr_0_error_mask)(struct gk20a *g); |
453 | int (*is_preempt_pending)(struct gk20a *g, u32 id, | ||
454 | unsigned int id_type, unsigned int timeout_rc_type); | ||
455 | int (*preempt_ch_tsg)(struct gk20a *g, u32 id, | ||
456 | unsigned int id_type, unsigned int timeout_rc_type); | ||
453 | } fifo; | 457 | } fifo; |
454 | struct pmu_v { | 458 | struct pmu_v { |
455 | /*used for change of enum zbc update cmd id from ver 0 to ver1*/ | 459 | /*used for change of enum zbc update cmd id from ver 0 to ver1*/ |
diff --git a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c index bf0fb018..0c270910 100644 --- a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c | |||
@@ -175,4 +175,5 @@ void gm20b_init_fifo(struct gpu_ops *gops) | |||
175 | gops->fifo.dump_eng_status = gk20a_dump_eng_status; | 175 | gops->fifo.dump_eng_status = gk20a_dump_eng_status; |
176 | gops->fifo.dump_channel_status_ramfc = gk20a_dump_channel_status_ramfc; | 176 | gops->fifo.dump_channel_status_ramfc = gk20a_dump_channel_status_ramfc; |
177 | gops->fifo.intr_0_error_mask = gk20a_fifo_intr_0_error_mask; | 177 | gops->fifo.intr_0_error_mask = gk20a_fifo_intr_0_error_mask; |
178 | gops->fifo.is_preempt_pending = gk20a_fifo_is_preempt_pending; | ||
178 | } | 179 | } |