Commit 6759a0a7a0496dbbd4fb062c6a76d61c55d0fbd9
Committed by
Alex Deucher
1 parent
b51ad12a36
drm/radeon/kms: implement timestamp userspace query (v2)
Returns a snapshot of the GPU clock counter. Needed for certain OpenGL extensions. v2: agd5f - address Jerome's comments - add function documentation Signed-off-by: Marek Olšák <maraeo@gmail.com> Reviewed-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Showing 10 changed files with 82 additions and 7 deletions Side-by-side Diff
- drivers/gpu/drm/radeon/r600.c
- drivers/gpu/drm/radeon/r600d.h
- drivers/gpu/drm/radeon/radeon.h
- drivers/gpu/drm/radeon/radeon_asic.h
- drivers/gpu/drm/radeon/radeon_device.c
- drivers/gpu/drm/radeon/radeon_drv.c
- drivers/gpu/drm/radeon/radeon_kms.c
- drivers/gpu/drm/radeon/si.c
- drivers/gpu/drm/radeon/sid.h
- include/drm/radeon_drm.h
drivers/gpu/drm/radeon/r600.c
... | ... | @@ -3789,4 +3789,24 @@ |
3789 | 3789 | WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); |
3790 | 3790 | } |
3791 | 3791 | } |
3792 | + | |
3793 | +/** | |
3794 | + * r600_get_gpu_clock - return GPU clock counter snapshot | |
3795 | + * | |
3796 | + * @rdev: radeon_device pointer | |
3797 | + * | |
3798 | + * Fetches a GPU clock counter snapshot (R6xx-cayman). | |
3799 | + * Returns the 64 bit clock counter snapshot. | |
3800 | + */ | |
3801 | +uint64_t r600_get_gpu_clock(struct radeon_device *rdev) | |
3802 | +{ | |
3803 | + uint64_t clock; | |
3804 | + | |
3805 | + mutex_lock(&rdev->gpu_clock_mutex); | |
3806 | + WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); | |
3807 | + clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | | |
3808 | + ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); | |
3809 | + mutex_unlock(&rdev->gpu_clock_mutex); | |
3810 | + return clock; | |
3811 | +} |
drivers/gpu/drm/radeon/r600d.h
... | ... | @@ -602,6 +602,9 @@ |
602 | 602 | #define RLC_HB_WPTR 0x3f1c |
603 | 603 | #define RLC_HB_WPTR_LSB_ADDR 0x3f14 |
604 | 604 | #define RLC_HB_WPTR_MSB_ADDR 0x3f18 |
605 | +#define RLC_GPU_CLOCK_COUNT_LSB 0x3f38 | |
606 | +#define RLC_GPU_CLOCK_COUNT_MSB 0x3f3c | |
607 | +#define RLC_CAPTURE_GPU_CLOCK_COUNT 0x3f40 | |
605 | 608 | #define RLC_MC_CNTL 0x3f44 |
606 | 609 | #define RLC_UCODE_CNTL 0x3f48 |
607 | 610 | #define RLC_UCODE_ADDR 0x3f2c |
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.h
... | ... | @@ -368,6 +368,7 @@ |
368 | 368 | unsigned num_gpu_pages, |
369 | 369 | struct radeon_sa_bo *vb); |
370 | 370 | int r600_mc_wait_for_idle(struct radeon_device *rdev); |
371 | +uint64_t r600_get_gpu_clock(struct radeon_device *rdev); | |
371 | 372 | |
372 | 373 | /* |
373 | 374 | * rv770,rv730,rv710,rv740 |
... | ... | @@ -468,6 +469,7 @@ |
468 | 469 | void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm); |
469 | 470 | void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm); |
470 | 471 | int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); |
472 | +uint64_t si_get_gpu_clock(struct radeon_device *rdev); | |
471 | 473 | |
472 | 474 | #endif |
drivers/gpu/drm/radeon/radeon_device.c
... | ... | @@ -1009,6 +1009,7 @@ |
1009 | 1009 | atomic_set(&rdev->ih.lock, 0); |
1010 | 1010 | mutex_init(&rdev->gem.mutex); |
1011 | 1011 | mutex_init(&rdev->pm.mutex); |
1012 | + mutex_init(&rdev->gpu_clock_mutex); | |
1012 | 1013 | init_rwsem(&rdev->pm.mclk_lock); |
1013 | 1014 | init_rwsem(&rdev->exclusive_lock); |
1014 | 1015 | init_waitqueue_head(&rdev->irq.vblank_queue); |
drivers/gpu/drm/radeon/radeon_drv.c
... | ... | @@ -61,9 +61,10 @@ |
61 | 61 | * 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx |
62 | 62 | * 2.18.0 - r600-eg: allow "invalid" DB formats |
63 | 63 | * 2.19.0 - r600-eg: MSAA textures |
64 | + * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query | |
64 | 65 | */ |
65 | 66 | #define KMS_DRIVER_MAJOR 2 |
66 | -#define KMS_DRIVER_MINOR 19 | |
67 | +#define KMS_DRIVER_MINOR 20 | |
67 | 68 | #define KMS_DRIVER_PATCHLEVEL 0 |
68 | 69 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
69 | 70 | int radeon_driver_unload_kms(struct drm_device *dev); |
drivers/gpu/drm/radeon/radeon_kms.c
... | ... | @@ -29,6 +29,7 @@ |
29 | 29 | #include "drm_sarea.h" |
30 | 30 | #include "radeon.h" |
31 | 31 | #include "radeon_drm.h" |
32 | +#include "radeon_asic.h" | |
32 | 33 | |
33 | 34 | #include <linux/vga_switcheroo.h> |
34 | 35 | #include <linux/slab.h> |
35 | 36 | |
36 | 37 | |
37 | 38 | |
38 | 39 | |
... | ... | @@ -167,17 +168,39 @@ |
167 | 168 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) |
168 | 169 | { |
169 | 170 | struct radeon_device *rdev = dev->dev_private; |
170 | - struct drm_radeon_info *info; | |
171 | + struct drm_radeon_info *info = data; | |
171 | 172 | struct radeon_mode_info *minfo = &rdev->mode_info; |
172 | - uint32_t *value_ptr; | |
173 | - uint32_t value; | |
173 | + uint32_t value, *value_ptr; | |
174 | + uint64_t value64, *value_ptr64; | |
174 | 175 | struct drm_crtc *crtc; |
175 | 176 | int i, found; |
176 | 177 | |
177 | - info = data; | |
178 | + /* TIMESTAMP is a 64-bit value, needs special handling. */ | |
179 | + if (info->request == RADEON_INFO_TIMESTAMP) { | |
180 | + if (rdev->family >= CHIP_R600) { | |
181 | + value_ptr64 = (uint64_t*)((unsigned long)info->value); | |
182 | + if (rdev->family >= CHIP_TAHITI) { | |
183 | + value64 = si_get_gpu_clock(rdev); | |
184 | + } else { | |
185 | + value64 = r600_get_gpu_clock(rdev); | |
186 | + } | |
187 | + | |
188 | + if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) { | |
189 | + DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); | |
190 | + return -EFAULT; | |
191 | + } | |
192 | + return 0; | |
193 | + } else { | |
194 | + DRM_DEBUG_KMS("timestamp is r6xx+ only!\n"); | |
195 | + return -EINVAL; | |
196 | + } | |
197 | + } | |
198 | + | |
178 | 199 | value_ptr = (uint32_t *)((unsigned long)info->value); |
179 | - if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) | |
200 | + if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) { | |
201 | + DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); | |
180 | 202 | return -EFAULT; |
203 | + } | |
181 | 204 | |
182 | 205 | switch (info->request) { |
183 | 206 | case RADEON_INFO_DEVICE_ID: |
... | ... | @@ -337,7 +360,7 @@ |
337 | 360 | return -EINVAL; |
338 | 361 | } |
339 | 362 | if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { |
340 | - DRM_ERROR("copy_to_user\n"); | |
363 | + DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); | |
341 | 364 | return -EFAULT; |
342 | 365 | } |
343 | 366 | return 0; |
drivers/gpu/drm/radeon/si.c
... | ... | @@ -3967,4 +3967,24 @@ |
3967 | 3967 | kfree(rdev->bios); |
3968 | 3968 | rdev->bios = NULL; |
3969 | 3969 | } |
3970 | + | |
3971 | +/** | |
3972 | + * si_get_gpu_clock - return GPU clock counter snapshot | |
3973 | + * | |
3974 | + * @rdev: radeon_device pointer | |
3975 | + * | |
3976 | + * Fetches a GPU clock counter snapshot (SI). | |
3977 | + * Returns the 64 bit clock counter snapshot. | |
3978 | + */ | |
3979 | +uint64_t si_get_gpu_clock(struct radeon_device *rdev) | |
3980 | +{ | |
3981 | + uint64_t clock; | |
3982 | + | |
3983 | + mutex_lock(&rdev->gpu_clock_mutex); | |
3984 | + WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); | |
3985 | + clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | | |
3986 | + ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); | |
3987 | + mutex_unlock(&rdev->gpu_clock_mutex); | |
3988 | + return clock; | |
3989 | +} |
drivers/gpu/drm/radeon/sid.h
... | ... | @@ -698,6 +698,9 @@ |
698 | 698 | #define RLC_UCODE_ADDR 0xC32C |
699 | 699 | #define RLC_UCODE_DATA 0xC330 |
700 | 700 | |
701 | +#define RLC_GPU_CLOCK_COUNT_LSB 0xC338 | |
702 | +#define RLC_GPU_CLOCK_COUNT_MSB 0xC33C | |
703 | +#define RLC_CAPTURE_GPU_CLOCK_COUNT 0xC340 | |
701 | 704 | #define RLC_MC_CNTL 0xC344 |
702 | 705 | #define RLC_UCODE_CNTL 0xC348 |
703 | 706 |
include/drm/radeon_drm.h
... | ... | @@ -964,6 +964,8 @@ |
964 | 964 | #define RADEON_INFO_IB_VM_MAX_SIZE 0x0f |
965 | 965 | /* max pipes - needed for compute shaders */ |
966 | 966 | #define RADEON_INFO_MAX_PIPES 0x10 |
967 | +/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */ | |
968 | +#define RADEON_INFO_TIMESTAMP 0x11 | |
967 | 969 | |
968 | 970 | struct drm_radeon_info { |
969 | 971 | uint32_t request; |