diff options
-rw-r--r-- | drivers/gpu/nvgpu/boardobj/boardobj.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/boardobj/boardobjgrp.h | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk.c | 31 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk.h | 8 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_arb.c | 668 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 7 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/clk_arb_gp106.c | 649 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/clk_arb_gp106.h | 8 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/clk_gp106.c | 33 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/clk_gp106.h | 7 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/hal_gp106.c | 5 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/clk_arb.h | 12 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/os/posix/clk_arb.c | 46 |
13 files changed, 790 insertions, 688 deletions
diff --git a/drivers/gpu/nvgpu/boardobj/boardobj.h b/drivers/gpu/nvgpu/boardobj/boardobj.h index a433fda8..8fc8d1cc 100644 --- a/drivers/gpu/nvgpu/boardobj/boardobj.h +++ b/drivers/gpu/nvgpu/boardobj/boardobj.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "ctrl/ctrlboardobj.h" | 28 | #include "ctrl/ctrlboardobj.h" |
29 | 29 | ||
30 | struct boardobj; | 30 | struct boardobj; |
31 | struct nvgpu_list_node; | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * check whether the specified BOARDOBJ object implements the queried | 34 | * check whether the specified BOARDOBJ object implements the queried |
diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp.h b/drivers/gpu/nvgpu/boardobj/boardobjgrp.h index 3c28963c..8fc7136f 100644 --- a/drivers/gpu/nvgpu/boardobj/boardobjgrp.h +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp.h | |||
@@ -25,6 +25,9 @@ | |||
25 | 25 | ||
26 | struct boardobjgrp; | 26 | struct boardobjgrp; |
27 | struct gk20a; | 27 | struct gk20a; |
28 | struct nvgpu_list_node; | ||
29 | struct pmu_surface; | ||
30 | |||
28 | 31 | ||
29 | /* ------------------------ Includes ----------------------------------------*/ | 32 | /* ------------------------ Includes ----------------------------------------*/ |
30 | #include "ctrl/ctrlboardobj.h" | 33 | #include "ctrl/ctrlboardobj.h" |
diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c index 49087468..731124f7 100644 --- a/drivers/gpu/nvgpu/clk/clk.c +++ b/drivers/gpu/nvgpu/clk/clk.c | |||
@@ -869,34 +869,3 @@ u32 clk_domain_get_f_or_v( | |||
869 | } | 869 | } |
870 | return status; | 870 | return status; |
871 | } | 871 | } |
872 | |||
873 | u32 clk_domain_get_f_points( | ||
874 | struct gk20a *g, | ||
875 | u32 clkapidomain, | ||
876 | u32 *pfpointscount, | ||
877 | u16 *pfreqpointsinmhz | ||
878 | ) | ||
879 | { | ||
880 | u32 status = -EINVAL; | ||
881 | struct clk_domain *pdomain; | ||
882 | u8 i; | ||
883 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
884 | |||
885 | if (pfpointscount == NULL) | ||
886 | return -EINVAL; | ||
887 | |||
888 | if ((pfreqpointsinmhz == NULL) && (*pfpointscount != 0)) | ||
889 | return -EINVAL; | ||
890 | |||
891 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
892 | struct clk_domain *, pdomain, i) { | ||
893 | if (pdomain->api_domain == clkapidomain) { | ||
894 | status = pdomain->clkdomainclkgetfpoints(g, pclk, | ||
895 | pdomain, pfpointscount, | ||
896 | pfreqpointsinmhz, | ||
897 | CLK_PROG_VFE_ENTRY_LOGIC); | ||
898 | return status; | ||
899 | } | ||
900 | } | ||
901 | return status; | ||
902 | } | ||
diff --git a/drivers/gpu/nvgpu/clk/clk.h b/drivers/gpu/nvgpu/clk/clk.h index cd65f6f5..afff6963 100644 --- a/drivers/gpu/nvgpu/clk/clk.h +++ b/drivers/gpu/nvgpu/clk/clk.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * general clock structures & definitions | 2 | * general clock structures & definitions |
3 | * | 3 | * |
4 | * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2016-2018, 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"), |
@@ -127,12 +127,6 @@ u32 clk_domain_get_f_or_v( | |||
127 | u32 *pvoltuv, | 127 | u32 *pvoltuv, |
128 | u8 railidx | 128 | u8 railidx |
129 | ); | 129 | ); |
130 | u32 clk_domain_get_f_points( | ||
131 | struct gk20a *g, | ||
132 | u32 clkapidomain, | ||
133 | u32 *fpointscount, | ||
134 | u16 *freqpointsinmhz | ||
135 | ); | ||
136 | int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); | 130 | int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); |
137 | int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); | 131 | int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); |
138 | int clk_pmu_freq_controller_load(struct gk20a *g, bool bload, u8 bit_idx); | 132 | int clk_pmu_freq_controller_load(struct gk20a *g, bool bload, u8 bit_idx); |
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 | ||
81 | static void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm) | 81 | void 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 | ||
106 | static int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | 106 | int 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 | ||
430 | static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | 429 | u32 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 | |||
466 | recalculate_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 | |||
542 | find_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 | |||
554 | static 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 | |||
608 | static 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 | ||
707 | static void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm) | 528 | void 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 | ||
729 | static 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 | |||
995 | exit_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 | */ |
1032 | static void nvgpu_clk_arb_worker_process_item( | 553 | static 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 | */ |
1207 | static int nvgpu_clk_arb_worker_init(struct gk20a *g) | 730 | int 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 | ||
1228 | int nvgpu_clk_arb_init_arbiter(struct gk20a *g) | 751 | int 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 | |||
1358 | init_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 | |||
1369 | mutex_fail: | ||
1370 | nvgpu_kfree(g, arb); | ||
1371 | |||
1372 | return err; | ||
1373 | } | 759 | } |
1374 | 760 | ||
1375 | void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g) | 761 | void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g) |
@@ -1396,22 +782,10 @@ static void nvgpu_clk_arb_worker_deinit(struct gk20a *g) | |||
1396 | void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g) | 782 | void 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 | } |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index ac1226fc..bdf3a168 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -41,6 +41,7 @@ struct nvgpu_nvhost_dev; | |||
41 | struct nvgpu_cpu_time_correlation_sample; | 41 | struct nvgpu_cpu_time_correlation_sample; |
42 | struct nvgpu_mem_sgt; | 42 | struct nvgpu_mem_sgt; |
43 | struct nvgpu_warpstate; | 43 | struct nvgpu_warpstate; |
44 | struct nvgpu_clk_session; | ||
44 | struct nvgpu_clk_arb; | 45 | struct nvgpu_clk_arb; |
45 | #ifdef CONFIG_GK20A_CTXSW_TRACE | 46 | #ifdef CONFIG_GK20A_CTXSW_TRACE |
46 | struct nvgpu_gpu_ctxsw_trace_filter; | 47 | struct nvgpu_gpu_ctxsw_trace_filter; |
@@ -1083,6 +1084,9 @@ struct gpu_ops { | |||
1083 | int (*init_clk_support)(struct gk20a *g); | 1084 | int (*init_clk_support)(struct gk20a *g); |
1084 | int (*suspend_clk_support)(struct gk20a *g); | 1085 | int (*suspend_clk_support)(struct gk20a *g); |
1085 | u32 (*get_crystal_clk_hz)(struct gk20a *g); | 1086 | u32 (*get_crystal_clk_hz)(struct gk20a *g); |
1087 | int (*clk_domain_get_f_points)(struct gk20a *g, | ||
1088 | u32 clkapidomain, u32 *pfpointscount, | ||
1089 | u16 *pfreqpointsinmhz); | ||
1086 | unsigned long (*measure_freq)(struct gk20a *g, u32 api_domain); | 1090 | unsigned long (*measure_freq)(struct gk20a *g, u32 api_domain); |
1087 | unsigned long (*get_rate)(struct gk20a *g, u32 api_domain); | 1091 | unsigned long (*get_rate)(struct gk20a *g, u32 api_domain); |
1088 | int (*set_rate)(struct gk20a *g, u32 api_domain, unsigned long rate); | 1092 | int (*set_rate)(struct gk20a *g, u32 api_domain, unsigned long rate); |
@@ -1107,15 +1111,18 @@ struct gpu_ops { | |||
1107 | bool support_lpwr_pg; | 1111 | bool support_lpwr_pg; |
1108 | } clk; | 1112 | } clk; |
1109 | struct { | 1113 | struct { |
1114 | int (*arbiter_clk_init)(struct gk20a *g); | ||
1110 | u32 (*get_arbiter_clk_domains)(struct gk20a *g); | 1115 | u32 (*get_arbiter_clk_domains)(struct gk20a *g); |
1111 | int (*get_arbiter_clk_range)(struct gk20a *g, u32 api_domain, | 1116 | int (*get_arbiter_clk_range)(struct gk20a *g, u32 api_domain, |
1112 | u16 *min_mhz, u16 *max_mhz); | 1117 | u16 *min_mhz, u16 *max_mhz); |
1113 | int (*get_arbiter_clk_default)(struct gk20a *g, u32 api_domain, | 1118 | int (*get_arbiter_clk_default)(struct gk20a *g, u32 api_domain, |
1114 | u16 *default_mhz); | 1119 | u16 *default_mhz); |
1120 | void (*clk_arb_run_arbiter_cb)(struct nvgpu_clk_arb *arb); | ||
1115 | /* This function is inherently unsafe to call while | 1121 | /* This function is inherently unsafe to call while |
1116 | * arbiter is running arbiter must be blocked | 1122 | * arbiter is running arbiter must be blocked |
1117 | * before calling this function */ | 1123 | * before calling this function */ |
1118 | int (*get_current_pstate)(struct gk20a *g); | 1124 | int (*get_current_pstate)(struct gk20a *g); |
1125 | void (*clk_arb_cleanup)(struct nvgpu_clk_arb *arb); | ||
1119 | } clk_arb; | 1126 | } clk_arb; |
1120 | struct { | 1127 | struct { |
1121 | int (*handle_pmu_perf_event)(struct gk20a *g, void *pmu_msg); | 1128 | int (*handle_pmu_perf_event)(struct gk20a *g, void *pmu_msg); |
diff --git a/drivers/gpu/nvgpu/gp106/clk_arb_gp106.c b/drivers/gpu/nvgpu/gp106/clk_arb_gp106.c index ca8015d6..860344d0 100644 --- a/drivers/gpu/nvgpu/gp106/clk_arb_gp106.c +++ b/drivers/gpu/nvgpu/gp106/clk_arb_gp106.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
@@ -21,6 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include "gk20a/gk20a.h" | 23 | #include "gk20a/gk20a.h" |
24 | #include <nvgpu/clk_arb.h> | ||
24 | 25 | ||
25 | #include "clk_arb_gp106.h" | 26 | #include "clk_arb_gp106.h" |
26 | 27 | ||
@@ -109,3 +110,649 @@ int gp106_get_arbiter_clk_default(struct gk20a *g, u32 api_domain, | |||
109 | 110 | ||
110 | return 0; | 111 | return 0; |
111 | } | 112 | } |
113 | |||
114 | int gp106_init_clk_arbiter(struct gk20a *g) | ||
115 | { | ||
116 | struct nvgpu_clk_arb *arb; | ||
117 | u16 default_mhz; | ||
118 | int err; | ||
119 | int index; | ||
120 | struct nvgpu_clk_vf_table *table; | ||
121 | |||
122 | clk_arb_dbg(g, " "); | ||
123 | |||
124 | arb = nvgpu_kzalloc(g, sizeof(struct nvgpu_clk_arb)); | ||
125 | if (!arb) | ||
126 | return -ENOMEM; | ||
127 | |||
128 | err = nvgpu_mutex_init(&arb->pstate_lock); | ||
129 | if (err) | ||
130 | goto mutex_fail; | ||
131 | nvgpu_spinlock_init(&arb->sessions_lock); | ||
132 | nvgpu_spinlock_init(&arb->users_lock); | ||
133 | nvgpu_spinlock_init(&arb->requests_lock); | ||
134 | |||
135 | arb->mclk_f_points = nvgpu_kcalloc(g, MAX_F_POINTS, sizeof(u16)); | ||
136 | if (!arb->mclk_f_points) { | ||
137 | err = -ENOMEM; | ||
138 | goto init_fail; | ||
139 | } | ||
140 | |||
141 | arb->gpc2clk_f_points = nvgpu_kcalloc(g, MAX_F_POINTS, sizeof(u16)); | ||
142 | if (!arb->gpc2clk_f_points) { | ||
143 | err = -ENOMEM; | ||
144 | goto init_fail; | ||
145 | } | ||
146 | |||
147 | for (index = 0; index < 2; index++) { | ||
148 | table = &arb->vf_table_pool[index]; | ||
149 | table->gpc2clk_num_points = MAX_F_POINTS; | ||
150 | table->mclk_num_points = MAX_F_POINTS; | ||
151 | |||
152 | table->gpc2clk_points = nvgpu_kcalloc(g, MAX_F_POINTS, | ||
153 | sizeof(struct nvgpu_clk_vf_point)); | ||
154 | if (!table->gpc2clk_points) { | ||
155 | err = -ENOMEM; | ||
156 | goto init_fail; | ||
157 | } | ||
158 | |||
159 | |||
160 | table->mclk_points = nvgpu_kcalloc(g, MAX_F_POINTS, | ||
161 | sizeof(struct nvgpu_clk_vf_point)); | ||
162 | if (!table->mclk_points) { | ||
163 | err = -ENOMEM; | ||
164 | goto init_fail; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | g->clk_arb = arb; | ||
169 | arb->g = g; | ||
170 | |||
171 | err = g->ops.clk_arb.get_arbiter_clk_default(g, | ||
172 | CTRL_CLK_DOMAIN_MCLK, &default_mhz); | ||
173 | if (err < 0) { | ||
174 | err = -EINVAL; | ||
175 | goto init_fail; | ||
176 | } | ||
177 | |||
178 | arb->mclk_default_mhz = default_mhz; | ||
179 | |||
180 | err = g->ops.clk_arb.get_arbiter_clk_default(g, | ||
181 | CTRL_CLK_DOMAIN_GPC2CLK, &default_mhz); | ||
182 | if (err < 0) { | ||
183 | err = -EINVAL; | ||
184 | goto init_fail; | ||
185 | } | ||
186 | |||
187 | arb->gpc2clk_default_mhz = default_mhz; | ||
188 | |||
189 | arb->actual = &arb->actual_pool[0]; | ||
190 | |||
191 | nvgpu_atomic_set(&arb->req_nr, 0); | ||
192 | |||
193 | nvgpu_atomic64_set(&arb->alarm_mask, 0); | ||
194 | err = nvgpu_clk_notification_queue_alloc(g, &arb->notification_queue, | ||
195 | DEFAULT_EVENT_NUMBER); | ||
196 | if (err < 0) | ||
197 | goto init_fail; | ||
198 | |||
199 | nvgpu_init_list_node(&arb->users); | ||
200 | nvgpu_init_list_node(&arb->sessions); | ||
201 | nvgpu_init_list_node(&arb->requests); | ||
202 | |||
203 | nvgpu_cond_init(&arb->request_wq); | ||
204 | |||
205 | nvgpu_init_list_node(&arb->update_vf_table_work_item.worker_item); | ||
206 | nvgpu_init_list_node(&arb->update_arb_work_item.worker_item); | ||
207 | arb->update_vf_table_work_item.arb = arb; | ||
208 | arb->update_arb_work_item.arb = arb; | ||
209 | arb->update_vf_table_work_item.item_type = CLK_ARB_WORK_UPDATE_VF_TABLE; | ||
210 | arb->update_arb_work_item.item_type = CLK_ARB_WORK_UPDATE_ARB; | ||
211 | |||
212 | err = nvgpu_clk_arb_worker_init(g); | ||
213 | if (err < 0) | ||
214 | goto init_fail; | ||
215 | |||
216 | #ifdef CONFIG_DEBUG_FS | ||
217 | arb->debug = &arb->debug_pool[0]; | ||
218 | |||
219 | if (!arb->debugfs_set) { | ||
220 | if (nvgpu_clk_arb_debugfs_init(g)) | ||
221 | arb->debugfs_set = true; | ||
222 | } | ||
223 | #endif | ||
224 | err = clk_vf_point_cache(g); | ||
225 | if (err < 0) | ||
226 | goto init_fail; | ||
227 | |||
228 | err = nvgpu_clk_arb_update_vf_table(arb); | ||
229 | if (err < 0) | ||
230 | goto init_fail; | ||
231 | do { | ||
232 | /* Check that first run is completed */ | ||
233 | nvgpu_smp_mb(); | ||
234 | NVGPU_COND_WAIT_INTERRUPTIBLE(&arb->request_wq, | ||
235 | nvgpu_atomic_read(&arb->req_nr), 0); | ||
236 | } while (!nvgpu_atomic_read(&arb->req_nr)); | ||
237 | |||
238 | |||
239 | return arb->status; | ||
240 | |||
241 | init_fail: | ||
242 | nvgpu_kfree(g, arb->gpc2clk_f_points); | ||
243 | nvgpu_kfree(g, arb->mclk_f_points); | ||
244 | |||
245 | for (index = 0; index < 2; index++) { | ||
246 | nvgpu_kfree(g, arb->vf_table_pool[index].gpc2clk_points); | ||
247 | nvgpu_kfree(g, arb->vf_table_pool[index].mclk_points); | ||
248 | } | ||
249 | |||
250 | nvgpu_mutex_destroy(&arb->pstate_lock); | ||
251 | |||
252 | mutex_fail: | ||
253 | nvgpu_kfree(g, arb); | ||
254 | |||
255 | return err; | ||
256 | } | ||
257 | |||
258 | static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | ||
259 | u16 *gpc2clk, u16 *sys2clk, u16 *xbar2clk, u16 *mclk, | ||
260 | u32 *voltuv, u32 *voltuv_sram, u32 *nuvmin, u32 *nuvmin_sram) | ||
261 | { | ||
262 | u16 gpc2clk_target, mclk_target; | ||
263 | u32 gpc2clk_voltuv, gpc2clk_voltuv_sram; | ||
264 | u32 mclk_voltuv, mclk_voltuv_sram; | ||
265 | u32 pstate = VF_POINT_INVALID_PSTATE; | ||
266 | struct nvgpu_clk_vf_table *table; | ||
267 | u32 index, index_mclk; | ||
268 | struct nvgpu_clk_vf_point *mclk_vf = NULL; | ||
269 | |||
270 | do { | ||
271 | gpc2clk_target = *gpc2clk; | ||
272 | mclk_target = *mclk; | ||
273 | gpc2clk_voltuv = 0; | ||
274 | gpc2clk_voltuv_sram = 0; | ||
275 | mclk_voltuv = 0; | ||
276 | mclk_voltuv_sram = 0; | ||
277 | |||
278 | table = NV_ACCESS_ONCE(arb->current_vf_table); | ||
279 | /* pointer to table can be updated by callback */ | ||
280 | nvgpu_smp_rmb(); | ||
281 | |||
282 | if (!table) | ||
283 | continue; | ||
284 | if ((!table->gpc2clk_num_points) || (!table->mclk_num_points)) { | ||
285 | nvgpu_err(arb->g, "found empty table"); | ||
286 | goto find_exit; | ||
287 | } | ||
288 | /* First we check MCLK to find out which PSTATE we are | ||
289 | * are requesting, and from there try to find the minimum | ||
290 | * GPC2CLK on the same PSTATE that satisfies the request. | ||
291 | * If no GPC2CLK can be found, then we need to up the PSTATE | ||
292 | */ | ||
293 | |||
294 | recalculate_vf_point: | ||
295 | for (index = 0; index < table->mclk_num_points; index++) { | ||
296 | if (table->mclk_points[index].mem_mhz >= mclk_target) { | ||
297 | mclk_vf = &table->mclk_points[index]; | ||
298 | break; | ||
299 | } | ||
300 | } | ||
301 | if (index == table->mclk_num_points) { | ||
302 | mclk_vf = &table->mclk_points[index-1]; | ||
303 | index = table->mclk_num_points - 1; | ||
304 | } | ||
305 | index_mclk = index; | ||
306 | |||
307 | /* round up the freq requests */ | ||
308 | for (index = 0; index < table->gpc2clk_num_points; index++) { | ||
309 | pstate = VF_POINT_COMMON_PSTATE( | ||
310 | &table->gpc2clk_points[index], mclk_vf); | ||
311 | |||
312 | if ((table->gpc2clk_points[index].gpc_mhz >= | ||
313 | gpc2clk_target) && | ||
314 | (pstate != VF_POINT_INVALID_PSTATE)) { | ||
315 | gpc2clk_target = | ||
316 | table->gpc2clk_points[index].gpc_mhz; | ||
317 | *sys2clk = | ||
318 | table->gpc2clk_points[index].sys_mhz; | ||
319 | *xbar2clk = | ||
320 | table->gpc2clk_points[index].xbar_mhz; | ||
321 | |||
322 | gpc2clk_voltuv = | ||
323 | table->gpc2clk_points[index].uvolt; | ||
324 | gpc2clk_voltuv_sram = | ||
325 | table->gpc2clk_points[index].uvolt_sram; | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | |||
330 | if (index == table->gpc2clk_num_points) { | ||
331 | pstate = VF_POINT_COMMON_PSTATE( | ||
332 | &table->gpc2clk_points[index-1], mclk_vf); | ||
333 | if (pstate != VF_POINT_INVALID_PSTATE) { | ||
334 | gpc2clk_target = | ||
335 | table->gpc2clk_points[index-1].gpc_mhz; | ||
336 | *sys2clk = | ||
337 | table->gpc2clk_points[index-1].sys_mhz; | ||
338 | *xbar2clk = | ||
339 | table->gpc2clk_points[index-1].xbar_mhz; | ||
340 | |||
341 | gpc2clk_voltuv = | ||
342 | table->gpc2clk_points[index-1].uvolt; | ||
343 | gpc2clk_voltuv_sram = | ||
344 | table->gpc2clk_points[index-1]. | ||
345 | uvolt_sram; | ||
346 | } else if (index_mclk >= table->mclk_num_points - 1) { | ||
347 | /* There is no available combination of MCLK | ||
348 | * and GPC2CLK, we need to fail this | ||
349 | */ | ||
350 | gpc2clk_target = 0; | ||
351 | mclk_target = 0; | ||
352 | pstate = VF_POINT_INVALID_PSTATE; | ||
353 | goto find_exit; | ||
354 | } else { | ||
355 | /* recalculate with higher PSTATE */ | ||
356 | gpc2clk_target = *gpc2clk; | ||
357 | mclk_target = table->mclk_points[index_mclk+1]. | ||
358 | mem_mhz; | ||
359 | goto recalculate_vf_point; | ||
360 | } | ||
361 | } | ||
362 | |||
363 | mclk_target = mclk_vf->mem_mhz; | ||
364 | mclk_voltuv = mclk_vf->uvolt; | ||
365 | mclk_voltuv_sram = mclk_vf->uvolt_sram; | ||
366 | |||
367 | } while (!table || | ||
368 | (NV_ACCESS_ONCE(arb->current_vf_table) != table)); | ||
369 | |||
370 | find_exit: | ||
371 | *voltuv = gpc2clk_voltuv > mclk_voltuv ? gpc2clk_voltuv : mclk_voltuv; | ||
372 | *voltuv_sram = gpc2clk_voltuv_sram > mclk_voltuv_sram ? | ||
373 | gpc2clk_voltuv_sram : mclk_voltuv_sram; | ||
374 | /* noise unaware vmin */ | ||
375 | *nuvmin = mclk_voltuv; | ||
376 | *nuvmin_sram = mclk_voltuv_sram; | ||
377 | *gpc2clk = gpc2clk_target < *gpc2clk ? gpc2clk_target : *gpc2clk; | ||
378 | *mclk = mclk_target; | ||
379 | return pstate; | ||
380 | } | ||
381 | |||
382 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, | ||
383 | u16 sys2clk_target, u16 xbar2clk_target, u16 mclk_target, u32 voltuv, | ||
384 | u32 voltuv_sram) | ||
385 | { | ||
386 | struct set_fll_clk fllclk; | ||
387 | struct nvgpu_clk_arb *arb = g->clk_arb; | ||
388 | int status; | ||
389 | |||
390 | fllclk.gpc2clkmhz = gpc2clk_target; | ||
391 | fllclk.sys2clkmhz = sys2clk_target; | ||
392 | fllclk.xbar2clkmhz = xbar2clk_target; | ||
393 | |||
394 | fllclk.voltuv = voltuv; | ||
395 | |||
396 | /* if voltage ascends we do: | ||
397 | * (1) FLL change | ||
398 | * (2) Voltage change | ||
399 | * (3) MCLK change | ||
400 | * If it goes down | ||
401 | * (1) MCLK change | ||
402 | * (2) Voltage change | ||
403 | * (3) FLL change | ||
404 | */ | ||
405 | |||
406 | /* descending */ | ||
407 | if (voltuv < arb->voltuv_actual) { | ||
408 | status = g->ops.clk.mclk_change(g, mclk_target); | ||
409 | if (status < 0) | ||
410 | return status; | ||
411 | |||
412 | status = volt_set_voltage(g, voltuv, voltuv_sram); | ||
413 | if (status < 0) | ||
414 | return status; | ||
415 | |||
416 | status = clk_set_fll_clks(g, &fllclk); | ||
417 | if (status < 0) | ||
418 | return status; | ||
419 | } else { | ||
420 | status = clk_set_fll_clks(g, &fllclk); | ||
421 | if (status < 0) | ||
422 | return status; | ||
423 | |||
424 | status = volt_set_voltage(g, voltuv, voltuv_sram); | ||
425 | if (status < 0) | ||
426 | return status; | ||
427 | |||
428 | status = g->ops.clk.mclk_change(g, mclk_target); | ||
429 | if (status < 0) | ||
430 | return status; | ||
431 | } | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | void gp106_clk_arb_run_arbiter_cb(struct nvgpu_clk_arb *arb) | ||
437 | { | ||
438 | struct nvgpu_clk_session *session; | ||
439 | struct nvgpu_clk_dev *dev; | ||
440 | struct nvgpu_clk_dev *tmp; | ||
441 | struct nvgpu_clk_arb_target *target, *actual; | ||
442 | struct gk20a *g = arb->g; | ||
443 | |||
444 | u32 pstate = VF_POINT_INVALID_PSTATE; | ||
445 | u32 voltuv, voltuv_sram; | ||
446 | bool mclk_set, gpc2clk_set; | ||
447 | u32 nuvmin, nuvmin_sram; | ||
448 | |||
449 | u32 alarms_notified = 0; | ||
450 | u32 current_alarm; | ||
451 | int status = 0; | ||
452 | |||
453 | /* Temporary variables for checking target frequency */ | ||
454 | u16 gpc2clk_target, sys2clk_target, xbar2clk_target, mclk_target; | ||
455 | u16 gpc2clk_session_target, mclk_session_target; | ||
456 | |||
457 | #ifdef CONFIG_DEBUG_FS | ||
458 | u64 t0, t1; | ||
459 | struct nvgpu_clk_arb_debug *debug; | ||
460 | |||
461 | #endif | ||
462 | |||
463 | clk_arb_dbg(g, " "); | ||
464 | |||
465 | /* bail out if gpu is down */ | ||
466 | if (nvgpu_atomic64_read(&arb->alarm_mask) & EVENT(ALARM_GPU_LOST)) | ||
467 | goto exit_arb; | ||
468 | |||
469 | #ifdef CONFIG_DEBUG_FS | ||
470 | g->ops.ptimer.read_ptimer(g, &t0); | ||
471 | #endif | ||
472 | |||
473 | /* Only one arbiter should be running */ | ||
474 | gpc2clk_target = 0; | ||
475 | mclk_target = 0; | ||
476 | |||
477 | nvgpu_spinlock_acquire(&arb->sessions_lock); | ||
478 | nvgpu_list_for_each_entry(session, &arb->sessions, | ||
479 | nvgpu_clk_session, link) { | ||
480 | if (!session->zombie) { | ||
481 | mclk_set = false; | ||
482 | gpc2clk_set = false; | ||
483 | target = (session->target == &session->target_pool[0] ? | ||
484 | &session->target_pool[1] : | ||
485 | &session->target_pool[0]); | ||
486 | nvgpu_spinlock_acquire(&session->session_lock); | ||
487 | if (!nvgpu_list_empty(&session->targets)) { | ||
488 | /* Copy over state */ | ||
489 | target->mclk = session->target->mclk; | ||
490 | target->gpc2clk = session->target->gpc2clk; | ||
491 | /* Query the latest committed request */ | ||
492 | nvgpu_list_for_each_entry_safe(dev, tmp, | ||
493 | &session->targets, nvgpu_clk_dev, node) { | ||
494 | if (!mclk_set && dev->mclk_target_mhz) { | ||
495 | target->mclk = | ||
496 | dev->mclk_target_mhz; | ||
497 | mclk_set = true; | ||
498 | } | ||
499 | if (!gpc2clk_set && | ||
500 | dev->gpc2clk_target_mhz) { | ||
501 | target->gpc2clk = | ||
502 | dev->gpc2clk_target_mhz; | ||
503 | gpc2clk_set = true; | ||
504 | } | ||
505 | nvgpu_ref_get(&dev->refcount); | ||
506 | nvgpu_list_del(&dev->node); | ||
507 | nvgpu_spinlock_acquire( | ||
508 | &arb->requests_lock); | ||
509 | nvgpu_list_add( | ||
510 | &dev->node, &arb->requests); | ||
511 | nvgpu_spinlock_release(&arb->requests_lock); | ||
512 | } | ||
513 | session->target = target; | ||
514 | } | ||
515 | nvgpu_spinlock_release( | ||
516 | &session->session_lock); | ||
517 | |||
518 | mclk_target = mclk_target > session->target->mclk ? | ||
519 | mclk_target : session->target->mclk; | ||
520 | |||
521 | gpc2clk_target = | ||
522 | gpc2clk_target > session->target->gpc2clk ? | ||
523 | gpc2clk_target : session->target->gpc2clk; | ||
524 | } | ||
525 | } | ||
526 | nvgpu_spinlock_release(&arb->sessions_lock); | ||
527 | |||
528 | gpc2clk_target = (gpc2clk_target > 0) ? gpc2clk_target : | ||
529 | arb->gpc2clk_default_mhz; | ||
530 | |||
531 | if (gpc2clk_target < arb->gpc2clk_min) | ||
532 | gpc2clk_target = arb->gpc2clk_min; | ||
533 | |||
534 | if (gpc2clk_target > arb->gpc2clk_max) | ||
535 | gpc2clk_target = arb->gpc2clk_max; | ||
536 | |||
537 | mclk_target = (mclk_target > 0) ? mclk_target : | ||
538 | arb->mclk_default_mhz; | ||
539 | |||
540 | if (mclk_target < arb->mclk_min) | ||
541 | mclk_target = arb->mclk_min; | ||
542 | |||
543 | if (mclk_target > arb->mclk_max) | ||
544 | mclk_target = arb->mclk_max; | ||
545 | |||
546 | sys2clk_target = 0; | ||
547 | xbar2clk_target = 0; | ||
548 | |||
549 | gpc2clk_session_target = gpc2clk_target; | ||
550 | mclk_session_target = mclk_target; | ||
551 | |||
552 | /* Query the table for the closest vf point to program */ | ||
553 | pstate = nvgpu_clk_arb_find_vf_point(arb, &gpc2clk_target, | ||
554 | &sys2clk_target, &xbar2clk_target, &mclk_target, &voltuv, | ||
555 | &voltuv_sram, &nuvmin, &nuvmin_sram); | ||
556 | |||
557 | if (pstate == VF_POINT_INVALID_PSTATE) { | ||
558 | arb->status = -EINVAL; | ||
559 | /* make status visible */ | ||
560 | nvgpu_smp_mb(); | ||
561 | goto exit_arb; | ||
562 | } | ||
563 | |||
564 | if ((gpc2clk_target < gpc2clk_session_target) || | ||
565 | (mclk_target < mclk_session_target)) | ||
566 | nvgpu_clk_arb_set_global_alarm(g, | ||
567 | EVENT(ALARM_TARGET_VF_NOT_POSSIBLE)); | ||
568 | |||
569 | if ((arb->actual->gpc2clk == gpc2clk_target) && | ||
570 | (arb->actual->mclk == mclk_target) && | ||
571 | (arb->voltuv_actual == voltuv)) { | ||
572 | goto exit_arb; | ||
573 | } | ||
574 | |||
575 | /* Program clocks */ | ||
576 | /* A change in both mclk of gpc2clk may require a change in voltage */ | ||
577 | |||
578 | nvgpu_mutex_acquire(&arb->pstate_lock); | ||
579 | status = nvgpu_lpwr_disable_pg(g, false); | ||
580 | |||
581 | status = clk_pmu_freq_controller_load(g, false, | ||
582 | CTRL_CLK_CLK_FREQ_CONTROLLER_ID_ALL); | ||
583 | if (status < 0) { | ||
584 | arb->status = status; | ||
585 | nvgpu_mutex_release(&arb->pstate_lock); | ||
586 | |||
587 | /* make status visible */ | ||
588 | nvgpu_smp_mb(); | ||
589 | goto exit_arb; | ||
590 | } | ||
591 | status = volt_set_noiseaware_vmin(g, nuvmin, nuvmin_sram); | ||
592 | if (status < 0) { | ||
593 | arb->status = status; | ||
594 | nvgpu_mutex_release(&arb->pstate_lock); | ||
595 | |||
596 | /* make status visible */ | ||
597 | nvgpu_smp_mb(); | ||
598 | goto exit_arb; | ||
599 | } | ||
600 | |||
601 | status = nvgpu_clk_arb_change_vf_point(g, gpc2clk_target, | ||
602 | sys2clk_target, xbar2clk_target, mclk_target, voltuv, | ||
603 | voltuv_sram); | ||
604 | if (status < 0) { | ||
605 | arb->status = status; | ||
606 | nvgpu_mutex_release(&arb->pstate_lock); | ||
607 | |||
608 | /* make status visible */ | ||
609 | nvgpu_smp_mb(); | ||
610 | goto exit_arb; | ||
611 | } | ||
612 | |||
613 | status = clk_pmu_freq_controller_load(g, true, | ||
614 | CTRL_CLK_CLK_FREQ_CONTROLLER_ID_ALL); | ||
615 | if (status < 0) { | ||
616 | arb->status = status; | ||
617 | nvgpu_mutex_release(&arb->pstate_lock); | ||
618 | |||
619 | /* make status visible */ | ||
620 | nvgpu_smp_mb(); | ||
621 | goto exit_arb; | ||
622 | } | ||
623 | |||
624 | status = nvgpu_lwpr_mclk_change(g, pstate); | ||
625 | if (status < 0) { | ||
626 | arb->status = status; | ||
627 | nvgpu_mutex_release(&arb->pstate_lock); | ||
628 | |||
629 | /* make status visible */ | ||
630 | nvgpu_smp_mb(); | ||
631 | goto exit_arb; | ||
632 | } | ||
633 | |||
634 | actual = NV_ACCESS_ONCE(arb->actual) == &arb->actual_pool[0] ? | ||
635 | &arb->actual_pool[1] : &arb->actual_pool[0]; | ||
636 | |||
637 | /* do not reorder this pointer */ | ||
638 | nvgpu_smp_rmb(); | ||
639 | actual->gpc2clk = gpc2clk_target; | ||
640 | actual->mclk = mclk_target; | ||
641 | arb->voltuv_actual = voltuv; | ||
642 | actual->pstate = pstate; | ||
643 | arb->status = status; | ||
644 | |||
645 | /* Make changes visible to other threads */ | ||
646 | nvgpu_smp_wmb(); | ||
647 | arb->actual = actual; | ||
648 | |||
649 | status = nvgpu_lpwr_enable_pg(g, false); | ||
650 | if (status < 0) { | ||
651 | arb->status = status; | ||
652 | nvgpu_mutex_release(&arb->pstate_lock); | ||
653 | |||
654 | /* make status visible */ | ||
655 | nvgpu_smp_mb(); | ||
656 | goto exit_arb; | ||
657 | } | ||
658 | |||
659 | /* status must be visible before atomic inc */ | ||
660 | nvgpu_smp_wmb(); | ||
661 | nvgpu_atomic_inc(&arb->req_nr); | ||
662 | |||
663 | /* Unlock pstate change for PG */ | ||
664 | nvgpu_mutex_release(&arb->pstate_lock); | ||
665 | |||
666 | /* VF Update complete */ | ||
667 | nvgpu_clk_arb_set_global_alarm(g, EVENT(VF_UPDATE)); | ||
668 | |||
669 | nvgpu_cond_signal_interruptible(&arb->request_wq); | ||
670 | |||
671 | #ifdef CONFIG_DEBUG_FS | ||
672 | g->ops.ptimer.read_ptimer(g, &t1); | ||
673 | |||
674 | debug = arb->debug == &arb->debug_pool[0] ? | ||
675 | &arb->debug_pool[1] : &arb->debug_pool[0]; | ||
676 | |||
677 | memcpy(debug, arb->debug, sizeof(arb->debug_pool[0])); | ||
678 | debug->switch_num++; | ||
679 | |||
680 | if (debug->switch_num == 1) { | ||
681 | debug->switch_max = debug->switch_min = | ||
682 | debug->switch_avg = (t1-t0)/1000; | ||
683 | debug->switch_std = 0; | ||
684 | } else { | ||
685 | s64 prev_avg; | ||
686 | s64 curr = (t1-t0)/1000; | ||
687 | |||
688 | debug->switch_max = curr > debug->switch_max ? | ||
689 | curr : debug->switch_max; | ||
690 | debug->switch_min = debug->switch_min ? | ||
691 | (curr < debug->switch_min ? | ||
692 | curr : debug->switch_min) : curr; | ||
693 | prev_avg = debug->switch_avg; | ||
694 | debug->switch_avg = (curr + | ||
695 | (debug->switch_avg * (debug->switch_num-1))) / | ||
696 | debug->switch_num; | ||
697 | debug->switch_std += | ||
698 | (curr - debug->switch_avg) * (curr - prev_avg); | ||
699 | } | ||
700 | /* commit changes before exchanging debug pointer */ | ||
701 | nvgpu_smp_wmb(); | ||
702 | arb->debug = debug; | ||
703 | #endif | ||
704 | |||
705 | exit_arb: | ||
706 | if (status < 0) { | ||
707 | nvgpu_err(g, "Error in arbiter update"); | ||
708 | nvgpu_clk_arb_set_global_alarm(g, | ||
709 | EVENT(ALARM_CLOCK_ARBITER_FAILED)); | ||
710 | } | ||
711 | |||
712 | current_alarm = (u32) nvgpu_atomic64_read(&arb->alarm_mask); | ||
713 | /* notify completion for all requests */ | ||
714 | nvgpu_spinlock_acquire(&arb->requests_lock); | ||
715 | nvgpu_list_for_each_entry_safe(dev, tmp, &arb->requests, | ||
716 | nvgpu_clk_dev, node) { | ||
717 | nvgpu_atomic_set(&dev->poll_mask, | ||
718 | NVGPU_POLLIN | NVGPU_POLLRDNORM); | ||
719 | nvgpu_clk_arb_event_post_event(dev); | ||
720 | nvgpu_ref_put(&dev->refcount, nvgpu_clk_arb_free_fd); | ||
721 | nvgpu_list_del(&dev->node); | ||
722 | } | ||
723 | nvgpu_spinlock_release(&arb->requests_lock); | ||
724 | |||
725 | nvgpu_atomic_set(&arb->notification_queue.head, | ||
726 | nvgpu_atomic_read(&arb->notification_queue.tail)); | ||
727 | /* notify event for all users */ | ||
728 | nvgpu_spinlock_acquire(&arb->users_lock); | ||
729 | nvgpu_list_for_each_entry(dev, &arb->users, nvgpu_clk_dev, link) { | ||
730 | alarms_notified |= | ||
731 | nvgpu_clk_arb_notify(dev, arb->actual, current_alarm); | ||
732 | } | ||
733 | nvgpu_spinlock_release(&arb->users_lock); | ||
734 | |||
735 | /* clear alarms */ | ||
736 | nvgpu_clk_arb_clear_global_alarm(g, alarms_notified & | ||
737 | ~EVENT(ALARM_GPU_LOST)); | ||
738 | } | ||
739 | |||
740 | void gp106_clk_arb_cleanup(struct nvgpu_clk_arb *arb) | ||
741 | { | ||
742 | struct gk20a *g = arb->g; | ||
743 | int index; | ||
744 | |||
745 | nvgpu_kfree(g, arb->gpc2clk_f_points); | ||
746 | nvgpu_kfree(g, arb->mclk_f_points); | ||
747 | |||
748 | for (index = 0; index < 2; index++) { | ||
749 | nvgpu_kfree(g, | ||
750 | arb->vf_table_pool[index].gpc2clk_points); | ||
751 | nvgpu_kfree(g, arb->vf_table_pool[index].mclk_points); | ||
752 | } | ||
753 | |||
754 | nvgpu_mutex_destroy(&g->clk_arb->pstate_lock); | ||
755 | nvgpu_kfree(g, g->clk_arb); | ||
756 | |||
757 | g->clk_arb = NULL; | ||
758 | } \ No newline at end of file | ||
diff --git a/drivers/gpu/nvgpu/gp106/clk_arb_gp106.h b/drivers/gpu/nvgpu/gp106/clk_arb_gp106.h index fc4657f5..e2b2834c 100644 --- a/drivers/gpu/nvgpu/gp106/clk_arb_gp106.h +++ b/drivers/gpu/nvgpu/gp106/clk_arb_gp106.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
@@ -22,10 +22,16 @@ | |||
22 | #ifndef CLK_ARB_GP106_H | 22 | #ifndef CLK_ARB_GP106_H |
23 | #define CLK_ARB_GP106_H | 23 | #define CLK_ARB_GP106_H |
24 | 24 | ||
25 | struct nvgpu_clk_session; | ||
26 | struct nvgpu_clk_arb; | ||
27 | |||
25 | u32 gp106_get_arbiter_clk_domains(struct gk20a *g); | 28 | u32 gp106_get_arbiter_clk_domains(struct gk20a *g); |
26 | int gp106_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, | 29 | int gp106_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, |
27 | u16 *min_mhz, u16 *max_mhz); | 30 | u16 *min_mhz, u16 *max_mhz); |
28 | int gp106_get_arbiter_clk_default(struct gk20a *g, u32 api_domain, | 31 | int gp106_get_arbiter_clk_default(struct gk20a *g, u32 api_domain, |
29 | u16 *default_mhz); | 32 | u16 *default_mhz); |
33 | int gp106_init_clk_arbiter(struct gk20a *g); | ||
34 | void gp106_clk_arb_run_arbiter_cb(struct nvgpu_clk_arb *arb); | ||
35 | void gp106_clk_arb_cleanup(struct nvgpu_clk_arb *arb); | ||
30 | 36 | ||
31 | #endif /* CLK_ARB_GP106_H */ | 37 | #endif /* CLK_ARB_GP106_H */ |
diff --git a/drivers/gpu/nvgpu/gp106/clk_gp106.c b/drivers/gpu/nvgpu/gp106/clk_gp106.c index 24b07112..dd7a2dd6 100644 --- a/drivers/gpu/nvgpu/gp106/clk_gp106.c +++ b/drivers/gpu/nvgpu/gp106/clk_gp106.c | |||
@@ -32,7 +32,9 @@ | |||
32 | #include <nvgpu/list.h> | 32 | #include <nvgpu/list.h> |
33 | #include <nvgpu/clk_arb.h> | 33 | #include <nvgpu/clk_arb.h> |
34 | #include <nvgpu/timers.h> | 34 | #include <nvgpu/timers.h> |
35 | #include <nvgpu/pmu.h> | ||
35 | 36 | ||
37 | #include "clk/clk.h" | ||
36 | #include "gk20a/gk20a.h" | 38 | #include "gk20a/gk20a.h" |
37 | #include "gp106/mclk_gp106.h" | 39 | #include "gp106/mclk_gp106.h" |
38 | 40 | ||
@@ -243,6 +245,37 @@ read_err: | |||
243 | 245 | ||
244 | } | 246 | } |
245 | 247 | ||
248 | int gp106_clk_domain_get_f_points( | ||
249 | struct gk20a *g, | ||
250 | u32 clkapidomain, | ||
251 | u32 *pfpointscount, | ||
252 | u16 *pfreqpointsinmhz) | ||
253 | { | ||
254 | int status = -EINVAL; | ||
255 | struct clk_domain *pdomain; | ||
256 | u8 i; | ||
257 | struct clk_pmupstate *pclk = &g->clk_pmu; | ||
258 | |||
259 | if (pfpointscount == NULL) | ||
260 | return -EINVAL; | ||
261 | |||
262 | if ((pfreqpointsinmhz == NULL) && (*pfpointscount != 0)) | ||
263 | return -EINVAL; | ||
264 | |||
265 | BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super), | ||
266 | struct clk_domain *, pdomain, i) { | ||
267 | if (pdomain->api_domain == clkapidomain) { | ||
268 | status = pdomain->clkdomainclkgetfpoints(g, pclk, | ||
269 | pdomain, pfpointscount, | ||
270 | pfreqpointsinmhz, | ||
271 | CLK_PROG_VFE_ENTRY_LOGIC); | ||
272 | return status; | ||
273 | } | ||
274 | } | ||
275 | return status; | ||
276 | } | ||
277 | |||
278 | |||
246 | #ifdef CONFIG_DEBUG_FS | 279 | #ifdef CONFIG_DEBUG_FS |
247 | static int gp106_get_rate_show(void *data , u64 *val) { | 280 | static int gp106_get_rate_show(void *data , u64 *val) { |
248 | struct namemap_cfg *c = (struct namemap_cfg *) data; | 281 | struct namemap_cfg *c = (struct namemap_cfg *) data; |
diff --git a/drivers/gpu/nvgpu/gp106/clk_gp106.h b/drivers/gpu/nvgpu/gp106/clk_gp106.h index 97baa224..b7ab3164 100644 --- a/drivers/gpu/nvgpu/gp106/clk_gp106.h +++ b/drivers/gpu/nvgpu/gp106/clk_gp106.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
@@ -56,5 +56,10 @@ int gp106_init_clk_support(struct gk20a *g); | |||
56 | u32 gp106_crystal_clk_hz(struct gk20a *g); | 56 | u32 gp106_crystal_clk_hz(struct gk20a *g); |
57 | unsigned long gp106_clk_measure_freq(struct gk20a *g, u32 api_domain); | 57 | unsigned long gp106_clk_measure_freq(struct gk20a *g, u32 api_domain); |
58 | int gp106_suspend_clk_support(struct gk20a *g); | 58 | int gp106_suspend_clk_support(struct gk20a *g); |
59 | int gp106_clk_domain_get_f_points( | ||
60 | struct gk20a *g, | ||
61 | u32 clkapidomain, | ||
62 | u32 *pfpointscount, | ||
63 | u16 *pfreqpointsinmhz); | ||
59 | 64 | ||
60 | #endif /* CLK_GP106_H */ | 65 | #endif /* CLK_GP106_H */ |
diff --git a/drivers/gpu/nvgpu/gp106/hal_gp106.c b/drivers/gpu/nvgpu/gp106/hal_gp106.c index 78a3ea63..167bfaac 100644 --- a/drivers/gpu/nvgpu/gp106/hal_gp106.c +++ b/drivers/gpu/nvgpu/gp106/hal_gp106.c | |||
@@ -675,6 +675,7 @@ static const struct gpu_ops gp106_ops = { | |||
675 | .get_crystal_clk_hz = gp106_crystal_clk_hz, | 675 | .get_crystal_clk_hz = gp106_crystal_clk_hz, |
676 | .measure_freq = gp106_clk_measure_freq, | 676 | .measure_freq = gp106_clk_measure_freq, |
677 | .suspend_clk_support = gp106_suspend_clk_support, | 677 | .suspend_clk_support = gp106_suspend_clk_support, |
678 | .clk_domain_get_f_points = gp106_clk_domain_get_f_points, | ||
678 | .mclk_init = gp106_mclk_init, | 679 | .mclk_init = gp106_mclk_init, |
679 | .mclk_change = gp106_mclk_change, | 680 | .mclk_change = gp106_mclk_change, |
680 | .mclk_deinit = gp106_mclk_deinit, | 681 | .mclk_deinit = gp106_mclk_deinit, |
@@ -684,6 +685,9 @@ static const struct gpu_ops gp106_ops = { | |||
684 | .get_arbiter_clk_range = gp106_get_arbiter_clk_range, | 685 | .get_arbiter_clk_range = gp106_get_arbiter_clk_range, |
685 | .get_arbiter_clk_default = gp106_get_arbiter_clk_default, | 686 | .get_arbiter_clk_default = gp106_get_arbiter_clk_default, |
686 | .get_current_pstate = nvgpu_clk_arb_get_current_pstate, | 687 | .get_current_pstate = nvgpu_clk_arb_get_current_pstate, |
688 | .arbiter_clk_init = gp106_init_clk_arbiter, | ||
689 | .clk_arb_run_arbiter_cb = gp106_clk_arb_run_arbiter_cb, | ||
690 | .clk_arb_cleanup = gp106_clk_arb_cleanup, | ||
687 | }, | 691 | }, |
688 | .regops = { | 692 | .regops = { |
689 | .exec_regops = exec_regops_gk20a, | 693 | .exec_regops = exec_regops_gk20a, |
@@ -849,6 +853,7 @@ int gp106_init_hal(struct gk20a *g) | |||
849 | gops->clk.mclk_init = gp106_ops.clk.mclk_init; | 853 | gops->clk.mclk_init = gp106_ops.clk.mclk_init; |
850 | gops->clk.mclk_change = gp106_ops.clk.mclk_change; | 854 | gops->clk.mclk_change = gp106_ops.clk.mclk_change; |
851 | gops->clk.mclk_deinit = gp106_ops.clk.mclk_deinit; | 855 | gops->clk.mclk_deinit = gp106_ops.clk.mclk_deinit; |
856 | gops->clk.clk_domain_get_f_points = gp106_ops.clk.clk_domain_get_f_points; | ||
852 | 857 | ||
853 | gops->clk_arb = gp106_ops.clk_arb; | 858 | gops->clk_arb = gp106_ops.clk_arb; |
854 | gops->regops = gp106_ops.regops; | 859 | gops->regops = gp106_ops.regops; |
diff --git a/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h b/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h index 328e03b5..e63545df 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h +++ b/drivers/gpu/nvgpu/include/nvgpu/clk_arb.h | |||
@@ -287,6 +287,10 @@ nvgpu_clk_arb_work_item_from_worker_item(struct nvgpu_list_node *node) | |||
287 | void nvgpu_clk_arb_worker_enqueue(struct gk20a *g, | 287 | void nvgpu_clk_arb_worker_enqueue(struct gk20a *g, |
288 | struct nvgpu_clk_arb_work_item *work_item); | 288 | struct nvgpu_clk_arb_work_item *work_item); |
289 | 289 | ||
290 | int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb); | ||
291 | |||
292 | int nvgpu_clk_arb_worker_init(struct gk20a *g); | ||
293 | |||
290 | int nvgpu_clk_arb_init_arbiter(struct gk20a *g); | 294 | int nvgpu_clk_arb_init_arbiter(struct gk20a *g); |
291 | 295 | ||
292 | int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, | 296 | int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, |
@@ -338,12 +342,20 @@ void nvgpu_clk_arb_pstate_change_lock(struct gk20a *g, bool lock); | |||
338 | 342 | ||
339 | void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g); | 343 | void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g); |
340 | 344 | ||
345 | void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm); | ||
346 | |||
341 | void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm); | 347 | void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm); |
342 | 348 | ||
349 | void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm); | ||
350 | |||
343 | void nvgpu_clk_arb_free_session(struct nvgpu_ref *refcount); | 351 | void nvgpu_clk_arb_free_session(struct nvgpu_ref *refcount); |
344 | 352 | ||
345 | void nvgpu_clk_arb_free_fd(struct nvgpu_ref *refcount); | 353 | void nvgpu_clk_arb_free_fd(struct nvgpu_ref *refcount); |
346 | 354 | ||
355 | u32 nvgpu_clk_arb_notify(struct nvgpu_clk_dev *dev, | ||
356 | struct nvgpu_clk_arb_target *target, | ||
357 | u32 alarm); | ||
358 | |||
347 | int nvgpu_clk_notification_queue_alloc(struct gk20a *g, | 359 | int nvgpu_clk_notification_queue_alloc(struct gk20a *g, |
348 | struct nvgpu_clk_notification_queue *queue, | 360 | struct nvgpu_clk_notification_queue *queue, |
349 | size_t events_number); | 361 | size_t events_number); |
diff --git a/drivers/gpu/nvgpu/os/posix/clk_arb.c b/drivers/gpu/nvgpu/os/posix/clk_arb.c index 2214b37b..63ab0f13 100644 --- a/drivers/gpu/nvgpu/os/posix/clk_arb.c +++ b/drivers/gpu/nvgpu/os/posix/clk_arb.c | |||
@@ -42,6 +42,16 @@ int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, | |||
42 | return -ENOSYS; | 42 | return -ENOSYS; |
43 | } | 43 | } |
44 | 44 | ||
45 | int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) | ||
46 | { | ||
47 | return -ENOSYS; | ||
48 | } | ||
49 | |||
50 | int nvgpu_clk_arb_worker_init(struct gk20a *g) | ||
51 | { | ||
52 | return -ENOSYS; | ||
53 | } | ||
54 | |||
45 | int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g, | 55 | int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g, |
46 | u32 api_domain, u16 *actual_mhz) | 56 | u32 api_domain, u16 *actual_mhz) |
47 | { | 57 | { |
@@ -54,7 +64,6 @@ int nvgpu_clk_arb_get_arbiter_effective_mhz(struct gk20a *g, | |||
54 | return -ENOSYS; | 64 | return -ENOSYS; |
55 | } | 65 | } |
56 | 66 | ||
57 | |||
58 | int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g, | 67 | int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g, |
59 | u32 api_domain, | 68 | u32 api_domain, |
60 | u32 *max_points, u16 *fpoints) | 69 | u32 *max_points, u16 *fpoints) |
@@ -127,6 +136,17 @@ int nvgpu_clk_arb_install_request_fd(struct gk20a *g, | |||
127 | return -ENOSYS; | 136 | return -ENOSYS; |
128 | } | 137 | } |
129 | 138 | ||
139 | u32 nvgpu_clk_arb_notify(struct nvgpu_clk_dev *dev, | ||
140 | struct nvgpu_clk_arb_target *target, | ||
141 | u32 alarm) | ||
142 | { | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | void nvgpu_clk_arb_free_fd(struct nvgpu_ref *refcount) | ||
147 | { | ||
148 | } | ||
149 | |||
130 | void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g) | 150 | void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g) |
131 | { | 151 | { |
132 | } | 152 | } |
@@ -147,3 +167,27 @@ void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g) | |||
147 | void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm) | 167 | void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm) |
148 | { | 168 | { |
149 | } | 169 | } |
170 | |||
171 | void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm) | ||
172 | { | ||
173 | } | ||
174 | |||
175 | void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm) | ||
176 | { | ||
177 | } | ||
178 | |||
179 | void nvgpu_clk_arb_event_post_event(struct nvgpu_clk_dev *dev) | ||
180 | { | ||
181 | } | ||
182 | |||
183 | void nvgpu_clk_arb_worker_enqueue(struct gk20a *g, | ||
184 | struct nvgpu_clk_arb_work_item *work_item) | ||
185 | { | ||
186 | } | ||
187 | |||
188 | int nvgpu_clk_notification_queue_alloc(struct gk20a *g, | ||
189 | struct nvgpu_clk_notification_queue *queue, | ||
190 | size_t events_number) | ||
191 | { | ||
192 | return -ENOSYS; | ||
193 | } | ||