⬢ DragonFlyBSD Kernel Audit
DF-4544 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/powerplay/hwmgr/vega20_processpptables.c
+++ b/sys/dev/drm/amd/powerplay/hwmgr/vega20_processpptables.c
@@ -685,13 +685,14 @@
 		struct pp_hwmgr *hwmgr,
 		uint8_t **pptable_info_array,
 		const uint8_t *pptable_array,
-		uint8_t od_feature_count)
+		uint8_t od_feature_count,	/* entries the VBIOS provides */
+		uint8_t od_feature_alloc)	/* entries the driver indexes */
 {
 	uint32_t array_size, i;
 	uint8_t *table;
 	bool od_supported = false;
 
-	array_size = sizeof(uint8_t) * od_feature_count;
+	array_size = sizeof(uint8_t) * od_feature_alloc;
 	table = kzalloc(array_size, GFP_KERNEL);
 	if (NULL == table)
 		return -ENOMEM;
@@ -711,6 +712,28 @@
 	return 0;
 }
 
+/* DF-4544: phm_copy_overdrive_settings_limits_array() (smu_helper.c:64)
+ * sizes the allocation from the count we pass it, while the driver-side
+ * OD8_SETTING_ID enum (vega20_hwmgr.h:398-417) indexes up to entry 13 --
+ * the allocation must never be smaller than ATOM_VEGA20_ODSETTING_COUNT.
+ */
+static int vega20_copy_od_settings_limits_array(
+		uint32_t **pptable_info_array,
+		const uint32_t *pptable_array,
+		uint32_t table_count)
+{
+	uint32_t i, *table;
+
+	table = kzalloc(sizeof(uint32_t) * ATOM_VEGA20_ODSETTING_COUNT,
+			GFP_KERNEL);
+	if (table == NULL)
+		return -ENOMEM;
+	for (i = 0; i < table_count && i < ATOM_VEGA20_ODSETTING_COUNT; i++)
+		table[i] = le32_to_cpu(pptable_array[i]);
+	*pptable_info_array = table;
+	return 0;
+}
+
 static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable)
 {
 	struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
@@ -835,12 +858,13 @@
 		copy_overdrive_feature_capabilities_array(hwmgr,
 				&pptable_information->od_feature_capabilities,
 				powerplay_table->OverDrive8Table.ODFeatureCapabilities,
-				od_feature_count);
-		phm_copy_overdrive_settings_limits_array(hwmgr,
+				od_feature_count,
+				ATOM_VEGA20_ODFEATURE_COUNT);
+		vega20_copy_od_settings_limits_array(
 				&pptable_information->od_settings_max,
 				powerplay_table->OverDrive8Table.ODSettingsMax,
 				od_setting_count);
-		phm_copy_overdrive_settings_limits_array(hwmgr,
+		vega20_copy_od_settings_limits_array(
 				&pptable_information->od_settings_min,
 				powerplay_table->OverDrive8Table.ODSettingsMin,
 				od_setting_count);