drm/amd/powerplay: add uploading pptable and resetting powerplay support
authorEric Huang <JinHuiEric.Huang@amd.com>
Wed, 1 Jun 2016 21:08:07 +0000 (17:08 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 7 Jul 2016 18:51:38 +0000 (14:51 -0400)
Necessary for re-initializing dpm with new pptables at runtime.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Eric Huang <JinHuiEric.Huang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h

index e931e87757de897a99702c8b38953aa1a7c525f0..f9e03ad0baa29faea18d5bd0fc123c9f7b769c88 100644 (file)
@@ -744,12 +744,12 @@ static int pp_dpm_get_pp_table(void *handle, char **table)
 
        PP_CHECK_HW(hwmgr);
 
-       if (hwmgr->hwmgr_func->get_pp_table == NULL) {
-               printk(KERN_INFO "%s was not implemented.\n", __func__);
-               return 0;
-       }
+       if (!hwmgr->soft_pp_table)
+               return -EINVAL;
+
+       *table = (char *)hwmgr->soft_pp_table;
 
-       return hwmgr->hwmgr_func->get_pp_table(hwmgr, table);
+       return hwmgr->soft_pp_table_size;
 }
 
 static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
@@ -763,12 +763,23 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size)
 
        PP_CHECK_HW(hwmgr);
 
-       if (hwmgr->hwmgr_func->set_pp_table == NULL) {
-               printk(KERN_INFO "%s was not implemented.\n", __func__);
-               return 0;
+       if (!hwmgr->hardcode_pp_table) {
+               hwmgr->hardcode_pp_table =
+                               kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL);
+
+               if (!hwmgr->hardcode_pp_table)
+                       return -ENOMEM;
+
+               /* to avoid powerplay crash when hardcode pptable is empty */
+               memcpy(hwmgr->hardcode_pp_table, hwmgr->soft_pp_table,
+                               hwmgr->soft_pp_table_size);
        }
 
-       return hwmgr->hwmgr_func->set_pp_table(hwmgr, buf, size);
+       memcpy(hwmgr->hardcode_pp_table, buf, size);
+
+       hwmgr->soft_pp_table = hwmgr->hardcode_pp_table;
+
+       return amd_powerplay_reset(handle);
 }
 
 static int pp_dpm_force_clock_level(void *handle,
@@ -993,6 +1004,44 @@ int amd_powerplay_fini(void *handle)
        return 0;
 }
 
+int amd_powerplay_reset(void *handle)
+{
+       struct pp_instance *instance = (struct pp_instance *)handle;
+       struct pp_eventmgr *eventmgr;
+       struct pem_event_data event_data = { {0} };
+       int ret;
+
+       if (instance == NULL)
+               return -EINVAL;
+
+       eventmgr = instance->eventmgr;
+       if (!eventmgr || !eventmgr->pp_eventmgr_fini)
+               return -EINVAL;
+
+       eventmgr->pp_eventmgr_fini(eventmgr);
+
+       ret = pp_sw_fini(handle);
+       if (ret)
+               return ret;
+
+       kfree(instance->hwmgr->ps);
+
+       ret = pp_sw_init(handle);
+       if (ret)
+               return ret;
+
+       hw_init_power_state_table(instance->hwmgr);
+
+       if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
+               return -EINVAL;
+
+       ret = eventmgr->pp_eventmgr_init(eventmgr);
+       if (ret)
+               return ret;
+
+       return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data);
+}
+
 /* export this function to DAL */
 
 int amd_powerplay_display_configuration_change(void *handle,
index 9ad25a8844e0a69e2352d12449771ae56d43e3b5..339a9361c5a51485de8e48b9dd966d3627d4e370 100644 (file)
@@ -95,6 +95,8 @@ int hwmgr_fini(struct pp_hwmgr *hwmgr)
                return -EINVAL;
 
        /* do hwmgr finish*/
+       kfree(hwmgr->hardcode_pp_table);
+
        kfree(hwmgr->backend);
 
        kfree(hwmgr->start_thermal_controller.function_list);
index d0dfaf9dfa06a738c2fc0968438fb39c9699ffbf..b764c8c05ec8127d64cc7b57ea233eb8cf581c3e 100644 (file)
@@ -360,6 +360,8 @@ int amd_powerplay_init(struct amd_pp_init *pp_init,
 
 int amd_powerplay_fini(void *handle);
 
+int amd_powerplay_reset(void *handle);
+
 int amd_powerplay_display_configuration_change(void *handle,
                const struct amd_pp_display_configuration *input);
 
index 8ef011e16b62a7917e8f585d28b2af22064c2eea..10e4787d56c1b126ca6ca550a31d1b117ff0c844 100644 (file)
@@ -584,6 +584,7 @@ struct pp_hwmgr {
        struct pp_smumgr *smumgr;
        const void *soft_pp_table;
        uint32_t soft_pp_table_size;
+       void *hardcode_pp_table;
        bool need_pp_table_upload;
        enum amd_dpm_forced_level dpm_level;
        bool block_hw_access;