root/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. perf_reg_read
  2. pipe_reg_read
  3. hi_total_cycle_read
  4. hi_total_idle_cycle_read
  5. num_pm_domains
  6. etnaviv_pm_query_dom
  7. etnaviv_pm_query_sig
  8. etnaviv_pm_req_validate
  9. etnaviv_perfmon_process

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

/* [<][>][^][v][top][bottom][index][help] */