Merge branch 'drm-fixes-5.2' of git://people.freedesktop.org/~agd5f/linux into drm...
authorDave Airlie <airlied@redhat.com>
Thu, 6 Jun 2019 01:53:13 +0000 (11:53 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 6 Jun 2019 01:53:36 +0000 (11:53 +1000)
- A fix to make VCE resume more reliable
- Updates for new raven variants

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexdeucher@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190605182332.4073-1-alexander.deucher@amd.com
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h

index cc8ad3831982d5e2e4dfa60ec76581fb9a3d777c..f4ac632a87b278d09a462bdfe4f145934f249884 100644 (file)
@@ -1589,6 +1589,7 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev)
 {
        int r = 0;
        int i;
+       uint32_t smu_version;
 
        if (adev->asic_type >= CHIP_VEGA10) {
                for (i = 0; i < adev->num_ip_blocks; i++) {
@@ -1614,16 +1615,9 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev)
                        }
                }
        }
+       r = amdgpu_pm_load_smu_firmware(adev, &smu_version);
 
-       if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) {
-               r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle);
-               if (r) {
-                       pr_err("firmware loading failed\n");
-                       return r;
-               }
-       }
-
-       return 0;
+       return r;
 }
 
 /**
index 34471dbaa872ad9d7b18c669a95c2fcd758def83..039cfa2ec89d9d9ada32d9a97731ac6204e8de95 100644 (file)
@@ -2490,6 +2490,21 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
 
 }
 
+int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version)
+{
+       int r = -EINVAL;
+
+       if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) {
+               r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle);
+               if (r) {
+                       pr_err("smu firmware loading failed\n");
+                       return r;
+               }
+               *smu_version = adev->pm.fw_version;
+       }
+       return r;
+}
+
 int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 {
        struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
index f21a7716b90e67b7cdd184046a107153bc49d19a..7ff0e7621fffb3ea1ab2f93ddaa94ea0578bb9c8 100644 (file)
@@ -34,6 +34,7 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev);
 int amdgpu_pm_sysfs_init(struct amdgpu_device *adev);
 void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev);
 void amdgpu_pm_print_power_states(struct amdgpu_device *adev);
+int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version);
 void amdgpu_pm_compute_clocks(struct amdgpu_device *adev);
 void amdgpu_dpm_thermal_work_handler(struct work_struct *work);
 void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable);
index c021b114c8a44ec04c6ca3bccc4479c141218232..f7189e22f6b7081ae45762e904a72343e09fd534 100644 (file)
@@ -1072,7 +1072,7 @@ void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
 int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
-       uint32_t rptr = amdgpu_ring_get_rptr(ring);
+       uint32_t rptr;
        unsigned i;
        int r, timeout = adev->usec_timeout;
 
@@ -1084,6 +1084,8 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
        if (r)
                return r;
 
+       rptr = amdgpu_ring_get_rptr(ring);
+
        amdgpu_ring_write(ring, VCE_CMD_END);
        amdgpu_ring_commit(ring);
 
index ba67d10232643cb9963c2b58954fd00cbaaa67ae..b610e3b30d95a2a0d2b03e68ff8ef0e15ef13ae2 100644 (file)
@@ -28,6 +28,7 @@
 #include "soc15.h"
 #include "soc15d.h"
 #include "amdgpu_atomfirmware.h"
+#include "amdgpu_pm.h"
 
 #include "gc/gc_9_0_offset.h"
 #include "gc/gc_9_0_sh_mask.h"
@@ -96,6 +97,7 @@ MODULE_FIRMWARE("amdgpu/raven2_me.bin");
 MODULE_FIRMWARE("amdgpu/raven2_mec.bin");
 MODULE_FIRMWARE("amdgpu/raven2_mec2.bin");
 MODULE_FIRMWARE("amdgpu/raven2_rlc.bin");
+MODULE_FIRMWARE("amdgpu/raven_kicker_rlc.bin");
 
 static const struct soc15_reg_golden golden_settings_gc_9_0[] =
 {
@@ -588,7 +590,8 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
        case CHIP_RAVEN:
                if (adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
                        break;
-               if ((adev->gfx.rlc_fw_version < 531) ||
+               if ((adev->gfx.rlc_fw_version != 106 &&
+                    adev->gfx.rlc_fw_version < 531) ||
                    (adev->gfx.rlc_fw_version == 53815) ||
                    (adev->gfx.rlc_feature_version < 1) ||
                    !adev->gfx.rlc.is_rlc_v2_1)
@@ -612,6 +615,7 @@ static int gfx_v9_0_init_microcode(struct amdgpu_device *adev)
        unsigned int i = 0;
        uint16_t version_major;
        uint16_t version_minor;
+       uint32_t smu_version;
 
        DRM_DEBUG("\n");
 
@@ -682,6 +686,12 @@ static int gfx_v9_0_init_microcode(struct amdgpu_device *adev)
                (((adev->pdev->revision >= 0xC8) && (adev->pdev->revision <= 0xCF)) ||
                ((adev->pdev->revision >= 0xD8) && (adev->pdev->revision <= 0xDF))))
                snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc_am4.bin", chip_name);
+       else if (!strcmp(chip_name, "raven") && (amdgpu_pm_load_smu_firmware(adev, &smu_version) == 0) &&
+               (smu_version >= 0x41e2b))
+               /**
+               *SMC is loaded by SBIOS on APU and it's able to get the SMU version directly.
+               */
+               snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_kicker_rlc.bin", chip_name);
        else
                snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
        err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
index 6cd6497c6fc21d3e935c4274de9d31048de2ee9f..f1d326caf69e1b6378cb89ae701758f8bede5c0a 100644 (file)
@@ -92,6 +92,7 @@ int hwmgr_early_init(struct pp_hwmgr *hwmgr)
        hwmgr_set_user_specify_caps(hwmgr);
        hwmgr->fan_ctrl_is_in_default_mode = true;
        hwmgr_init_workload_prority(hwmgr);
+       hwmgr->gfxoff_state_changed_by_workload = false;
 
        switch (hwmgr->chip_family) {
        case AMDGPU_FAMILY_CI:
index 9a595f7525e6b61fa81100e66bfe1538c4d45622..e32ae9d3373ca3e45fcea4a793be0d3951adf2a5 100644 (file)
@@ -1258,21 +1258,46 @@ static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        return size;
 }
 
+static bool smu10_is_raven1_refresh(struct pp_hwmgr *hwmgr)
+{
+       struct amdgpu_device *adev = hwmgr->adev;
+       if ((adev->asic_type == CHIP_RAVEN) &&
+           (adev->rev_id != 0x15d8) &&
+           (hwmgr->smu_version >= 0x41e2b))
+               return true;
+       else
+               return false;
+}
+
 static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
 {
        int workload_type = 0;
+       int result = 0;
 
        if (input[size] > PP_SMC_POWER_PROFILE_COMPUTE) {
                pr_err("Invalid power profile mode %ld\n", input[size]);
                return -EINVAL;
        }
-       hwmgr->power_profile_mode = input[size];
+       if (hwmgr->power_profile_mode == input[size])
+               return 0;
 
        /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
        workload_type =
-               conv_power_profile_to_pplib_workload(hwmgr->power_profile_mode);
-       smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ActiveProcessNotify,
+               conv_power_profile_to_pplib_workload(input[size]);
+       if (workload_type &&
+           smu10_is_raven1_refresh(hwmgr) &&
+           !hwmgr->gfxoff_state_changed_by_workload) {
+               smu10_gfx_off_control(hwmgr, false);
+               hwmgr->gfxoff_state_changed_by_workload = true;
+       }
+       result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ActiveProcessNotify,
                                                1 << workload_type);
+       if (!result)
+               hwmgr->power_profile_mode = input[size];
+       if (workload_type && hwmgr->gfxoff_state_changed_by_workload) {
+               smu10_gfx_off_control(hwmgr, true);
+               hwmgr->gfxoff_state_changed_by_workload = false;
+       }
 
        return 0;
 }
index bac3d85e3b82ce02a5ee91ab52c5064c04f8273a..c92999aac07c9984d39a8314be242d977606b439 100644 (file)
@@ -782,6 +782,7 @@ struct pp_hwmgr {
        uint32_t workload_mask;
        uint32_t workload_prority[Workload_Policy_Max];
        uint32_t workload_setting[Workload_Policy_Max];
+       bool gfxoff_state_changed_by_workload;
 };
 
 int hwmgr_early_init(struct pp_hwmgr *hwmgr);