Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2017 Etnaviv Project
0004  * Copyright (C) 2017 Zodiac Inflight Innovations
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     /* profile register */
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     /* switch back to pixel pipe 0 to prevent GPU hang */
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     /* switch back to pixel pipe 0 to prevent GPU hang */
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 }