[PATCH 066/109] drm/amd/ras: harden error handling and fix resource/lock issues

Alex Deucher <[email protected]>
Newsgroups org.freedesktop.lists.amd-gfx
Message-ID <[email protected]>
From: YiPeng Chai <[email protected]>

Harden error handling and fix resource/lock issues.

Signed-off-by: YiPeng Chai <[email protected]>
Reviewed-by: Hawking Zhang <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/ras/core/eeprom_fw.c | 19 +++++++++++++------
 drivers/gpu/drm/amd/ras/core/ras_mp1.c   |  2 +-
 drivers/gpu/drm/amd/ras/core/ras_umc.c   | 11 ++++++++---
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/ras/core/eeprom_fw.c b/drivers/gpu/drm/amd/ras/core/eeprom_fw.c
index f7fb2dd7afe72..5f86ff54d9ed7 100644
--- a/drivers/gpu/drm/amd/ras/core/eeprom_fw.c
+++ b/drivers/gpu/drm/amd/ras/core/eeprom_fw.c
@@ -36,10 +36,11 @@ static int fw_eeprom_reset_ras_table(struct ras_core_context *ras_core)
 	mutex_lock(&ctl->record_lock);
 	res = ras_mp1_reset_ras_table(ras_core, &erase_res);
 	if (res || erase_res) {
-		RAS_DEV_WARN(ras_core->dev, "RAS EEPROM reset failed, res:%d result:%d",
-									res, erase_res);
+		RAS_DEV_WARN(ras_core->dev,
+			"RAS EEPROM reset failed, res:%d result:%d\n", res, erase_res);
 		if (!res)
 			res = -EIO;
+		goto out;
 	}
 
 	ctl->record_count = 0;
@@ -51,6 +52,8 @@ static int fw_eeprom_reset_ras_table(struct ras_core_context *ras_core)
 	ctl->rma_status = 0;
 	ctl->bad_channel_bitmap = 0;
 
+out:
+	mutex_unlock(&ctl->record_lock);
 	return res;
 }
 
@@ -73,6 +76,11 @@ static int fw_eeprom_sync_data(struct ras_core_context *ras_core,
 		RAS_DEV_ERR(ras_core->dev, "EEPROM ECC error count mismatch!\n");
 		ret = -EFAULT;
 		goto out;
+	} else if (fw_err_rec_num > MAX_EEPROM_ERR_RECORD_NUM) {
+		RAS_DEV_ERR(ras_core->dev,
+			"Invalid EEPROM error count:0x%x\n", fw_err_rec_num);
+		ret = -EOVERFLOW;
+		goto out;
 	}
 
 	for (idx = ctl->record_count;
@@ -141,9 +149,6 @@ static int fw_eeprom_sw_init(struct ras_core_context *ras_core,
 	if (!ctl)
 		return -ENOMEM;
 
-	mgr->ras_eeprom = ctl;
-	memset(ctl, 0, sizeof(*ctl));
-
 	ctl->eeprom_ip_version = param->eeprom_ip_version;
 	ctl->records = kzalloc(sizeof(*ctl->records) * MAX_EEPROM_ERR_RECORD_NUM, GFP_KERNEL);
 	if (!ctl->records) {
@@ -154,10 +159,12 @@ static int fw_eeprom_sw_init(struct ras_core_context *ras_core,
 	ctl->max_record_count = MAX_EEPROM_ERR_RECORD_NUM;
 	mutex_init(&ctl->record_lock);
 
+	mgr->ras_eeprom = ctl;
+
 	return 0;
 
 out:
-	kfree(ctl->records);
+	kfree(ctl);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/amd/ras/core/ras_mp1.c b/drivers/gpu/drm/amd/ras/core/ras_mp1.c
index 34578806ef3c0..2452448806f65 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_mp1.c
+++ b/drivers/gpu/drm/amd/ras/core/ras_mp1.c
@@ -148,7 +148,7 @@ int ras_mp1_get_record_count(struct ras_core_context *ras_core, u32 *count)
 	int ret;
 
 	if (!count || !mp1->ip_func || !mp1->ip_func->get_record_count)
-		return 0;
+		return -EOPNOTSUPP;
 
 	mutex_lock(&mp1->op_mutex);
 	ret = mp1->ip_func->get_record_count(ras_core, count);
diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.c b/drivers/gpu/drm/amd/ras/core/ras_umc.c
index 0e6a341f0729a..3558d4633a4e7 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_umc.c
+++ b/drivers/gpu/drm/amd/ras/core/ras_umc.c
@@ -488,6 +488,7 @@ static int ras_umc_log_record(struct ras_core_context *ras_core,
 				struct eeprom_umc_record *record)
 {
 	struct eeprom_umc_record *rec;
+	int ret;
 
 	rec = kzalloc(sizeof(*rec), GFP_KERNEL);
 	if (!rec)
@@ -495,7 +496,11 @@ static int ras_umc_log_record(struct ras_core_context *ras_core,
 
 	memcpy(rec, record, sizeof(*rec));
 
-	return ras_umc_log_ecc(ras_core, rec->cur_nps_retired_row_pfn, rec);
+	ret = ras_umc_log_ecc(ras_core, rec->cur_nps_retired_row_pfn, rec);
+	if (ret)
+		kfree(rec);
+
+	return ret;
 }
 
 /* alloc/realloc bps array */
@@ -537,7 +542,7 @@ static int ras_umc_update_eeprom_rom_data(struct ras_core_context *ras_core,
 
 	/* update bad channel bitmap */
 	if (bps->mem_channel < BITS_PER_TYPE(data->umc_channel_bitmap))
-		data->umc_channel_bitmap |= 1 << bps->mem_channel;
+		data->umc_channel_bitmap |= 0x1ULL << bps->mem_channel;
 
 	return 0;
 }
@@ -585,7 +590,7 @@ static int ras_umc_update_eeprom_ram_data(struct ras_core_context *ras_core,
 
 	/* update bad channel bitmap */
 	if (bps->mem_channel < BITS_PER_TYPE(data->umc_channel_bitmap))
-		data->umc_channel_bitmap |= 1 << bps->mem_channel;
+		data->umc_channel_bitmap |= 0x1ULL << bps->mem_channel;
 
 	return 0;
 }
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.