lkml.org 
[lkml]   [2020]   [Nov]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.9 319/391] drm/amdgpu: vcn and jpeg ring synchronization
    Date
    From: Veerabadhran G <vegopala@amd.com>

    commit 187561dd76531945126b15c9486fec7cfa5f0415 upstream.

    Synchronize the ring usage for vcn1 and jpeg1 to workaround a hardware bug.

    Signed-off-by: Veerabadhran Gopalakrishnan <veerabadhran.gopalakrishnan@amd.com>
    Acked-by: Christian König <christian.koenig@amd.com>
    Reviewed-by: Christian König <christian.koenig@amd.com>
    Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 2 ++
    drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 1 +
    drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c | 24 ++++++++++++++++++++++--
    drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 28 ++++++++++++++++++++++++----
    drivers/gpu/drm/amd/amdgpu/vcn_v1_0.h | 3 ++-
    5 files changed, 51 insertions(+), 7 deletions(-)

    --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
    +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
    @@ -68,6 +68,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_dev

    INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
    mutex_init(&adev->vcn.vcn_pg_lock);
    + mutex_init(&adev->vcn.vcn1_jpeg1_workaround);
    atomic_set(&adev->vcn.total_submission_cnt, 0);
    for (i = 0; i < adev->vcn.num_vcn_inst; i++)
    atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
    @@ -237,6 +238,7 @@ int amdgpu_vcn_sw_fini(struct amdgpu_dev
    }

    release_firmware(adev->vcn.fw);
    + mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);
    mutex_destroy(&adev->vcn.vcn_pg_lock);

    return 0;
    --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
    +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
    @@ -220,6 +220,7 @@ struct amdgpu_vcn {
    struct amdgpu_vcn_inst inst[AMDGPU_MAX_VCN_INSTANCES];
    struct amdgpu_vcn_reg internal;
    struct mutex vcn_pg_lock;
    + struct mutex vcn1_jpeg1_workaround;
    atomic_t total_submission_cnt;

    unsigned harvest_config;
    --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v1_0.c
    @@ -33,6 +33,7 @@

    static void jpeg_v1_0_set_dec_ring_funcs(struct amdgpu_device *adev);
    static void jpeg_v1_0_set_irq_funcs(struct amdgpu_device *adev);
    +static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring);

    static void jpeg_v1_0_decode_ring_patch_wreg(struct amdgpu_ring *ring, uint32_t *ptr, uint32_t reg_offset, uint32_t val)
    {
    @@ -564,8 +565,8 @@ static const struct amdgpu_ring_funcs jp
    .insert_start = jpeg_v1_0_decode_ring_insert_start,
    .insert_end = jpeg_v1_0_decode_ring_insert_end,
    .pad_ib = amdgpu_ring_generic_pad_ib,
    - .begin_use = vcn_v1_0_ring_begin_use,
    - .end_use = amdgpu_vcn_ring_end_use,
    + .begin_use = jpeg_v1_0_ring_begin_use,
    + .end_use = vcn_v1_0_ring_end_use,
    .emit_wreg = jpeg_v1_0_decode_ring_emit_wreg,
    .emit_reg_wait = jpeg_v1_0_decode_ring_emit_reg_wait,
    .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
    @@ -586,3 +587,22 @@ static void jpeg_v1_0_set_irq_funcs(stru
    {
    adev->jpeg.inst->irq.funcs = &jpeg_v1_0_irq_funcs;
    }
    +
    +static void jpeg_v1_0_ring_begin_use(struct amdgpu_ring *ring)
    +{
    + struct amdgpu_device *adev = ring->adev;
    + bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
    + int cnt = 0;
    +
    + mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
    +
    + if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_dec))
    + DRM_ERROR("JPEG dec: vcn dec ring may not be empty\n");
    +
    + for (cnt = 0; cnt < adev->vcn.num_enc_rings; cnt++) {
    + if (amdgpu_fence_wait_empty(&adev->vcn.inst->ring_enc[cnt]))
    + DRM_ERROR("JPEG dec: vcn enc ring[%d] may not be empty\n", cnt);
    + }
    +
    + vcn_v1_0_set_pg_for_begin_use(ring, set_clocks);
    +}
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
    @@ -54,6 +54,7 @@ static int vcn_v1_0_pause_dpg_mode(struc
    int inst_idx, struct dpg_pause_state *new_state);

    static void vcn_v1_0_idle_work_handler(struct work_struct *work);
    +static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);

    /**
    * vcn_v1_0_early_init - set function pointers
    @@ -1804,11 +1805,24 @@ static void vcn_v1_0_idle_work_handler(s
    }
    }

    -void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
    +static void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
    {
    - struct amdgpu_device *adev = ring->adev;
    + struct amdgpu_device *adev = ring->adev;
    bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);

    + mutex_lock(&adev->vcn.vcn1_jpeg1_workaround);
    +
    + if (amdgpu_fence_wait_empty(&ring->adev->jpeg.inst->ring_dec))
    + DRM_ERROR("VCN dec: jpeg dec ring may not be empty\n");
    +
    + vcn_v1_0_set_pg_for_begin_use(ring, set_clocks);
    +
    +}
    +
    +void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks)
    +{
    + struct amdgpu_device *adev = ring->adev;
    +
    if (set_clocks) {
    amdgpu_gfx_off_ctrl(adev, false);
    if (adev->pm.dpm_enabled)
    @@ -1844,6 +1858,12 @@ void vcn_v1_0_ring_begin_use(struct amdg
    }
    }

    +void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring)
    +{
    + schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
    + mutex_unlock(&ring->adev->vcn.vcn1_jpeg1_workaround);
    +}
    +
    static const struct amd_ip_funcs vcn_v1_0_ip_funcs = {
    .name = "vcn_v1_0",
    .early_init = vcn_v1_0_early_init,
    @@ -1891,7 +1911,7 @@ static const struct amdgpu_ring_funcs vc
    .insert_end = vcn_v1_0_dec_ring_insert_end,
    .pad_ib = amdgpu_ring_generic_pad_ib,
    .begin_use = vcn_v1_0_ring_begin_use,
    - .end_use = amdgpu_vcn_ring_end_use,
    + .end_use = vcn_v1_0_ring_end_use,
    .emit_wreg = vcn_v1_0_dec_ring_emit_wreg,
    .emit_reg_wait = vcn_v1_0_dec_ring_emit_reg_wait,
    .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
    @@ -1923,7 +1943,7 @@ static const struct amdgpu_ring_funcs vc
    .insert_end = vcn_v1_0_enc_ring_insert_end,
    .pad_ib = amdgpu_ring_generic_pad_ib,
    .begin_use = vcn_v1_0_ring_begin_use,
    - .end_use = amdgpu_vcn_ring_end_use,
    + .end_use = vcn_v1_0_ring_end_use,
    .emit_wreg = vcn_v1_0_enc_ring_emit_wreg,
    .emit_reg_wait = vcn_v1_0_enc_ring_emit_reg_wait,
    .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
    --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.h
    +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.h
    @@ -24,7 +24,8 @@
    #ifndef __VCN_V1_0_H__
    #define __VCN_V1_0_H__

    -void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);
    +void vcn_v1_0_ring_end_use(struct amdgpu_ring *ring);
    +void vcn_v1_0_set_pg_for_begin_use(struct amdgpu_ring *ring, bool set_clocks);

    extern const struct amdgpu_ip_block_version vcn_v1_0_ip_block;


    \
     
     \ /
      Last update: 2020-11-03 22:49    [W:2.683 / U:1.404 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site