diff mbox

[2/2] drm/radeon: handle more than 10 UVD sessions

Message ID 1459971232-4648-2-git-send-email-leo.liu@amd.com (mailing list archive)
State New, archived
Headers show

Commit Message

Leo Liu April 6, 2016, 7:33 p.m. UTC
From: Arindam Nath <arindam.nath@amd.com>

Signed-off-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Arindam Nath <arindam.nath@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
---
 drivers/gpu/drm/radeon/cikd.h       |  1 +
 drivers/gpu/drm/radeon/radeon.h     |  9 ++++++---
 drivers/gpu/drm/radeon/radeon_uvd.c | 33 +++++++++++++++++++++++++--------
 drivers/gpu/drm/radeon/uvd_v1_0.c   |  5 +++--
 drivers/gpu/drm/radeon/uvd_v2_2.c   |  5 +++--
 drivers/gpu/drm/radeon/uvd_v4_2.c   |  8 ++++++--
 6 files changed, 44 insertions(+), 17 deletions(-)

Comments

Alex Deucher April 7, 2016, 2:17 p.m. UTC | #1
On Wed, Apr 6, 2016 at 3:33 PM, Leo Liu <leo.liu@amd.com> wrote:
> From: Arindam Nath <arindam.nath@amd.com>
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> Signed-off-by: Arindam Nath <arindam.nath@amd.com>
> Reviewed-by: Leo Liu <leo.liu@amd.com>

Applied the series.  Thanks!

Alex


> ---
>  drivers/gpu/drm/radeon/cikd.h       |  1 +
>  drivers/gpu/drm/radeon/radeon.h     |  9 ++++++---
>  drivers/gpu/drm/radeon/radeon_uvd.c | 33 +++++++++++++++++++++++++--------
>  drivers/gpu/drm/radeon/uvd_v1_0.c   |  5 +++--
>  drivers/gpu/drm/radeon/uvd_v2_2.c   |  5 +++--
>  drivers/gpu/drm/radeon/uvd_v4_2.c   |  8 ++++++--
>  6 files changed, 44 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
> index 391ff9d..cead228 100644
> --- a/drivers/gpu/drm/radeon/cikd.h
> +++ b/drivers/gpu/drm/radeon/cikd.h
> @@ -2071,6 +2071,7 @@
>  #define UVD_UDEC_DBW_ADDR_CONFIG       0xef54
>
>  #define UVD_LMI_EXT40_ADDR             0xf498
> +#define UVD_GP_SCRATCH4                        0xf4e0
>  #define UVD_LMI_ADDR_EXT               0xf594
>  #define UVD_VCPU_CACHE_OFFSET0         0xf608
>  #define UVD_VCPU_CACHE_SIZE0           0xf60c
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 34694ad..827e623 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -1669,15 +1669,18 @@ int radeon_pm_get_type_index(struct radeon_device *rdev,
>  /*
>   * UVD
>   */
> -#define RADEON_MAX_UVD_HANDLES 10
> -#define RADEON_UVD_STACK_SIZE  (1024*1024)
> -#define RADEON_UVD_HEAP_SIZE   (1024*1024)
> +#define RADEON_DEFAULT_UVD_HANDLES     10
> +#define RADEON_MAX_UVD_HANDLES         30
> +#define RADEON_UVD_STACK_SIZE          (200*1024)
> +#define RADEON_UVD_HEAP_SIZE           (256*1024)
> +#define RADEON_UVD_SESSION_SIZE                (50*1024)
>
>  struct radeon_uvd {
>         bool                    fw_header_present;
>         struct radeon_bo        *vcpu_bo;
>         void                    *cpu_addr;
>         uint64_t                gpu_addr;
> +       unsigned                max_handles;
>         atomic_t                handles[RADEON_MAX_UVD_HANDLES];
>         struct drm_file         *filp[RADEON_MAX_UVD_HANDLES];
>         unsigned                img_size[RADEON_MAX_UVD_HANDLES];
> diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
> index 0897c66..f8de6d0 100644
> --- a/drivers/gpu/drm/radeon/radeon_uvd.c
> +++ b/drivers/gpu/drm/radeon/radeon_uvd.c
> @@ -135,6 +135,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
>         }
>
>         rdev->uvd.fw_header_present = false;
> +       rdev->uvd.max_handles = RADEON_DEFAULT_UVD_HANDLES;
>         if (fw_name) {
>                 /* Let's try to load the newer firmware first */
>                 r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
> @@ -142,11 +143,27 @@ int radeon_uvd_init(struct radeon_device *rdev)
>                         dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
>                                 fw_name);
>                 } else {
> +                       struct common_firmware_header *hdr = (void *)rdev->uvd_fw->data;
> +                       unsigned version_major, version_minor, family_id;
> +
>                         r = radeon_ucode_validate(rdev->uvd_fw);
>                         if (r)
>                                 return r;
>
>                         rdev->uvd.fw_header_present = true;
> +
> +                       family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
> +                       version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
> +                       version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> +                       DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n",
> +                                version_major, version_minor, family_id);
> +
> +                       /*
> +                        * Limit the number of UVD handles depending on
> +                        * microcode major and minor versions.
> +                        */
> +                       if ((version_major >= 0x01) && (version_minor >= 0x37))
> +                               rdev->uvd.max_handles = RADEON_MAX_UVD_HANDLES;
>                 }
>         }
>
> @@ -166,7 +183,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
>
>         bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
>                   RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE +
> -                 RADEON_GPU_PAGE_SIZE;
> +                 RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles;
>         r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
>                              RADEON_GEM_DOMAIN_VRAM, 0, NULL,
>                              NULL, &rdev->uvd.vcpu_bo);
> @@ -199,7 +216,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
>
>         radeon_bo_unreserve(rdev->uvd.vcpu_bo);
>
> -       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +       for (i = 0; i < rdev->uvd.max_handles; ++i) {
>                 atomic_set(&rdev->uvd.handles[i], 0);
>                 rdev->uvd.filp[i] = NULL;
>                 rdev->uvd.img_size[i] = 0;
> @@ -236,7 +253,7 @@ int radeon_uvd_suspend(struct radeon_device *rdev)
>         if (rdev->uvd.vcpu_bo == NULL)
>                 return 0;
>
> -       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +       for (i = 0; i < rdev->uvd.max_handles; ++i) {
>                 uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
>                 if (handle != 0) {
>                         struct radeon_fence *fence;
> @@ -311,7 +328,7 @@ void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo,
>  void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
>  {
>         int i, r;
> -       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +       for (i = 0; i < rdev->uvd.max_handles; ++i) {
>                 uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
>                 if (handle != 0 && rdev->uvd.filp[i] == filp) {
>                         struct radeon_fence *fence;
> @@ -496,7 +513,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
>                         return r;
>
>                 /* try to alloc a new handle */
> -               for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +               for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
>                         if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
>                                 DRM_ERROR("Handle 0x%x already in use!\n", handle);
>                                 return -EINVAL;
> @@ -522,7 +539,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
>                         return r;
>
>                 /* validate the handle */
> -               for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +               for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
>                         if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
>                                 if (p->rdev->uvd.filp[i] != p->filp) {
>                                         DRM_ERROR("UVD handle collision detected!\n");
> @@ -537,7 +554,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
>
>         case 2:
>                 /* it's a destroy msg, free the handle */
> -               for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
> +               for (i = 0; i < p->rdev->uvd.max_handles; ++i)
>                         atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
>                 radeon_bo_kunmap(bo);
>                 return 0;
> @@ -834,7 +851,7 @@ static void radeon_uvd_count_handles(struct radeon_device *rdev,
>         *sd = 0;
>         *hd = 0;
>
> -       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +       for (i = 0; i < rdev->uvd.max_handles; ++i) {
>                 if (!atomic_read(&rdev->uvd.handles[i]))
>                         continue;
>
> diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c
> index c6b1cbc..ff471cb 100644
> --- a/drivers/gpu/drm/radeon/uvd_v1_0.c
> +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
> @@ -124,12 +124,13 @@ int uvd_v1_0_resume(struct radeon_device *rdev)
>         WREG32(UVD_VCPU_CACHE_SIZE0, size);
>
>         addr += size;
> -       size = RADEON_UVD_STACK_SIZE >> 3;
> +       size = RADEON_UVD_HEAP_SIZE >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE1, size);
>
>         addr += size;
> -       size = RADEON_UVD_HEAP_SIZE >> 3;
> +       size = (RADEON_UVD_STACK_SIZE +
> +              (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE2, size);
>
> diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c
> index 7ed778c..9071e65 100644
> --- a/drivers/gpu/drm/radeon/uvd_v2_2.c
> +++ b/drivers/gpu/drm/radeon/uvd_v2_2.c
> @@ -116,12 +116,13 @@ int uvd_v2_2_resume(struct radeon_device *rdev)
>         WREG32(UVD_VCPU_CACHE_SIZE0, size);
>
>         addr += size;
> -       size = RADEON_UVD_STACK_SIZE >> 3;
> +       size = RADEON_UVD_HEAP_SIZE >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE1, size);
>
>         addr += size;
> -       size = RADEON_UVD_HEAP_SIZE >> 3;
> +       size = (RADEON_UVD_STACK_SIZE +
> +              (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE2, size);
>
> diff --git a/drivers/gpu/drm/radeon/uvd_v4_2.c b/drivers/gpu/drm/radeon/uvd_v4_2.c
> index 205562f..91613b8 100644
> --- a/drivers/gpu/drm/radeon/uvd_v4_2.c
> +++ b/drivers/gpu/drm/radeon/uvd_v4_2.c
> @@ -53,12 +53,13 @@ int uvd_v4_2_resume(struct radeon_device *rdev)
>         WREG32(UVD_VCPU_CACHE_SIZE0, size);
>
>         addr += size;
> -       size = RADEON_UVD_STACK_SIZE >> 3;
> +       size = RADEON_UVD_HEAP_SIZE >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE1, size);
>
>         addr += size;
> -       size = RADEON_UVD_HEAP_SIZE >> 3;
> +       size = (RADEON_UVD_STACK_SIZE +
> +              (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE2, size);
>
> @@ -70,5 +71,8 @@ int uvd_v4_2_resume(struct radeon_device *rdev)
>         addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
>         WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
>
> +       if (rdev->uvd.fw_header_present)
> +               WREG32(UVD_GP_SCRATCH4, rdev->uvd.max_handles);
> +
>         return 0;
>  }
> --
> 1.9.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
Ayyappa Ch April 12, 2016, 12:10 p.m. UTC | #2
+                       if ((version_major >= 0x01) && (version_minor >= 0x37))
+                               rdev->uvd.max_handles = RADEON_MAX_UVD_HANDLES;

If major version greater than 01 no need to verify for minor version.

Can we modify like this?

                      if ((version_major > 0x01) ||
                              (version_major == 0x01 && version_minor >= 0x37)
                         )
                            rdev->uvd.max_handles = RADEON_MAX_UVD_HANDLES;

Thanks,
Ayyappa

On Thu, Apr 7, 2016 at 1:03 AM, Leo Liu <leo.liu@amd.com> wrote:
> From: Arindam Nath <arindam.nath@amd.com>
>
> Signed-off-by: Christian König <christian.koenig@amd.com>
> Signed-off-by: Arindam Nath <arindam.nath@amd.com>
> Reviewed-by: Leo Liu <leo.liu@amd.com>
> ---
>  drivers/gpu/drm/radeon/cikd.h       |  1 +
>  drivers/gpu/drm/radeon/radeon.h     |  9 ++++++---
>  drivers/gpu/drm/radeon/radeon_uvd.c | 33 +++++++++++++++++++++++++--------
>  drivers/gpu/drm/radeon/uvd_v1_0.c   |  5 +++--
>  drivers/gpu/drm/radeon/uvd_v2_2.c   |  5 +++--
>  drivers/gpu/drm/radeon/uvd_v4_2.c   |  8 ++++++--
>  6 files changed, 44 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
> index 391ff9d..cead228 100644
> --- a/drivers/gpu/drm/radeon/cikd.h
> +++ b/drivers/gpu/drm/radeon/cikd.h
> @@ -2071,6 +2071,7 @@
>  #define UVD_UDEC_DBW_ADDR_CONFIG       0xef54
>
>  #define UVD_LMI_EXT40_ADDR             0xf498
> +#define UVD_GP_SCRATCH4                        0xf4e0
>  #define UVD_LMI_ADDR_EXT               0xf594
>  #define UVD_VCPU_CACHE_OFFSET0         0xf608
>  #define UVD_VCPU_CACHE_SIZE0           0xf60c
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 34694ad..827e623 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -1669,15 +1669,18 @@ int radeon_pm_get_type_index(struct radeon_device *rdev,
>  /*
>   * UVD
>   */
> -#define RADEON_MAX_UVD_HANDLES 10
> -#define RADEON_UVD_STACK_SIZE  (1024*1024)
> -#define RADEON_UVD_HEAP_SIZE   (1024*1024)
> +#define RADEON_DEFAULT_UVD_HANDLES     10
> +#define RADEON_MAX_UVD_HANDLES         30
> +#define RADEON_UVD_STACK_SIZE          (200*1024)
> +#define RADEON_UVD_HEAP_SIZE           (256*1024)
> +#define RADEON_UVD_SESSION_SIZE                (50*1024)
>
>  struct radeon_uvd {
>         bool                    fw_header_present;
>         struct radeon_bo        *vcpu_bo;
>         void                    *cpu_addr;
>         uint64_t                gpu_addr;
> +       unsigned                max_handles;
>         atomic_t                handles[RADEON_MAX_UVD_HANDLES];
>         struct drm_file         *filp[RADEON_MAX_UVD_HANDLES];
>         unsigned                img_size[RADEON_MAX_UVD_HANDLES];
> diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
> index 0897c66..f8de6d0 100644
> --- a/drivers/gpu/drm/radeon/radeon_uvd.c
> +++ b/drivers/gpu/drm/radeon/radeon_uvd.c
> @@ -135,6 +135,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
>         }
>
>         rdev->uvd.fw_header_present = false;
> +       rdev->uvd.max_handles = RADEON_DEFAULT_UVD_HANDLES;
>         if (fw_name) {
>                 /* Let's try to load the newer firmware first */
>                 r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
> @@ -142,11 +143,27 @@ int radeon_uvd_init(struct radeon_device *rdev)
>                         dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
>                                 fw_name);
>                 } else {
> +                       struct common_firmware_header *hdr = (void *)rdev->uvd_fw->data;
> +                       unsigned version_major, version_minor, family_id;
> +
>                         r = radeon_ucode_validate(rdev->uvd_fw);
>                         if (r)
>                                 return r;
>
>                         rdev->uvd.fw_header_present = true;
> +
> +                       family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
> +                       version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
> +                       version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
> +                       DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n",
> +                                version_major, version_minor, family_id);
> +
> +                       /*
> +                        * Limit the number of UVD handles depending on
> +                        * microcode major and minor versions.
> +                        */
> +                       if ((version_major >= 0x01) && (version_minor >= 0x37))
> +                               rdev->uvd.max_handles = RADEON_MAX_UVD_HANDLES;
>                 }
>         }
>
> @@ -166,7 +183,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
>
>         bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
>                   RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE +
> -                 RADEON_GPU_PAGE_SIZE;
> +                 RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles;
>         r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
>                              RADEON_GEM_DOMAIN_VRAM, 0, NULL,
>                              NULL, &rdev->uvd.vcpu_bo);
> @@ -199,7 +216,7 @@ int radeon_uvd_init(struct radeon_device *rdev)
>
>         radeon_bo_unreserve(rdev->uvd.vcpu_bo);
>
> -       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +       for (i = 0; i < rdev->uvd.max_handles; ++i) {
>                 atomic_set(&rdev->uvd.handles[i], 0);
>                 rdev->uvd.filp[i] = NULL;
>                 rdev->uvd.img_size[i] = 0;
> @@ -236,7 +253,7 @@ int radeon_uvd_suspend(struct radeon_device *rdev)
>         if (rdev->uvd.vcpu_bo == NULL)
>                 return 0;
>
> -       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +       for (i = 0; i < rdev->uvd.max_handles; ++i) {
>                 uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
>                 if (handle != 0) {
>                         struct radeon_fence *fence;
> @@ -311,7 +328,7 @@ void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo,
>  void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
>  {
>         int i, r;
> -       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +       for (i = 0; i < rdev->uvd.max_handles; ++i) {
>                 uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
>                 if (handle != 0 && rdev->uvd.filp[i] == filp) {
>                         struct radeon_fence *fence;
> @@ -496,7 +513,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
>                         return r;
>
>                 /* try to alloc a new handle */
> -               for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +               for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
>                         if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
>                                 DRM_ERROR("Handle 0x%x already in use!\n", handle);
>                                 return -EINVAL;
> @@ -522,7 +539,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
>                         return r;
>
>                 /* validate the handle */
> -               for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +               for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
>                         if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
>                                 if (p->rdev->uvd.filp[i] != p->filp) {
>                                         DRM_ERROR("UVD handle collision detected!\n");
> @@ -537,7 +554,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
>
>         case 2:
>                 /* it's a destroy msg, free the handle */
> -               for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
> +               for (i = 0; i < p->rdev->uvd.max_handles; ++i)
>                         atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
>                 radeon_bo_kunmap(bo);
>                 return 0;
> @@ -834,7 +851,7 @@ static void radeon_uvd_count_handles(struct radeon_device *rdev,
>         *sd = 0;
>         *hd = 0;
>
> -       for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
> +       for (i = 0; i < rdev->uvd.max_handles; ++i) {
>                 if (!atomic_read(&rdev->uvd.handles[i]))
>                         continue;
>
> diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c
> index c6b1cbc..ff471cb 100644
> --- a/drivers/gpu/drm/radeon/uvd_v1_0.c
> +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
> @@ -124,12 +124,13 @@ int uvd_v1_0_resume(struct radeon_device *rdev)
>         WREG32(UVD_VCPU_CACHE_SIZE0, size);
>
>         addr += size;
> -       size = RADEON_UVD_STACK_SIZE >> 3;
> +       size = RADEON_UVD_HEAP_SIZE >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE1, size);
>
>         addr += size;
> -       size = RADEON_UVD_HEAP_SIZE >> 3;
> +       size = (RADEON_UVD_STACK_SIZE +
> +              (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE2, size);
>
> diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c
> index 7ed778c..9071e65 100644
> --- a/drivers/gpu/drm/radeon/uvd_v2_2.c
> +++ b/drivers/gpu/drm/radeon/uvd_v2_2.c
> @@ -116,12 +116,13 @@ int uvd_v2_2_resume(struct radeon_device *rdev)
>         WREG32(UVD_VCPU_CACHE_SIZE0, size);
>
>         addr += size;
> -       size = RADEON_UVD_STACK_SIZE >> 3;
> +       size = RADEON_UVD_HEAP_SIZE >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE1, size);
>
>         addr += size;
> -       size = RADEON_UVD_HEAP_SIZE >> 3;
> +       size = (RADEON_UVD_STACK_SIZE +
> +              (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE2, size);
>
> diff --git a/drivers/gpu/drm/radeon/uvd_v4_2.c b/drivers/gpu/drm/radeon/uvd_v4_2.c
> index 205562f..91613b8 100644
> --- a/drivers/gpu/drm/radeon/uvd_v4_2.c
> +++ b/drivers/gpu/drm/radeon/uvd_v4_2.c
> @@ -53,12 +53,13 @@ int uvd_v4_2_resume(struct radeon_device *rdev)
>         WREG32(UVD_VCPU_CACHE_SIZE0, size);
>
>         addr += size;
> -       size = RADEON_UVD_STACK_SIZE >> 3;
> +       size = RADEON_UVD_HEAP_SIZE >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE1, size);
>
>         addr += size;
> -       size = RADEON_UVD_HEAP_SIZE >> 3;
> +       size = (RADEON_UVD_STACK_SIZE +
> +              (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
>         WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
>         WREG32(UVD_VCPU_CACHE_SIZE2, size);
>
> @@ -70,5 +71,8 @@ int uvd_v4_2_resume(struct radeon_device *rdev)
>         addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
>         WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
>
> +       if (rdev->uvd.fw_header_present)
> +               WREG32(UVD_GP_SCRATCH4, rdev->uvd.max_handles);
> +
>         return 0;
>  }
> --
> 1.9.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h
index 391ff9d..cead228 100644
--- a/drivers/gpu/drm/radeon/cikd.h
+++ b/drivers/gpu/drm/radeon/cikd.h
@@ -2071,6 +2071,7 @@ 
 #define UVD_UDEC_DBW_ADDR_CONFIG	0xef54
 
 #define UVD_LMI_EXT40_ADDR		0xf498
+#define UVD_GP_SCRATCH4			0xf4e0
 #define UVD_LMI_ADDR_EXT		0xf594
 #define UVD_VCPU_CACHE_OFFSET0		0xf608
 #define UVD_VCPU_CACHE_SIZE0		0xf60c
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 34694ad..827e623 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1669,15 +1669,18 @@  int radeon_pm_get_type_index(struct radeon_device *rdev,
 /*
  * UVD
  */
-#define RADEON_MAX_UVD_HANDLES	10
-#define RADEON_UVD_STACK_SIZE	(1024*1024)
-#define RADEON_UVD_HEAP_SIZE	(1024*1024)
+#define RADEON_DEFAULT_UVD_HANDLES	10
+#define RADEON_MAX_UVD_HANDLES		30
+#define RADEON_UVD_STACK_SIZE		(200*1024)
+#define RADEON_UVD_HEAP_SIZE		(256*1024)
+#define RADEON_UVD_SESSION_SIZE		(50*1024)
 
 struct radeon_uvd {
 	bool			fw_header_present;
 	struct radeon_bo	*vcpu_bo;
 	void			*cpu_addr;
 	uint64_t		gpu_addr;
+	unsigned		max_handles;
 	atomic_t		handles[RADEON_MAX_UVD_HANDLES];
 	struct drm_file		*filp[RADEON_MAX_UVD_HANDLES];
 	unsigned		img_size[RADEON_MAX_UVD_HANDLES];
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 0897c66..f8de6d0 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -135,6 +135,7 @@  int radeon_uvd_init(struct radeon_device *rdev)
 	}
 
 	rdev->uvd.fw_header_present = false;
+	rdev->uvd.max_handles = RADEON_DEFAULT_UVD_HANDLES;
 	if (fw_name) {
 		/* Let's try to load the newer firmware first */
 		r = request_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
@@ -142,11 +143,27 @@  int radeon_uvd_init(struct radeon_device *rdev)
 			dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
 				fw_name);
 		} else {
+			struct common_firmware_header *hdr = (void *)rdev->uvd_fw->data;
+			unsigned version_major, version_minor, family_id;
+
 			r = radeon_ucode_validate(rdev->uvd_fw);
 			if (r)
 				return r;
 
 			rdev->uvd.fw_header_present = true;
+
+			family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
+			version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
+			version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
+			DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n",
+				 version_major, version_minor, family_id);
+
+			/*
+			 * Limit the number of UVD handles depending on
+			 * microcode major and minor versions.
+			 */
+			if ((version_major >= 0x01) && (version_minor >= 0x37))
+				rdev->uvd.max_handles = RADEON_MAX_UVD_HANDLES;
 		}
 	}
 
@@ -166,7 +183,7 @@  int radeon_uvd_init(struct radeon_device *rdev)
 
 	bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
 		  RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE +
-		  RADEON_GPU_PAGE_SIZE;
+		  RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles;
 	r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
 			     RADEON_GEM_DOMAIN_VRAM, 0, NULL,
 			     NULL, &rdev->uvd.vcpu_bo);
@@ -199,7 +216,7 @@  int radeon_uvd_init(struct radeon_device *rdev)
 
 	radeon_bo_unreserve(rdev->uvd.vcpu_bo);
 
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < rdev->uvd.max_handles; ++i) {
 		atomic_set(&rdev->uvd.handles[i], 0);
 		rdev->uvd.filp[i] = NULL;
 		rdev->uvd.img_size[i] = 0;
@@ -236,7 +253,7 @@  int radeon_uvd_suspend(struct radeon_device *rdev)
 	if (rdev->uvd.vcpu_bo == NULL)
 		return 0;
 
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < rdev->uvd.max_handles; ++i) {
 		uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
 		if (handle != 0) {
 			struct radeon_fence *fence;
@@ -311,7 +328,7 @@  void radeon_uvd_force_into_uvd_segment(struct radeon_bo *rbo,
 void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
 {
 	int i, r;
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < rdev->uvd.max_handles; ++i) {
 		uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
 		if (handle != 0 && rdev->uvd.filp[i] == filp) {
 			struct radeon_fence *fence;
@@ -496,7 +513,7 @@  static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 			return r;
 
 		/* try to alloc a new handle */
-		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+		for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
 			if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
 				DRM_ERROR("Handle 0x%x already in use!\n", handle);
 				return -EINVAL;
@@ -522,7 +539,7 @@  static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 			return r;
 
 		/* validate the handle */
-		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+		for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
 			if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
 				if (p->rdev->uvd.filp[i] != p->filp) {
 					DRM_ERROR("UVD handle collision detected!\n");
@@ -537,7 +554,7 @@  static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
 
 	case 2:
 		/* it's a destroy msg, free the handle */
-		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
+		for (i = 0; i < p->rdev->uvd.max_handles; ++i)
 			atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
 		radeon_bo_kunmap(bo);
 		return 0;
@@ -834,7 +851,7 @@  static void radeon_uvd_count_handles(struct radeon_device *rdev,
 	*sd = 0;
 	*hd = 0;
 
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < rdev->uvd.max_handles; ++i) {
 		if (!atomic_read(&rdev->uvd.handles[i]))
 			continue;
 
diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c
index c6b1cbc..ff471cb 100644
--- a/drivers/gpu/drm/radeon/uvd_v1_0.c
+++ b/drivers/gpu/drm/radeon/uvd_v1_0.c
@@ -124,12 +124,13 @@  int uvd_v1_0_resume(struct radeon_device *rdev)
 	WREG32(UVD_VCPU_CACHE_SIZE0, size);
 
 	addr += size;
-	size = RADEON_UVD_STACK_SIZE >> 3;
+	size = RADEON_UVD_HEAP_SIZE >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE1, size);
 
 	addr += size;
-	size = RADEON_UVD_HEAP_SIZE >> 3;
+	size = (RADEON_UVD_STACK_SIZE +
+	       (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE2, size);
 
diff --git a/drivers/gpu/drm/radeon/uvd_v2_2.c b/drivers/gpu/drm/radeon/uvd_v2_2.c
index 7ed778c..9071e65 100644
--- a/drivers/gpu/drm/radeon/uvd_v2_2.c
+++ b/drivers/gpu/drm/radeon/uvd_v2_2.c
@@ -116,12 +116,13 @@  int uvd_v2_2_resume(struct radeon_device *rdev)
 	WREG32(UVD_VCPU_CACHE_SIZE0, size);
 
 	addr += size;
-	size = RADEON_UVD_STACK_SIZE >> 3;
+	size = RADEON_UVD_HEAP_SIZE >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE1, size);
 
 	addr += size;
-	size = RADEON_UVD_HEAP_SIZE >> 3;
+	size = (RADEON_UVD_STACK_SIZE +
+	       (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE2, size);
 
diff --git a/drivers/gpu/drm/radeon/uvd_v4_2.c b/drivers/gpu/drm/radeon/uvd_v4_2.c
index 205562f..91613b8 100644
--- a/drivers/gpu/drm/radeon/uvd_v4_2.c
+++ b/drivers/gpu/drm/radeon/uvd_v4_2.c
@@ -53,12 +53,13 @@  int uvd_v4_2_resume(struct radeon_device *rdev)
 	WREG32(UVD_VCPU_CACHE_SIZE0, size);
 
 	addr += size;
-	size = RADEON_UVD_STACK_SIZE >> 3;
+	size = RADEON_UVD_HEAP_SIZE >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE1, size);
 
 	addr += size;
-	size = RADEON_UVD_HEAP_SIZE >> 3;
+	size = (RADEON_UVD_STACK_SIZE +
+	       (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE2, size);
 
@@ -70,5 +71,8 @@  int uvd_v4_2_resume(struct radeon_device *rdev)
 	addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
 	WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
 
+	if (rdev->uvd.fw_header_present)
+		WREG32(UVD_GP_SCRATCH4, rdev->uvd.max_handles);
+
 	return 0;
 }