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>
This commit is contained in:
parent
b51ad12a36
commit
6759a0a7a0
|
@ -3789,3 +3789,23 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
|
||||||
WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
|
WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* r600_get_gpu_clock - return GPU clock counter snapshot
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
*
|
||||||
|
* Fetches a GPU clock counter snapshot (R6xx-cayman).
|
||||||
|
* Returns the 64 bit clock counter snapshot.
|
||||||
|
*/
|
||||||
|
uint64_t r600_get_gpu_clock(struct radeon_device *rdev)
|
||||||
|
{
|
||||||
|
uint64_t clock;
|
||||||
|
|
||||||
|
mutex_lock(&rdev->gpu_clock_mutex);
|
||||||
|
WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1);
|
||||||
|
clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) |
|
||||||
|
((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
|
||||||
|
mutex_unlock(&rdev->gpu_clock_mutex);
|
||||||
|
return clock;
|
||||||
|
}
|
||||||
|
|
|
@ -602,6 +602,9 @@
|
||||||
#define RLC_HB_WPTR 0x3f1c
|
#define RLC_HB_WPTR 0x3f1c
|
||||||
#define RLC_HB_WPTR_LSB_ADDR 0x3f14
|
#define RLC_HB_WPTR_LSB_ADDR 0x3f14
|
||||||
#define RLC_HB_WPTR_MSB_ADDR 0x3f18
|
#define RLC_HB_WPTR_MSB_ADDR 0x3f18
|
||||||
|
#define RLC_GPU_CLOCK_COUNT_LSB 0x3f38
|
||||||
|
#define RLC_GPU_CLOCK_COUNT_MSB 0x3f3c
|
||||||
|
#define RLC_CAPTURE_GPU_CLOCK_COUNT 0x3f40
|
||||||
#define RLC_MC_CNTL 0x3f44
|
#define RLC_MC_CNTL 0x3f44
|
||||||
#define RLC_UCODE_CNTL 0x3f48
|
#define RLC_UCODE_CNTL 0x3f48
|
||||||
#define RLC_UCODE_ADDR 0x3f2c
|
#define RLC_UCODE_ADDR 0x3f2c
|
||||||
|
|
|
@ -1534,6 +1534,7 @@ struct radeon_device {
|
||||||
unsigned debugfs_count;
|
unsigned debugfs_count;
|
||||||
/* virtual memory */
|
/* virtual memory */
|
||||||
struct radeon_vm_manager vm_manager;
|
struct radeon_vm_manager vm_manager;
|
||||||
|
struct mutex gpu_clock_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
int radeon_device_init(struct radeon_device *rdev,
|
int radeon_device_init(struct radeon_device *rdev,
|
||||||
|
|
|
@ -368,6 +368,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
|
||||||
unsigned num_gpu_pages,
|
unsigned num_gpu_pages,
|
||||||
struct radeon_sa_bo *vb);
|
struct radeon_sa_bo *vb);
|
||||||
int r600_mc_wait_for_idle(struct radeon_device *rdev);
|
int r600_mc_wait_for_idle(struct radeon_device *rdev);
|
||||||
|
uint64_t r600_get_gpu_clock(struct radeon_device *rdev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rv770,rv730,rv710,rv740
|
* rv770,rv730,rv710,rv740
|
||||||
|
@ -468,5 +469,6 @@ int si_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id);
|
||||||
void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm);
|
void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm);
|
||||||
void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm);
|
void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm);
|
||||||
int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
|
int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
|
||||||
|
uint64_t si_get_gpu_clock(struct radeon_device *rdev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1009,6 +1009,7 @@ int radeon_device_init(struct radeon_device *rdev,
|
||||||
atomic_set(&rdev->ih.lock, 0);
|
atomic_set(&rdev->ih.lock, 0);
|
||||||
mutex_init(&rdev->gem.mutex);
|
mutex_init(&rdev->gem.mutex);
|
||||||
mutex_init(&rdev->pm.mutex);
|
mutex_init(&rdev->pm.mutex);
|
||||||
|
mutex_init(&rdev->gpu_clock_mutex);
|
||||||
init_rwsem(&rdev->pm.mclk_lock);
|
init_rwsem(&rdev->pm.mclk_lock);
|
||||||
init_rwsem(&rdev->exclusive_lock);
|
init_rwsem(&rdev->exclusive_lock);
|
||||||
init_waitqueue_head(&rdev->irq.vblank_queue);
|
init_waitqueue_head(&rdev->irq.vblank_queue);
|
||||||
|
|
|
@ -61,9 +61,10 @@
|
||||||
* 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx
|
* 2.17.0 - add STRMOUT_BASE_UPDATE for r7xx
|
||||||
* 2.18.0 - r600-eg: allow "invalid" DB formats
|
* 2.18.0 - r600-eg: allow "invalid" DB formats
|
||||||
* 2.19.0 - r600-eg: MSAA textures
|
* 2.19.0 - r600-eg: MSAA textures
|
||||||
|
* 2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query
|
||||||
*/
|
*/
|
||||||
#define KMS_DRIVER_MAJOR 2
|
#define KMS_DRIVER_MAJOR 2
|
||||||
#define KMS_DRIVER_MINOR 19
|
#define KMS_DRIVER_MINOR 20
|
||||||
#define KMS_DRIVER_PATCHLEVEL 0
|
#define KMS_DRIVER_PATCHLEVEL 0
|
||||||
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
|
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
|
||||||
int radeon_driver_unload_kms(struct drm_device *dev);
|
int radeon_driver_unload_kms(struct drm_device *dev);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "drm_sarea.h"
|
#include "drm_sarea.h"
|
||||||
#include "radeon.h"
|
#include "radeon.h"
|
||||||
#include "radeon_drm.h"
|
#include "radeon_drm.h"
|
||||||
|
#include "radeon_asic.h"
|
||||||
|
|
||||||
#include <linux/vga_switcheroo.h>
|
#include <linux/vga_switcheroo.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -167,17 +168,39 @@ static void radeon_set_filp_rights(struct drm_device *dev,
|
||||||
int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||||
{
|
{
|
||||||
struct radeon_device *rdev = dev->dev_private;
|
struct radeon_device *rdev = dev->dev_private;
|
||||||
struct drm_radeon_info *info;
|
struct drm_radeon_info *info = data;
|
||||||
struct radeon_mode_info *minfo = &rdev->mode_info;
|
struct radeon_mode_info *minfo = &rdev->mode_info;
|
||||||
uint32_t *value_ptr;
|
uint32_t value, *value_ptr;
|
||||||
uint32_t value;
|
uint64_t value64, *value_ptr64;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
int i, found;
|
int i, found;
|
||||||
|
|
||||||
info = data;
|
/* TIMESTAMP is a 64-bit value, needs special handling. */
|
||||||
|
if (info->request == RADEON_INFO_TIMESTAMP) {
|
||||||
|
if (rdev->family >= CHIP_R600) {
|
||||||
|
value_ptr64 = (uint64_t*)((unsigned long)info->value);
|
||||||
|
if (rdev->family >= CHIP_TAHITI) {
|
||||||
|
value64 = si_get_gpu_clock(rdev);
|
||||||
|
} else {
|
||||||
|
value64 = r600_get_gpu_clock(rdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) {
|
||||||
|
DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
value_ptr = (uint32_t *)((unsigned long)info->value);
|
value_ptr = (uint32_t *)((unsigned long)info->value);
|
||||||
if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value)))
|
if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) {
|
||||||
|
DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
switch (info->request) {
|
switch (info->request) {
|
||||||
case RADEON_INFO_DEVICE_ID:
|
case RADEON_INFO_DEVICE_ID:
|
||||||
|
@ -337,7 +360,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) {
|
if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) {
|
||||||
DRM_ERROR("copy_to_user\n");
|
DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -3968,3 +3968,22 @@ void si_fini(struct radeon_device *rdev)
|
||||||
rdev->bios = NULL;
|
rdev->bios = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* si_get_gpu_clock - return GPU clock counter snapshot
|
||||||
|
*
|
||||||
|
* @rdev: radeon_device pointer
|
||||||
|
*
|
||||||
|
* Fetches a GPU clock counter snapshot (SI).
|
||||||
|
* Returns the 64 bit clock counter snapshot.
|
||||||
|
*/
|
||||||
|
uint64_t si_get_gpu_clock(struct radeon_device *rdev)
|
||||||
|
{
|
||||||
|
uint64_t clock;
|
||||||
|
|
||||||
|
mutex_lock(&rdev->gpu_clock_mutex);
|
||||||
|
WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1);
|
||||||
|
clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) |
|
||||||
|
((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
|
||||||
|
mutex_unlock(&rdev->gpu_clock_mutex);
|
||||||
|
return clock;
|
||||||
|
}
|
||||||
|
|
|
@ -698,6 +698,9 @@
|
||||||
#define RLC_UCODE_ADDR 0xC32C
|
#define RLC_UCODE_ADDR 0xC32C
|
||||||
#define RLC_UCODE_DATA 0xC330
|
#define RLC_UCODE_DATA 0xC330
|
||||||
|
|
||||||
|
#define RLC_GPU_CLOCK_COUNT_LSB 0xC338
|
||||||
|
#define RLC_GPU_CLOCK_COUNT_MSB 0xC33C
|
||||||
|
#define RLC_CAPTURE_GPU_CLOCK_COUNT 0xC340
|
||||||
#define RLC_MC_CNTL 0xC344
|
#define RLC_MC_CNTL 0xC344
|
||||||
#define RLC_UCODE_CNTL 0xC348
|
#define RLC_UCODE_CNTL 0xC348
|
||||||
|
|
||||||
|
|
|
@ -964,6 +964,8 @@ struct drm_radeon_cs {
|
||||||
#define RADEON_INFO_IB_VM_MAX_SIZE 0x0f
|
#define RADEON_INFO_IB_VM_MAX_SIZE 0x0f
|
||||||
/* max pipes - needed for compute shaders */
|
/* max pipes - needed for compute shaders */
|
||||||
#define RADEON_INFO_MAX_PIPES 0x10
|
#define RADEON_INFO_MAX_PIPES 0x10
|
||||||
|
/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */
|
||||||
|
#define RADEON_INFO_TIMESTAMP 0x11
|
||||||
|
|
||||||
struct drm_radeon_info {
|
struct drm_radeon_info {
|
||||||
uint32_t request;
|
uint32_t request;
|
||||||
|
|
Loading…
Reference in New Issue