[PATCH] drm/radeon: Adding UVD handle basis fps estimation v2
Christian König
deathsimple at vodafone.de
Thu Aug 7 08:32:26 PDT 2014
Am 07.08.2014 um 16:32 schrieb Alex Deucher:
> On Thu, Aug 7, 2014 at 7:33 AM, Christian König <deathsimple at vodafone.de> wrote:
>> From: Marco A Benatto <marco.antonio.780 at gmail.com>
>>
>> Adding a Frames Per Second estimation logic on UVD handles
>> when it has being used. This estimation is per handle basis
>> and will help on DPM profile calculation.
>>
>> v2 (chk): fix timestamp type, move functions around and
>> cleanup code a bit.
> Will this really help much? I thought the problem was mainly due to
> sclk and mclk for post processing.
It should at least handle the UVD side for upclocking when you get a lot
of streams / fps. And at on my NI the patch seems to do exactly that.
Switching sclk and mclk for post processing is a different task, and I
actually have no idea what to do with them.
Christian.
>
> Alex
>
>> Signed-off-by: Marco A Benatto <marco.antonio.780 at gmail.com>
>> Signed-off-by: Christian König <christian.koenig at amd.com>
>> ---
>> drivers/gpu/drm/radeon/radeon.h | 10 ++++++
>> drivers/gpu/drm/radeon/radeon_uvd.c | 64 +++++++++++++++++++++++++++++++++----
>> 2 files changed, 68 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
>> index 9e1732e..e92f6cb 100644
>> --- a/drivers/gpu/drm/radeon/radeon.h
>> +++ b/drivers/gpu/drm/radeon/radeon.h
>> @@ -1617,6 +1617,15 @@ int radeon_pm_get_type_index(struct radeon_device *rdev,
>> #define RADEON_UVD_STACK_SIZE (1024*1024)
>> #define RADEON_UVD_HEAP_SIZE (1024*1024)
>>
>> +#define RADEON_UVD_FPS_EVENTS_MAX 8
>> +#define RADEON_UVD_DEFAULT_FPS 60
>> +
>> +struct radeon_uvd_fps {
>> + uint64_t timestamp;
>> + uint8_t event_index;
>> + uint8_t events[RADEON_UVD_FPS_EVENTS_MAX];
>> +};
>> +
>> struct radeon_uvd {
>> struct radeon_bo *vcpu_bo;
>> void *cpu_addr;
>> @@ -1626,6 +1635,7 @@ struct radeon_uvd {
>> struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
>> unsigned img_size[RADEON_MAX_UVD_HANDLES];
>> struct delayed_work idle_work;
>> + struct radeon_uvd_fps fps_info[RADEON_MAX_UVD_HANDLES];
>> };
>>
>> int radeon_uvd_init(struct radeon_device *rdev);
>> diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
>> index 6bf55ec..ef5667a 100644
>> --- a/drivers/gpu/drm/radeon/radeon_uvd.c
>> +++ b/drivers/gpu/drm/radeon/radeon_uvd.c
>> @@ -237,6 +237,51 @@ void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo)
>> rbo->placement.lpfn = (256 * 1024 * 1024) >> PAGE_SHIFT;
>> }
>>
>> +static void radeon_uvd_fps_clear_events(struct radeon_device *rdev, int idx)
>> +{
>> + struct radeon_uvd_fps *fps = &rdev->uvd.fps_info[idx];
>> + unsigned i;
>> +
>> + fps->timestamp = jiffies_64;
>> + fps->event_index = 0;
>> + for (i = 0; i < RADEON_UVD_FPS_EVENTS_MAX; i++)
>> + fps->events[i] = 0;
>> +}
>> +
>> +static void radeon_uvd_fps_note_event(struct radeon_device *rdev, int idx)
>> +{
>> + struct radeon_uvd_fps *fps = &rdev->uvd.fps_info[idx];
>> + uint64_t timestamp = jiffies_64;
>> + unsigned rate = 0;
>> +
>> + uint8_t index = fps->event_index++;
>> + fps->event_index %= RADEON_UVD_FPS_EVENTS_MAX;
>> +
>> + rate = div64_u64(HZ, max(timestamp - fps->timestamp, 1ULL));
>> +
>> + fps->timestamp = timestamp;
>> + fps->events[index] = min(rate, 120u);
>> +}
>> +
>> +static unsigned radeon_uvd_estimate_fps(struct radeon_device *rdev, int idx)
>> +{
>> + struct radeon_uvd_fps *fps = &rdev->uvd.fps_info[idx];
>> + unsigned i, valid = 0, count = 0;
>> +
>> + for (i = 0; i < RADEON_UVD_FPS_EVENTS_MAX; i++) {
>> + /* We should ignore zero values */
>> + if (fps->events[i] != 0) {
>> + count += fps->events[i];
>> + valid++;
>> + }
>> + }
>> +
>> + if (valid > 0)
>> + return count / valid;
>> + else
>> + return RADEON_UVD_DEFAULT_FPS;
>> +}
>> +
>> void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
>> {
>> int i, r;
>> @@ -419,8 +464,10 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
>>
>> /* create or decode, validate the handle */
>> for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
>> - if (atomic_read(&p->rdev->uvd.handles[i]) == handle)
>> + if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
>> + radeon_uvd_fps_note_event(p->rdev, i);
>> return 0;
>> + }
>> }
>>
>> /* handle not found try to alloc a new one */
>> @@ -428,6 +475,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
>> if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
>> p->rdev->uvd.filp[i] = p->filp;
>> p->rdev->uvd.img_size[i] = img_size;
>> + radeon_uvd_fps_clear_events(p->rdev, i);
>> return 0;
>> }
>> }
>> @@ -763,7 +811,7 @@ int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring,
>> static void radeon_uvd_count_handles(struct radeon_device *rdev,
>> unsigned *sd, unsigned *hd)
>> {
>> - unsigned i;
>> + unsigned i, fps_rate = 0;
>>
>> *sd = 0;
>> *hd = 0;
>> @@ -772,10 +820,13 @@ static void radeon_uvd_count_handles(struct radeon_device *rdev,
>> if (!atomic_read(&rdev->uvd.handles[i]))
>> continue;
>>
>> - if (rdev->uvd.img_size[i] >= 720*576)
>> - ++(*hd);
>> - else
>> - ++(*sd);
>> + fps_rate = radeon_uvd_estimate_fps(rdev, i);
>> +
>> + if (rdev->uvd.img_size[i] >= 720*576) {
>> + (*hd) += fps_rate > 30 ? 1 : 2;
>> + } else {
>> + (*sd) += fps_rate > 30 ? 1 : 2;
>> + }
>> }
>> }
>>
>> @@ -805,6 +856,7 @@ void radeon_uvd_note_usage(struct radeon_device *rdev)
>> set_clocks &= schedule_delayed_work(&rdev->uvd.idle_work,
>> msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS));
>>
>> +
>> if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
>> unsigned hd = 0, sd = 0;
>> radeon_uvd_count_handles(rdev, &sd, &hd);
>> --
>> 1.9.1
>>
More information about the dri-devel
mailing list