0001
0002
0003
0004
0005
0006
0007 #include "common.xml.h"
0008 #include "etnaviv_gpu.h"
0009 #include "etnaviv_perfmon.h"
0010 #include "state_hi.xml.h"
0011
0012 struct etnaviv_pm_domain;
0013
0014 struct etnaviv_pm_signal {
0015 char name[64];
0016 u32 data;
0017
0018 u32 (*sample)(struct etnaviv_gpu *gpu,
0019 const struct etnaviv_pm_domain *domain,
0020 const struct etnaviv_pm_signal *signal);
0021 };
0022
0023 struct etnaviv_pm_domain {
0024 char name[64];
0025
0026
0027 u32 profile_read;
0028 u32 profile_config;
0029
0030 u8 nr_signals;
0031 const struct etnaviv_pm_signal *signal;
0032 };
0033
0034 struct etnaviv_pm_domain_meta {
0035 unsigned int feature;
0036 const struct etnaviv_pm_domain *domains;
0037 u32 nr_domains;
0038 };
0039
0040 static u32 perf_reg_read(struct etnaviv_gpu *gpu,
0041 const struct etnaviv_pm_domain *domain,
0042 const struct etnaviv_pm_signal *signal)
0043 {
0044 gpu_write(gpu, domain->profile_config, signal->data);
0045
0046 return gpu_read(gpu, domain->profile_read);
0047 }
0048
0049 static inline void pipe_select(struct etnaviv_gpu *gpu, u32 clock, unsigned pipe)
0050 {
0051 clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK);
0052 clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(pipe);
0053
0054 gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock);
0055 }
0056
0057 static u32 pipe_perf_reg_read(struct etnaviv_gpu *gpu,
0058 const struct etnaviv_pm_domain *domain,
0059 const struct etnaviv_pm_signal *signal)
0060 {
0061 u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
0062 u32 value = 0;
0063 unsigned i;
0064
0065 for (i = 0; i < gpu->identity.pixel_pipes; i++) {
0066 pipe_select(gpu, clock, i);
0067 value += perf_reg_read(gpu, domain, signal);
0068 }
0069
0070
0071 pipe_select(gpu, clock, 0);
0072
0073 return value;
0074 }
0075
0076 static u32 pipe_reg_read(struct etnaviv_gpu *gpu,
0077 const struct etnaviv_pm_domain *domain,
0078 const struct etnaviv_pm_signal *signal)
0079 {
0080 u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
0081 u32 value = 0;
0082 unsigned i;
0083
0084 for (i = 0; i < gpu->identity.pixel_pipes; i++) {
0085 pipe_select(gpu, clock, i);
0086 value += gpu_read(gpu, signal->data);
0087 }
0088
0089
0090 pipe_select(gpu, clock, 0);
0091
0092 return value;
0093 }
0094
0095 static u32 hi_total_cycle_read(struct etnaviv_gpu *gpu,
0096 const struct etnaviv_pm_domain *domain,
0097 const struct etnaviv_pm_signal *signal)
0098 {
0099 u32 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
0100
0101 if (gpu->identity.model == chipModel_GC880 ||
0102 gpu->identity.model == chipModel_GC2000 ||
0103 gpu->identity.model == chipModel_GC2100)
0104 reg = VIVS_MC_PROFILE_CYCLE_COUNTER;
0105
0106 return gpu_read(gpu, reg);
0107 }
0108
0109 static u32 hi_total_idle_cycle_read(struct etnaviv_gpu *gpu,
0110 const struct etnaviv_pm_domain *domain,
0111 const struct etnaviv_pm_signal *signal)
0112 {
0113 u32 reg = VIVS_HI_PROFILE_IDLE_CYCLES;
0114
0115 if (gpu->identity.model == chipModel_GC880 ||
0116 gpu->identity.model == chipModel_GC2000 ||
0117 gpu->identity.model == chipModel_GC2100)
0118 reg = VIVS_HI_PROFILE_TOTAL_CYCLES;
0119
0120 return gpu_read(gpu, reg);
0121 }
0122
0123 static const struct etnaviv_pm_domain doms_3d[] = {
0124 {
0125 .name = "HI",
0126 .profile_read = VIVS_MC_PROFILE_HI_READ,
0127 .profile_config = VIVS_MC_PROFILE_CONFIG2,
0128 .nr_signals = 7,
0129 .signal = (const struct etnaviv_pm_signal[]) {
0130 {
0131 "TOTAL_READ_BYTES8",
0132 VIVS_HI_PROFILE_READ_BYTES8,
0133 &pipe_reg_read,
0134 },
0135 {
0136 "TOTAL_WRITE_BYTES8",
0137 VIVS_HI_PROFILE_WRITE_BYTES8,
0138 &pipe_reg_read,
0139 },
0140 {
0141 "TOTAL_CYCLES",
0142 0,
0143 &hi_total_cycle_read
0144 },
0145 {
0146 "IDLE_CYCLES",
0147 0,
0148 &hi_total_idle_cycle_read
0149 },
0150 {
0151 "AXI_CYCLES_READ_REQUEST_STALLED",
0152 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED,
0153 &perf_reg_read
0154 },
0155 {
0156 "AXI_CYCLES_WRITE_REQUEST_STALLED",
0157 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED,
0158 &perf_reg_read
0159 },
0160 {
0161 "AXI_CYCLES_WRITE_DATA_STALLED",
0162 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED,
0163 &perf_reg_read
0164 }
0165 }
0166 },
0167 {
0168 .name = "PE",
0169 .profile_read = VIVS_MC_PROFILE_PE_READ,
0170 .profile_config = VIVS_MC_PROFILE_CONFIG0,
0171 .nr_signals = 4,
0172 .signal = (const struct etnaviv_pm_signal[]) {
0173 {
0174 "PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
0175 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE,
0176 &pipe_perf_reg_read
0177 },
0178 {
0179 "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
0180 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE,
0181 &pipe_perf_reg_read
0182 },
0183 {
0184 "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
0185 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE,
0186 &pipe_perf_reg_read
0187 },
0188 {
0189 "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
0190 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE,
0191 &pipe_perf_reg_read
0192 }
0193 }
0194 },
0195 {
0196 .name = "SH",
0197 .profile_read = VIVS_MC_PROFILE_SH_READ,
0198 .profile_config = VIVS_MC_PROFILE_CONFIG0,
0199 .nr_signals = 9,
0200 .signal = (const struct etnaviv_pm_signal[]) {
0201 {
0202 "SHADER_CYCLES",
0203 VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES,
0204 &perf_reg_read
0205 },
0206 {
0207 "PS_INST_COUNTER",
0208 VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER,
0209 &perf_reg_read
0210 },
0211 {
0212 "RENDERED_PIXEL_COUNTER",
0213 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER,
0214 &perf_reg_read
0215 },
0216 {
0217 "VS_INST_COUNTER",
0218 VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER,
0219 &pipe_perf_reg_read
0220 },
0221 {
0222 "RENDERED_VERTICE_COUNTER",
0223 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER,
0224 &pipe_perf_reg_read
0225 },
0226 {
0227 "VTX_BRANCH_INST_COUNTER",
0228 VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER,
0229 &pipe_perf_reg_read
0230 },
0231 {
0232 "VTX_TEXLD_INST_COUNTER",
0233 VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER,
0234 &pipe_perf_reg_read
0235 },
0236 {
0237 "PXL_BRANCH_INST_COUNTER",
0238 VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER,
0239 &pipe_perf_reg_read
0240 },
0241 {
0242 "PXL_TEXLD_INST_COUNTER",
0243 VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER,
0244 &pipe_perf_reg_read
0245 }
0246 }
0247 },
0248 {
0249 .name = "PA",
0250 .profile_read = VIVS_MC_PROFILE_PA_READ,
0251 .profile_config = VIVS_MC_PROFILE_CONFIG1,
0252 .nr_signals = 6,
0253 .signal = (const struct etnaviv_pm_signal[]) {
0254 {
0255 "INPUT_VTX_COUNTER",
0256 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER,
0257 &perf_reg_read
0258 },
0259 {
0260 "INPUT_PRIM_COUNTER",
0261 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER,
0262 &perf_reg_read
0263 },
0264 {
0265 "OUTPUT_PRIM_COUNTER",
0266 VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER,
0267 &perf_reg_read
0268 },
0269 {
0270 "DEPTH_CLIPPED_COUNTER",
0271 VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER,
0272 &pipe_perf_reg_read
0273 },
0274 {
0275 "TRIVIAL_REJECTED_COUNTER",
0276 VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER,
0277 &pipe_perf_reg_read
0278 },
0279 {
0280 "CULLED_COUNTER",
0281 VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER,
0282 &pipe_perf_reg_read
0283 }
0284 }
0285 },
0286 {
0287 .name = "SE",
0288 .profile_read = VIVS_MC_PROFILE_SE_READ,
0289 .profile_config = VIVS_MC_PROFILE_CONFIG1,
0290 .nr_signals = 2,
0291 .signal = (const struct etnaviv_pm_signal[]) {
0292 {
0293 "CULLED_TRIANGLE_COUNT",
0294 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT,
0295 &perf_reg_read
0296 },
0297 {
0298 "CULLED_LINES_COUNT",
0299 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT,
0300 &perf_reg_read
0301 }
0302 }
0303 },
0304 {
0305 .name = "RA",
0306 .profile_read = VIVS_MC_PROFILE_RA_READ,
0307 .profile_config = VIVS_MC_PROFILE_CONFIG1,
0308 .nr_signals = 7,
0309 .signal = (const struct etnaviv_pm_signal[]) {
0310 {
0311 "VALID_PIXEL_COUNT",
0312 VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT,
0313 &perf_reg_read
0314 },
0315 {
0316 "TOTAL_QUAD_COUNT",
0317 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT,
0318 &perf_reg_read
0319 },
0320 {
0321 "VALID_QUAD_COUNT_AFTER_EARLY_Z",
0322 VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z,
0323 &perf_reg_read
0324 },
0325 {
0326 "TOTAL_PRIMITIVE_COUNT",
0327 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT,
0328 &perf_reg_read
0329 },
0330 {
0331 "PIPE_CACHE_MISS_COUNTER",
0332 VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER,
0333 &perf_reg_read
0334 },
0335 {
0336 "PREFETCH_CACHE_MISS_COUNTER",
0337 VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER,
0338 &perf_reg_read
0339 },
0340 {
0341 "CULLED_QUAD_COUNT",
0342 VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT,
0343 &perf_reg_read
0344 }
0345 }
0346 },
0347 {
0348 .name = "TX",
0349 .profile_read = VIVS_MC_PROFILE_TX_READ,
0350 .profile_config = VIVS_MC_PROFILE_CONFIG1,
0351 .nr_signals = 9,
0352 .signal = (const struct etnaviv_pm_signal[]) {
0353 {
0354 "TOTAL_BILINEAR_REQUESTS",
0355 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS,
0356 &perf_reg_read
0357 },
0358 {
0359 "TOTAL_TRILINEAR_REQUESTS",
0360 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS,
0361 &perf_reg_read
0362 },
0363 {
0364 "TOTAL_DISCARDED_TEXTURE_REQUESTS",
0365 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS,
0366 &perf_reg_read
0367 },
0368 {
0369 "TOTAL_TEXTURE_REQUESTS",
0370 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS,
0371 &perf_reg_read
0372 },
0373 {
0374 "MEM_READ_COUNT",
0375 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT,
0376 &perf_reg_read
0377 },
0378 {
0379 "MEM_READ_IN_8B_COUNT",
0380 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT,
0381 &perf_reg_read
0382 },
0383 {
0384 "CACHE_MISS_COUNT",
0385 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT,
0386 &perf_reg_read
0387 },
0388 {
0389 "CACHE_HIT_TEXEL_COUNT",
0390 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT,
0391 &perf_reg_read
0392 },
0393 {
0394 "CACHE_MISS_TEXEL_COUNT",
0395 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT,
0396 &perf_reg_read
0397 }
0398 }
0399 },
0400 {
0401 .name = "MC",
0402 .profile_read = VIVS_MC_PROFILE_MC_READ,
0403 .profile_config = VIVS_MC_PROFILE_CONFIG2,
0404 .nr_signals = 3,
0405 .signal = (const struct etnaviv_pm_signal[]) {
0406 {
0407 "TOTAL_READ_REQ_8B_FROM_PIPELINE",
0408 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE,
0409 &perf_reg_read
0410 },
0411 {
0412 "TOTAL_READ_REQ_8B_FROM_IP",
0413 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP,
0414 &perf_reg_read
0415 },
0416 {
0417 "TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
0418 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE,
0419 &perf_reg_read
0420 }
0421 }
0422 }
0423 };
0424
0425 static const struct etnaviv_pm_domain doms_2d[] = {
0426 {
0427 .name = "PE",
0428 .profile_read = VIVS_MC_PROFILE_PE_READ,
0429 .profile_config = VIVS_MC_PROFILE_CONFIG0,
0430 .nr_signals = 1,
0431 .signal = (const struct etnaviv_pm_signal[]) {
0432 {
0433 "PIXELS_RENDERED_2D",
0434 VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D,
0435 &pipe_perf_reg_read
0436 }
0437 }
0438 }
0439 };
0440
0441 static const struct etnaviv_pm_domain doms_vg[] = {
0442 };
0443
0444 static const struct etnaviv_pm_domain_meta doms_meta[] = {
0445 {
0446 .feature = chipFeatures_PIPE_3D,
0447 .nr_domains = ARRAY_SIZE(doms_3d),
0448 .domains = &doms_3d[0]
0449 },
0450 {
0451 .feature = chipFeatures_PIPE_2D,
0452 .nr_domains = ARRAY_SIZE(doms_2d),
0453 .domains = &doms_2d[0]
0454 },
0455 {
0456 .feature = chipFeatures_PIPE_VG,
0457 .nr_domains = ARRAY_SIZE(doms_vg),
0458 .domains = &doms_vg[0]
0459 }
0460 };
0461
0462 static unsigned int num_pm_domains(const struct etnaviv_gpu *gpu)
0463 {
0464 unsigned int num = 0, i;
0465
0466 for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
0467 const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
0468
0469 if (gpu->identity.features & meta->feature)
0470 num += meta->nr_domains;
0471 }
0472
0473 return num;
0474 }
0475
0476 static const struct etnaviv_pm_domain *pm_domain(const struct etnaviv_gpu *gpu,
0477 unsigned int index)
0478 {
0479 const struct etnaviv_pm_domain *domain = NULL;
0480 unsigned int offset = 0, i;
0481
0482 for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
0483 const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
0484
0485 if (!(gpu->identity.features & meta->feature))
0486 continue;
0487
0488 if (index - offset >= meta->nr_domains) {
0489 offset += meta->nr_domains;
0490 continue;
0491 }
0492
0493 domain = meta->domains + (index - offset);
0494 }
0495
0496 return domain;
0497 }
0498
0499 int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
0500 struct drm_etnaviv_pm_domain *domain)
0501 {
0502 const unsigned int nr_domains = num_pm_domains(gpu);
0503 const struct etnaviv_pm_domain *dom;
0504
0505 if (domain->iter >= nr_domains)
0506 return -EINVAL;
0507
0508 dom = pm_domain(gpu, domain->iter);
0509 if (!dom)
0510 return -EINVAL;
0511
0512 domain->id = domain->iter;
0513 domain->nr_signals = dom->nr_signals;
0514 strncpy(domain->name, dom->name, sizeof(domain->name));
0515
0516 domain->iter++;
0517 if (domain->iter == nr_domains)
0518 domain->iter = 0xff;
0519
0520 return 0;
0521 }
0522
0523 int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
0524 struct drm_etnaviv_pm_signal *signal)
0525 {
0526 const unsigned int nr_domains = num_pm_domains(gpu);
0527 const struct etnaviv_pm_domain *dom;
0528 const struct etnaviv_pm_signal *sig;
0529
0530 if (signal->domain >= nr_domains)
0531 return -EINVAL;
0532
0533 dom = pm_domain(gpu, signal->domain);
0534 if (!dom)
0535 return -EINVAL;
0536
0537 if (signal->iter >= dom->nr_signals)
0538 return -EINVAL;
0539
0540 sig = &dom->signal[signal->iter];
0541
0542 signal->id = signal->iter;
0543 strncpy(signal->name, sig->name, sizeof(signal->name));
0544
0545 signal->iter++;
0546 if (signal->iter == dom->nr_signals)
0547 signal->iter = 0xffff;
0548
0549 return 0;
0550 }
0551
0552 int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r,
0553 u32 exec_state)
0554 {
0555 const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
0556 const struct etnaviv_pm_domain *dom;
0557
0558 if (r->domain >= meta->nr_domains)
0559 return -EINVAL;
0560
0561 dom = meta->domains + r->domain;
0562
0563 if (r->signal >= dom->nr_signals)
0564 return -EINVAL;
0565
0566 return 0;
0567 }
0568
0569 void etnaviv_perfmon_process(struct etnaviv_gpu *gpu,
0570 const struct etnaviv_perfmon_request *pmr, u32 exec_state)
0571 {
0572 const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state];
0573 const struct etnaviv_pm_domain *dom;
0574 const struct etnaviv_pm_signal *sig;
0575 u32 *bo = pmr->bo_vma;
0576 u32 val;
0577
0578 dom = meta->domains + pmr->domain;
0579 sig = &dom->signal[pmr->signal];
0580 val = sig->sample(gpu, dom, sig);
0581
0582 *(bo + pmr->offset) = val;
0583 }