Commit c7429b3a authored by Rex Zhu's avatar Rex Zhu Committed by Alex Deucher

drm/amd/pp: Add struct profile_mode_setting for smu7

Move configurable profiling parameters to struct
profile_mode_setting and initialize current_profile_setting.
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarRex Zhu <Rex.Zhu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 527d9427
...@@ -1484,8 +1484,6 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) ...@@ -1484,8 +1484,6 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
data->dll_default_on = false; data->dll_default_on = false;
data->mclk_dpm0_activity_target = 0xa; data->mclk_dpm0_activity_target = 0xa;
data->mclk_activity_target = SMU7_MCLK_TARGETACTIVITY_DFLT;
data->sclk_activity_target = SMU7_SCLK_TARGETACTIVITY_DFLT;
data->vddc_vddgfx_delta = 300; data->vddc_vddgfx_delta = 300;
data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT; data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT;
data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT; data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT;
...@@ -1509,6 +1507,14 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) ...@@ -1509,6 +1507,14 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
data->enable_pkg_pwr_tracking_feature = true; data->enable_pkg_pwr_tracking_feature = true;
data->force_pcie_gen = PP_PCIEGenInvalid; data->force_pcie_gen = PP_PCIEGenInvalid;
data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false; data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false;
data->current_profile_setting.bupdate_sclk = 1;
data->current_profile_setting.sclk_up_hyst = 0;
data->current_profile_setting.sclk_down_hyst = 100;
data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT;
data->current_profile_setting.bupdate_sclk = 1;
data->current_profile_setting.mclk_up_hyst = 0;
data->current_profile_setting.mclk_down_hyst = 100;
data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT;
if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) { if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) {
uint8_t tmp1, tmp2; uint8_t tmp1, tmp2;
......
...@@ -186,6 +186,17 @@ struct smu7_odn_dpm_table { ...@@ -186,6 +186,17 @@ struct smu7_odn_dpm_table {
uint32_t odn_mclk_min_limit; uint32_t odn_mclk_min_limit;
}; };
struct profile_mode_setting {
uint8_t bupdate_sclk;
uint8_t sclk_up_hyst;
uint8_t sclk_down_hyst;
uint16_t sclk_activity;
uint8_t bupdate_mclk;
uint8_t mclk_up_hyst;
uint8_t mclk_down_hyst;
uint16_t mclk_activity;
};
struct smu7_hwmgr { struct smu7_hwmgr {
struct smu7_dpm_table dpm_table; struct smu7_dpm_table dpm_table;
struct smu7_dpm_table golden_dpm_table; struct smu7_dpm_table golden_dpm_table;
...@@ -289,8 +300,6 @@ struct smu7_hwmgr { ...@@ -289,8 +300,6 @@ struct smu7_hwmgr {
struct smu7_pcie_perf_range pcie_lane_power_saving; struct smu7_pcie_perf_range pcie_lane_power_saving;
bool use_pcie_performance_levels; bool use_pcie_performance_levels;
bool use_pcie_power_saving_levels; bool use_pcie_power_saving_levels;
uint16_t mclk_activity_target;
uint16_t sclk_activity_target;
uint32_t mclk_dpm0_activity_target; uint32_t mclk_dpm0_activity_target;
uint32_t low_sclk_interrupt_threshold; uint32_t low_sclk_interrupt_threshold;
uint32_t last_mclk_dpm_enable_mask; uint32_t last_mclk_dpm_enable_mask;
...@@ -316,6 +325,8 @@ struct smu7_hwmgr { ...@@ -316,6 +325,8 @@ struct smu7_hwmgr {
uint16_t mem_latency_high; uint16_t mem_latency_high;
uint16_t mem_latency_low; uint16_t mem_latency_low;
uint32_t vr_config; uint32_t vr_config;
struct profile_mode_setting custom_profile_setting;
struct profile_mode_setting current_profile_setting;
}; };
/* To convert to Q8.8 format for firmware */ /* To convert to Q8.8 format for firmware */
......
...@@ -444,8 +444,8 @@ static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr, ...@@ -444,8 +444,8 @@ static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
level->EnabledForActivity = 0; level->EnabledForActivity = 0;
/* this level can be used for throttling.*/ /* this level can be used for throttling.*/
level->EnabledForThrottle = 1; level->EnabledForThrottle = 1;
level->UpH = 0; level->UpH = data->current_profile_setting.sclk_up_hyst;
level->DownH = 0; level->DownH = data->current_profile_setting.sclk_down_hyst;
level->VoltageDownH = 0; level->VoltageDownH = 0;
level->PowerThrottle = 0; level->PowerThrottle = 0;
...@@ -492,7 +492,7 @@ static int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) ...@@ -492,7 +492,7 @@ static int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) { for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = ci_populate_single_graphic_level(hwmgr, result = ci_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value, dpm_table->sclk_table.dpm_levels[i].value,
data->sclk_activity_target, data->current_profile_setting.sclk_activity,
&levels[i]); &levels[i]);
if (result) if (result)
return result; return result;
...@@ -1226,12 +1226,12 @@ static int ci_populate_single_memory_level( ...@@ -1226,12 +1226,12 @@ static int ci_populate_single_memory_level(
memory_level->EnabledForThrottle = 1; memory_level->EnabledForThrottle = 1;
memory_level->EnabledForActivity = 1; memory_level->EnabledForActivity = 1;
memory_level->UpH = 0; memory_level->UpH = data->current_profile_setting.mclk_up_hyst;
memory_level->DownH = 100; memory_level->DownH = data->current_profile_setting.mclk_down_hyst;
memory_level->VoltageDownH = 0; memory_level->VoltageDownH = 0;
/* Indicates maximum activity level for this performance level.*/ /* Indicates maximum activity level for this performance level.*/
memory_level->ActivityLevel = data->mclk_activity_target; memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
memory_level->StutterEnable = 0; memory_level->StutterEnable = 0;
memory_level->StrobeEnable = 0; memory_level->StrobeEnable = 0;
memory_level->EdcReadEnable = 0; memory_level->EdcReadEnable = 0;
...@@ -1515,7 +1515,7 @@ static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, ...@@ -1515,7 +1515,7 @@ static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownH = 100; table->MemoryACPILevel.DownH = 100;
table->MemoryACPILevel.VoltageDownH = 0; table->MemoryACPILevel.VoltageDownH = 0;
/* Indicates maximum activity level for this performance level.*/ /* Indicates maximum activity level for this performance level.*/
table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->mclk_activity_target); table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = 0; table->MemoryACPILevel.StutterEnable = 0;
table->MemoryACPILevel.StrobeEnable = 0; table->MemoryACPILevel.StrobeEnable = 0;
......
...@@ -1001,8 +1001,8 @@ static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr, ...@@ -1001,8 +1001,8 @@ static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
level->CcPwrDynRm1 = 0; level->CcPwrDynRm1 = 0;
level->EnabledForActivity = 0; level->EnabledForActivity = 0;
level->EnabledForThrottle = 1; level->EnabledForThrottle = 1;
level->UpHyst = 10; level->UpHyst = data->current_profile_setting.sclk_up_hyst;
level->DownHyst = 0; level->DownHyst = data->current_profile_setting.sclk_down_hyst;
level->VoltageDownHyst = 0; level->VoltageDownHyst = 0;
level->PowerThrottle = 0; level->PowerThrottle = 0;
...@@ -1059,7 +1059,7 @@ static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) ...@@ -1059,7 +1059,7 @@ static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) { for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = fiji_populate_single_graphic_level(hwmgr, result = fiji_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value, dpm_table->sclk_table.dpm_levels[i].value,
data->sclk_activity_target, data->current_profile_setting.sclk_activity,
&levels[i]); &levels[i]);
if (result) if (result)
return result; return result;
...@@ -1222,10 +1222,10 @@ static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr, ...@@ -1222,10 +1222,10 @@ static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr,
mem_level->EnabledForThrottle = 1; mem_level->EnabledForThrottle = 1;
mem_level->EnabledForActivity = 0; mem_level->EnabledForActivity = 0;
mem_level->UpHyst = 0; mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
mem_level->DownHyst = 100; mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
mem_level->VoltageDownHyst = 0; mem_level->VoltageDownHyst = 0;
mem_level->ActivityLevel = data->mclk_activity_target; mem_level->ActivityLevel = data->current_profile_setting.mclk_activity;
mem_level->StutterEnable = false; mem_level->StutterEnable = false;
mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
...@@ -1443,7 +1443,7 @@ static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, ...@@ -1443,7 +1443,7 @@ static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownHyst = 100; table->MemoryACPILevel.DownHyst = 100;
table->MemoryACPILevel.VoltageDownHyst = 0; table->MemoryACPILevel.VoltageDownHyst = 0;
table->MemoryACPILevel.ActivityLevel = table->MemoryACPILevel.ActivityLevel =
PP_HOST_TO_SMC_US(data->mclk_activity_target); PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = false; table->MemoryACPILevel.StutterEnable = false;
CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
......
...@@ -928,8 +928,8 @@ static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr, ...@@ -928,8 +928,8 @@ static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
graphic_level->EnabledForActivity = 0; graphic_level->EnabledForActivity = 0;
/* this level can be used for throttling.*/ /* this level can be used for throttling.*/
graphic_level->EnabledForThrottle = 1; graphic_level->EnabledForThrottle = 1;
graphic_level->UpHyst = 0; graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst;
graphic_level->DownHyst = 100; graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst;
graphic_level->VoltageDownHyst = 0; graphic_level->VoltageDownHyst = 0;
graphic_level->PowerThrottle = 0; graphic_level->PowerThrottle = 0;
...@@ -985,7 +985,7 @@ static int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) ...@@ -985,7 +985,7 @@ static int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) { for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = iceland_populate_single_graphic_level(hwmgr, result = iceland_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value, dpm_table->sclk_table.dpm_levels[i].value,
data->sclk_activity_target, data->current_profile_setting.sclk_activity,
&(smu_data->smc_state_table.GraphicsLevel[i])); &(smu_data->smc_state_table.GraphicsLevel[i]));
if (result != 0) if (result != 0)
return result; return result;
...@@ -1271,12 +1271,12 @@ static int iceland_populate_single_memory_level( ...@@ -1271,12 +1271,12 @@ static int iceland_populate_single_memory_level(
memory_level->EnabledForThrottle = 1; memory_level->EnabledForThrottle = 1;
memory_level->EnabledForActivity = 0; memory_level->EnabledForActivity = 0;
memory_level->UpHyst = 0; memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
memory_level->DownHyst = 100; memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
memory_level->VoltageDownHyst = 0; memory_level->VoltageDownHyst = 0;
/* Indicates maximum activity level for this performance level.*/ /* Indicates maximum activity level for this performance level.*/
memory_level->ActivityLevel = data->mclk_activity_target; memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
memory_level->StutterEnable = 0; memory_level->StutterEnable = 0;
memory_level->StrobeEnable = 0; memory_level->StrobeEnable = 0;
memory_level->EdcReadEnable = 0; memory_level->EdcReadEnable = 0;
...@@ -1557,7 +1557,7 @@ static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, ...@@ -1557,7 +1557,7 @@ static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownHyst = 100; table->MemoryACPILevel.DownHyst = 100;
table->MemoryACPILevel.VoltageDownHyst = 0; table->MemoryACPILevel.VoltageDownHyst = 0;
/* Indicates maximum activity level for this performance level.*/ /* Indicates maximum activity level for this performance level.*/
table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->mclk_activity_target); table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = 0; table->MemoryACPILevel.StutterEnable = 0;
table->MemoryACPILevel.StrobeEnable = 0; table->MemoryACPILevel.StrobeEnable = 0;
......
...@@ -968,8 +968,8 @@ static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr, ...@@ -968,8 +968,8 @@ static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
level->CcPwrDynRm1 = 0; level->CcPwrDynRm1 = 0;
level->EnabledForActivity = 0; level->EnabledForActivity = 0;
level->EnabledForThrottle = 1; level->EnabledForThrottle = 1;
level->UpHyst = 10; level->UpHyst = data->current_profile_setting.sclk_up_hyst;
level->DownHyst = 0; level->DownHyst = data->current_profile_setting.sclk_down_hyst;
level->VoltageDownHyst = 0; level->VoltageDownHyst = 0;
level->PowerThrottle = 0; level->PowerThrottle = 0;
data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr; data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr;
...@@ -1033,7 +1033,7 @@ static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) ...@@ -1033,7 +1033,7 @@ static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
result = polaris10_populate_single_graphic_level(hwmgr, result = polaris10_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value, dpm_table->sclk_table.dpm_levels[i].value,
hw_data->sclk_activity_target, hw_data->current_profile_setting.sclk_activity,
&(smu_data->smc_state_table.GraphicsLevel[i])); &(smu_data->smc_state_table.GraphicsLevel[i]));
if (result) if (result)
return result; return result;
...@@ -1130,10 +1130,10 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, ...@@ -1130,10 +1130,10 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
mem_level->MclkFrequency = clock; mem_level->MclkFrequency = clock;
mem_level->EnabledForThrottle = 1; mem_level->EnabledForThrottle = 1;
mem_level->EnabledForActivity = 0; mem_level->EnabledForActivity = 0;
mem_level->UpHyst = 0; mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
mem_level->DownHyst = 100; mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
mem_level->VoltageDownHyst = 0; mem_level->VoltageDownHyst = 0;
mem_level->ActivityLevel = data->mclk_activity_target; mem_level->ActivityLevel = data->current_profile_setting.mclk_activity;
mem_level->StutterEnable = false; mem_level->StutterEnable = false;
mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
...@@ -1314,7 +1314,7 @@ static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, ...@@ -1314,7 +1314,7 @@ static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownHyst = 100; table->MemoryACPILevel.DownHyst = 100;
table->MemoryACPILevel.VoltageDownHyst = 0; table->MemoryACPILevel.VoltageDownHyst = 0;
table->MemoryACPILevel.ActivityLevel = table->MemoryACPILevel.ActivityLevel =
PP_HOST_TO_SMC_US(data->mclk_activity_target); PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);
......
...@@ -644,8 +644,8 @@ static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, ...@@ -644,8 +644,8 @@ static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
graphic_level->EnabledForActivity = 0; graphic_level->EnabledForActivity = 0;
/* this level can be used for throttling.*/ /* this level can be used for throttling.*/
graphic_level->EnabledForThrottle = 1; graphic_level->EnabledForThrottle = 1;
graphic_level->UpHyst = 0; graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst;
graphic_level->DownHyst = 0; graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst;
graphic_level->VoltageDownHyst = 0; graphic_level->VoltageDownHyst = 0;
graphic_level->PowerThrottle = 0; graphic_level->PowerThrottle = 0;
...@@ -704,7 +704,7 @@ static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) ...@@ -704,7 +704,7 @@ static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) { for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = tonga_populate_single_graphic_level(hwmgr, result = tonga_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value, dpm_table->sclk_table.dpm_levels[i].value,
data->sclk_activity_target, data->current_profile_setting.sclk_activity,
&(smu_data->smc_state_table.GraphicsLevel[i])); &(smu_data->smc_state_table.GraphicsLevel[i]));
if (result != 0) if (result != 0)
return result; return result;
...@@ -994,12 +994,12 @@ static int tonga_populate_single_memory_level( ...@@ -994,12 +994,12 @@ static int tonga_populate_single_memory_level(
memory_level->EnabledForThrottle = 1; memory_level->EnabledForThrottle = 1;
memory_level->EnabledForActivity = 0; memory_level->EnabledForActivity = 0;
memory_level->UpHyst = 0; memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
memory_level->DownHyst = 100; memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
memory_level->VoltageDownHyst = 0; memory_level->VoltageDownHyst = 0;
/* Indicates maximum activity level for this performance level.*/ /* Indicates maximum activity level for this performance level.*/
memory_level->ActivityLevel = data->mclk_activity_target; memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
memory_level->StutterEnable = 0; memory_level->StutterEnable = 0;
memory_level->StrobeEnable = 0; memory_level->StrobeEnable = 0;
memory_level->EdcReadEnable = 0; memory_level->EdcReadEnable = 0;
...@@ -1289,7 +1289,7 @@ static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, ...@@ -1289,7 +1289,7 @@ static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.VoltageDownHyst = 0; table->MemoryACPILevel.VoltageDownHyst = 0;
/* Indicates maximum activity level for this performance level.*/ /* Indicates maximum activity level for this performance level.*/
table->MemoryACPILevel.ActivityLevel = table->MemoryACPILevel.ActivityLevel =
PP_HOST_TO_SMC_US(data->mclk_activity_target); PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = 0; table->MemoryACPILevel.StutterEnable = 0;
table->MemoryACPILevel.StrobeEnable = 0; table->MemoryACPILevel.StrobeEnable = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment