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