[PATCH 3/3] drm/radeon/kms: implement timestamp userspace query

Jerome Glisse j.glisse at gmail.com
Thu Aug 9 07:57:12 PDT 2012


On Thu, Aug 9, 2012 at 10:34 AM, Marek Olšák <maraeo at gmail.com> wrote:
> Signed-off-by: Marek Olšák <maraeo at gmail.com>

Some comment inline that need a v2 at least for version otherwise

Reviewed-by: Jerome Glisse <jglisse at redhat.com>

> ---
>  drivers/gpu/drm/radeon/r600.c          |   12 +++++++++++
>  drivers/gpu/drm/radeon/r600d.h         |    3 +++
>  drivers/gpu/drm/radeon/radeon.h        |    1 +
>  drivers/gpu/drm/radeon/radeon_asic.h   |    2 ++
>  drivers/gpu/drm/radeon/radeon_device.c |    1 +
>  drivers/gpu/drm/radeon/radeon_drv.c    |    2 +-
>  drivers/gpu/drm/radeon/radeon_kms.c    |   35 ++++++++++++++++++++++++++------
>  drivers/gpu/drm/radeon/si.c            |   11 ++++++++++
>  drivers/gpu/drm/radeon/sid.h           |    3 +++
>  include/drm/radeon_drm.h               |    2 ++
>  10 files changed, 65 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
> index 637280f..be0e320 100644
> --- a/drivers/gpu/drm/radeon/r600.c
> +++ b/drivers/gpu/drm/radeon/r600.c
> @@ -3789,3 +3789,15 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
>                 WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
>         }
>  }
> +
> +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) << 32);

I keep forgeting about c type rules but i think you want 32ULL

> +       mutex_unlock(&rdev->gpu_clock_mutex);
> +       return clock;
> +}
> diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
> index 4b116ae..fd328f4 100644
> --- a/drivers/gpu/drm/radeon/r600d.h
> +++ b/drivers/gpu/drm/radeon/r600d.h
> @@ -602,6 +602,9 @@
>  #define RLC_HB_WPTR                                       0x3f1c
>  #define RLC_HB_WPTR_LSB_ADDR                              0x3f14
>  #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_UCODE_CNTL                                    0x3f48
>  #define RLC_UCODE_ADDR                                    0x3f2c
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 5431af2..150097f 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -1533,6 +1533,7 @@ struct radeon_device {
>         unsigned                debugfs_count;
>         /* virtual memory */
>         struct radeon_vm_manager        vm_manager;
> +       struct mutex                    gpu_clock_mutex;
>  };
>
>  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 f4af243..cbba387 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.h
> +++ b/drivers/gpu/drm/radeon/radeon_asic.h
> @@ -371,6 +371,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
>                         unsigned num_gpu_pages,
>                         struct radeon_sa_bo *vb);
>  int r600_mc_wait_for_idle(struct radeon_device *rdev);
> +uint64_t r600_get_gpu_clock(struct radeon_device *rdev);
>
>  /*
>   * rv770,rv730,rv710,rv740
> @@ -472,5 +473,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_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm);
>  int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
> +uint64_t si_get_gpu_clock(struct radeon_device *rdev);
>
>  #endif
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
> index 742af82..d2e2438 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,
>         atomic_set(&rdev->ih.lock, 0);
>         mutex_init(&rdev->gem.mutex);
>         mutex_init(&rdev->pm.mutex);
> +       mutex_init(&rdev->gpu_clock_mutex);
>         init_rwsem(&rdev->pm.mclk_lock);
>         init_rwsem(&rdev->exclusive_lock);
>         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 a7f8ac0..f940806 100644
> --- a/drivers/gpu/drm/radeon/radeon_drv.c
> +++ b/drivers/gpu/drm/radeon/radeon_drv.c
> @@ -60,7 +60,7 @@
>   *   2.16.0 - fix evergreen 2D tiled surface calculation
>   *   2.17.0 - add STRMOUT_BASE_UPDATE for r7xx
>   *   2.18.0 - r600-eg: allow "invalid" DB formats
> - *   2.19.0 - r600-eg: MSAA textures
> + *   2.19.0 - r600-eg: MSAA textures; r600-si: RADEON_INFO_TIMESTAMP query

Given the failure that have been the streamout one, i would prefer to
also bump the version for timestamp ie 2.20.0

>   */
>  #define KMS_DRIVER_MAJOR       2
>  #define KMS_DRIVER_MINOR       19
> diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
> index 1d73f16..414b4ac 100644
> --- a/drivers/gpu/drm/radeon/radeon_kms.c
> +++ b/drivers/gpu/drm/radeon/radeon_kms.c
> @@ -29,6 +29,7 @@
>  #include "drm_sarea.h"
>  #include "radeon.h"
>  #include "radeon_drm.h"
> +#include "radeon_asic.h"
>
>  #include <linux/vga_switcheroo.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)
>  {
>         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;
> -       uint32_t *value_ptr;
> -       uint32_t value;
> +       uint32_t value, *value_ptr;
> +       uint64_t value64, *value_ptr64;
>         struct drm_crtc *crtc;
>         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);
> -       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;
> +       }
>
>         switch (info->request) {
>         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;
>         }
>         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 0;
> diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
> index c053f81..0f177d5 100644
> --- a/drivers/gpu/drm/radeon/si.c
> +++ b/drivers/gpu/drm/radeon/si.c
> @@ -3960,3 +3960,14 @@ void si_fini(struct radeon_device *rdev)
>         rdev->bios = NULL;
>  }
>
> +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) << 32);
> +       mutex_unlock(&rdev->gpu_clock_mutex);
> +       return clock;
> +}
> diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
> index 7869089..ef4815c 100644
> --- a/drivers/gpu/drm/radeon/sid.h
> +++ b/drivers/gpu/drm/radeon/sid.h
> @@ -698,6 +698,9 @@
>  #define RLC_UCODE_ADDR                                    0xC32C
>  #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_UCODE_CNTL                                    0xC348
>
> diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
> index 5805686..dc3a8cd 100644
> --- a/include/drm/radeon_drm.h
> +++ b/include/drm/radeon_drm.h
> @@ -964,6 +964,8 @@ struct drm_radeon_cs {
>  #define RADEON_INFO_IB_VM_MAX_SIZE     0x0f
>  /* max pipes - needed for compute shaders */
>  #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 {
>         uint32_t                request;
> --
> 1.7.9.5
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list