diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 5 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 443 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 17 |
4 files changed, 33 insertions, 435 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index b038cd81..8624d601 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <nvgpu/timers.h> | 24 | #include <nvgpu/timers.h> |
25 | #include <nvgpu/soc.h> | 25 | #include <nvgpu/soc.h> |
26 | #include <nvgpu/enabled.h> | 26 | #include <nvgpu/enabled.h> |
27 | #include <nvgpu/pmu.h> | ||
27 | 28 | ||
28 | #include <trace/events/gk20a.h> | 29 | #include <trace/events/gk20a.h> |
29 | 30 | ||
@@ -130,7 +131,7 @@ int gk20a_prepare_poweroff(struct gk20a *g) | |||
130 | 131 | ||
131 | /* disable elpg before gr or fifo suspend */ | 132 | /* disable elpg before gr or fifo suspend */ |
132 | if (g->ops.pmu.is_pmu_supported(g)) | 133 | if (g->ops.pmu.is_pmu_supported(g)) |
133 | ret |= gk20a_pmu_destroy(g); | 134 | ret |= nvgpu_pmu_destroy(g); |
134 | 135 | ||
135 | ret |= gk20a_gr_suspend(g); | 136 | ret |= gk20a_gr_suspend(g); |
136 | ret |= gk20a_mm_suspend(g); | 137 | ret |= gk20a_mm_suspend(g); |
@@ -259,7 +260,7 @@ int gk20a_finalize_poweron(struct gk20a *g) | |||
259 | #endif | 260 | #endif |
260 | 261 | ||
261 | if (g->ops.pmu.is_pmu_supported(g)) { | 262 | if (g->ops.pmu.is_pmu_supported(g)) { |
262 | err = gk20a_init_pmu_support(g); | 263 | err = nvgpu_init_pmu_support(g); |
263 | if (err) { | 264 | if (err) { |
264 | nvgpu_err(g, "failed to init gk20a pmu"); | 265 | nvgpu_err(g, "failed to init gk20a pmu"); |
265 | goto done; | 266 | goto done; |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 269f0d68..1d867912 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -741,6 +741,9 @@ struct gpu_ops { | |||
741 | struct pmu_queue *queue, u32 *head, bool set); | 741 | struct pmu_queue *queue, u32 *head, bool set); |
742 | int (*pmu_queue_tail)(struct nvgpu_pmu *pmu, | 742 | int (*pmu_queue_tail)(struct nvgpu_pmu *pmu, |
743 | struct pmu_queue *queue, u32 *tail, bool set); | 743 | struct pmu_queue *queue, u32 *tail, bool set); |
744 | void (*pmu_msgq_tail)(struct nvgpu_pmu *pmu, | ||
745 | u32 *tail, bool set); | ||
746 | u32 (*pmu_mutex_size)(void); | ||
744 | int (*pmu_mutex_acquire)(struct nvgpu_pmu *pmu, | 747 | int (*pmu_mutex_acquire)(struct nvgpu_pmu *pmu, |
745 | u32 id, u32 *token); | 748 | u32 id, u32 *token); |
746 | int (*pmu_mutex_release)(struct nvgpu_pmu *pmu, | 749 | int (*pmu_mutex_release)(struct nvgpu_pmu *pmu, |
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 | ||
46 | int gk20a_pmu_get_pg_stats(struct gk20a *g, | ||
47 | u32 pg_engine_id, | ||
48 | struct pmu_pg_stats_data *pg_stat_data); | ||
49 | static void ap_callback_init_and_enable_ctrl( | 46 | static 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 | ||
53 | static int nvgpu_init_task_pg_init(struct gk20a *g); | ||
54 | static void nvgpu_pmu_state_change(struct gk20a *g, u32 pmu_state, | ||
55 | bool post_change_event); | ||
56 | |||
57 | static int pmu_init_powergating(struct gk20a *g); | ||
58 | |||
59 | static u32 pmu_perfmon_cntr_sz_v0(struct nvgpu_pmu *pmu) | 50 | static 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 | ||
2777 | void 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 | |||
2786 | void gk20a_remove_pmu_support(struct nvgpu_pmu *pmu) | 2796 | void 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 | ||
2804 | static 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 | |||
2815 | static int gk20a_prepare_ucode(struct gk20a *g) | 2814 | static 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 | ||
2854 | static 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 | |||
2937 | skip_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 | |||
2951 | static void pmu_handle_pg_buf_config_msg(struct gk20a *g, struct pmu_msg *msg, | 2853 | static 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 | ||
3009 | static void pmu_setup_hw_load_zbc(struct gk20a *g); | 2911 | int nvgpu_pmu_init_bind_fecs(struct gk20a *g) |
3010 | static void pmu_setup_hw_enable_elpg(struct gk20a *g); | ||
3011 | |||
3012 | static 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 | |||
3028 | static 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 | |||
3082 | static 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 | |||
3101 | int 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 | ||
3140 | static void pmu_setup_hw_load_zbc(struct gk20a *g) | 2950 | void 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 | ||
3175 | static 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 | |||
3212 | static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr) | 2985 | static 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 | ||
3282 | int 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 | |||
3310 | static void pmu_handle_pg_elpg_msg(struct gk20a *g, struct pmu_msg *msg, | 3057 | static 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 | } |
3456 | static int pmu_init_powergating(struct gk20a *g) | 3203 | |
3204 | int 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 | ||
3616 | int 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 | |||
3694 | static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg, | 3364 | static 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 | ||
4416 | int 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 | |||
4476 | int gk20a_pmu_load_norm(struct gk20a *g, u32 *load) | 4086 | int 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 | ||
4546 | int gk20a_pmu_get_pg_stats(struct gk20a *g, | 4156 | int 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; |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index a53329b4..1c29b380 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | |||
@@ -63,15 +63,6 @@ struct pmu_surface { | |||
63 | struct flcn_mem_desc_v0 params; | 63 | struct flcn_mem_desc_v0 params; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | /*PG defines used by nvpgu-pmu*/ | ||
67 | struct pmu_pg_stats_data { | ||
68 | u32 gating_cnt; | ||
69 | u32 ingating_time; | ||
70 | u32 ungating_time; | ||
71 | u32 avg_entry_latency_us; | ||
72 | u32 avg_exit_latency_us; | ||
73 | }; | ||
74 | |||
75 | #define PMU_PG_IDLE_THRESHOLD_SIM 1000 | 66 | #define PMU_PG_IDLE_THRESHOLD_SIM 1000 |
76 | #define PMU_PG_POST_POWERUP_IDLE_THRESHOLD_SIM 4000000 | 67 | #define PMU_PG_POST_POWERUP_IDLE_THRESHOLD_SIM 4000000 |
77 | /* TBD: QT or else ? */ | 68 | /* TBD: QT or else ? */ |
@@ -105,10 +96,6 @@ struct pmu_pg_stats_data { | |||
105 | #define APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US (10000) | 96 | #define APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US (10000) |
106 | #define APCTRL_POWER_BREAKEVEN_DEFAULT_US (2000) | 97 | #define APCTRL_POWER_BREAKEVEN_DEFAULT_US (2000) |
107 | #define APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT (200) | 98 | #define APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT (200) |
108 | /*PG defines used by nvpgu-pmu*/ | ||
109 | |||
110 | int gk20a_init_pmu_support(struct gk20a *g); | ||
111 | int gk20a_init_pmu_bind_fecs(struct gk20a *g); | ||
112 | 99 | ||
113 | bool gk20a_pmu_is_interrupted(struct nvgpu_pmu *pmu); | 100 | bool gk20a_pmu_is_interrupted(struct nvgpu_pmu *pmu); |
114 | void gk20a_pmu_isr(struct gk20a *g); | 101 | void gk20a_pmu_isr(struct gk20a *g); |
@@ -131,8 +118,8 @@ int gk20a_pmu_queue_head(struct nvgpu_pmu *pmu, struct pmu_queue *queue, | |||
131 | u32 *head, bool set); | 118 | u32 *head, bool set); |
132 | int gk20a_pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue, | 119 | int gk20a_pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue, |
133 | u32 *tail, bool set); | 120 | u32 *tail, bool set); |
121 | void gk20a_pmu_msgq_tail(struct nvgpu_pmu *pmu, u32 *tail, bool set); | ||
134 | 122 | ||
135 | int gk20a_pmu_destroy(struct gk20a *g); | ||
136 | int gk20a_pmu_load_norm(struct gk20a *g, u32 *load); | 123 | int gk20a_pmu_load_norm(struct gk20a *g, u32 *load); |
137 | int gk20a_pmu_load_update(struct gk20a *g); | 124 | int gk20a_pmu_load_update(struct gk20a *g); |
138 | void gk20a_pmu_reset_load_counters(struct gk20a *g); | 125 | void gk20a_pmu_reset_load_counters(struct gk20a *g); |
@@ -174,8 +161,6 @@ int gk20a_pmu_vidmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem, | |||
174 | u32 size); | 161 | u32 size); |
175 | int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem, | 162 | int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem, |
176 | u32 size); | 163 | u32 size); |
177 | int gk20a_pmu_get_pg_stats(struct gk20a *g, | ||
178 | u32 pg_engine_id, struct pmu_pg_stats_data *pg_stat_data); | ||
179 | bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos); | 164 | bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos); |
180 | 165 | ||
181 | int nvgpu_pmu_perfmon_start_sampling(struct nvgpu_pmu *pmu); | 166 | int nvgpu_pmu_perfmon_start_sampling(struct nvgpu_pmu *pmu); |