diff options
| author | Marek Olšák <maraeo@gmail.com> | 2012-08-09 10:34:17 -0400 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2012-08-13 10:50:56 -0400 |
| commit | 6759a0a7a0496dbbd4fb062c6a76d61c55d0fbd9 (patch) | |
| tree | e16a78229435a2277d11f55ad8dd07780ce7499c | |
| parent | b51ad12a36234c1f6707c9c54a414cfca23f3cdb (diff) | |
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>
| -rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600d.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/si.c | 19 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/sid.h | 3 | ||||
| -rw-r--r-- | include/drm/radeon_drm.h | 2 |
10 files changed, 82 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 637280f541a3..d79c639ae739 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -3789,3 +3789,23 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) | |||
| 3789 | WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); | 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 | } | ||
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 4b116ae75fc2..fd328f4c3ea8 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
| @@ -602,6 +602,9 @@ | |||
| 602 | #define RLC_HB_WPTR 0x3f1c | 602 | #define RLC_HB_WPTR 0x3f1c |
| 603 | #define RLC_HB_WPTR_LSB_ADDR 0x3f14 | 603 | #define RLC_HB_WPTR_LSB_ADDR 0x3f14 |
| 604 | #define RLC_HB_WPTR_MSB_ADDR 0x3f18 | 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 | #define RLC_MC_CNTL 0x3f44 | 608 | #define RLC_MC_CNTL 0x3f44 |
| 606 | #define RLC_UCODE_CNTL 0x3f48 | 609 | #define RLC_UCODE_CNTL 0x3f48 |
| 607 | #define RLC_UCODE_ADDR 0x3f2c | 610 | #define RLC_UCODE_ADDR 0x3f2c |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b237a29142d1..99304194a65c 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -1534,6 +1534,7 @@ struct radeon_device { | |||
| 1534 | unsigned debugfs_count; | 1534 | unsigned debugfs_count; |
| 1535 | /* virtual memory */ | 1535 | /* virtual memory */ |
| 1536 | struct radeon_vm_manager vm_manager; | 1536 | struct radeon_vm_manager vm_manager; |
| 1537 | struct mutex gpu_clock_mutex; | ||
| 1537 | }; | 1538 | }; |
| 1538 | 1539 | ||
| 1539 | int radeon_device_init(struct radeon_device *rdev, | 1540 | int radeon_device_init(struct radeon_device *rdev, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 0d445e7d00d1..18c38d14c8cd 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -368,6 +368,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev, | |||
| 368 | unsigned num_gpu_pages, | 368 | unsigned num_gpu_pages, |
| 369 | struct radeon_sa_bo *vb); | 369 | struct radeon_sa_bo *vb); |
| 370 | int r600_mc_wait_for_idle(struct radeon_device *rdev); | 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 | * rv770,rv730,rv710,rv740 | 374 | * rv770,rv730,rv710,rv740 |
| @@ -468,5 +469,6 @@ int si_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id); | |||
| 468 | void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm); | 469 | void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm); |
| 469 | void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm); | 470 | void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm); |
| 470 | int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); | 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 | #endif | 474 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 742af8244e89..d2e243867ac6 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -1009,6 +1009,7 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 1009 | atomic_set(&rdev->ih.lock, 0); | 1009 | atomic_set(&rdev->ih.lock, 0); |
| 1010 | mutex_init(&rdev->gem.mutex); | 1010 | mutex_init(&rdev->gem.mutex); |
| 1011 | mutex_init(&rdev->pm.mutex); | 1011 | mutex_init(&rdev->pm.mutex); |
| 1012 | mutex_init(&rdev->gpu_clock_mutex); | ||
| 1012 | init_rwsem(&rdev->pm.mclk_lock); | 1013 | init_rwsem(&rdev->pm.mclk_lock); |
| 1013 | init_rwsem(&rdev->exclusive_lock); | 1014 | init_rwsem(&rdev->exclusive_lock); |
| 1014 | init_waitqueue_head(&rdev->irq.vblank_queue); | 1015 | init_waitqueue_head(&rdev->irq.vblank_queue); |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index a7f8ac0d8f03..d7269f48d37c 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -61,9 +61,10 @@ | |||
| 61 | * 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx | 61 | * 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx |
| 62 | * 2.18.0 - r600-eg: allow "invalid" DB formats | 62 | * 2.18.0 - r600-eg: allow "invalid" DB formats |
| 63 | * 2.19.0 - r600-eg: MSAA textures | 63 | * 2.19.0 - r600-eg: MSAA textures |
| 64 | * 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query | ||
| 64 | */ | 65 | */ |
| 65 | #define KMS_DRIVER_MAJOR 2 | 66 | #define KMS_DRIVER_MAJOR 2 |
| 66 | #define KMS_DRIVER_MINOR 19 | 67 | #define KMS_DRIVER_MINOR 20 |
| 67 | #define KMS_DRIVER_PATCHLEVEL 0 | 68 | #define KMS_DRIVER_PATCHLEVEL 0 |
| 68 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 69 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
| 69 | int radeon_driver_unload_kms(struct drm_device *dev); | 70 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 1d73f16b5d97..414b4acf6947 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "drm_sarea.h" | 29 | #include "drm_sarea.h" |
| 30 | #include "radeon.h" | 30 | #include "radeon.h" |
| 31 | #include "radeon_drm.h" | 31 | #include "radeon_drm.h" |
| 32 | #include "radeon_asic.h" | ||
| 32 | 33 | ||
| 33 | #include <linux/vga_switcheroo.h> | 34 | #include <linux/vga_switcheroo.h> |
| 34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| @@ -167,17 +168,39 @@ static void radeon_set_filp_rights(struct drm_device *dev, | |||
| 167 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | 168 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) |
| 168 | { | 169 | { |
| 169 | struct radeon_device *rdev = dev->dev_private; | 170 | struct radeon_device *rdev = dev->dev_private; |
| 170 | struct drm_radeon_info *info; | 171 | struct drm_radeon_info *info = data; |
| 171 | struct radeon_mode_info *minfo = &rdev->mode_info; | 172 | struct radeon_mode_info *minfo = &rdev->mode_info; |
| 172 | uint32_t *value_ptr; | 173 | uint32_t value, *value_ptr; |
| 173 | uint32_t value; | 174 | uint64_t value64, *value_ptr64; |
| 174 | struct drm_crtc *crtc; | 175 | struct drm_crtc *crtc; |
| 175 | int i, found; | 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 | value_ptr = (uint32_t *)((unsigned long)info->value); | 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 | return -EFAULT; | 202 | return -EFAULT; |
| 203 | } | ||
| 181 | 204 | ||
| 182 | switch (info->request) { | 205 | switch (info->request) { |
| 183 | case RADEON_INFO_DEVICE_ID: | 206 | case RADEON_INFO_DEVICE_ID: |
| @@ -337,7 +360,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
| 337 | return -EINVAL; | 360 | return -EINVAL; |
| 338 | } | 361 | } |
| 339 | if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { | 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 | return -EFAULT; | 364 | return -EFAULT; |
| 342 | } | 365 | } |
| 343 | return 0; | 366 | return 0; |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index c153a7f359c8..0139e227e3c7 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -3968,3 +3968,22 @@ void si_fini(struct radeon_device *rdev) | |||
| 3968 | rdev->bios = NULL; | 3968 | rdev->bios = NULL; |
| 3969 | } | 3969 | } |
| 3970 | 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 | } | ||
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7869089e8761..ef4815c27b1c 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -698,6 +698,9 @@ | |||
| 698 | #define RLC_UCODE_ADDR 0xC32C | 698 | #define RLC_UCODE_ADDR 0xC32C |
| 699 | #define RLC_UCODE_DATA 0xC330 | 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 | #define RLC_MC_CNTL 0xC344 | 704 | #define RLC_MC_CNTL 0xC344 |
| 702 | #define RLC_UCODE_CNTL 0xC348 | 705 | #define RLC_UCODE_CNTL 0xC348 |
| 703 | 706 | ||
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 58056865b8e9..dc3a8cd7db8a 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h | |||
| @@ -964,6 +964,8 @@ struct drm_radeon_cs { | |||
| 964 | #define RADEON_INFO_IB_VM_MAX_SIZE 0x0f | 964 | #define RADEON_INFO_IB_VM_MAX_SIZE 0x0f |
| 965 | /* max pipes - needed for compute shaders */ | 965 | /* max pipes - needed for compute shaders */ |
| 966 | #define RADEON_INFO_MAX_PIPES 0x10 | 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 | struct drm_radeon_info { | 970 | struct drm_radeon_info { |
| 969 | uint32_t request; | 971 | uint32_t request; |
