summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
diff options
context:
space:
mode:
authorMahantesh Kumbar <mkumbar@nvidia.com>2017-06-06 05:56:32 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-06-12 14:03:37 -0400
commit69dee6a648ad434b75e1a9c64b022ee45d3ff87b (patch)
treeeba316aa07b17760afb1609b331bb3cf0602e545 /drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
parent914bb78a7dc0687b349310cc28613ea4a4c0be33 (diff)
gpu: nvgpu: reorganize PMU init
- Moved PMU init code from pmu_gk20a.c to "drivers/gpu/nvgpu/common/pmu/pmu.c" file - Moved below related methods SW/HW init, init msg handler, deinit/destroy, PMU state machine -Created HAL methods to read message queue tail & supported mutex count. -prepend with nvgpu_ for pmu init global mehtods JIRA NVGPU-56 JIRA NVGPU-92 Change-Id: Iea9efc194fefa74fb5641d2b2f4633577d2c3a47 Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com> Reviewed-on: http://git-master/r/1480002 Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/pmu_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c443
1 files changed, 26 insertions, 417 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
index deab46c8..03728378 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
@@ -43,19 +43,10 @@
43#define gk20a_dbg_pmu(fmt, arg...) \ 43#define gk20a_dbg_pmu(fmt, arg...) \
44 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) 44 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
45 45
46int gk20a_pmu_get_pg_stats(struct gk20a *g,
47 u32 pg_engine_id,
48 struct pmu_pg_stats_data *pg_stat_data);
49static void ap_callback_init_and_enable_ctrl( 46static void ap_callback_init_and_enable_ctrl(
50 struct gk20a *g, struct pmu_msg *msg, 47 struct gk20a *g, struct pmu_msg *msg,
51 void *param, u32 seq_desc, u32 status); 48 void *param, u32 seq_desc, u32 status);
52 49
53static int nvgpu_init_task_pg_init(struct gk20a *g);
54static void nvgpu_pmu_state_change(struct gk20a *g, u32 pmu_state,
55 bool post_change_event);
56
57static int pmu_init_powergating(struct gk20a *g);
58
59static u32 pmu_perfmon_cntr_sz_v0(struct nvgpu_pmu *pmu) 50static u32 pmu_perfmon_cntr_sz_v0(struct nvgpu_pmu *pmu)
60{ 51{
61 return sizeof(struct pmu_perfmon_counter_v0); 52 return sizeof(struct pmu_perfmon_counter_v0);
@@ -2783,6 +2774,25 @@ int gk20a_pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
2783 return 0; 2774 return 0;
2784} 2775}
2785 2776
2777void gk20a_pmu_msgq_tail(struct nvgpu_pmu *pmu, u32 *tail, bool set)
2778{
2779 struct gk20a *g = gk20a_from_pmu(pmu);
2780 u32 queue_tail_size = 0;
2781
2782 if (g->ops.pmu.pmu_get_queue_tail_size)
2783 queue_tail_size = g->ops.pmu.pmu_get_queue_tail_size();
2784
2785 BUG_ON(!tail || !queue_tail_size);
2786
2787 if (!set)
2788 *tail = pwr_pmu_msgq_tail_val_v(
2789 gk20a_readl(g, pwr_pmu_msgq_tail_r()));
2790 else
2791 gk20a_writel(g,
2792 pwr_pmu_msgq_tail_r(),
2793 pwr_pmu_msgq_tail_val_f(*tail));
2794}
2795
2786void gk20a_remove_pmu_support(struct nvgpu_pmu *pmu) 2796void gk20a_remove_pmu_support(struct nvgpu_pmu *pmu)
2787{ 2797{
2788 struct gk20a *g = gk20a_from_pmu(pmu); 2798 struct gk20a *g = gk20a_from_pmu(pmu);
@@ -2801,17 +2811,6 @@ void gk20a_remove_pmu_support(struct nvgpu_pmu *pmu)
2801 nvgpu_mutex_destroy(&pmu->pmu_seq_lock); 2811 nvgpu_mutex_destroy(&pmu->pmu_seq_lock);
2802} 2812}
2803 2813
2804static int gk20a_init_pmu_reset_enable_hw(struct gk20a *g)
2805{
2806 struct nvgpu_pmu *pmu = &g->pmu;
2807
2808 gk20a_dbg_fn("");
2809
2810 pmu_enable_hw(pmu, true);
2811
2812 return 0;
2813}
2814
2815static int gk20a_prepare_ucode(struct gk20a *g) 2814static int gk20a_prepare_ucode(struct gk20a *g)
2816{ 2815{
2817 struct nvgpu_pmu *pmu = &g->pmu; 2816 struct nvgpu_pmu *pmu = &g->pmu;
@@ -2851,103 +2850,6 @@ static int gk20a_prepare_ucode(struct gk20a *g)
2851 return err; 2850 return err;
2852} 2851}
2853 2852
2854static int gk20a_init_pmu_setup_sw(struct gk20a *g)
2855{
2856 struct nvgpu_pmu *pmu = &g->pmu;
2857 struct mm_gk20a *mm = &g->mm;
2858 struct vm_gk20a *vm = mm->pmu.vm;
2859 unsigned int i;
2860 int err = 0;
2861 u8 *ptr;
2862
2863 gk20a_dbg_fn("");
2864
2865 /* start with elpg disabled until first enable call */
2866 pmu->elpg_refcnt = 0;
2867
2868 /* Create thread to handle PMU state machine */
2869 nvgpu_init_task_pg_init(g);
2870
2871 if (pmu->sw_ready) {
2872 for (i = 0; i < pmu->mutex_cnt; i++) {
2873 pmu->mutex[i].id = i;
2874 pmu->mutex[i].index = i;
2875 }
2876 nvgpu_pmu_seq_init(pmu);
2877
2878 gk20a_dbg_fn("skip init");
2879 goto skip_init;
2880 }
2881
2882 /* no infoRom script from vbios? */
2883
2884 /* TBD: sysmon subtask */
2885
2886 if (IS_ENABLED(CONFIG_TEGRA_GK20A_PERFMON))
2887 pmu->perfmon_sampling_enabled = true;
2888
2889 pmu->mutex_cnt = pwr_pmu_mutex__size_1_v();
2890 pmu->mutex = nvgpu_kzalloc(g, pmu->mutex_cnt *
2891 sizeof(struct pmu_mutex));
2892 if (!pmu->mutex) {
2893 err = -ENOMEM;
2894 goto err;
2895 }
2896
2897 for (i = 0; i < pmu->mutex_cnt; i++) {
2898 pmu->mutex[i].id = i;
2899 pmu->mutex[i].index = i;
2900 }
2901
2902 pmu->seq = nvgpu_kzalloc(g, PMU_MAX_NUM_SEQUENCES *
2903 sizeof(struct pmu_sequence));
2904 if (!pmu->seq) {
2905 err = -ENOMEM;
2906 goto err_free_mutex;
2907 }
2908
2909 nvgpu_pmu_seq_init(pmu);
2910
2911 err = nvgpu_dma_alloc_map_sys(vm, GK20A_PMU_SEQ_BUF_SIZE,
2912 &pmu->seq_buf);
2913 if (err) {
2914 nvgpu_err(g, "failed to allocate memory");
2915 goto err_free_seq;
2916 }
2917
2918 ptr = (u8 *)pmu->seq_buf.cpu_va;
2919
2920 /* TBD: remove this if ZBC save/restore is handled by PMU
2921 * end an empty ZBC sequence for now */
2922 ptr[0] = 0x16; /* opcode EXIT */
2923 ptr[1] = 0; ptr[2] = 1; ptr[3] = 0;
2924 ptr[4] = 0; ptr[5] = 0; ptr[6] = 0; ptr[7] = 0;
2925
2926 pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE;
2927
2928 err = nvgpu_dma_alloc_map(vm, GK20A_PMU_TRACE_BUFSIZE,
2929 &pmu->trace_buf);
2930 if (err) {
2931 nvgpu_err(g, "failed to allocate pmu trace buffer");
2932 goto err_free_seq_buf;
2933 }
2934
2935 pmu->sw_ready = true;
2936
2937skip_init:
2938 gk20a_dbg_fn("done");
2939 return 0;
2940 err_free_seq_buf:
2941 nvgpu_dma_unmap_free(vm, &pmu->seq_buf);
2942 err_free_seq:
2943 nvgpu_kfree(g, pmu->seq);
2944 err_free_mutex:
2945 nvgpu_kfree(g, pmu->mutex);
2946 err:
2947 gk20a_dbg_fn("fail");
2948 return err;
2949}
2950
2951static void pmu_handle_pg_buf_config_msg(struct gk20a *g, struct pmu_msg *msg, 2853static void pmu_handle_pg_buf_config_msg(struct gk20a *g, struct pmu_msg *msg,
2952 void *param, u32 handle, u32 status) 2854 void *param, u32 handle, u32 status)
2953{ 2855{
@@ -3006,99 +2908,7 @@ static int gk20a_init_pmu_setup_hw1(struct gk20a *g)
3006 2908
3007} 2909}
3008 2910
3009static void pmu_setup_hw_load_zbc(struct gk20a *g); 2911int nvgpu_pmu_init_bind_fecs(struct gk20a *g)
3010static void pmu_setup_hw_enable_elpg(struct gk20a *g);
3011
3012static void nvgpu_pmu_state_change(struct gk20a *g, u32 pmu_state,
3013 bool post_change_event)
3014{
3015 struct nvgpu_pmu *pmu = &g->pmu;
3016
3017 pmu->pmu_state = pmu_state;
3018
3019 if (post_change_event) {
3020 pmu->pg_init.state_change = true;
3021 nvgpu_cond_signal(&pmu->pg_init.wq);
3022 }
3023
3024 /* make status visible */
3025 smp_mb();
3026}
3027
3028static int nvgpu_pg_init_task(void *arg)
3029{
3030 struct gk20a *g = (struct gk20a *)arg;
3031 struct nvgpu_pmu *pmu = &g->pmu;
3032 struct nvgpu_pg_init *pg_init = &pmu->pg_init;
3033 u32 pmu_state = 0;
3034
3035 while (true) {
3036
3037 NVGPU_COND_WAIT(&pg_init->wq,
3038 (pg_init->state_change == true), 0);
3039
3040 pmu->pg_init.state_change = false;
3041 pmu_state = ACCESS_ONCE(pmu->pmu_state);
3042
3043 if (pmu_state == PMU_STATE_EXIT) {
3044 gk20a_dbg_pmu("pmu state exit");
3045 break;
3046 }
3047
3048 switch (pmu_state) {
3049 case PMU_STATE_INIT_RECEIVED:
3050 gk20a_dbg_pmu("pmu starting");
3051 if (g->can_elpg)
3052 pmu_init_powergating(g);
3053 break;
3054 case PMU_STATE_ELPG_BOOTED:
3055 gk20a_dbg_pmu("elpg booted");
3056 gk20a_init_pmu_bind_fecs(g);
3057 break;
3058 case PMU_STATE_LOADING_PG_BUF:
3059 gk20a_dbg_pmu("loaded pg buf");
3060 pmu_setup_hw_load_zbc(g);
3061 break;
3062 case PMU_STATE_LOADING_ZBC:
3063 gk20a_dbg_pmu("loaded zbc");
3064 pmu_setup_hw_enable_elpg(g);
3065 break;
3066 case PMU_STATE_STARTED:
3067 gk20a_dbg_pmu("PMU booted");
3068 break;
3069 default:
3070 gk20a_dbg_pmu("invalid state");
3071 break;
3072 }
3073
3074 }
3075
3076 while (!nvgpu_thread_should_stop(&pg_init->state_task))
3077 nvgpu_msleep(5);
3078
3079 return 0;
3080}
3081
3082static int nvgpu_init_task_pg_init(struct gk20a *g)
3083{
3084 struct nvgpu_pmu *pmu = &g->pmu;
3085 char thread_name[64];
3086 int err = 0;
3087
3088 nvgpu_cond_init(&pmu->pg_init.wq);
3089
3090 snprintf(thread_name, sizeof(thread_name),
3091 "nvgpu_pg_init_%s", g->name);
3092
3093 err = nvgpu_thread_create(&pmu->pg_init.state_task, g,
3094 nvgpu_pg_init_task, thread_name);
3095 if (err)
3096 nvgpu_err(g, "failed to start nvgpu_pg_init thread");
3097
3098 return err;
3099}
3100
3101int gk20a_init_pmu_bind_fecs(struct gk20a *g)
3102{ 2912{
3103 struct nvgpu_pmu *pmu = &g->pmu; 2913 struct nvgpu_pmu *pmu = &g->pmu;
3104 struct pmu_cmd cmd; 2914 struct pmu_cmd cmd;
@@ -3137,7 +2947,7 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g)
3137 return err; 2947 return err;
3138} 2948}
3139 2949
3140static void pmu_setup_hw_load_zbc(struct gk20a *g) 2950void nvgpu_pmu_setup_hw_load_zbc(struct gk20a *g)
3141{ 2951{
3142 struct nvgpu_pmu *pmu = &g->pmu; 2952 struct nvgpu_pmu *pmu = &g->pmu;
3143 struct pmu_cmd cmd; 2953 struct pmu_cmd cmd;
@@ -3172,43 +2982,6 @@ static void pmu_setup_hw_load_zbc(struct gk20a *g)
3172 nvgpu_pmu_state_change(g, PMU_STATE_LOADING_ZBC, false); 2982 nvgpu_pmu_state_change(g, PMU_STATE_LOADING_ZBC, false);
3173} 2983}
3174 2984
3175static void pmu_setup_hw_enable_elpg(struct gk20a *g)
3176{
3177 struct nvgpu_pmu *pmu = &g->pmu;
3178
3179 /*
3180 * FIXME: To enable ELPG, we increase the PMU ext2priv timeout unit to
3181 * 7. This prevents PMU stalling on Host register accesses. Once the
3182 * cause for this hang is discovered and fixed, this WAR should be
3183 * removed.
3184 */
3185 gk20a_writel(g, 0x10a164, 0x109ff);
3186
3187 pmu->initialized = true;
3188 nvgpu_pmu_state_change(g, PMU_STATE_STARTED, false);
3189
3190 if (g->ops.pmu_ver.is_pmu_zbc_save_supported) {
3191 /* Save zbc table after PMU is initialized. */
3192 pmu->zbc_ready = true;
3193 gk20a_pmu_save_zbc(g, 0xf);
3194 }
3195
3196 if (g->elpg_enabled) {
3197 /* Init reg with prod values*/
3198 if (g->ops.pmu.pmu_setup_elpg)
3199 g->ops.pmu.pmu_setup_elpg(g);
3200 gk20a_pmu_enable_elpg(g);
3201 }
3202
3203 nvgpu_udelay(50);
3204
3205 /* Enable AELPG */
3206 if (g->aelpg_enabled) {
3207 gk20a_aelpg_init(g);
3208 gk20a_aelpg_init_and_enable(g, PMU_AP_CTRL_ID_GRAPHICS);
3209 }
3210}
3211
3212static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr) 2985static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr)
3213{ 2986{
3214 gk20a_writel(g, pwr_falcon_dmatrfbase_r(), addr); 2987 gk20a_writel(g, pwr_falcon_dmatrfbase_r(), addr);
@@ -3254,6 +3027,8 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops)
3254 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v; 3027 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v;
3255 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head; 3028 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head;
3256 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail; 3029 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail;
3030 gops->pmu.pmu_msgq_tail = gk20a_pmu_msgq_tail;
3031 gops->pmu.pmu_mutex_size = pwr_pmu_mutex__size_1_v;
3257 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire; 3032 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire;
3258 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release; 3033 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release;
3259 gops->pmu.pmu_setup_elpg = NULL; 3034 gops->pmu.pmu_setup_elpg = NULL;
@@ -3279,34 +3054,6 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops)
3279 gops->pmu.reset = gk20a_pmu_reset; 3054 gops->pmu.reset = gk20a_pmu_reset;
3280} 3055}
3281 3056
3282int gk20a_init_pmu_support(struct gk20a *g)
3283{
3284 struct nvgpu_pmu *pmu = &g->pmu;
3285 u32 err;
3286
3287 gk20a_dbg_fn("");
3288
3289 if (pmu->initialized)
3290 return 0;
3291
3292 err = gk20a_init_pmu_reset_enable_hw(g);
3293 if (err)
3294 return err;
3295
3296 if (g->support_pmu) {
3297 err = gk20a_init_pmu_setup_sw(g);
3298 if (err)
3299 return err;
3300 err = g->ops.pmu.pmu_setup_hw_and_bootstrap(g);
3301 if (err)
3302 return err;
3303
3304 nvgpu_pmu_state_change(g, PMU_STATE_STARTING, false);
3305 }
3306
3307 return err;
3308}
3309
3310static void pmu_handle_pg_elpg_msg(struct gk20a *g, struct pmu_msg *msg, 3057static void pmu_handle_pg_elpg_msg(struct gk20a *g, struct pmu_msg *msg,
3311 void *param, u32 handle, u32 status) 3058 void *param, u32 handle, u32 status)
3312{ 3059{
@@ -3453,7 +3200,8 @@ static int pmu_pg_init_send(struct gk20a *g, u32 pg_engine_id)
3453 3200
3454 return 0; 3201 return 0;
3455} 3202}
3456static int pmu_init_powergating(struct gk20a *g) 3203
3204int nvgpu_pmu_init_powergating(struct gk20a *g)
3457{ 3205{
3458 struct nvgpu_pmu *pmu = &g->pmu; 3206 struct nvgpu_pmu *pmu = &g->pmu;
3459 u32 pg_engine_id; 3207 u32 pg_engine_id;
@@ -3613,84 +3361,6 @@ int nvgpu_pmu_init_perfmon(struct nvgpu_pmu *pmu)
3613 return 0; 3361 return 0;
3614} 3362}
3615 3363
3616int nvgpu_pmu_process_init_msg(struct nvgpu_pmu *pmu,
3617 struct pmu_msg *msg)
3618{
3619 struct gk20a *g = gk20a_from_pmu(pmu);
3620 struct pmu_v *pv = &g->ops.pmu_ver;
3621 union pmu_init_msg_pmu *init;
3622 struct pmu_sha1_gid_data gid_data;
3623 u32 i, tail = 0;
3624 gk20a_dbg_pmu("init received\n");
3625
3626 tail = pwr_pmu_msgq_tail_val_v(
3627 gk20a_readl(g, pwr_pmu_msgq_tail_r()));
3628
3629 pmu_copy_from_dmem(pmu, tail,
3630 (u8 *)&msg->hdr, PMU_MSG_HDR_SIZE, 0);
3631 if (msg->hdr.unit_id != PMU_UNIT_INIT) {
3632 nvgpu_err(g, "expecting init msg");
3633 return -EINVAL;
3634 }
3635
3636 pmu_copy_from_dmem(pmu, tail + PMU_MSG_HDR_SIZE,
3637 (u8 *)&msg->msg, msg->hdr.size - PMU_MSG_HDR_SIZE, 0);
3638
3639 if (msg->msg.init.msg_type != PMU_INIT_MSG_TYPE_PMU_INIT) {
3640 nvgpu_err(g, "expecting init msg");
3641 return -EINVAL;
3642 }
3643
3644 tail += ALIGN(msg->hdr.size, PMU_DMEM_ALIGNMENT);
3645 gk20a_writel(g, pwr_pmu_msgq_tail_r(),
3646 pwr_pmu_msgq_tail_val_f(tail));
3647
3648 init = pv->get_pmu_msg_pmu_init_msg_ptr(&(msg->msg.init));
3649 if (!pmu->gid_info.valid) {
3650
3651 pmu_copy_from_dmem(pmu,
3652 pv->get_pmu_init_msg_pmu_sw_mg_off(init),
3653 (u8 *)&gid_data,
3654 sizeof(struct pmu_sha1_gid_data), 0);
3655
3656 pmu->gid_info.valid =
3657 (*(u32 *)gid_data.signature == PMU_SHA1_GID_SIGNATURE);
3658
3659 if (pmu->gid_info.valid) {
3660
3661 BUG_ON(sizeof(pmu->gid_info.gid) !=
3662 sizeof(gid_data.gid));
3663
3664 memcpy(pmu->gid_info.gid, gid_data.gid,
3665 sizeof(pmu->gid_info.gid));
3666 }
3667 }
3668
3669 for (i = 0; i < PMU_QUEUE_COUNT; i++)
3670 nvgpu_pmu_queue_init(pmu, i, init);
3671
3672 if (!nvgpu_alloc_initialized(&pmu->dmem)) {
3673 /* Align start and end addresses */
3674 u32 start = ALIGN(pv->get_pmu_init_msg_pmu_sw_mg_off(init),
3675 PMU_DMEM_ALLOC_ALIGNMENT);
3676 u32 end = (pv->get_pmu_init_msg_pmu_sw_mg_off(init) +
3677 pv->get_pmu_init_msg_pmu_sw_mg_size(init)) &
3678 ~(PMU_DMEM_ALLOC_ALIGNMENT - 1);
3679 u32 size = end - start;
3680 nvgpu_bitmap_allocator_init(g, &pmu->dmem, "gk20a_pmu_dmem",
3681 start, size,
3682 PMU_DMEM_ALLOC_ALIGNMENT, 0);
3683 }
3684
3685 pmu->pmu_ready = true;
3686
3687 nvgpu_pmu_state_change(g, PMU_STATE_INIT_RECEIVED, true);
3688
3689 gk20a_dbg_pmu("init received end\n");
3690
3691 return 0;
3692}
3693
3694static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg, 3364static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg,
3695 void *param, u32 handle, u32 status) 3365 void *param, u32 handle, u32 status)
3696{ 3366{
@@ -4413,66 +4083,6 @@ int gk20a_pmu_perfmon_enable(struct gk20a *g, bool enable)
4413 return err; 4083 return err;
4414} 4084}
4415 4085
4416int gk20a_pmu_destroy(struct gk20a *g)
4417{
4418 struct nvgpu_pmu *pmu = &g->pmu;
4419 struct pmu_pg_stats_data pg_stat_data = { 0 };
4420 struct nvgpu_timeout timeout;
4421 int i;
4422
4423 gk20a_dbg_fn("");
4424
4425 if (!g->support_pmu)
4426 return 0;
4427
4428 /* make sure the pending operations are finished before we continue */
4429 if (nvgpu_thread_is_running(&pmu->pg_init.state_task)) {
4430
4431 /* post PMU_STATE_EXIT to exit PMU state machine loop */
4432 nvgpu_pmu_state_change(g, PMU_STATE_EXIT, true);
4433
4434 /* Make thread stop*/
4435 nvgpu_thread_stop(&pmu->pg_init.state_task);
4436
4437 /* wait to confirm thread stopped */
4438 nvgpu_timeout_init(g, &timeout, 1000, NVGPU_TIMER_RETRY_TIMER);
4439 do {
4440 if (!nvgpu_thread_is_running(&pmu->pg_init.state_task))
4441 break;
4442 nvgpu_udelay(2);
4443 } while (!nvgpu_timeout_expired_msg(&timeout,
4444 "timeout - waiting PMU state machine thread stop"));
4445 }
4446
4447 gk20a_pmu_get_pg_stats(g,
4448 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
4449
4450 gk20a_pmu_disable_elpg(g);
4451 pmu->initialized = false;
4452
4453 /* update the s/w ELPG residency counters */
4454 g->pg_ingating_time_us += (u64)pg_stat_data.ingating_time;
4455 g->pg_ungating_time_us += (u64)pg_stat_data.ungating_time;
4456 g->pg_gating_cnt += pg_stat_data.gating_cnt;
4457
4458 nvgpu_mutex_acquire(&pmu->isr_mutex);
4459 pmu->isr_enabled = false;
4460 nvgpu_mutex_release(&pmu->isr_mutex);
4461
4462 for (i = 0; i < PMU_QUEUE_COUNT; i++)
4463 nvgpu_mutex_destroy(&pmu->queue[i].mutex);
4464
4465 nvgpu_pmu_state_change(g, PMU_STATE_OFF, false);
4466 pmu->pmu_ready = false;
4467 pmu->perfmon_ready = false;
4468 pmu->zbc_ready = false;
4469 g->ops.pmu.lspmuwprinitdone = false;
4470 g->ops.pmu.fecsbootstrapdone = false;
4471
4472 gk20a_dbg_fn("done");
4473 return 0;
4474}
4475
4476int gk20a_pmu_load_norm(struct gk20a *g, u32 *load) 4086int gk20a_pmu_load_norm(struct gk20a *g, u32 *load)
4477{ 4087{
4478 *load = g->pmu.load_shadow; 4088 *load = g->pmu.load_shadow;
@@ -4543,8 +4153,7 @@ void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
4543 pg_stat_data->avg_exit_latency_us = stats.pg_avg_exit_time_us; 4153 pg_stat_data->avg_exit_latency_us = stats.pg_avg_exit_time_us;
4544} 4154}
4545 4155
4546int gk20a_pmu_get_pg_stats(struct gk20a *g, 4156int nvgpu_pmu_get_pg_stats(struct gk20a *g, u32 pg_engine_id,
4547 u32 pg_engine_id,
4548 struct pmu_pg_stats_data *pg_stat_data) 4157 struct pmu_pg_stats_data *pg_stat_data)
4549{ 4158{
4550 struct nvgpu_pmu *pmu = &g->pmu; 4159 struct nvgpu_pmu *pmu = &g->pmu;