diff mbox

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

Message ID CADnq5_M=75e0S76SWsqYum8ZrLmK4ge7na0wQy7sj=D=FXPhCA@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Alex Deucher Aug. 9, 2012, 3:44 p.m. UTC
On Thu, Aug 9, 2012 at 10:57 AM, Jerome Glisse <j.glisse@gmail.com> wrote:
> On Thu, Aug 9, 2012 at 10:34 AM, Marek Olšák <maraeo@gmail.com> wrote:
>> Signed-off-by: Marek Olšák <maraeo@gmail.com>
>
> Some comment inline that need a v2 at least for version otherwise

How about the attached updated patch?  I'd like to get this series in
the radeon drm-fixes pull.

Alex

>
> Reviewed-by: Jerome Glisse <jglisse@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@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

Comments

Jerome Glisse Aug. 9, 2012, 3:57 p.m. UTC | #1
On Thu, Aug 9, 2012 at 11:44 AM, Alex Deucher <alexdeucher@gmail.com> wrote:
> On Thu, Aug 9, 2012 at 10:57 AM, Jerome Glisse <j.glisse@gmail.com> wrote:
>> On Thu, Aug 9, 2012 at 10:34 AM, Marek Olšák <maraeo@gmail.com> wrote:
>>> Signed-off-by: Marek Olšák <maraeo@gmail.com>
>>
>> Some comment inline that need a v2 at least for version otherwise
>
> How about the attached updated patch?  I'd like to get this series in
> the radeon drm-fixes pull.
>
> Alex

Looks good to me

>>
>> Reviewed-by: Jerome Glisse <jglisse@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@lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

From 156c58ff876b8ee76f9a40ec00bf56d37197547b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= <maraeo@gmail.com>
Date: Thu, 9 Aug 2012 16:34:17 +0200
Subject: [PATCH] drm/radeon/kms: implement timestamp userspace query (v2)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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>
---
 drivers/gpu/drm/radeon/r600.c          |   20 ++++++++++++++++++
 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    |    3 +-
 drivers/gpu/drm/radeon/radeon_kms.c    |   35 ++++++++++++++++++++++++++-----
 drivers/gpu/drm/radeon/si.c            |   19 +++++++++++++++++
 drivers/gpu/drm/radeon/sid.h           |    3 ++
 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 637280f..d79c639 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)
 		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;
+}
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 b237a29..9930419 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1534,6 +1534,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 0d445e7..18c38d1 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,
 			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
@@ -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_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..d7269f4 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -61,9 +61,10 @@ 
  *   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.20.0 - r600-si: RADEON_INFO_TIMESTAMP query
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	19
+#define KMS_DRIVER_MINOR	20
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 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 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 c153a7f..0139e22 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)
 	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;
+}
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.7.5