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

Reply via email to