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