diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gv11b')
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/fifo_gv11b.c | 97 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/fifo_gv11b.h | 4 |
2 files changed, 68 insertions, 33 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c index be4d56a8..cc43ee33 100644 --- a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GV11B fifo | 2 | * GV11B fifo |
3 | * | 3 | * |
4 | * Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2015-2021, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), | 7 | * copy of this software and associated documentation files (the "Software"), |
@@ -498,7 +498,8 @@ static int gv11b_fifo_poll_pbdma_chan_status(struct gk20a *g, u32 id, | |||
498 | } | 498 | } |
499 | 499 | ||
500 | static int gv11b_fifo_poll_eng_ctx_status(struct gk20a *g, u32 id, | 500 | static int gv11b_fifo_poll_eng_ctx_status(struct gk20a *g, u32 id, |
501 | u32 act_eng_id, u32 *reset_eng_bitmask) | 501 | u32 act_eng_id, u32 *reset_eng_bitmask, |
502 | bool preempt_retries_left) | ||
502 | { | 503 | { |
503 | struct nvgpu_timeout timeout; | 504 | struct nvgpu_timeout timeout; |
504 | unsigned long delay = GR_IDLE_CHECK_DEFAULT; /* in micro seconds */ | 505 | unsigned long delay = GR_IDLE_CHECK_DEFAULT; /* in micro seconds */ |
@@ -507,6 +508,7 @@ static int gv11b_fifo_poll_eng_ctx_status(struct gk20a *g, u32 id, | |||
507 | int ret = -EBUSY; | 508 | int ret = -EBUSY; |
508 | unsigned int loop_count = 0; | 509 | unsigned int loop_count = 0; |
509 | u32 eng_intr_pending; | 510 | u32 eng_intr_pending; |
511 | bool check_preempt_retry = false; | ||
510 | 512 | ||
511 | /* timeout in milli seconds */ | 513 | /* timeout in milli seconds */ |
512 | nvgpu_timeout_init(g, &timeout, g->ops.fifo.get_preempt_timeout(g), | 514 | nvgpu_timeout_init(g, &timeout, g->ops.fifo.get_preempt_timeout(g), |
@@ -565,9 +567,7 @@ static int gv11b_fifo_poll_eng_ctx_status(struct gk20a *g, u32 id, | |||
565 | fifo_engine_status_ctx_status_ctxsw_switch_v()) { | 567 | fifo_engine_status_ctx_status_ctxsw_switch_v()) { |
566 | /* Eng save hasn't started yet. Continue polling */ | 568 | /* Eng save hasn't started yet. Continue polling */ |
567 | if (eng_intr_pending) { | 569 | if (eng_intr_pending) { |
568 | /* if eng intr, stop polling */ | 570 | check_preempt_retry = true; |
569 | *reset_eng_bitmask |= BIT(act_eng_id); | ||
570 | ret = 0; | ||
571 | break; | 571 | break; |
572 | } | 572 | } |
573 | 573 | ||
@@ -578,9 +578,7 @@ static int gv11b_fifo_poll_eng_ctx_status(struct gk20a *g, u32 id, | |||
578 | 578 | ||
579 | if (id == fifo_engine_status_id_v(eng_stat)) { | 579 | if (id == fifo_engine_status_id_v(eng_stat)) { |
580 | if (eng_intr_pending) { | 580 | if (eng_intr_pending) { |
581 | /* preemption will not finish */ | 581 | check_preempt_retry = true; |
582 | *reset_eng_bitmask |= BIT(act_eng_id); | ||
583 | ret = 0; | ||
584 | break; | 582 | break; |
585 | } | 583 | } |
586 | } else { | 584 | } else { |
@@ -594,9 +592,7 @@ static int gv11b_fifo_poll_eng_ctx_status(struct gk20a *g, u32 id, | |||
594 | 592 | ||
595 | if (id == fifo_engine_status_next_id_v(eng_stat)) { | 593 | if (id == fifo_engine_status_next_id_v(eng_stat)) { |
596 | if (eng_intr_pending) { | 594 | if (eng_intr_pending) { |
597 | /* preemption will not finish */ | 595 | check_preempt_retry = true; |
598 | *reset_eng_bitmask |= BIT(act_eng_id); | ||
599 | ret = 0; | ||
600 | break; | 596 | break; |
601 | } | 597 | } |
602 | } else { | 598 | } else { |
@@ -606,8 +602,13 @@ static int gv11b_fifo_poll_eng_ctx_status(struct gk20a *g, u32 id, | |||
606 | } | 602 | } |
607 | 603 | ||
608 | } else { | 604 | } else { |
609 | /* Preempt should be finished */ | 605 | if (eng_intr_pending) { |
610 | ret = 0; | 606 | check_preempt_retry = true; |
607 | } else { | ||
608 | /* Preempt should be finished */ | ||
609 | ret = 0; | ||
610 | } | ||
611 | |||
611 | break; | 612 | break; |
612 | } | 613 | } |
613 | nvgpu_usleep_range(delay, delay * 2); | 614 | nvgpu_usleep_range(delay, delay * 2); |
@@ -615,7 +616,19 @@ static int gv11b_fifo_poll_eng_ctx_status(struct gk20a *g, u32 id, | |||
615 | delay << 1, GR_IDLE_CHECK_MAX); | 616 | delay << 1, GR_IDLE_CHECK_MAX); |
616 | } while (!nvgpu_timeout_expired(&timeout)); | 617 | } while (!nvgpu_timeout_expired(&timeout)); |
617 | 618 | ||
618 | if (ret) { | 619 | |
620 | /* if eng intr, stop polling and check if we can retry preempts. */ | ||
621 | if (check_preempt_retry) { | ||
622 | if (preempt_retries_left) { | ||
623 | ret = -EAGAIN; | ||
624 | } else { | ||
625 | /* preemption will not finish */ | ||
626 | *reset_eng_bitmask |= BIT32(act_eng_id); | ||
627 | ret = 0; | ||
628 | } | ||
629 | } | ||
630 | |||
631 | if (ret && ret != -EAGAIN) { | ||
619 | /* | 632 | /* |
620 | * The reasons a preempt can fail are: | 633 | * The reasons a preempt can fail are: |
621 | * 1.Some other stalling interrupt is asserted preventing | 634 | * 1.Some other stalling interrupt is asserted preventing |
@@ -770,7 +783,7 @@ static void gv11b_fifo_issue_runlist_preempt(struct gk20a *g, | |||
770 | } | 783 | } |
771 | 784 | ||
772 | int gv11b_fifo_is_preempt_pending(struct gk20a *g, u32 id, | 785 | int gv11b_fifo_is_preempt_pending(struct gk20a *g, u32 id, |
773 | unsigned int id_type) | 786 | unsigned int id_type, bool preempt_retries_left) |
774 | { | 787 | { |
775 | struct fifo_gk20a *f = &g->fifo; | 788 | struct fifo_gk20a *f = &g->fifo; |
776 | unsigned long runlist_served_pbdmas; | 789 | unsigned long runlist_served_pbdmas; |
@@ -778,7 +791,7 @@ int gv11b_fifo_is_preempt_pending(struct gk20a *g, u32 id, | |||
778 | u32 pbdma_id; | 791 | u32 pbdma_id; |
779 | u32 act_eng_id; | 792 | u32 act_eng_id; |
780 | u32 runlist_id; | 793 | u32 runlist_id; |
781 | int ret = 0; | 794 | int err, ret = 0; |
782 | u32 tsgid; | 795 | u32 tsgid; |
783 | 796 | ||
784 | if (id_type == ID_TYPE_TSG) { | 797 | if (id_type == ID_TYPE_TSG) { |
@@ -795,14 +808,21 @@ int gv11b_fifo_is_preempt_pending(struct gk20a *g, u32 id, | |||
795 | runlist_served_engines = f->runlist_info[runlist_id].eng_bitmask; | 808 | runlist_served_engines = f->runlist_info[runlist_id].eng_bitmask; |
796 | 809 | ||
797 | for_each_set_bit(pbdma_id, &runlist_served_pbdmas, f->num_pbdma) { | 810 | for_each_set_bit(pbdma_id, &runlist_served_pbdmas, f->num_pbdma) { |
798 | ret |= gv11b_fifo_poll_pbdma_chan_status(g, tsgid, pbdma_id); | 811 | err = gv11b_fifo_poll_pbdma_chan_status(g, tsgid, pbdma_id); |
812 | if (err != 0) { | ||
813 | ret = err; | ||
814 | } | ||
799 | } | 815 | } |
800 | 816 | ||
801 | f->runlist_info[runlist_id].reset_eng_bitmask = 0; | 817 | f->runlist_info[runlist_id].reset_eng_bitmask = 0; |
802 | 818 | ||
803 | for_each_set_bit(act_eng_id, &runlist_served_engines, f->max_engines) { | 819 | for_each_set_bit(act_eng_id, &runlist_served_engines, f->max_engines) { |
804 | ret |= gv11b_fifo_poll_eng_ctx_status(g, tsgid, act_eng_id, | 820 | err = gv11b_fifo_poll_eng_ctx_status(g, tsgid, act_eng_id, |
805 | &f->runlist_info[runlist_id].reset_eng_bitmask); | 821 | &f->runlist_info[runlist_id].reset_eng_bitmask, |
822 | preempt_retries_left); | ||
823 | if ((err != 0) && (ret == 0)) { | ||
824 | ret = err; | ||
825 | } | ||
806 | } | 826 | } |
807 | return ret; | 827 | return ret; |
808 | } | 828 | } |
@@ -847,10 +867,13 @@ int gv11b_fifo_enable_tsg(struct tsg_gk20a *tsg) | |||
847 | int gv11b_fifo_preempt_tsg(struct gk20a *g, struct tsg_gk20a *tsg) | 867 | int gv11b_fifo_preempt_tsg(struct gk20a *g, struct tsg_gk20a *tsg) |
848 | { | 868 | { |
849 | struct fifo_gk20a *f = &g->fifo; | 869 | struct fifo_gk20a *f = &g->fifo; |
850 | u32 ret = 0; | 870 | int ret = 0; |
851 | u32 token = PMU_INVALID_MUTEX_OWNER_ID; | 871 | u32 token = PMU_INVALID_MUTEX_OWNER_ID; |
852 | u32 mutex_ret = 0; | 872 | u32 mutex_ret = 0; |
853 | u32 runlist_id; | 873 | u32 runlist_id; |
874 | u32 preempt_retry_count = 10U; | ||
875 | u32 preempt_retry_timeout = | ||
876 | g->ops.fifo.get_preempt_timeout(g) / preempt_retry_count; | ||
854 | 877 | ||
855 | nvgpu_log_fn(g, "tsgid: %d", tsg->tsgid); | 878 | nvgpu_log_fn(g, "tsgid: %d", tsg->tsgid); |
856 | 879 | ||
@@ -860,23 +883,35 @@ int gv11b_fifo_preempt_tsg(struct gk20a *g, struct tsg_gk20a *tsg) | |||
860 | return 0; | 883 | return 0; |
861 | } | 884 | } |
862 | 885 | ||
863 | nvgpu_mutex_acquire(&f->runlist_info[runlist_id].runlist_lock); | 886 | do { |
887 | nvgpu_mutex_acquire(&f->runlist_info[runlist_id].runlist_lock); | ||
864 | 888 | ||
865 | /* WAR for Bug 2065990 */ | 889 | /* WAR for Bug 2065990 */ |
866 | gk20a_fifo_disable_tsg_sched(g, tsg); | 890 | gk20a_fifo_disable_tsg_sched(g, tsg); |
867 | 891 | ||
868 | mutex_ret = nvgpu_pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | 892 | mutex_ret = nvgpu_pmu_mutex_acquire(&g->pmu, PMU_MUTEX_ID_FIFO, &token); |
869 | 893 | ||
870 | ret = __locked_fifo_preempt(g, tsg->tsgid, true); | 894 | ret = __locked_fifo_preempt(g, tsg->tsgid, true, |
895 | preempt_retry_count > 1U); | ||
871 | 896 | ||
872 | if (!mutex_ret) { | 897 | if (!mutex_ret) { |
873 | nvgpu_pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); | 898 | nvgpu_pmu_mutex_release(&g->pmu, PMU_MUTEX_ID_FIFO, &token); |
874 | } | 899 | } |
900 | |||
901 | /* WAR for Bug 2065990 */ | ||
902 | gk20a_fifo_enable_tsg_sched(g, tsg); | ||
875 | 903 | ||
876 | /* WAR for Bug 2065990 */ | 904 | nvgpu_mutex_release(&f->runlist_info[runlist_id].runlist_lock); |
877 | gk20a_fifo_enable_tsg_sched(g, tsg); | ||
878 | 905 | ||
879 | nvgpu_mutex_release(&f->runlist_info[runlist_id].runlist_lock); | 906 | if (ret != -EAGAIN) { |
907 | break; | ||
908 | } | ||
909 | |||
910 | ret = nvgpu_wait_for_stall_interrupts(g, preempt_retry_timeout); | ||
911 | if (ret != 0) { | ||
912 | nvgpu_log_info(g, "wait for stall interrupts failed %d", ret); | ||
913 | } | ||
914 | } while (--preempt_retry_count != 0U); | ||
880 | 915 | ||
881 | if (ret) { | 916 | if (ret) { |
882 | if (nvgpu_platform_is_silicon(g)) { | 917 | if (nvgpu_platform_is_silicon(g)) { |
diff --git a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.h b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.h index abbf77a6..4e6bd6ba 100644 --- a/drivers/gpu/nvgpu/gv11b/fifo_gv11b.h +++ b/drivers/gpu/nvgpu/gv11b/fifo_gv11b.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GV11B Fifo | 2 | * GV11B Fifo |
3 | * | 3 | * |
4 | * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2016-2021, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), | 7 | * copy of this software and associated documentation files (the "Software"), |
@@ -80,7 +80,7 @@ void gv11b_dump_eng_status(struct gk20a *g, | |||
80 | u32 gv11b_fifo_intr_0_error_mask(struct gk20a *g); | 80 | u32 gv11b_fifo_intr_0_error_mask(struct gk20a *g); |
81 | int gv11b_fifo_reschedule_runlist(struct channel_gk20a *ch, bool preempt_next); | 81 | int gv11b_fifo_reschedule_runlist(struct channel_gk20a *ch, bool preempt_next); |
82 | int gv11b_fifo_is_preempt_pending(struct gk20a *g, u32 id, | 82 | int gv11b_fifo_is_preempt_pending(struct gk20a *g, u32 id, |
83 | unsigned int id_type); | 83 | unsigned int id_type, bool preempt_retries_left); |
84 | int gv11b_fifo_preempt_channel(struct gk20a *g, struct channel_gk20a *ch); | 84 | int gv11b_fifo_preempt_channel(struct gk20a *g, struct channel_gk20a *ch); |
85 | int gv11b_fifo_preempt_tsg(struct gk20a *g, struct tsg_gk20a *tsg); | 85 | int gv11b_fifo_preempt_tsg(struct gk20a *g, struct tsg_gk20a *tsg); |
86 | int gv11b_fifo_enable_tsg(struct tsg_gk20a *tsg); | 86 | int gv11b_fifo_enable_tsg(struct tsg_gk20a *tsg); |