--- /dev/null
+From 9a458402fb69bda886aa6cbe067311b6e3d9c52a Mon Sep 17 00:00:00 2001
+From: Jingwen Chen <Jingwen.Chen2@amd.com>
+Date: Thu, 13 Jan 2022 19:06:59 +0800
+Subject: drm/amd/amdgpu: fixing read wrong pf2vf data in SRIOV
+
+From: Jingwen Chen <Jingwen.Chen2@amd.com>
+
+commit 9a458402fb69bda886aa6cbe067311b6e3d9c52a upstream.
+
+[Why]
+This fixes 892deb48269c ("drm/amdgpu: Separate vf2pf work item init from virt data exchange").
+we should read pf2vf data based at mman.fw_vram_usage_va after gmc
+sw_init. commit 892deb48269c breaks this logic.
+
+[How]
+calling amdgpu_virt_exchange_data in amdgpu_virt_init_data_exchange to
+set the right base in the right sequence.
+
+v2:
+call amdgpu_virt_init_data_exchange after gmc sw_init to make data
+exchange workqueue run
+
+v3:
+clean up the code logic
+
+v4:
+add some comment and make the code more readable
+
+Fixes: 892deb48269c ("drm/amdgpu: Separate vf2pf work item init from virt data exchange")
+Signed-off-by: Jingwen Chen <Jingwen.Chen2@amd.com>
+Reviewed-by: Horace Chen <horace.chen@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +-
+ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 20 +++++++-------------
+ 2 files changed, 8 insertions(+), 14 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -2224,7 +2224,7 @@ static int amdgpu_device_ip_init(struct
+ }
+
+ if (amdgpu_sriov_vf(adev))
+- amdgpu_virt_exchange_data(adev);
++ amdgpu_virt_init_data_exchange(adev);
+
+ r = amdgpu_ib_pool_init(adev);
+ if (r) {
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+@@ -584,20 +584,20 @@ void amdgpu_virt_init_data_exchange(stru
+ adev->virt.fw_reserve.p_vf2pf = NULL;
+ adev->virt.vf2pf_update_interval_ms = 0;
+
+- if (adev->bios != NULL) {
+- adev->virt.vf2pf_update_interval_ms = 2000;
++ if (adev->mman.fw_vram_usage_va != NULL) {
++ /* go through this logic in ip_init and reset to init workqueue*/
++ amdgpu_virt_exchange_data(adev);
+
++ INIT_DELAYED_WORK(&adev->virt.vf2pf_work, amdgpu_virt_update_vf2pf_work_item);
++ schedule_delayed_work(&(adev->virt.vf2pf_work), msecs_to_jiffies(adev->virt.vf2pf_update_interval_ms));
++ } else if (adev->bios != NULL) {
++ /* got through this logic in early init stage to get necessary flags, e.g. rlcg_acc related*/
+ adev->virt.fw_reserve.p_pf2vf =
+ (struct amd_sriov_msg_pf2vf_info_header *)
+ (adev->bios + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10));
+
+ amdgpu_virt_read_pf2vf_data(adev);
+ }
+-
+- if (adev->virt.vf2pf_update_interval_ms != 0) {
+- INIT_DELAYED_WORK(&adev->virt.vf2pf_work, amdgpu_virt_update_vf2pf_work_item);
+- schedule_delayed_work(&(adev->virt.vf2pf_work), msecs_to_jiffies(adev->virt.vf2pf_update_interval_ms));
+- }
+ }
+
+
+@@ -633,12 +633,6 @@ void amdgpu_virt_exchange_data(struct am
+ if (adev->virt.ras_init_done)
+ amdgpu_virt_add_bad_page(adev, bp_block_offset, bp_block_size);
+ }
+- } else if (adev->bios != NULL) {
+- adev->virt.fw_reserve.p_pf2vf =
+- (struct amd_sriov_msg_pf2vf_info_header *)
+- (adev->bios + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10));
+-
+- amdgpu_virt_read_pf2vf_data(adev);
+ }
+ }
+