aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/modules/stats/stats.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/modules/stats/stats.c')
-rw-r--r--drivers/gpu/drm/amd/display/modules/stats/stats.c254
1 files changed, 187 insertions, 67 deletions
diff --git a/drivers/gpu/drm/amd/display/modules/stats/stats.c b/drivers/gpu/drm/amd/display/modules/stats/stats.c
index 041f87b73d5f..3f7d47fdc367 100644
--- a/drivers/gpu/drm/amd/display/modules/stats/stats.c
+++ b/drivers/gpu/drm/amd/display/modules/stats/stats.c
@@ -36,9 +36,14 @@
36#define DAL_STATS_ENTRIES_REGKEY_DEFAULT 0x00350000 36#define DAL_STATS_ENTRIES_REGKEY_DEFAULT 0x00350000
37#define DAL_STATS_ENTRIES_REGKEY_MAX 0x01000000 37#define DAL_STATS_ENTRIES_REGKEY_MAX 0x01000000
38 38
39#define DAL_STATS_EVENT_ENTRIES_DEFAULT 0x00000100
40
39#define MOD_STATS_NUM_VSYNCS 5 41#define MOD_STATS_NUM_VSYNCS 5
42#define MOD_STATS_EVENT_STRING_MAX 512
40 43
41struct stats_time_cache { 44struct stats_time_cache {
45 unsigned int entry_id;
46
42 unsigned long flip_timestamp_in_ns; 47 unsigned long flip_timestamp_in_ns;
43 unsigned long vupdate_timestamp_in_ns; 48 unsigned long vupdate_timestamp_in_ns;
44 49
@@ -63,15 +68,26 @@ struct stats_time_cache {
63 unsigned int flags; 68 unsigned int flags;
64}; 69};
65 70
71struct stats_event_cache {
72 unsigned int entry_id;
73 char event_string[MOD_STATS_EVENT_STRING_MAX];
74};
75
66struct core_stats { 76struct core_stats {
67 struct mod_stats public; 77 struct mod_stats public;
68 struct dc *dc; 78 struct dc *dc;
69 79
80 bool enabled;
81 unsigned int entries;
82 unsigned int event_entries;
83 unsigned int entry_id;
84
70 struct stats_time_cache *time; 85 struct stats_time_cache *time;
71 unsigned int index; 86 unsigned int index;
72 87
73 bool enabled; 88 struct stats_event_cache *events;
74 unsigned int entries; 89 unsigned int event_index;
90
75}; 91};
76 92
77#define MOD_STATS_TO_CORE(mod_stats)\ 93#define MOD_STATS_TO_CORE(mod_stats)\
@@ -99,12 +115,12 @@ struct mod_stats *mod_stats_create(struct dc *dc)
99 unsigned int reg_data; 115 unsigned int reg_data;
100 int i = 0; 116 int i = 0;
101 117
118 if (dc == NULL)
119 goto fail_construct;
120
102 core_stats = kzalloc(sizeof(struct core_stats), GFP_KERNEL); 121 core_stats = kzalloc(sizeof(struct core_stats), GFP_KERNEL);
103 122
104 if (core_stats == NULL) 123 if (core_stats == NULL)
105 goto fail_alloc_context;
106
107 if (dc == NULL)
108 goto fail_construct; 124 goto fail_construct;
109 125
110 core_stats->dc = dc; 126 core_stats->dc = dc;
@@ -115,33 +131,55 @@ struct mod_stats *mod_stats_create(struct dc *dc)
115 &reg_data, sizeof(unsigned int), &flag)) 131 &reg_data, sizeof(unsigned int), &flag))
116 core_stats->enabled = reg_data; 132 core_stats->enabled = reg_data;
117 133
118 core_stats->entries = DAL_STATS_ENTRIES_REGKEY_DEFAULT; 134 if (core_stats->enabled) {
119 if (dm_read_persistent_data(dc->ctx, NULL, NULL, 135 core_stats->entries = DAL_STATS_ENTRIES_REGKEY_DEFAULT;
120 DAL_STATS_ENTRIES_REGKEY, 136 if (dm_read_persistent_data(dc->ctx, NULL, NULL,
121 &reg_data, sizeof(unsigned int), &flag)) { 137 DAL_STATS_ENTRIES_REGKEY,
122 if (reg_data > DAL_STATS_ENTRIES_REGKEY_MAX) 138 &reg_data, sizeof(unsigned int), &flag)) {
123 core_stats->entries = DAL_STATS_ENTRIES_REGKEY_MAX; 139 if (reg_data > DAL_STATS_ENTRIES_REGKEY_MAX)
124 else 140 core_stats->entries = DAL_STATS_ENTRIES_REGKEY_MAX;
125 core_stats->entries = reg_data; 141 else
126 } 142 core_stats->entries = reg_data;
143 }
144 core_stats->time = kzalloc(
145 sizeof(struct stats_time_cache) *
146 core_stats->entries,
147 GFP_KERNEL);
127 148
128 core_stats->time = kzalloc(sizeof(struct stats_time_cache) * core_stats->entries, 149 if (core_stats->time == NULL)
129 GFP_KERNEL); 150 goto fail_construct_time;
130 151
131 if (core_stats->time == NULL) 152 core_stats->event_entries = DAL_STATS_EVENT_ENTRIES_DEFAULT;
132 goto fail_construct; 153 core_stats->events = kzalloc(
154 sizeof(struct stats_event_cache) *
155 core_stats->event_entries,
156 GFP_KERNEL);
157
158 if (core_stats->events == NULL)
159 goto fail_construct_events;
160
161 } else {
162 core_stats->entries = 0;
163 }
133 164
134 /* Purposely leave index 0 unused so we don't need special logic to 165 /* Purposely leave index 0 unused so we don't need special logic to
135 * handle calculation cases that depend on previous flip data. 166 * handle calculation cases that depend on previous flip data.
136 */ 167 */
137 core_stats->index = 1; 168 core_stats->index = 1;
169 core_stats->event_index = 0;
170
171 // Keeps track of ordering within the different stats structures
172 core_stats->entry_id = 0;
138 173
139 return &core_stats->public; 174 return &core_stats->public;
140 175
141fail_construct: 176fail_construct_events:
177 kfree(core_stats->time);
178
179fail_construct_time:
142 kfree(core_stats); 180 kfree(core_stats);
143 181
144fail_alloc_context: 182fail_construct:
145 return NULL; 183 return NULL;
146} 184}
147 185
@@ -153,6 +191,9 @@ void mod_stats_destroy(struct mod_stats *mod_stats)
153 if (core_stats->time != NULL) 191 if (core_stats->time != NULL)
154 kfree(core_stats->time); 192 kfree(core_stats->time);
155 193
194 if (core_stats->events != NULL)
195 kfree(core_stats->events);
196
156 kfree(core_stats); 197 kfree(core_stats);
157 } 198 }
158} 199}
@@ -163,7 +204,11 @@ void mod_stats_dump(struct mod_stats *mod_stats)
163 struct dal_logger *logger = NULL; 204 struct dal_logger *logger = NULL;
164 struct core_stats *core_stats = NULL; 205 struct core_stats *core_stats = NULL;
165 struct stats_time_cache *time = NULL; 206 struct stats_time_cache *time = NULL;
207 struct stats_event_cache *events = NULL;
208 unsigned int time_index = 1;
209 unsigned int event_index = 0;
166 unsigned int index = 0; 210 unsigned int index = 0;
211 struct log_entry log_entry;
167 212
168 if (mod_stats == NULL) 213 if (mod_stats == NULL)
169 return; 214 return;
@@ -172,45 +217,62 @@ void mod_stats_dump(struct mod_stats *mod_stats)
172 dc = core_stats->dc; 217 dc = core_stats->dc;
173 logger = dc->ctx->logger; 218 logger = dc->ctx->logger;
174 time = core_stats->time; 219 time = core_stats->time;
175 220 events = core_stats->events;
176 //LogEntry* pLog = GetLog()->Open(LogMajor_ISR, LogMinor_ISR_FreeSyncSW); 221
177 222 DISPLAY_STATS_BEGIN(log_entry);
178 //if (!pLog->IsDummyEntry()) 223
179 { 224 DISPLAY_STATS("==Display Caps==\n");
180 dm_logger_write(logger, LOG_PROFILING, "==Display Caps==\n"); 225
181 dm_logger_write(logger, LOG_PROFILING, "\n"); 226 DISPLAY_STATS("==Display Stats==\n");
182 dm_logger_write(logger, LOG_PROFILING, "\n"); 227
183 228 DISPLAY_STATS("%10s %10s %10s %10s %10s"
184 dm_logger_write(logger, LOG_PROFILING, "==Stats==\n"); 229 " %11s %11s %17s %10s %14s"
185 dm_logger_write(logger, LOG_PROFILING, 230 " %10s %10s %10s %10s %10s"
186 "render avgRender minWindow midPoint maxWindow vsyncToFlip flipToVsync #vsyncBetweenFlip #frame insertDuration vTotalMin vTotalMax eventTrigs vSyncTime1 vSyncTime2 vSyncTime3 vSyncTime4 vSyncTime5 flags\n"); 231 " %10s %10s %10s %10s\n",
187 232 "render", "avgRender",
188 for (int i = 0; i < core_stats->index && i < core_stats->entries; i++) { 233 "minWindow", "midPoint", "maxWindow",
189 dm_logger_write(logger, LOG_PROFILING, 234 "vsyncToFlip", "flipToVsync", "vsyncsBetweenFlip",
190 "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n", 235 "numFrame", "insertDuration",
191 time[i].render_time_in_us, 236 "vTotalMin", "vTotalMax", "eventTrigs",
192 time[i].avg_render_time_in_us_last_ten, 237 "vSyncTime1", "vSyncTime2", "vSyncTime3",
193 time[i].min_window, 238 "vSyncTime4", "vSyncTime5", "flags");
194 time[i].lfc_mid_point_in_us, 239
195 time[i].max_window, 240 for (int i = 0; i < core_stats->entry_id; i++) {
196 time[i].vsync_to_flip_time_in_us, 241 if (event_index < core_stats->event_index &&
197 time[i].flip_to_vsync_time_in_us, 242 i == events[event_index].entry_id) {
198 time[i].num_vsync_between_flips, 243 DISPLAY_STATS("%s\n", events[event_index].event_string);
199 time[i].num_frames_inserted, 244 event_index++;
200 time[i].inserted_duration_in_us, 245 } else if (time_index < core_stats->index &&
201 time[i].v_total_min, 246 i == time[time_index].entry_id) {
202 time[i].v_total_max, 247 DISPLAY_STATS("%10u %10u %10u %10u %10u"
203 time[i].event_triggers, 248 " %11u %11u %17u %10u %14u"
204 time[i].v_sync_time_in_us[0], 249 " %10u %10u %10u %10u %10u"
205 time[i].v_sync_time_in_us[1], 250 " %10u %10u %10u %10u\n",
206 time[i].v_sync_time_in_us[2], 251 time[time_index].render_time_in_us,
207 time[i].v_sync_time_in_us[3], 252 time[time_index].avg_render_time_in_us_last_ten,
208 time[i].v_sync_time_in_us[4], 253 time[time_index].min_window,
209 time[i].flags); 254 time[time_index].lfc_mid_point_in_us,
255 time[time_index].max_window,
256 time[time_index].vsync_to_flip_time_in_us,
257 time[time_index].flip_to_vsync_time_in_us,
258 time[time_index].num_vsync_between_flips,
259 time[time_index].num_frames_inserted,
260 time[time_index].inserted_duration_in_us,
261 time[time_index].v_total_min,
262 time[time_index].v_total_max,
263 time[time_index].event_triggers,
264 time[time_index].v_sync_time_in_us[0],
265 time[time_index].v_sync_time_in_us[1],
266 time[time_index].v_sync_time_in_us[2],
267 time[time_index].v_sync_time_in_us[3],
268 time[time_index].v_sync_time_in_us[4],
269 time[time_index].flags);
270
271 time_index++;
210 } 272 }
211 } 273 }
212 //GetLog()->Close(pLog); 274
213 //GetLog()->UnSetLogMask(LogMajor_ISR, LogMinor_ISR_FreeSyncSW); 275 DISPLAY_STATS_END(log_entry);
214} 276}
215 277
216void mod_stats_reset_data(struct mod_stats *mod_stats) 278void mod_stats_reset_data(struct mod_stats *mod_stats)
@@ -227,7 +289,46 @@ void mod_stats_reset_data(struct mod_stats *mod_stats)
227 memset(core_stats->time, 0, 289 memset(core_stats->time, 0,
228 sizeof(struct stats_time_cache) * core_stats->entries); 290 sizeof(struct stats_time_cache) * core_stats->entries);
229 291
230 core_stats->index = 0; 292 memset(core_stats->events, 0,
293 sizeof(struct stats_event_cache) * core_stats->event_entries);
294
295 core_stats->index = 1;
296 core_stats->event_index = 0;
297
298 // Keeps track of ordering within the different stats structures
299 core_stats->entry_id = 0;
300}
301
302void mod_stats_update_event(struct mod_stats *mod_stats,
303 char *event_string,
304 unsigned int length)
305{
306 struct core_stats *core_stats = NULL;
307 struct stats_event_cache *events = NULL;
308 unsigned int index = 0;
309 unsigned int copy_length = 0;
310
311 if (mod_stats == NULL)
312 return;
313
314 core_stats = MOD_STATS_TO_CORE(mod_stats);
315
316 if (core_stats->event_index >= core_stats->event_entries)
317 return;
318
319 events = core_stats->events;
320 index = core_stats->event_index;
321
322 copy_length = length;
323 if (length > MOD_STATS_EVENT_STRING_MAX)
324 copy_length = MOD_STATS_EVENT_STRING_MAX;
325
326 memcpy(&events[index].event_string, event_string, copy_length);
327 events[index].event_string[copy_length - 1] = '\0';
328
329 events[index].entry_id = core_stats->entry_id;
330 core_stats->event_index++;
331 core_stats->entry_id++;
231} 332}
232 333
233void mod_stats_update_flip(struct mod_stats *mod_stats, 334void mod_stats_update_flip(struct mod_stats *mod_stats,
@@ -250,7 +351,7 @@ void mod_stats_update_flip(struct mod_stats *mod_stats,
250 351
251 time[index].flip_timestamp_in_ns = timestamp_in_ns; 352 time[index].flip_timestamp_in_ns = timestamp_in_ns;
252 time[index].render_time_in_us = 353 time[index].render_time_in_us =
253 timestamp_in_ns - time[index - 1].flip_timestamp_in_ns; 354 (timestamp_in_ns - time[index - 1].flip_timestamp_in_ns) / 1000;
254 355
255 if (index >= 10) { 356 if (index >= 10) {
256 for (unsigned int i = 0; i < 10; i++) 357 for (unsigned int i = 0; i < 10; i++)
@@ -261,12 +362,16 @@ void mod_stats_update_flip(struct mod_stats *mod_stats,
261 362
262 if (time[index].num_vsync_between_flips > 0) 363 if (time[index].num_vsync_between_flips > 0)
263 time[index].vsync_to_flip_time_in_us = 364 time[index].vsync_to_flip_time_in_us =
264 timestamp_in_ns - time[index].vupdate_timestamp_in_ns; 365 (timestamp_in_ns -
366 time[index].vupdate_timestamp_in_ns) / 1000;
265 else 367 else
266 time[index].vsync_to_flip_time_in_us = 368 time[index].vsync_to_flip_time_in_us =
267 timestamp_in_ns - time[index - 1].vupdate_timestamp_in_ns; 369 (timestamp_in_ns -
370 time[index - 1].vupdate_timestamp_in_ns) / 1000;
268 371
372 time[index].entry_id = core_stats->entry_id;
269 core_stats->index++; 373 core_stats->index++;
374 core_stats->entry_id++;
270} 375}
271 376
272void mod_stats_update_vupdate(struct mod_stats *mod_stats, 377void mod_stats_update_vupdate(struct mod_stats *mod_stats,
@@ -275,6 +380,8 @@ void mod_stats_update_vupdate(struct mod_stats *mod_stats,
275 struct core_stats *core_stats = NULL; 380 struct core_stats *core_stats = NULL;
276 struct stats_time_cache *time = NULL; 381 struct stats_time_cache *time = NULL;
277 unsigned int index = 0; 382 unsigned int index = 0;
383 unsigned int num_vsyncs = 0;
384 unsigned int prev_vsync_in_ns = 0;
278 385
279 if (mod_stats == NULL) 386 if (mod_stats == NULL)
280 return; 387 return;
@@ -286,14 +393,27 @@ void mod_stats_update_vupdate(struct mod_stats *mod_stats,
286 393
287 time = core_stats->time; 394 time = core_stats->time;
288 index = core_stats->index; 395 index = core_stats->index;
396 num_vsyncs = time[index].num_vsync_between_flips;
397
398 if (num_vsyncs < MOD_STATS_NUM_VSYNCS) {
399 if (num_vsyncs == 0) {
400 prev_vsync_in_ns =
401 time[index - 1].vupdate_timestamp_in_ns;
402
403 time[index].flip_to_vsync_time_in_us =
404 (timestamp_in_ns -
405 time[index - 1].flip_timestamp_in_ns) /
406 1000;
407 } else {
408 prev_vsync_in_ns =
409 time[index].vupdate_timestamp_in_ns;
410 }
289 411
290 time[index].vupdate_timestamp_in_ns = timestamp_in_ns; 412 time[index].v_sync_time_in_us[num_vsyncs] =
291 if (time[index].num_vsync_between_flips < MOD_STATS_NUM_VSYNCS) 413 (timestamp_in_ns - prev_vsync_in_ns) / 1000;
292 time[index].v_sync_time_in_us[time[index].num_vsync_between_flips] = 414 }
293 timestamp_in_ns - time[index - 1].vupdate_timestamp_in_ns;
294 time[index].flip_to_vsync_time_in_us =
295 timestamp_in_ns - time[index - 1].flip_timestamp_in_ns;
296 415
416 time[index].vupdate_timestamp_in_ns = timestamp_in_ns;
297 time[index].num_vsync_between_flips++; 417 time[index].num_vsync_between_flips++;
298} 418}
299 419