mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-08-09 06:14:34 +02:00
Pull drm updates from Dave Airlie:
"Highlights:
- xe: add initial CRI platform support
- amdgpu: initial HDMI 2.1 FRL support
- rust: add some new type concepts for device lifetimes
- scheduler: moves to a fair algorithm and lots of cleanups
But it's mostly the usual mountain of changes across the board.
core:
- add docbook for DRM_IOCTL_SYNCOBJ_EVENTFD
- change signature of drm_connector_attach_hdr_output_metadata_property
- dedup counter and timestamp retrieval in vblank code
- parse AMD VSDB v3 in CTA extension blocks
- add P230, Y7, XYYY2101010, T430, XVUY210101010 formats
- don't call drop master on file close if not master
- use drm_printf_indent in atomic / bridge
- fix 32b format descriptions
- docs: fix toctree
- hdmi: add common TMDS character rates
- fix drm_syncobj_find_fence leak
rust:
- introduce Higher-Ranked lifetime types
- replace drvdata with scoped registration data
- add GPUVM immediate mode abstraction for rust GPU drivers
- introduce DeviceContext type state for drm::Device
bridge:
- clarify drm_bridge_get/put
- create drm_get_bridge_by_endpoint and use it
- analogix_dp: add panel probing
- ite-it6211 - use drm audio hdmi helpers
buddy:
- add lockdep annotations
dp:
- add PR and VRR updates
- mst: fix buffer overflows
- add Adaptive Sync SDP decoding support
- fix OOB reads in dp-mst
ttm:
- bump fpfn/lpfn to 64-bit
scheduler:
- change default to fair scheduler
- map runqueue 1:1 with scheduler
dma-buf:
- port selftests to kunit
- convert dma-buf system/heap allocators to module
- add separate DMABUF_HEAPS_SYSTEM_CC_SHARED Kconfig
udmabuf:
- revert hugetlb support
- fix error with CONFIG_DMA_API_DEBUG
dma-fence:
- fix tracepoints lifetime
- remove unused signal on any support
ras:
- add clear error counter netlink command to drm ras
gpusvm:
- reject VMAs with VM_IO or VM_PFNMAP when creating SVM ranges
- use IOVA allocations
pagemap:
- use IOVA allocations
panels:
- update to use ref counts
- add support for CSW PNB601LS1-2, LGD LP116WHA-SPB1
- add support for waveshare panels
- CMN N116BCN-EA1, CMN N140HCA-EEK, IVO M140NWFQ R5,
- IVO, R140NWFW R0, BOE NT140*, BOE NV133FHM-N4F,
- AUO B140*, AUO B133HAN06.6 and AUO B116XTN02.3 eDP panels
- Surface Pro 12 Panel
xe:
- add CRI PCI-IDs
- debugfs add multi-lrc info
- engine init cleanup
- PF fair scheduling auto provisioning
- system controller support for CRI/Xe3p
- PXP state machine fixes
- Reset/wedge/unload corner case fixes
- Wedge path memory allocation fixes
- PAT type cleanups
- Reject unsafe PAT for CPU cached memory
- OA improvements for CRI device memory
- kernel doc syntax in xe headers
- xe_drm.h documentation fixes
- include guard cleanups
- VF CCS memory pool
- i915/xe step unification
- Xe3p GT tuning fixes
- forcewake cleanup in GT and GuC
- admin-only PF mode
- enable hwmon energy attributes for CRI
- enable GT_MI_USER_INTERRUPT
- refactor emit functions
- oa workarounds
- multi_queue: allow QUEUE_TIMESTAMP register
- convert stolen memory to ttm range manager
- use xe2 style blitter as a feature flag
- make drm_driver const
- add/use IRQ page to HW engine definition
- fix oops when display disabled
i915:
- enable PIPEDMC_ERROR interrupt
- more common display code refactoring
- restructure DP/HDMI sink format handling
- eliminate FB usage from lowlevel pinning code
- panel replay bw optimization
- integrate sharpness filter into the scaler
- new fb_pin abstraction for xe/i915 fb transparent handling
- skip inactive MST connectors on HDCP
- start switching to display specific registers
- use polling when irq unavailable
- Adaptive-sync SDP prep
amdgpu:
- use drm_display_info for AMD VSDB data
- Initial HDMI 2.1 FRL support
- Initial DCN 4.2.1 support
- GART fixes for non-4k pages
- GC 11.5.6/SDMA 6.4.0/and other new IPs
- GFX9/DCE6/Hawaii/SDMA4/GART/Userq fixes
- Finish support for using multiple SDMA queues for TTM operations
- SWSMU updates
- GC 12.1 updates
- SMU 15.0.8 updates
- DCN 4.2 updates
- DC type conversion fixes
- Enable DC power module
- Replay/PSR updates
- SMU 13.x updates
- Compute queue quantum MQD updates
- ASPM fix
- Align VKMS with common implementation
- DC analog support fixes
- UVD 3 fixes
- TCC harvesting fixes for SI
- GC 11 APU module reload fix
- NBIO 6.3.2 support
- IH 7.1 updates
- DC cursor fixes
- VCN/JPEG user fence fixes
- DC support for connectors without DDC
- Prefer ROM BAR for default VGA device
- DC bandwidth fixes
- Add PTL support for profiler
- Introduce dc_plane_cm and migrate surface update color path
- Add FRL registers for HDMI 2.1
- Restructure VM state machine
- Auxless ALPM support
- GEM_OP locking/warning fixes
- switch to system_dfl_wq
amdkfd:
- GPUVM TLB flush fix
- Hotplug fix
- Boundary check fixes
- SVM fixes
- CRIU fixes
- add profiler API
- MES 12.1 updates
msm:
- core:
- fix shrinker documentation
- IFPC enabled for gen8
- PERFCNTR_CONFIG ioctl support
- GPU:
- reworked UBWC handling
- a810 support
- MDSS:
- add support for Milos platform
- reworked UBWC handling
- DisplayPort:
- reworked HPD handling as prep for MST
- DPU:
- Milos platform support
- reworked UBWC handling
- DSI:
- Milos platform support
nova:
- Hopper/Blackwell enablement (GH100/GB100/GB202)
- FSP support
- 32-bit firmware support
- HAL functions
- refactor GSP boot/unload
- GA100 support
- VBIOS hardening/refactoring
- Adopt higher order lifetime types
tyr:
- define register blocks
- add shmem backed GEM objects
- adopt higher order lifetime types
- move clock cleanup into Drop
radeon:
- Hawaii SMU fixes
- CS parser fix
- use struct drm_edid instead of edid
amdxdna:
- export per-client BO memory via fdinfo
- AIE4 device support
- support medium/lower power modes
- expandable device heap support
- revert read-only user-pointer BO mappings
ivpu:
- support frequency limiting
panthor:
- enable GEM shrinker support
- add eviction and reclaim info to fdinfo
v3d:
- enable runtime PM
mgag200:
- support XRGB1555 + C8
ast:
- support XRGB1555 + C8
- use constants for lots of registers
- fix register handling
imagination:
- fence handling refactoring
nouveau:
- fix sched double call
- expose VBIOS on GSP-RM systems
- add GA100 support
virtio:
- add VIRTIO_GPU_F_BLOB_ALIGNMENT flag
- add deferred mapping support
gud:
- add RCade Display Adapter
hibmc:
- fix no connectors usage
mediatek:
- hdmi: convert error handling
- simplify mtk_crtc allocation
exynos:
- move fbdev emulation to drm client buffers
- use drm format helpers for geometry/size
- adopt core DMA tracking
- fix framebuffer offset handling
renesas:
- add RZ/T2H SOC support
versilicon:
- add cursor plane support
tegra:
- use drm client for framebuffer"
* tag 'drm-next-2026-06-17' of https://gitlab.freedesktop.org/drm/kernel: (1731 commits)
dma-buf: move system_cc_shared heap under separate Kconfig
accel/amdxdna: Clear sva pointer after unbind
agp/amd64: Fix broken error propagation in agp_amd64_probe()
accel/amdxdna: Require carveout when PASID and force_iova are disabled
drm/amdkfd: always resume_all after suspend_all
drm/amdgpu/gfx: move fault and EOP IRQ get/put to hw_init/hw_fini
drm/amd/display: Consult MCCS FreeSync cap only if requested & supported
drm/amd/pm: Use strscpy in profile mode parsing
drm/amdkfd: Fix infinite loop parsing CRAT with zero subtype length
drm/amdkfd: fix sysfs topology prop length on buffer truncation
drm/amdgpu: drop retry loop in amdgpu_hmm_range_get_pages
drm/amd/pm: bound OD parameter parsing to stack array size
drm/amd/pm: Stop pp_od_clk_voltage emit at PAGE_SIZE
drm/amdkfd: Unwind debug trap enable on copy_to_user failure
drm/amdgpu: validate the mes firmware version for gfx12.1
drm/amdgpu: validate the mes firmware version for gfx12
drm/amdgpu: compare MES firmware version ucode for gfx11
drm/amdkfd: Add bounds check for AMDKFD_IOC_WAIT_EVENTS
drm/amdgpu: restart the CS if some parts of the VM are still invalidated
drm/amd/display: use unsigned types for local pipe and REG_GET counters
...
501 lines
22 KiB
C
501 lines
22 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2021 Raspberry Pi
|
|
*/
|
|
|
|
#include "v3d_drv.h"
|
|
#include "v3d_regs.h"
|
|
|
|
static const struct v3d_perf_counter_desc v3d_v42_performance_counters[] = {
|
|
{"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"},
|
|
{"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"},
|
|
{"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"},
|
|
{"FEP", "FEP-valid-quads", "[FEP] Valid quads"},
|
|
{"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"},
|
|
{"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"},
|
|
{"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"},
|
|
{"TLB", "TLB-quads-with-zero-coverage", "[TLB] Quads with all pixels having zero coverage"},
|
|
{"TLB", "TLB-quads-with-non-zero-coverage", "[TLB] Quads with any pixels having non-zero coverage"},
|
|
{"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"},
|
|
{"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"},
|
|
{"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"},
|
|
{"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"},
|
|
{"QPU", "QPU-total-idle-clk-cycles", "[QPU] Total idle clock cycles for all QPUs"},
|
|
{"QPU", "QPU-total-active-clk-cycles-vertex-coord-shading", "[QPU] Total active clock cycles for all QPUs doing vertex/coordinate/user shading (counts only when QPU is not stalled)"},
|
|
{"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"},
|
|
{"QPU", "QPU-total-clk-cycles-executing-valid-instr", "[QPU] Total clock cycles for all QPUs executing valid instructions"},
|
|
{"QPU", "QPU-total-clk-cycles-waiting-TMU", "[QPU] Total clock cycles for all QPUs stalled waiting for TMUs only (counter won't increment if QPU also stalling for another reason)"},
|
|
{"QPU", "QPU-total-clk-cycles-waiting-scoreboard", "[QPU] Total clock cycles for all QPUs stalled waiting for Scoreboard only (counter won't increment if QPU also stalling for another reason)"},
|
|
{"QPU", "QPU-total-clk-cycles-waiting-varyings", "[QPU] Total clock cycles for all QPUs stalled waiting for Varyings only (counter won't increment if QPU also stalling for another reason)"},
|
|
{"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"},
|
|
{"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"},
|
|
{"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"},
|
|
{"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"},
|
|
{"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"},
|
|
{"TMU", "TMU-total-text-cache-miss", "[TMU] Total texture cache misses (number of fetches from memory/L2cache)"},
|
|
{"VPM", "VPM-total-clk-cycles-VDW-stalled", "[VPM] Total clock cycles VDW is stalled waiting for VPM access"},
|
|
{"VPM", "VPM-total-clk-cycles-VCD-stalled", "[VPM] Total clock cycles VCD is stalled waiting for VPM access"},
|
|
{"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"},
|
|
{"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"},
|
|
{"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"},
|
|
{"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"},
|
|
{"CORE", "cycle-count", "[CORE] Cycle counter"},
|
|
{"QPU", "QPU-total-clk-cycles-waiting-vertex-coord-shading", "[QPU] Total stalled clock cycles for all QPUs doing vertex/coordinate/user shading"},
|
|
{"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"},
|
|
{"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"},
|
|
{"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"},
|
|
{"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"},
|
|
{"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"},
|
|
{"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"},
|
|
{"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"},
|
|
{"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"},
|
|
{"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"},
|
|
{"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"},
|
|
{"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"},
|
|
{"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"},
|
|
{"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"},
|
|
{"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"},
|
|
{"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"},
|
|
{"TMU", "TMU-total-config-access", "[TMU] Total config accesses"},
|
|
{"L2T", "L2T-no-id-stalled", "[L2T] No ID stall"},
|
|
{"L2T", "L2T-command-queue-stalled", "[L2T] Command queue full stall"},
|
|
{"L2T", "L2T-TMU-writes", "[L2T] TMU write accesses"},
|
|
{"TMU", "TMU-active-cycles", "[TMU] Active cycles"},
|
|
{"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"},
|
|
{"CLE", "CLE-thread-active-cycles", "[CLE] Bin or render thread active cycles"},
|
|
{"L2T", "L2T-TMU-reads", "[L2T] TMU read accesses"},
|
|
{"L2T", "L2T-CLE-reads", "[L2T] CLE read accesses"},
|
|
{"L2T", "L2T-VCD-reads", "[L2T] VCD read accesses"},
|
|
{"L2T", "L2T-TMU-config-reads", "[L2T] TMU CFG read accesses"},
|
|
{"L2T", "L2T-SLC0-reads", "[L2T] SLC0 read accesses"},
|
|
{"L2T", "L2T-SLC1-reads", "[L2T] SLC1 read accesses"},
|
|
{"L2T", "L2T-SLC2-reads", "[L2T] SLC2 read accesses"},
|
|
{"L2T", "L2T-TMU-write-miss", "[L2T] TMU write misses"},
|
|
{"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"},
|
|
{"L2T", "L2T-CLE-read-miss", "[L2T] CLE read misses"},
|
|
{"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"},
|
|
{"L2T", "L2T-TMU-config-read-miss", "[L2T] TMU CFG read misses"},
|
|
{"L2T", "L2T-SLC0-read-miss", "[L2T] SLC0 read misses"},
|
|
{"L2T", "L2T-SLC1-read-miss", "[L2T] SLC1 read misses"},
|
|
{"L2T", "L2T-SLC2-read-miss", "[L2T] SLC2 read misses"},
|
|
{"CORE", "core-memory-writes", "[CORE] Total memory writes"},
|
|
{"L2T", "L2T-memory-writes", "[L2T] Total memory writes"},
|
|
{"PTB", "PTB-memory-writes", "[PTB] Total memory writes"},
|
|
{"TLB", "TLB-memory-writes", "[TLB] Total memory writes"},
|
|
{"CORE", "core-memory-reads", "[CORE] Total memory reads"},
|
|
{"L2T", "L2T-memory-reads", "[L2T] Total memory reads"},
|
|
{"PTB", "PTB-memory-reads", "[PTB] Total memory reads"},
|
|
{"PSE", "PSE-memory-reads", "[PSE] Total memory reads"},
|
|
{"TLB", "TLB-memory-reads", "[TLB] Total memory reads"},
|
|
{"GMP", "GMP-memory-reads", "[GMP] Total memory reads"},
|
|
{"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"},
|
|
{"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"},
|
|
{"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"},
|
|
{"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"},
|
|
{"TMU", "TMU-MRU-hits", "[TMU] Total MRU hits"},
|
|
{"CORE", "compute-active-cycles", "[CORE] Compute active cycles"},
|
|
};
|
|
|
|
static const struct v3d_perf_counter_desc v3d_v71_performance_counters[] = {
|
|
{"CORE", "cycle-count", "[CORE] Cycle counter"},
|
|
{"CORE", "core-active", "[CORE] Bin/Render/Compute active cycles"},
|
|
{"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"},
|
|
{"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"},
|
|
{"CORE", "compute-active-cycles", "[CORE] Compute active cycles"},
|
|
{"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"},
|
|
{"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"},
|
|
{"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"},
|
|
{"FEP", "FEP-valid-quads", "[FEP] Valid quads"},
|
|
{"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"},
|
|
{"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"},
|
|
{"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"},
|
|
{"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"},
|
|
{"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"},
|
|
{"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"},
|
|
{"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"},
|
|
{"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"},
|
|
{"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"},
|
|
{"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"},
|
|
{"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"},
|
|
{"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"},
|
|
{"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"},
|
|
{"TMU", "TMU-active-cycles", "[TMU] Active cycles"},
|
|
{"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"},
|
|
{"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"},
|
|
{"TMU", "TMU-cache-x4-active-cycles", "[TMU] Cache active cycles for x4 access"},
|
|
{"TMU", "TMU-cache-x4-stalled-cycles", "[TMU] Cache stalled cycles for x4 access"},
|
|
{"TMU", "TMU-total-text-quads-x4-access", "[TMU] Total texture cache x4 access"},
|
|
{"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"},
|
|
{"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"},
|
|
{"L2T", "L2T-local", "[L2T] Local mode access"},
|
|
{"L2T", "L2T-writeback", "[L2T] Writeback"},
|
|
{"L2T", "L2T-zero", "[L2T] Zero"},
|
|
{"L2T", "L2T-merge", "[L2T] Merge"},
|
|
{"L2T", "L2T-fill", "[L2T] Fill"},
|
|
{"L2T", "L2T-stalls-no-wid", "[L2T] Stalls because no WID available"},
|
|
{"L2T", "L2T-stalls-no-rid", "[L2T] Stalls because no RID available"},
|
|
{"L2T", "L2T-stalls-queue-full", "[L2T] Stalls because internal queue full"},
|
|
{"L2T", "L2T-stalls-wrightback", "[L2T] Stalls because writeback in flight"},
|
|
{"L2T", "L2T-stalls-mem", "[L2T] Stalls because AXI blocks read"},
|
|
{"L2T", "L2T-stalls-fill", "[L2T] Stalls because fill pending for victim cache-line"},
|
|
{"L2T", "L2T-hitq", "[L2T] Sent request via hit queue"},
|
|
{"L2T", "L2T-hitq-full", "[L2T] Sent request via main queue because hit queue is full"},
|
|
{"L2T", "L2T-stalls-read-data", "[L2T] Stalls because waiting for data from SDRAM"},
|
|
{"L2T", "L2T-TMU-read-hits", "[L2T] TMU read hits"},
|
|
{"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"},
|
|
{"L2T", "L2T-VCD-read-hits", "[L2T] VCD read hits"},
|
|
{"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"},
|
|
{"L2T", "L2T-SLC-read-hits", "[L2T] SLC read hits (all slices)"},
|
|
{"L2T", "L2T-SLC-read-miss", "[L2T] SLC read misses (all slices)"},
|
|
{"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"},
|
|
{"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"},
|
|
{"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"},
|
|
{"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"},
|
|
{"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"},
|
|
{"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"},
|
|
{"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"},
|
|
{"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"},
|
|
{"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"},
|
|
{"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"},
|
|
{"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"},
|
|
{"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"},
|
|
{"CORE", "core-memory-writes", "[CORE] Total memory writes"},
|
|
{"L2T", "L2T-memory-writes", "[L2T] Total memory writes"},
|
|
{"PTB", "PTB-memory-writes", "[PTB] Total memory writes"},
|
|
{"TLB", "TLB-memory-writes", "[TLB] Total memory writes"},
|
|
{"CORE", "core-memory-reads", "[CORE] Total memory reads"},
|
|
{"L2T", "L2T-memory-reads", "[L2T] Total memory reads"},
|
|
{"PTB", "PTB-memory-reads", "[PTB] Total memory reads"},
|
|
{"PSE", "PSE-memory-reads", "[PSE] Total memory reads"},
|
|
{"TLB", "TLB-memory-reads", "[TLB] Total memory reads"},
|
|
{"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"},
|
|
{"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"},
|
|
{"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"},
|
|
{"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"},
|
|
{"AXI", "AXI-read-trans", "[AXI] Read transaction count"},
|
|
{"AXI", "AXI-write-trans", "[AXI] Write transaction count"},
|
|
{"AXI", "AXI-read-wait-cycles", "[AXI] Read total wait cycles"},
|
|
{"AXI", "AXI-write-wait-cycles", "[AXI] Write total wait cycles"},
|
|
{"AXI", "AXI-max-outstanding-reads", "[AXI] Maximum outstanding read transactions"},
|
|
{"AXI", "AXI-max-outstanding-writes", "[AXI] Maximum outstanding write transactions"},
|
|
{"QPU", "QPU-wait-bubble", "[QPU] Pipeline bubble in qcycles due all threads waiting"},
|
|
{"QPU", "QPU-ic-miss-bubble", "[QPU] Pipeline bubble in qcycles due instruction-cache miss"},
|
|
{"QPU", "QPU-active", "[QPU] Executed shader instruction"},
|
|
{"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"},
|
|
{"QPU", "QPU-stalls", "[QPU] Stalled qcycles executing shader instruction"},
|
|
{"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"},
|
|
{"QPU", "QPU-stalls-TMU", "[QPU] Stalled qcycles waiting for TMU"},
|
|
{"QPU", "QPU-stalls-TLB", "[QPU] Stalled qcycles waiting for TLB"},
|
|
{"QPU", "QPU-stalls-VPM", "[QPU] Stalled qcycles waiting for VPM"},
|
|
{"QPU", "QPU-stalls-uniforms", "[QPU] Stalled qcycles waiting for uniforms"},
|
|
{"QPU", "QPU-stalls-SFU", "[QPU] Stalled qcycles waiting for SFU"},
|
|
{"QPU", "QPU-stalls-other", "[QPU] Stalled qcycles waiting for any other reason (vary/W/Z)"},
|
|
};
|
|
|
|
void v3d_perfmon_init(struct v3d_dev *v3d)
|
|
{
|
|
const struct v3d_perf_counter_desc *counters = NULL;
|
|
unsigned int max = 0;
|
|
|
|
if (v3d->ver >= V3D_GEN_71) {
|
|
counters = v3d_v71_performance_counters;
|
|
max = ARRAY_SIZE(v3d_v71_performance_counters);
|
|
} else if (v3d->ver >= V3D_GEN_42) {
|
|
counters = v3d_v42_performance_counters;
|
|
max = ARRAY_SIZE(v3d_v42_performance_counters);
|
|
}
|
|
|
|
v3d->perfmon_info.max_counters = max;
|
|
v3d->perfmon_info.counters = counters;
|
|
}
|
|
|
|
void v3d_perfmon_get(struct v3d_perfmon *perfmon)
|
|
{
|
|
if (perfmon)
|
|
refcount_inc(&perfmon->refcnt);
|
|
}
|
|
|
|
void v3d_perfmon_put(struct v3d_perfmon *perfmon)
|
|
{
|
|
if (perfmon && refcount_dec_and_test(&perfmon->refcnt)) {
|
|
mutex_destroy(&perfmon->lock);
|
|
kfree(perfmon);
|
|
}
|
|
}
|
|
|
|
void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon)
|
|
{
|
|
unsigned int i;
|
|
u32 mask;
|
|
u8 ncounters;
|
|
|
|
if (WARN_ON_ONCE(!perfmon || v3d->active_perfmon))
|
|
return;
|
|
|
|
if (!pm_runtime_get_if_active(v3d->drm.dev))
|
|
return;
|
|
|
|
ncounters = perfmon->ncounters;
|
|
mask = GENMASK(ncounters - 1, 0);
|
|
|
|
for (i = 0; i < ncounters; i++) {
|
|
u32 source = i / 4;
|
|
u32 channel = V3D_SET_FIELD_VER(perfmon->counters[i], V3D_PCTR_S0,
|
|
v3d->ver);
|
|
|
|
i++;
|
|
channel |= V3D_SET_FIELD_VER(i < ncounters ? perfmon->counters[i] : 0,
|
|
V3D_PCTR_S1, v3d->ver);
|
|
i++;
|
|
channel |= V3D_SET_FIELD_VER(i < ncounters ? perfmon->counters[i] : 0,
|
|
V3D_PCTR_S2, v3d->ver);
|
|
i++;
|
|
channel |= V3D_SET_FIELD_VER(i < ncounters ? perfmon->counters[i] : 0,
|
|
V3D_PCTR_S3, v3d->ver);
|
|
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_SRC_X(source), channel);
|
|
}
|
|
|
|
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
|
|
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_CLR, mask);
|
|
V3D_CORE_WRITE(0, V3D_PCTR_0_OVERFLOW, mask);
|
|
|
|
v3d->active_perfmon = perfmon;
|
|
|
|
v3d_pm_runtime_put(v3d);
|
|
}
|
|
|
|
void v3d_perfmon_stop(struct v3d_dev *v3d, struct v3d_perfmon *perfmon,
|
|
bool capture)
|
|
{
|
|
unsigned int i;
|
|
|
|
if (!perfmon || !v3d->active_perfmon)
|
|
return;
|
|
|
|
mutex_lock(&perfmon->lock);
|
|
if (perfmon != v3d->active_perfmon)
|
|
goto out;
|
|
|
|
if (!pm_runtime_get_if_active(v3d->drm.dev))
|
|
goto out_clear;
|
|
|
|
if (capture)
|
|
for (i = 0; i < perfmon->ncounters; i++)
|
|
perfmon->values[i] += V3D_CORE_READ(0, V3D_PCTR_0_PCTRX(i));
|
|
|
|
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, 0);
|
|
|
|
v3d_pm_runtime_put(v3d);
|
|
|
|
out_clear:
|
|
v3d->active_perfmon = NULL;
|
|
out:
|
|
mutex_unlock(&perfmon->lock);
|
|
}
|
|
|
|
struct v3d_perfmon *v3d_perfmon_find(struct v3d_file_priv *v3d_priv, int id)
|
|
{
|
|
struct v3d_perfmon *perfmon;
|
|
|
|
xa_lock(&v3d_priv->perfmons);
|
|
perfmon = xa_load(&v3d_priv->perfmons, id);
|
|
v3d_perfmon_get(perfmon);
|
|
xa_unlock(&v3d_priv->perfmons);
|
|
|
|
return perfmon;
|
|
}
|
|
|
|
void v3d_perfmon_open_file(struct v3d_file_priv *v3d_priv)
|
|
{
|
|
xa_init_flags(&v3d_priv->perfmons, XA_FLAGS_ALLOC1);
|
|
}
|
|
|
|
static void v3d_perfmon_delete(struct v3d_file_priv *v3d_priv,
|
|
struct v3d_perfmon *perfmon)
|
|
{
|
|
struct v3d_dev *v3d = v3d_priv->v3d;
|
|
|
|
/* If the active perfmon is being destroyed, stop it first */
|
|
if (perfmon == v3d->active_perfmon)
|
|
v3d_perfmon_stop(v3d, perfmon, false);
|
|
|
|
/* If the global perfmon is being destroyed, clean it and release
|
|
* the reference stashed in v3d_perfmon_set_global_ioctl().
|
|
*/
|
|
if (cmpxchg(&v3d->global_perfmon, perfmon, NULL) == perfmon)
|
|
v3d_perfmon_put(perfmon);
|
|
|
|
v3d_perfmon_put(perfmon);
|
|
}
|
|
|
|
void v3d_perfmon_close_file(struct v3d_file_priv *v3d_priv)
|
|
{
|
|
struct v3d_perfmon *perfmon;
|
|
unsigned long id;
|
|
|
|
xa_for_each(&v3d_priv->perfmons, id, perfmon)
|
|
v3d_perfmon_delete(v3d_priv, perfmon);
|
|
|
|
xa_destroy(&v3d_priv->perfmons);
|
|
}
|
|
|
|
int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv)
|
|
{
|
|
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
|
|
struct drm_v3d_perfmon_create *req = data;
|
|
struct v3d_dev *v3d = v3d_priv->v3d;
|
|
struct v3d_perfmon *perfmon;
|
|
unsigned int i;
|
|
int ret;
|
|
u32 id;
|
|
|
|
/* Number of monitored counters cannot exceed HW limits. */
|
|
if (req->ncounters > DRM_V3D_MAX_PERF_COUNTERS ||
|
|
!req->ncounters)
|
|
return -EINVAL;
|
|
|
|
/* Make sure all counters are valid. */
|
|
for (i = 0; i < req->ncounters; i++) {
|
|
if (req->counters[i] >= v3d->perfmon_info.max_counters)
|
|
return -EINVAL;
|
|
}
|
|
|
|
perfmon = kzalloc_flex(*perfmon, values, req->ncounters);
|
|
if (!perfmon)
|
|
return -ENOMEM;
|
|
|
|
for (i = 0; i < req->ncounters; i++)
|
|
perfmon->counters[i] = req->counters[i];
|
|
|
|
perfmon->ncounters = req->ncounters;
|
|
|
|
refcount_set(&perfmon->refcnt, 1);
|
|
mutex_init(&perfmon->lock);
|
|
|
|
ret = xa_alloc(&v3d_priv->perfmons, &id, perfmon, xa_limit_32b,
|
|
GFP_KERNEL);
|
|
if (ret < 0) {
|
|
mutex_destroy(&perfmon->lock);
|
|
kfree(perfmon);
|
|
return ret;
|
|
}
|
|
|
|
req->id = id;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv)
|
|
{
|
|
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
|
|
struct drm_v3d_perfmon_destroy *req = data;
|
|
struct v3d_perfmon *perfmon;
|
|
|
|
perfmon = xa_erase(&v3d_priv->perfmons, req->id);
|
|
if (!perfmon)
|
|
return -EINVAL;
|
|
|
|
v3d_perfmon_delete(v3d_priv, perfmon);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int v3d_perfmon_get_values_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv)
|
|
{
|
|
struct v3d_dev *v3d = to_v3d_dev(dev);
|
|
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
|
|
struct drm_v3d_perfmon_get_values *req = data;
|
|
struct v3d_perfmon *perfmon;
|
|
int ret = 0;
|
|
|
|
if (req->pad != 0)
|
|
return -EINVAL;
|
|
|
|
perfmon = v3d_perfmon_find(v3d_priv, req->id);
|
|
if (!perfmon)
|
|
return -EINVAL;
|
|
|
|
v3d_perfmon_stop(v3d, perfmon, true);
|
|
|
|
if (copy_to_user(u64_to_user_ptr(req->values_ptr), perfmon->values,
|
|
perfmon->ncounters * sizeof(u64)))
|
|
ret = -EFAULT;
|
|
|
|
v3d_perfmon_put(perfmon);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv)
|
|
{
|
|
struct drm_v3d_perfmon_get_counter *req = data;
|
|
struct v3d_dev *v3d = to_v3d_dev(dev);
|
|
const struct v3d_perf_counter_desc *counter;
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(req->reserved); i++) {
|
|
if (req->reserved[i] != 0)
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!v3d->perfmon_info.max_counters)
|
|
return -EOPNOTSUPP;
|
|
|
|
/* Make sure that the counter ID is valid */
|
|
if (req->counter >= v3d->perfmon_info.max_counters)
|
|
return -EINVAL;
|
|
|
|
counter = &v3d->perfmon_info.counters[req->counter];
|
|
|
|
strscpy(req->name, counter->name, sizeof(req->name));
|
|
strscpy(req->category, counter->category, sizeof(req->category));
|
|
strscpy(req->description, counter->description, sizeof(req->description));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int v3d_perfmon_set_global_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv)
|
|
{
|
|
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
|
|
struct drm_v3d_perfmon_set_global *req = data;
|
|
struct v3d_dev *v3d = to_v3d_dev(dev);
|
|
struct v3d_perfmon *perfmon;
|
|
|
|
if (req->flags & ~DRM_V3D_PERFMON_CLEAR_GLOBAL)
|
|
return -EINVAL;
|
|
|
|
perfmon = v3d_perfmon_find(v3d_priv, req->id);
|
|
if (!perfmon)
|
|
return -EINVAL;
|
|
|
|
/* If the request is to clear the global performance monitor */
|
|
if (req->flags & DRM_V3D_PERFMON_CLEAR_GLOBAL) {
|
|
struct v3d_perfmon *old;
|
|
|
|
/* DRM_V3D_PERFMON_CLEAR_GLOBAL doesn't check if
|
|
* v3d->global_perfmon == perfmon. Therefore, there
|
|
* is no need to keep perfmon's reference.
|
|
*/
|
|
v3d_perfmon_put(perfmon);
|
|
|
|
old = xchg(&v3d->global_perfmon, NULL);
|
|
if (!old)
|
|
return -EINVAL;
|
|
|
|
v3d_perfmon_put(old);
|
|
|
|
return 0;
|
|
}
|
|
|
|
if (cmpxchg(&v3d->global_perfmon, NULL, perfmon)) {
|
|
v3d_perfmon_put(perfmon);
|
|
return -EBUSY;
|
|
}
|
|
|
|
return 0;
|
|
}
|