diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_arb.c | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c index 1b974d17..f3d6cfab 100644 --- a/drivers/gpu/nvgpu/clk/clk_arb.c +++ b/drivers/gpu/nvgpu/clk/clk_arb.c | |||
@@ -83,6 +83,7 @@ struct nvgpu_clk_arb { | |||
83 | struct llist_head requests; | 83 | struct llist_head requests; |
84 | 84 | ||
85 | struct gk20a *g; | 85 | struct gk20a *g; |
86 | int status; | ||
86 | 87 | ||
87 | struct nvgpu_clk_arb_target actual_pool[2]; | 88 | struct nvgpu_clk_arb_target actual_pool[2]; |
88 | struct nvgpu_clk_arb_target *actual; | 89 | struct nvgpu_clk_arb_target *actual; |
@@ -269,7 +270,8 @@ int nvgpu_clk_arb_init_arbiter(struct gk20a *g) | |||
269 | atomic_read(&arb->req_nr)); | 270 | atomic_read(&arb->req_nr)); |
270 | } while (!atomic_read(&arb->req_nr)); | 271 | } while (!atomic_read(&arb->req_nr)); |
271 | 272 | ||
272 | return 0; | 273 | |
274 | return arb->status; | ||
273 | 275 | ||
274 | init_fail: | 276 | init_fail: |
275 | 277 | ||
@@ -533,6 +535,7 @@ static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | |||
533 | clk_cur = table->mclk_points[j].mhz; | 535 | clk_cur = table->mclk_points[j].mhz; |
534 | j++; | 536 | j++; |
535 | num_points++; | 537 | num_points++; |
538 | |||
536 | } | 539 | } |
537 | } | 540 | } |
538 | table->mclk_num_points = num_points; | 541 | table->mclk_num_points = num_points; |
@@ -605,7 +608,7 @@ static void nvgpu_clk_arb_run_vf_table_cb(struct work_struct *work) | |||
605 | err = clk_vf_point_cache(g); | 608 | err = clk_vf_point_cache(g); |
606 | if (err) { | 609 | if (err) { |
607 | gk20a_err(dev_from_gk20a(g), | 610 | gk20a_err(dev_from_gk20a(g), |
608 | "failed to get GPC2CLK SRAM voltage"); | 611 | "failed to cache VF table"); |
609 | return; | 612 | return; |
610 | } | 613 | } |
611 | nvgpu_clk_arb_update_vf_table(arb); | 614 | nvgpu_clk_arb_update_vf_table(arb); |
@@ -625,7 +628,7 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
625 | u32 voltuv, voltuv_sram; | 628 | u32 voltuv, voltuv_sram; |
626 | bool mclk_set, gpc2clk_set; | 629 | bool mclk_set, gpc2clk_set; |
627 | 630 | ||
628 | int status; | 631 | int status = 0; |
629 | 632 | ||
630 | /* Temporary variables for checking target frequency */ | 633 | /* Temporary variables for checking target frequency */ |
631 | u16 gpc2clk_target, mclk_target; | 634 | u16 gpc2clk_target, mclk_target; |
@@ -742,15 +745,21 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
742 | actual->gpc2clk = gpc2clk_target; | 745 | actual->gpc2clk = gpc2clk_target; |
743 | actual->mclk = mclk_target; | 746 | actual->mclk = mclk_target; |
744 | arb->voltuv_actual = voltuv; | 747 | arb->voltuv_actual = voltuv; |
748 | arb->status = status; | ||
745 | 749 | ||
746 | /* Make changes visible to other threads */ | 750 | /* Make changes visible to other threads */ |
747 | smp_wmb(); | 751 | smp_wmb(); |
748 | xchg(&arb->actual, actual); | 752 | xchg(&arb->actual, actual); |
749 | 753 | ||
754 | /* status must be visible before atomic inc */ | ||
755 | smp_wmb(); | ||
750 | atomic_inc(&arb->req_nr); | 756 | atomic_inc(&arb->req_nr); |
751 | 757 | ||
752 | wake_up_interruptible(&arb->request_wq); | 758 | wake_up_interruptible(&arb->request_wq); |
753 | 759 | ||
760 | if (status < 0) | ||
761 | gk20a_err(dev_from_gk20a(g), | ||
762 | "Error in arbiter update"); | ||
754 | 763 | ||
755 | #ifdef CONFIG_DEBUG_FS | 764 | #ifdef CONFIG_DEBUG_FS |
756 | g->ops.read_ptimer(g, &t1); | 765 | g->ops.read_ptimer(g, &t1); |
@@ -1016,20 +1025,23 @@ static void nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | |||
1016 | struct nvgpu_clk_vf_table *table; | 1025 | struct nvgpu_clk_vf_table *table; |
1017 | u32 index; | 1026 | u32 index; |
1018 | 1027 | ||
1019 | gpc2clk_target = *gpc2clk; | ||
1020 | mclk_target = *mclk; | ||
1021 | gpc2clk_voltuv = 0; | ||
1022 | gpc2clk_voltuv_sram = 0; | ||
1023 | mclk_voltuv = 0; | ||
1024 | mclk_voltuv_sram = 0; | ||
1025 | |||
1026 | do { | 1028 | do { |
1029 | gpc2clk_target = *gpc2clk; | ||
1030 | mclk_target = *mclk; | ||
1031 | gpc2clk_voltuv = 0; | ||
1032 | gpc2clk_voltuv_sram = 0; | ||
1033 | mclk_voltuv = 0; | ||
1034 | mclk_voltuv_sram = 0; | ||
1035 | |||
1027 | table = ACCESS_ONCE(arb->current_vf_table); | 1036 | table = ACCESS_ONCE(arb->current_vf_table); |
1028 | /* pointer to table can be updated by callback */ | 1037 | /* pointer to table can be updated by callback */ |
1029 | smp_rmb(); | 1038 | smp_rmb(); |
1030 | 1039 | ||
1031 | if (!table) | 1040 | if (!table) |
1032 | continue; | 1041 | continue; |
1042 | if ((!table->gpc2clk_num_points) || (!table->mclk_num_points)) | ||
1043 | goto find_exit; | ||
1044 | |||
1033 | /* round up the freq requests */ | 1045 | /* round up the freq requests */ |
1034 | for (index = 0; index < table->gpc2clk_num_points; index++) { | 1046 | for (index = 0; index < table->gpc2clk_num_points; index++) { |
1035 | if (table->gpc2clk_points[index].mhz >= | 1047 | if (table->gpc2clk_points[index].mhz >= |
@@ -1045,10 +1057,10 @@ static void nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | |||
1045 | } | 1057 | } |
1046 | 1058 | ||
1047 | if (index == table->gpc2clk_num_points) { | 1059 | if (index == table->gpc2clk_num_points) { |
1048 | gpc2clk_target = table->gpc2clk_points[index].mhz; | 1060 | gpc2clk_target = table->gpc2clk_points[index-1].mhz; |
1049 | gpc2clk_voltuv = table->gpc2clk_points[index].uvolt; | 1061 | gpc2clk_voltuv = table->gpc2clk_points[index-1].uvolt; |
1050 | gpc2clk_voltuv_sram = | 1062 | gpc2clk_voltuv_sram = |
1051 | table->gpc2clk_points[index].uvolt_sram; | 1063 | table->gpc2clk_points[index-1].uvolt_sram; |
1052 | } | 1064 | } |
1053 | 1065 | ||
1054 | for (index = 0; index < table->mclk_num_points; index++) { | 1066 | for (index = 0; index < table->mclk_num_points; index++) { |
@@ -1061,14 +1073,15 @@ static void nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | |||
1061 | } | 1073 | } |
1062 | } | 1074 | } |
1063 | if (index == table->mclk_num_points) { | 1075 | if (index == table->mclk_num_points) { |
1064 | mclk_target = table->mclk_points[index].mhz; | 1076 | mclk_target = table->mclk_points[index-1].mhz; |
1065 | mclk_voltuv = table->mclk_points[index].uvolt; | 1077 | mclk_voltuv = table->mclk_points[index-1].uvolt; |
1066 | mclk_voltuv_sram = | 1078 | mclk_voltuv_sram = |
1067 | table->mclk_points[index].uvolt_sram; | 1079 | table->mclk_points[index-1].uvolt_sram; |
1068 | } | 1080 | } |
1069 | } while (!table || | 1081 | } while (!table || |
1070 | (ACCESS_ONCE(arb->current_vf_table) != table)); | 1082 | (ACCESS_ONCE(arb->current_vf_table) != table)); |
1071 | 1083 | ||
1084 | find_exit: | ||
1072 | *voltuv = gpc2clk_voltuv > mclk_voltuv ? gpc2clk_voltuv : mclk_voltuv; | 1085 | *voltuv = gpc2clk_voltuv > mclk_voltuv ? gpc2clk_voltuv : mclk_voltuv; |
1073 | *voltuv_sram = gpc2clk_voltuv_sram > mclk_voltuv_sram ? | 1086 | *voltuv_sram = gpc2clk_voltuv_sram > mclk_voltuv_sram ? |
1074 | gpc2clk_voltuv_sram : mclk_voltuv_sram; | 1087 | gpc2clk_voltuv_sram : mclk_voltuv_sram; |
@@ -1136,7 +1149,6 @@ static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, | |||
1136 | status = clk_program_fll_clks(g, &fllclk); | 1149 | status = clk_program_fll_clks(g, &fllclk); |
1137 | if (status < 0) | 1150 | if (status < 0) |
1138 | return status; | 1151 | return status; |
1139 | |||
1140 | } | 1152 | } |
1141 | 1153 | ||
1142 | return 0; | 1154 | return 0; |