584 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2017 Etnaviv Project4 * Copyright (C) 2017 Zodiac Inflight Innovations5 */6 7#include "common.xml.h"8#include "etnaviv_gpu.h"9#include "etnaviv_perfmon.h"10#include "state_hi.xml.h"11 12struct etnaviv_pm_domain;13 14struct etnaviv_pm_signal {15 char name[64];16 u32 data;17 18 u32 (*sample)(struct etnaviv_gpu *gpu,19 const struct etnaviv_pm_domain *domain,20 const struct etnaviv_pm_signal *signal);21};22 23struct etnaviv_pm_domain {24 char name[64];25 26 /* profile register */27 u32 profile_read;28 u32 profile_config;29 30 u8 nr_signals;31 const struct etnaviv_pm_signal *signal;32};33 34struct etnaviv_pm_domain_meta {35 unsigned int feature;36 const struct etnaviv_pm_domain *domains;37 u32 nr_domains;38};39 40static u32 perf_reg_read(struct etnaviv_gpu *gpu,41 const struct etnaviv_pm_domain *domain,42 const struct etnaviv_pm_signal *signal)43{44 gpu_write(gpu, domain->profile_config, signal->data);45 46 return gpu_read(gpu, domain->profile_read);47}48 49static inline void pipe_select(struct etnaviv_gpu *gpu, u32 clock, unsigned pipe)50{51 clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);52 clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(pipe);53 54 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);55}56 57static u32 pipe_perf_reg_read(struct etnaviv_gpu *gpu,58 const struct etnaviv_pm_domain *domain,59 const struct etnaviv_pm_signal *signal)60{61 u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);62 u32 value = 0;63 unsigned i;64 65 for (i = 0; i < gpu->identity.pixel_pipes; i++) {66 pipe_select(gpu, clock, i);67 value += perf_reg_read(gpu, domain, signal);68 }69 70 /* switch back to pixel pipe 0 to prevent GPU hang */71 pipe_select(gpu, clock, 0);72 73 return value;74}75 76static u32 pipe_reg_read(struct etnaviv_gpu *gpu,77 const struct etnaviv_pm_domain *domain,78 const struct etnaviv_pm_signal *signal)79{80 u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);81 u32 value = 0;82 unsigned i;83 84 for (i = 0; i < gpu->identity.pixel_pipes; i++) {85 pipe_select(gpu, clock, i);86 value += gpu_read(gpu, signal->data);87 }88 89 /* switch back to pixel pipe 0 to prevent GPU hang */90 pipe_select(gpu, clock, 0);91 92 return value;93}94 95static u32 hi_total_cycle_read(struct etnaviv_gpu *gpu,96 const struct etnaviv_pm_domain *domain,97 const struct etnaviv_pm_signal *signal)98{99 u32 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;100 101 if (gpu->identity.model == chipModel_GC880 ||102 gpu->identity.model == chipModel_GC2000 ||103 gpu->identity.model == chipModel_GC2100)104 reg = VIVS_MC_PROFILE_CYCLE_COUNTER;105 106 return gpu_read(gpu, reg);107}108 109static u32 hi_total_idle_cycle_read(struct etnaviv_gpu *gpu,110 const struct etnaviv_pm_domain *domain,111 const struct etnaviv_pm_signal *signal)112{113 u32 reg = VIVS_HI_PROFILE_IDLE_CYCLES;114 115 if (gpu->identity.model == chipModel_GC880 ||116 gpu->identity.model == chipModel_GC2000 ||117 gpu->identity.model == chipModel_GC2100)118 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;119 120 return gpu_read(gpu, reg);121}122 123static const struct etnaviv_pm_domain doms_3d[] = {124 {125 .name = "HI",126 .profile_read = VIVS_MC_PROFILE_HI_READ,127 .profile_config = VIVS_MC_PROFILE_CONFIG2,128 .nr_signals = 7,129 .signal = (const struct etnaviv_pm_signal[]) {130 {131 "TOTAL_READ_BYTES8",132 VIVS_HI_PROFILE_READ_BYTES8,133 &pipe_reg_read,134 },135 {136 "TOTAL_WRITE_BYTES8",137 VIVS_HI_PROFILE_WRITE_BYTES8,138 &pipe_reg_read,139 },140 {141 "TOTAL_CYCLES",142 0,143 &hi_total_cycle_read144 },145 {146 "IDLE_CYCLES",147 0,148 &hi_total_idle_cycle_read149 },150 {151 "AXI_CYCLES_READ_REQUEST_STALLED",152 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED,153 &perf_reg_read154 },155 {156 "AXI_CYCLES_WRITE_REQUEST_STALLED",157 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,158 &perf_reg_read159 },160 {161 "AXI_CYCLES_WRITE_DATA_STALLED",162 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED,163 &perf_reg_read164 }165 }166 },167 {168 .name = "PE",169 .profile_read = VIVS_MC_PROFILE_PE_READ,170 .profile_config = VIVS_MC_PROFILE_CONFIG0,171 .nr_signals = 4,172 .signal = (const struct etnaviv_pm_signal[]) {173 {174 "PIXEL_COUNT_KILLED_BY_COLOR_PIPE",175 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,176 &pipe_perf_reg_read177 },178 {179 "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",180 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,181 &pipe_perf_reg_read182 },183 {184 "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",185 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,186 &pipe_perf_reg_read187 },188 {189 "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",190 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,191 &pipe_perf_reg_read192 }193 }194 },195 {196 .name = "SH",197 .profile_read = VIVS_MC_PROFILE_SH_READ,198 .profile_config = VIVS_MC_PROFILE_CONFIG0,199 .nr_signals = 9,200 .signal = (const struct etnaviv_pm_signal[]) {201 {202 "SHADER_CYCLES",203 VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES,204 &perf_reg_read205 },206 {207 "PS_INST_COUNTER",208 VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER,209 &perf_reg_read210 },211 {212 "RENDERED_PIXEL_COUNTER",213 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER,214 &perf_reg_read215 },216 {217 "VS_INST_COUNTER",218 VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER,219 &pipe_perf_reg_read220 },221 {222 "RENDERED_VERTICE_COUNTER",223 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER,224 &pipe_perf_reg_read225 },226 {227 "VTX_BRANCH_INST_COUNTER",228 VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER,229 &pipe_perf_reg_read230 },231 {232 "VTX_TEXLD_INST_COUNTER",233 VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER,234 &pipe_perf_reg_read235 },236 {237 "PXL_BRANCH_INST_COUNTER",238 VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER,239 &pipe_perf_reg_read240 },241 {242 "PXL_TEXLD_INST_COUNTER",243 VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER,244 &pipe_perf_reg_read245 }246 }247 },248 {249 .name = "PA",250 .profile_read = VIVS_MC_PROFILE_PA_READ,251 .profile_config = VIVS_MC_PROFILE_CONFIG1,252 .nr_signals = 6,253 .signal = (const struct etnaviv_pm_signal[]) {254 {255 "INPUT_VTX_COUNTER",256 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER,257 &perf_reg_read258 },259 {260 "INPUT_PRIM_COUNTER",261 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER,262 &perf_reg_read263 },264 {265 "OUTPUT_PRIM_COUNTER",266 VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER,267 &perf_reg_read268 },269 {270 "DEPTH_CLIPPED_COUNTER",271 VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER,272 &pipe_perf_reg_read273 },274 {275 "TRIVIAL_REJECTED_COUNTER",276 VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER,277 &pipe_perf_reg_read278 },279 {280 "CULLED_COUNTER",281 VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER,282 &pipe_perf_reg_read283 }284 }285 },286 {287 .name = "SE",288 .profile_read = VIVS_MC_PROFILE_SE_READ,289 .profile_config = VIVS_MC_PROFILE_CONFIG1,290 .nr_signals = 2,291 .signal = (const struct etnaviv_pm_signal[]) {292 {293 "CULLED_TRIANGLE_COUNT",294 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT,295 &perf_reg_read296 },297 {298 "CULLED_LINES_COUNT",299 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT,300 &perf_reg_read301 }302 }303 },304 {305 .name = "RA",306 .profile_read = VIVS_MC_PROFILE_RA_READ,307 .profile_config = VIVS_MC_PROFILE_CONFIG1,308 .nr_signals = 7,309 .signal = (const struct etnaviv_pm_signal[]) {310 {311 "VALID_PIXEL_COUNT",312 VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT,313 &perf_reg_read314 },315 {316 "TOTAL_QUAD_COUNT",317 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT,318 &perf_reg_read319 },320 {321 "VALID_QUAD_COUNT_AFTER_EARLY_Z",322 VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,323 &perf_reg_read324 },325 {326 "TOTAL_PRIMITIVE_COUNT",327 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT,328 &perf_reg_read329 },330 {331 "PIPE_CACHE_MISS_COUNTER",332 VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER,333 &perf_reg_read334 },335 {336 "PREFETCH_CACHE_MISS_COUNTER",337 VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER,338 &perf_reg_read339 },340 {341 "CULLED_QUAD_COUNT",342 VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT,343 &perf_reg_read344 }345 }346 },347 {348 .name = "TX",349 .profile_read = VIVS_MC_PROFILE_TX_READ,350 .profile_config = VIVS_MC_PROFILE_CONFIG1,351 .nr_signals = 9,352 .signal = (const struct etnaviv_pm_signal[]) {353 {354 "TOTAL_BILINEAR_REQUESTS",355 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS,356 &perf_reg_read357 },358 {359 "TOTAL_TRILINEAR_REQUESTS",360 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS,361 &perf_reg_read362 },363 {364 "TOTAL_DISCARDED_TEXTURE_REQUESTS",365 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,366 &perf_reg_read367 },368 {369 "TOTAL_TEXTURE_REQUESTS",370 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS,371 &perf_reg_read372 },373 {374 "MEM_READ_COUNT",375 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT,376 &perf_reg_read377 },378 {379 "MEM_READ_IN_8B_COUNT",380 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT,381 &perf_reg_read382 },383 {384 "CACHE_MISS_COUNT",385 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT,386 &perf_reg_read387 },388 {389 "CACHE_HIT_TEXEL_COUNT",390 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT,391 &perf_reg_read392 },393 {394 "CACHE_MISS_TEXEL_COUNT",395 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT,396 &perf_reg_read397 }398 }399 },400 {401 .name = "MC",402 .profile_read = VIVS_MC_PROFILE_MC_READ,403 .profile_config = VIVS_MC_PROFILE_CONFIG2,404 .nr_signals = 3,405 .signal = (const struct etnaviv_pm_signal[]) {406 {407 "TOTAL_READ_REQ_8B_FROM_PIPELINE",408 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,409 &perf_reg_read410 },411 {412 "TOTAL_READ_REQ_8B_FROM_IP",413 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP,414 &perf_reg_read415 },416 {417 "TOTAL_WRITE_REQ_8B_FROM_PIPELINE",418 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,419 &perf_reg_read420 }421 }422 }423};424 425static const struct etnaviv_pm_domain doms_2d[] = {426 {427 .name = "PE",428 .profile_read = VIVS_MC_PROFILE_PE_READ,429 .profile_config = VIVS_MC_PROFILE_CONFIG0,430 .nr_signals = 1,431 .signal = (const struct etnaviv_pm_signal[]) {432 {433 "PIXELS_RENDERED_2D",434 VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D,435 &pipe_perf_reg_read436 }437 }438 }439};440 441static const struct etnaviv_pm_domain doms_vg[] = {442};443 444static const struct etnaviv_pm_domain_meta doms_meta[] = {445 {446 .feature = chipFeatures_PIPE_3D,447 .nr_domains = ARRAY_SIZE(doms_3d),448 .domains = &doms_3d[0]449 },450 {451 .feature = chipFeatures_PIPE_2D,452 .nr_domains = ARRAY_SIZE(doms_2d),453 .domains = &doms_2d[0]454 },455 {456 .feature = chipFeatures_PIPE_VG,457 .nr_domains = ARRAY_SIZE(doms_vg),458 .domains = &doms_vg[0]459 }460};461 462static unsigned int num_pm_domains(const struct etnaviv_gpu *gpu)463{464 unsigned int num = 0, i;465 466 for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {467 const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];468 469 if (gpu->identity.features & meta->feature)470 num += meta->nr_domains;471 }472 473 return num;474}475 476static const struct etnaviv_pm_domain *pm_domain(const struct etnaviv_gpu *gpu,477 unsigned int index)478{479 const struct etnaviv_pm_domain *domain = NULL;480 unsigned int offset = 0, i;481 482 for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {483 const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];484 485 if (!(gpu->identity.features & meta->feature))486 continue;487 488 if (index - offset >= meta->nr_domains) {489 offset += meta->nr_domains;490 continue;491 }492 493 domain = meta->domains + (index - offset);494 }495 496 return domain;497}498 499int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,500 struct drm_etnaviv_pm_domain *domain)501{502 const unsigned int nr_domains = num_pm_domains(gpu);503 const struct etnaviv_pm_domain *dom;504 505 if (domain->iter >= nr_domains)506 return -EINVAL;507 508 dom = pm_domain(gpu, domain->iter);509 if (!dom)510 return -EINVAL;511 512 domain->id = domain->iter;513 domain->nr_signals = dom->nr_signals;514 strscpy_pad(domain->name, dom->name, sizeof(domain->name));515 516 domain->iter++;517 if (domain->iter == nr_domains)518 domain->iter = 0xff;519 520 return 0;521}522 523int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,524 struct drm_etnaviv_pm_signal *signal)525{526 const unsigned int nr_domains = num_pm_domains(gpu);527 const struct etnaviv_pm_domain *dom;528 const struct etnaviv_pm_signal *sig;529 530 if (signal->domain >= nr_domains)531 return -EINVAL;532 533 dom = pm_domain(gpu, signal->domain);534 if (!dom)535 return -EINVAL;536 537 if (signal->iter >= dom->nr_signals)538 return -EINVAL;539 540 sig = &dom->signal[signal->iter];541 542 signal->id = signal->iter;543 strscpy_pad(signal->name, sig->name, sizeof(signal->name));544 545 signal->iter++;546 if (signal->iter == dom->nr_signals)547 signal->iter = 0xffff;548 549 return 0;550}551 552int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,553 u32 exec_state)554{555 const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];556 const struct etnaviv_pm_domain *dom;557 558 if (r->domain >= meta->nr_domains)559 return -EINVAL;560 561 dom = meta->domains + r->domain;562 563 if (r->signal >= dom->nr_signals)564 return -EINVAL;565 566 return 0;567}568 569void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,570 const struct etnaviv_perfmon_request *pmr, u32 exec_state)571{572 const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];573 const struct etnaviv_pm_domain *dom;574 const struct etnaviv_pm_signal *sig;575 u32 *bo = pmr->bo_vma;576 u32 val;577 578 dom = meta->domains + pmr->domain;579 sig = &dom->signal[pmr->signal];580 val = sig->sample(gpu, dom, sig);581 582 *(bo + pmr->offset) = val;583}584