summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/clk/clk_arb.c
diff options
context:
space:
mode:
authorDebarshi Dutta <ddutta@nvidia.com>2018-06-26 06:11:12 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-09-04 10:25:41 -0400
commit16ad9f537979c5f3717fc5781b1c2fad22a76f96 (patch)
tree2a150c50983180051fa5ecc942764e081961d787 /drivers/gpu/nvgpu/clk/clk_arb.c
parentf125d1b681c324d5d58abcc42fac1301e1faa921 (diff)
gpu: nvgpu: move gp106 specific clk_arbiter code into HAL
Currently, clock arbiter code is extensively using dgpu specific implementation. This patch restructures the clk_arbiter code and moves gp106 specific code into HAL. Following changes are made in this patch 1) clk_domain_get_f_points is now invoked via HAL for gp106 i.e. g->ops.clk.clk_domain_get_f_points. 2) moved nvgpu_clk_arb_change_vf_point and other related static functions to clk_arb_gp106.c. 3) Instead of only checking if get_arbiter_clk_domain is empty, a check for support_clk_freq_controller is also added. This is to enable the clk_arbiter based on support from both the OS and the chips. Bug 2061372 Change-Id: I65b0a4e02145a86fbbfb420ed591b1fa3c86f6dc Signed-off-by: Debarshi Dutta <ddutta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1774279 Reviewed-by: svc-misra-checker <svc-misra-checker@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Deepak Nibade <dnibade@nvidia.com> Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/clk/clk_arb.c')
-rw-r--r--drivers/gpu/nvgpu/clk/clk_arb.c668
1 files changed, 22 insertions, 646 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c
index 357a1416..983a82f9 100644
--- a/drivers/gpu/nvgpu/clk/clk_arb.c
+++ b/drivers/gpu/nvgpu/clk/clk_arb.c
@@ -78,7 +78,7 @@ static void nvgpu_clk_arb_queue_notification(struct gk20a *g,
78 78
79} 79}
80 80
81static void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm) 81void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm)
82{ 82{
83 struct nvgpu_clk_arb *arb = g->clk_arb; 83 struct nvgpu_clk_arb *arb = g->clk_arb;
84 84
@@ -103,7 +103,7 @@ static void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm)
103} 103}
104 104
105 105
106static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) 106int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb)
107{ 107{
108 struct gk20a *g = arb->g; 108 struct gk20a *g = arb->g;
109 struct nvgpu_clk_vf_table *table; 109 struct nvgpu_clk_vf_table *table;
@@ -117,7 +117,6 @@ static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb)
117 117
118 struct clk_set_info *p5_info, *p0_info; 118 struct clk_set_info *p5_info, *p0_info;
119 119
120
121 table = NV_ACCESS_ONCE(arb->current_vf_table); 120 table = NV_ACCESS_ONCE(arb->current_vf_table);
122 /* make flag visible when all data has resolved in the tables */ 121 /* make flag visible when all data has resolved in the tables */
123 nvgpu_smp_rmb(); 122 nvgpu_smp_rmb();
@@ -142,13 +141,13 @@ static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb)
142 table->gpc2clk_num_points = MAX_F_POINTS; 141 table->gpc2clk_num_points = MAX_F_POINTS;
143 table->mclk_num_points = MAX_F_POINTS; 142 table->mclk_num_points = MAX_F_POINTS;
144 143
145 if (clk_domain_get_f_points(arb->g, CTRL_CLK_DOMAIN_GPC2CLK, 144 if (g->ops.clk.clk_domain_get_f_points(arb->g, CTRL_CLK_DOMAIN_GPC2CLK,
146 &table->gpc2clk_num_points, arb->gpc2clk_f_points)) { 145 &table->gpc2clk_num_points, arb->gpc2clk_f_points)) {
147 nvgpu_err(g, "failed to fetch GPC2CLK frequency points"); 146 nvgpu_err(g, "failed to fetch GPC2CLK frequency points");
148 goto exit_vf_table; 147 goto exit_vf_table;
149 } 148 }
150 149
151 if (clk_domain_get_f_points(arb->g, CTRL_CLK_DOMAIN_MCLK, 150 if (g->ops.clk.clk_domain_get_f_points(arb->g, CTRL_CLK_DOMAIN_MCLK,
152 &table->mclk_num_points, arb->mclk_f_points)) { 151 &table->mclk_num_points, arb->mclk_f_points)) {
153 nvgpu_err(g, "failed to fetch MCLK frequency points"); 152 nvgpu_err(g, "failed to fetch MCLK frequency points");
154 goto exit_vf_table; 153 goto exit_vf_table;
@@ -427,185 +426,7 @@ static void nvgpu_clk_arb_run_vf_table_cb(struct nvgpu_clk_arb *arb)
427 nvgpu_clk_arb_update_vf_table(arb); 426 nvgpu_clk_arb_update_vf_table(arb);
428} 427}
429 428
430static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, 429u32 nvgpu_clk_arb_notify(struct nvgpu_clk_dev *dev,
431 u16 *gpc2clk, u16 *sys2clk, u16 *xbar2clk, u16 *mclk,
432 u32 *voltuv, u32 *voltuv_sram, u32 *nuvmin, u32 *nuvmin_sram)
433{
434 u16 gpc2clk_target, mclk_target;
435 u32 gpc2clk_voltuv, gpc2clk_voltuv_sram;
436 u32 mclk_voltuv, mclk_voltuv_sram;
437 u32 pstate = VF_POINT_INVALID_PSTATE;
438 struct nvgpu_clk_vf_table *table;
439 u32 index, index_mclk;
440 struct nvgpu_clk_vf_point *mclk_vf = NULL;
441
442 do {
443 gpc2clk_target = *gpc2clk;
444 mclk_target = *mclk;
445 gpc2clk_voltuv = 0;
446 gpc2clk_voltuv_sram = 0;
447 mclk_voltuv = 0;
448 mclk_voltuv_sram = 0;
449
450 table = NV_ACCESS_ONCE(arb->current_vf_table);
451 /* pointer to table can be updated by callback */
452 nvgpu_smp_rmb();
453
454 if (!table)
455 continue;
456 if ((!table->gpc2clk_num_points) || (!table->mclk_num_points)) {
457 nvgpu_err(arb->g, "found empty table");
458 goto find_exit;
459 }
460 /* First we check MCLK to find out which PSTATE we are
461 * are requesting, and from there try to find the minimum
462 * GPC2CLK on the same PSTATE that satisfies the request.
463 * If no GPC2CLK can be found, then we need to up the PSTATE
464 */
465
466recalculate_vf_point:
467 for (index = 0; index < table->mclk_num_points; index++) {
468 if (table->mclk_points[index].mem_mhz >= mclk_target) {
469 mclk_vf = &table->mclk_points[index];
470 break;
471 }
472 }
473 if (index == table->mclk_num_points) {
474 mclk_vf = &table->mclk_points[index-1];
475 index = table->mclk_num_points - 1;
476 }
477 index_mclk = index;
478
479 /* round up the freq requests */
480 for (index = 0; index < table->gpc2clk_num_points; index++) {
481 pstate = VF_POINT_COMMON_PSTATE(
482 &table->gpc2clk_points[index], mclk_vf);
483
484 if ((table->gpc2clk_points[index].gpc_mhz >=
485 gpc2clk_target) &&
486 (pstate != VF_POINT_INVALID_PSTATE)) {
487 gpc2clk_target =
488 table->gpc2clk_points[index].gpc_mhz;
489 *sys2clk =
490 table->gpc2clk_points[index].sys_mhz;
491 *xbar2clk =
492 table->gpc2clk_points[index].xbar_mhz;
493
494 gpc2clk_voltuv =
495 table->gpc2clk_points[index].uvolt;
496 gpc2clk_voltuv_sram =
497 table->gpc2clk_points[index].uvolt_sram;
498 break;
499 }
500 }
501
502 if (index == table->gpc2clk_num_points) {
503 pstate = VF_POINT_COMMON_PSTATE(
504 &table->gpc2clk_points[index-1], mclk_vf);
505 if (pstate != VF_POINT_INVALID_PSTATE) {
506 gpc2clk_target =
507 table->gpc2clk_points[index-1].gpc_mhz;
508 *sys2clk =
509 table->gpc2clk_points[index-1].sys_mhz;
510 *xbar2clk =
511 table->gpc2clk_points[index-1].xbar_mhz;
512
513 gpc2clk_voltuv =
514 table->gpc2clk_points[index-1].uvolt;
515 gpc2clk_voltuv_sram =
516 table->gpc2clk_points[index-1].
517 uvolt_sram;
518 } else if (index_mclk >= table->mclk_num_points - 1) {
519 /* There is no available combination of MCLK
520 * and GPC2CLK, we need to fail this
521 */
522 gpc2clk_target = 0;
523 mclk_target = 0;
524 pstate = VF_POINT_INVALID_PSTATE;
525 goto find_exit;
526 } else {
527 /* recalculate with higher PSTATE */
528 gpc2clk_target = *gpc2clk;
529 mclk_target = table->mclk_points[index_mclk+1].
530 mem_mhz;
531 goto recalculate_vf_point;
532 }
533 }
534
535 mclk_target = mclk_vf->mem_mhz;
536 mclk_voltuv = mclk_vf->uvolt;
537 mclk_voltuv_sram = mclk_vf->uvolt_sram;
538
539 } while (!table ||
540 (NV_ACCESS_ONCE(arb->current_vf_table) != table));
541
542find_exit:
543 *voltuv = gpc2clk_voltuv > mclk_voltuv ? gpc2clk_voltuv : mclk_voltuv;
544 *voltuv_sram = gpc2clk_voltuv_sram > mclk_voltuv_sram ?
545 gpc2clk_voltuv_sram : mclk_voltuv_sram;
546 /* noise unaware vmin */
547 *nuvmin = mclk_voltuv;
548 *nuvmin_sram = mclk_voltuv_sram;
549 *gpc2clk = gpc2clk_target;
550 *mclk = mclk_target;
551 return pstate;
552}
553
554static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target,
555 u16 sys2clk_target, u16 xbar2clk_target, u16 mclk_target, u32 voltuv,
556 u32 voltuv_sram)
557{
558 struct set_fll_clk fllclk;
559 struct nvgpu_clk_arb *arb = g->clk_arb;
560 int status;
561
562 fllclk.gpc2clkmhz = gpc2clk_target;
563 fllclk.sys2clkmhz = sys2clk_target;
564 fllclk.xbar2clkmhz = xbar2clk_target;
565
566 fllclk.voltuv = voltuv;
567
568 /* if voltage ascends we do:
569 * (1) FLL change
570 * (2) Voltage change
571 * (3) MCLK change
572 * If it goes down
573 * (1) MCLK change
574 * (2) Voltage change
575 * (3) FLL change
576 */
577
578 /* descending */
579 if (voltuv < arb->voltuv_actual) {
580 status = g->ops.clk.mclk_change(g, mclk_target);
581 if (status < 0)
582 return status;
583
584 status = volt_set_voltage(g, voltuv, voltuv_sram);
585 if (status < 0)
586 return status;
587
588 status = clk_set_fll_clks(g, &fllclk);
589 if (status < 0)
590 return status;
591 } else {
592 status = clk_set_fll_clks(g, &fllclk);
593 if (status < 0)
594 return status;
595
596 status = volt_set_voltage(g, voltuv, voltuv_sram);
597 if (status < 0)
598 return status;
599
600 status = g->ops.clk.mclk_change(g, mclk_target);
601 if (status < 0)
602 return status;
603 }
604
605 return 0;
606}
607
608static u32 nvgpu_clk_arb_notify(struct nvgpu_clk_dev *dev,
609 struct nvgpu_clk_arb_target *target, 430 struct nvgpu_clk_arb_target *target,
610 u32 alarm) { 431 u32 alarm) {
611 432
@@ -704,7 +525,7 @@ static u32 nvgpu_clk_arb_notify(struct nvgpu_clk_dev *dev,
704 return new_alarms_reported; 525 return new_alarms_reported;
705} 526}
706 527
707static void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm) 528void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm)
708{ 529{
709 struct nvgpu_clk_arb *arb = g->clk_arb; 530 struct nvgpu_clk_arb *arb = g->clk_arb;
710 531
@@ -726,318 +547,20 @@ static void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm)
726 current_mask, new_mask))); 547 current_mask, new_mask)));
727} 548}
728 549
729static void nvgpu_clk_arb_run_arbiter_cb(struct nvgpu_clk_arb *arb)
730{
731 struct nvgpu_clk_session *session;
732 struct nvgpu_clk_dev *dev;
733 struct nvgpu_clk_dev *tmp;
734 struct nvgpu_clk_arb_target *target, *actual;
735 struct gk20a *g = arb->g;
736
737 u32 pstate = VF_POINT_INVALID_PSTATE;
738 u32 voltuv, voltuv_sram;
739 bool mclk_set, gpc2clk_set;
740 u32 nuvmin, nuvmin_sram;
741
742 u32 alarms_notified = 0;
743 u32 current_alarm;
744 int status = 0;
745
746 /* Temporary variables for checking target frequency */
747 u16 gpc2clk_target, sys2clk_target, xbar2clk_target, mclk_target;
748 u16 gpc2clk_session_target, mclk_session_target;
749
750#ifdef CONFIG_DEBUG_FS
751 u64 t0, t1;
752 struct nvgpu_clk_arb_debug *debug;
753
754#endif
755
756 clk_arb_dbg(g, " ");
757
758 /* bail out if gpu is down */
759 if (nvgpu_atomic64_read(&arb->alarm_mask) & EVENT(ALARM_GPU_LOST))
760 goto exit_arb;
761
762#ifdef CONFIG_DEBUG_FS
763 g->ops.ptimer.read_ptimer(g, &t0);
764#endif
765
766 /* Only one arbiter should be running */
767 gpc2clk_target = 0;
768 mclk_target = 0;
769
770 nvgpu_spinlock_acquire(&arb->sessions_lock);
771 nvgpu_list_for_each_entry(session, &arb->sessions,
772 nvgpu_clk_session, link) {
773 if (!session->zombie) {
774 mclk_set = false;
775 gpc2clk_set = false;
776 target = (session->target == &session->target_pool[0] ?
777 &session->target_pool[1] :
778 &session->target_pool[0]);
779 nvgpu_spinlock_acquire(&session->session_lock);
780 if (!nvgpu_list_empty(&session->targets)) {
781 /* Copy over state */
782 target->mclk = session->target->mclk;
783 target->gpc2clk = session->target->gpc2clk;
784 /* Query the latest committed request */
785 nvgpu_list_for_each_entry_safe(dev, tmp, &session->targets,
786 nvgpu_clk_dev, node) {
787 if (!mclk_set && dev->mclk_target_mhz) {
788 target->mclk =
789 dev->mclk_target_mhz;
790 mclk_set = true;
791 }
792 if (!gpc2clk_set &&
793 dev->gpc2clk_target_mhz) {
794 target->gpc2clk =
795 dev->gpc2clk_target_mhz;
796 gpc2clk_set = true;
797 }
798 nvgpu_ref_get(&dev->refcount);
799 nvgpu_list_del(&dev->node);
800 nvgpu_spinlock_acquire(&arb->requests_lock);
801 nvgpu_list_add(&dev->node, &arb->requests);
802 nvgpu_spinlock_release(&arb->requests_lock);
803 }
804 session->target = target;
805 }
806 nvgpu_spinlock_release(&session->session_lock);
807
808 mclk_target = mclk_target > session->target->mclk ?
809 mclk_target : session->target->mclk;
810
811 gpc2clk_target =
812 gpc2clk_target > session->target->gpc2clk ?
813 gpc2clk_target : session->target->gpc2clk;
814 }
815 }
816 nvgpu_spinlock_release(&arb->sessions_lock);
817
818 gpc2clk_target = (gpc2clk_target > 0) ? gpc2clk_target :
819 arb->gpc2clk_default_mhz;
820
821 if (gpc2clk_target < arb->gpc2clk_min)
822 gpc2clk_target = arb->gpc2clk_min;
823
824 if (gpc2clk_target > arb->gpc2clk_max)
825 gpc2clk_target = arb->gpc2clk_max;
826
827 mclk_target = (mclk_target > 0) ? mclk_target :
828 arb->mclk_default_mhz;
829
830 if (mclk_target < arb->mclk_min)
831 mclk_target = arb->mclk_min;
832
833 if (mclk_target > arb->mclk_max)
834 mclk_target = arb->mclk_max;
835
836 sys2clk_target = 0;
837 xbar2clk_target = 0;
838
839 gpc2clk_session_target = gpc2clk_target;
840 mclk_session_target = mclk_target;
841
842 /* Query the table for the closest vf point to program */
843 pstate = nvgpu_clk_arb_find_vf_point(arb, &gpc2clk_target,
844 &sys2clk_target, &xbar2clk_target, &mclk_target, &voltuv,
845 &voltuv_sram, &nuvmin, &nuvmin_sram);
846
847 if (pstate == VF_POINT_INVALID_PSTATE) {
848 arb->status = -EINVAL;
849 /* make status visible */
850 nvgpu_smp_mb();
851 goto exit_arb;
852 }
853
854 if ((gpc2clk_target < gpc2clk_session_target) ||
855 (mclk_target < mclk_session_target))
856 nvgpu_clk_arb_set_global_alarm(g,
857 EVENT(ALARM_TARGET_VF_NOT_POSSIBLE));
858
859 if ((arb->actual->gpc2clk == gpc2clk_target) &&
860 (arb->actual->mclk == mclk_target) &&
861 (arb->voltuv_actual == voltuv)) {
862 goto exit_arb;
863 }
864
865 /* Program clocks */
866 /* A change in both mclk of gpc2clk may require a change in voltage */
867
868 nvgpu_mutex_acquire(&arb->pstate_lock);
869 status = nvgpu_lpwr_disable_pg(g, false);
870
871 status = clk_pmu_freq_controller_load(g, false,
872 CTRL_CLK_CLK_FREQ_CONTROLLER_ID_ALL);
873 if (status < 0) {
874 arb->status = status;
875 nvgpu_mutex_release(&arb->pstate_lock);
876
877 /* make status visible */
878 nvgpu_smp_mb();
879 goto exit_arb;
880 }
881 status = volt_set_noiseaware_vmin(g, nuvmin, nuvmin_sram);
882 if (status < 0) {
883 arb->status = status;
884 nvgpu_mutex_release(&arb->pstate_lock);
885
886 /* make status visible */
887 nvgpu_smp_mb();
888 goto exit_arb;
889 }
890
891 status = nvgpu_clk_arb_change_vf_point(g, gpc2clk_target,
892 sys2clk_target, xbar2clk_target, mclk_target, voltuv,
893 voltuv_sram);
894 if (status < 0) {
895 arb->status = status;
896 nvgpu_mutex_release(&arb->pstate_lock);
897
898 /* make status visible */
899 nvgpu_smp_mb();
900 goto exit_arb;
901 }
902
903 status = clk_pmu_freq_controller_load(g, true,
904 CTRL_CLK_CLK_FREQ_CONTROLLER_ID_ALL);
905 if (status < 0) {
906 arb->status = status;
907 nvgpu_mutex_release(&arb->pstate_lock);
908
909 /* make status visible */
910 nvgpu_smp_mb();
911 goto exit_arb;
912 }
913
914 status = nvgpu_lwpr_mclk_change(g, pstate);
915 if (status < 0) {
916 arb->status = status;
917 nvgpu_mutex_release(&arb->pstate_lock);
918
919 /* make status visible */
920 nvgpu_smp_mb();
921 goto exit_arb;
922 }
923
924 actual = NV_ACCESS_ONCE(arb->actual) == &arb->actual_pool[0] ?
925 &arb->actual_pool[1] : &arb->actual_pool[0];
926
927 /* do not reorder this pointer */
928 nvgpu_smp_rmb();
929 actual->gpc2clk = gpc2clk_target;
930 actual->mclk = mclk_target;
931 arb->voltuv_actual = voltuv;
932 actual->pstate = pstate;
933 arb->status = status;
934
935 /* Make changes visible to other threads */
936 nvgpu_smp_wmb();
937 arb->actual = actual;
938
939 status = nvgpu_lpwr_enable_pg(g, false);
940 if (status < 0) {
941 arb->status = status;
942 nvgpu_mutex_release(&arb->pstate_lock);
943
944 /* make status visible */
945 nvgpu_smp_mb();
946 goto exit_arb;
947 }
948
949 /* status must be visible before atomic inc */
950 nvgpu_smp_wmb();
951 nvgpu_atomic_inc(&arb->req_nr);
952
953 /* Unlock pstate change for PG */
954 nvgpu_mutex_release(&arb->pstate_lock);
955
956 /* VF Update complete */
957 nvgpu_clk_arb_set_global_alarm(g, EVENT(VF_UPDATE));
958
959 nvgpu_cond_signal_interruptible(&arb->request_wq);
960
961#ifdef CONFIG_DEBUG_FS
962 g->ops.ptimer.read_ptimer(g, &t1);
963
964 debug = arb->debug == &arb->debug_pool[0] ?
965 &arb->debug_pool[1] : &arb->debug_pool[0];
966
967 memcpy(debug, arb->debug, sizeof(arb->debug_pool[0]));
968 debug->switch_num++;
969
970 if (debug->switch_num == 1) {
971 debug->switch_max = debug->switch_min =
972 debug->switch_avg = (t1-t0)/1000;
973 debug->switch_std = 0;
974 } else {
975 s64 prev_avg;
976 s64 curr = (t1-t0)/1000;
977
978 debug->switch_max = curr > debug->switch_max ?
979 curr : debug->switch_max;
980 debug->switch_min = debug->switch_min ?
981 (curr < debug->switch_min ?
982 curr : debug->switch_min) : curr;
983 prev_avg = debug->switch_avg;
984 debug->switch_avg = (curr +
985 (debug->switch_avg * (debug->switch_num-1))) /
986 debug->switch_num;
987 debug->switch_std +=
988 (curr - debug->switch_avg) * (curr - prev_avg);
989 }
990 /* commit changes before exchanging debug pointer */
991 nvgpu_smp_wmb();
992 arb->debug = debug;
993#endif
994
995exit_arb:
996 if (status < 0) {
997 nvgpu_err(g, "Error in arbiter update");
998 nvgpu_clk_arb_set_global_alarm(g,
999 EVENT(ALARM_CLOCK_ARBITER_FAILED));
1000 }
1001
1002 current_alarm = (u32) nvgpu_atomic64_read(&arb->alarm_mask);
1003 /* notify completion for all requests */
1004 nvgpu_spinlock_acquire(&arb->requests_lock);
1005 nvgpu_list_for_each_entry_safe(dev, tmp, &arb->requests,
1006 nvgpu_clk_dev, node) {
1007 nvgpu_atomic_set(&dev->poll_mask, NVGPU_POLLIN | NVGPU_POLLRDNORM);
1008 nvgpu_clk_arb_event_post_event(dev);
1009 nvgpu_ref_put(&dev->refcount, nvgpu_clk_arb_free_fd);
1010 nvgpu_list_del(&dev->node);
1011 }
1012 nvgpu_spinlock_release(&arb->requests_lock);
1013
1014 nvgpu_atomic_set(&arb->notification_queue.head,
1015 nvgpu_atomic_read(&arb->notification_queue.tail));
1016 /* notify event for all users */
1017 nvgpu_spinlock_acquire(&arb->users_lock);
1018 nvgpu_list_for_each_entry(dev, &arb->users, nvgpu_clk_dev, link) {
1019 alarms_notified |=
1020 nvgpu_clk_arb_notify(dev, arb->actual, current_alarm);
1021 }
1022 nvgpu_spinlock_release(&arb->users_lock);
1023
1024 /* clear alarms */
1025 nvgpu_clk_arb_clear_global_alarm(g, alarms_notified &
1026 ~EVENT(ALARM_GPU_LOST));
1027}
1028
1029/* 550/*
1030 * Process one scheduled work item. 551 * Process one scheduled work item.
1031 */ 552 */
1032static void nvgpu_clk_arb_worker_process_item( 553static void nvgpu_clk_arb_worker_process_item(
1033 struct nvgpu_clk_arb_work_item *work_item) 554 struct nvgpu_clk_arb_work_item *work_item)
1034{ 555{
1035 clk_arb_dbg(work_item->arb->g, " "); 556 struct gk20a *g = work_item->arb->g;
557
558 clk_arb_dbg(g, " ");
1036 559
1037 if (work_item->item_type == CLK_ARB_WORK_UPDATE_VF_TABLE) 560 if (work_item->item_type == CLK_ARB_WORK_UPDATE_VF_TABLE)
1038 nvgpu_clk_arb_run_vf_table_cb(work_item->arb); 561 nvgpu_clk_arb_run_vf_table_cb(work_item->arb);
1039 else if (work_item->item_type == CLK_ARB_WORK_UPDATE_ARB) 562 else if (work_item->item_type == CLK_ARB_WORK_UPDATE_ARB)
1040 nvgpu_clk_arb_run_arbiter_cb(work_item->arb); 563 g->ops.clk_arb.clk_arb_run_arbiter_cb(work_item->arb);
1041} 564}
1042 565
1043/** 566/**
@@ -1204,7 +727,7 @@ void nvgpu_clk_arb_worker_enqueue(struct gk20a *g,
1204/** 727/**
1205 * Initialize the clk arb worker's metadata and start the background thread. 728 * Initialize the clk arb worker's metadata and start the background thread.
1206 */ 729 */
1207static int nvgpu_clk_arb_worker_init(struct gk20a *g) 730int nvgpu_clk_arb_worker_init(struct gk20a *g)
1208{ 731{
1209 int err; 732 int err;
1210 733
@@ -1227,149 +750,12 @@ error_check:
1227 750
1228int nvgpu_clk_arb_init_arbiter(struct gk20a *g) 751int nvgpu_clk_arb_init_arbiter(struct gk20a *g)
1229{ 752{
1230 struct nvgpu_clk_arb *arb; 753 if (!g->ops.clk.support_clk_freq_controller ||
1231 u16 default_mhz; 754 !g->ops.clk_arb.get_arbiter_clk_domains) {
1232 int err;
1233 int index;
1234 struct nvgpu_clk_vf_table *table;
1235
1236 clk_arb_dbg(g, " ");
1237
1238 if (!g->ops.clk_arb.get_arbiter_clk_domains)
1239 return 0; 755 return 0;
1240
1241 arb = nvgpu_kzalloc(g, sizeof(struct nvgpu_clk_arb));
1242 if (!arb)
1243 return -ENOMEM;
1244
1245 err = nvgpu_mutex_init(&arb->pstate_lock);
1246 if (err)
1247 goto mutex_fail;
1248 nvgpu_spinlock_init(&arb->sessions_lock);
1249 nvgpu_spinlock_init(&arb->users_lock);
1250 nvgpu_spinlock_init(&arb->requests_lock);
1251
1252 arb->mclk_f_points = nvgpu_kcalloc(g, MAX_F_POINTS, sizeof(u16));
1253 if (!arb->mclk_f_points) {
1254 err = -ENOMEM;
1255 goto init_fail;
1256 }
1257
1258 arb->gpc2clk_f_points = nvgpu_kcalloc(g, MAX_F_POINTS, sizeof(u16));
1259 if (!arb->gpc2clk_f_points) {
1260 err = -ENOMEM;
1261 goto init_fail;
1262 }
1263
1264 for (index = 0; index < 2; index++) {
1265 table = &arb->vf_table_pool[index];
1266 table->gpc2clk_num_points = MAX_F_POINTS;
1267 table->mclk_num_points = MAX_F_POINTS;
1268
1269 table->gpc2clk_points = nvgpu_kcalloc(g, MAX_F_POINTS,
1270 sizeof(struct nvgpu_clk_vf_point));
1271 if (!table->gpc2clk_points) {
1272 err = -ENOMEM;
1273 goto init_fail;
1274 }
1275
1276
1277 table->mclk_points = nvgpu_kcalloc(g, MAX_F_POINTS,
1278 sizeof(struct nvgpu_clk_vf_point));
1279 if (!table->mclk_points) {
1280 err = -ENOMEM;
1281 goto init_fail;
1282 }
1283 }
1284
1285 g->clk_arb = arb;
1286 arb->g = g;
1287
1288 err = g->ops.clk_arb.get_arbiter_clk_default(g,
1289 CTRL_CLK_DOMAIN_MCLK, &default_mhz);
1290 if (err < 0) {
1291 err = -EINVAL;
1292 goto init_fail;
1293 } 756 }
1294 757
1295 arb->mclk_default_mhz = default_mhz; 758 return g->ops.clk_arb.arbiter_clk_init(g);
1296
1297 err = g->ops.clk_arb.get_arbiter_clk_default(g,
1298 CTRL_CLK_DOMAIN_GPC2CLK, &default_mhz);
1299 if (err < 0) {
1300 err = -EINVAL;
1301 goto init_fail;
1302 }
1303
1304 arb->gpc2clk_default_mhz = default_mhz;
1305
1306 arb->actual = &arb->actual_pool[0];
1307
1308 nvgpu_atomic_set(&arb->req_nr, 0);
1309
1310 nvgpu_atomic64_set(&arb->alarm_mask, 0);
1311 err = nvgpu_clk_notification_queue_alloc(g, &arb->notification_queue,
1312 DEFAULT_EVENT_NUMBER);
1313 if (err < 0)
1314 goto init_fail;
1315
1316 nvgpu_init_list_node(&arb->users);
1317 nvgpu_init_list_node(&arb->sessions);
1318 nvgpu_init_list_node(&arb->requests);
1319
1320 nvgpu_cond_init(&arb->request_wq);
1321
1322 nvgpu_init_list_node(&arb->update_vf_table_work_item.worker_item);
1323 nvgpu_init_list_node(&arb->update_arb_work_item.worker_item);
1324 arb->update_vf_table_work_item.arb = arb;
1325 arb->update_arb_work_item.arb = arb;
1326 arb->update_vf_table_work_item.item_type = CLK_ARB_WORK_UPDATE_VF_TABLE;
1327 arb->update_arb_work_item.item_type = CLK_ARB_WORK_UPDATE_ARB;
1328
1329 err = nvgpu_clk_arb_worker_init(g);
1330 if (err < 0)
1331 goto init_fail;
1332
1333#ifdef CONFIG_DEBUG_FS
1334 arb->debug = &arb->debug_pool[0];
1335
1336 if (!arb->debugfs_set) {
1337 if (nvgpu_clk_arb_debugfs_init(g))
1338 arb->debugfs_set = true;
1339 }
1340#endif
1341 err = clk_vf_point_cache(g);
1342 if (err < 0)
1343 goto init_fail;
1344
1345 err = nvgpu_clk_arb_update_vf_table(arb);
1346 if (err < 0)
1347 goto init_fail;
1348 do {
1349 /* Check that first run is completed */
1350 nvgpu_smp_mb();
1351 NVGPU_COND_WAIT_INTERRUPTIBLE(&arb->request_wq,
1352 nvgpu_atomic_read(&arb->req_nr), 0);
1353 } while (!nvgpu_atomic_read(&arb->req_nr));
1354
1355
1356 return arb->status;
1357
1358init_fail:
1359 nvgpu_kfree(g, arb->gpc2clk_f_points);
1360 nvgpu_kfree(g, arb->mclk_f_points);
1361
1362 for (index = 0; index < 2; index++) {
1363 nvgpu_kfree(g, arb->vf_table_pool[index].gpc2clk_points);
1364 nvgpu_kfree(g, arb->vf_table_pool[index].mclk_points);
1365 }
1366
1367 nvgpu_mutex_destroy(&arb->pstate_lock);
1368
1369mutex_fail:
1370 nvgpu_kfree(g, arb);
1371
1372 return err;
1373} 759}
1374 760
1375void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g) 761void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g)
@@ -1396,22 +782,10 @@ static void nvgpu_clk_arb_worker_deinit(struct gk20a *g)
1396void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g) 782void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g)
1397{ 783{
1398 struct nvgpu_clk_arb *arb = g->clk_arb; 784 struct nvgpu_clk_arb *arb = g->clk_arb;
1399 int index;
1400 785
1401 if (arb) { 786 if (arb) {
1402 nvgpu_clk_arb_worker_deinit(g); 787 nvgpu_clk_arb_worker_deinit(g);
1403 788 g->ops.clk_arb.clk_arb_cleanup(g->clk_arb);
1404 nvgpu_kfree(g, arb->gpc2clk_f_points);
1405 nvgpu_kfree(g, arb->mclk_f_points);
1406
1407 for (index = 0; index < 2; index++) {
1408 nvgpu_kfree(g,
1409 arb->vf_table_pool[index].gpc2clk_points);
1410 nvgpu_kfree(g, arb->vf_table_pool[index].mclk_points);
1411 }
1412 nvgpu_mutex_destroy(&g->clk_arb->pstate_lock);
1413 nvgpu_kfree(g, g->clk_arb);
1414 g->clk_arb = NULL;
1415 } 789 }
1416} 790}
1417 791
@@ -1423,8 +797,10 @@ int nvgpu_clk_arb_init_session(struct gk20a *g,
1423 797
1424 clk_arb_dbg(g, " "); 798 clk_arb_dbg(g, " ");
1425 799
1426 if (!g->ops.clk_arb.get_arbiter_clk_domains) 800 if (!g->ops.clk.support_clk_freq_controller ||
801 !g->ops.clk_arb.get_arbiter_clk_domains) {
1427 return 0; 802 return 0;
803 }
1428 804
1429 session = nvgpu_kzalloc(g, sizeof(struct nvgpu_clk_session)); 805 session = nvgpu_kzalloc(g, sizeof(struct nvgpu_clk_session));
1430 if (!session) 806 if (!session)
@@ -1576,16 +952,16 @@ int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g,
1576 952
1577 switch (api_domain) { 953 switch (api_domain) {
1578 case NVGPU_CLK_DOMAIN_GPCCLK: 954 case NVGPU_CLK_DOMAIN_GPCCLK:
1579 err = clk_domain_get_f_points(g, CTRL_CLK_DOMAIN_GPC2CLK, 955 err = g->ops.clk.clk_domain_get_f_points(g,
1580 max_points, fpoints); 956 CTRL_CLK_DOMAIN_GPC2CLK, max_points, fpoints);
1581 if (err || !fpoints) 957 if (err || !fpoints)
1582 return err; 958 return err;
1583 for (i = 0; i < *max_points; i++) 959 for (i = 0; i < *max_points; i++)
1584 fpoints[i] /= 2; 960 fpoints[i] /= 2;
1585 return 0; 961 return 0;
1586 case NVGPU_CLK_DOMAIN_MCLK: 962 case NVGPU_CLK_DOMAIN_MCLK:
1587 return clk_domain_get_f_points(g, CTRL_CLK_DOMAIN_MCLK, 963 return g->ops.clk.clk_domain_get_f_points(g,
1588 max_points, fpoints); 964 CTRL_CLK_DOMAIN_MCLK, max_points, fpoints);
1589 default: 965 default:
1590 return -EINVAL; 966 return -EINVAL;
1591 } 967 }