From 1b3ae7eb92ee5158b051a6d801f1ba5a3189ae29 Mon Sep 17 00:00:00 2001 From: Debarshi Dutta Date: Tue, 11 Jan 2022 15:07:10 +0530 Subject: [PATCH] gpu: nvgpu: fix ecc issues Fixed memory leaks within the ltc ecc code. Memory leak occurs as some of the stats are not free'd during Rmmod. Add a common API to handle the same. Bug 3364181 Signed-off-by: Debarshi Dutta Change-Id: I1ec5a7d7e57580bc75b7679c922d1e3af8418f6b Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2652684 Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: Sagar Kamble Reviewed-by: Vijayakumar Subbu GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/common/ltc/ltc.c | 80 +++++++++++------------------- 1 file changed, 29 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/nvgpu/common/ltc/ltc.c b/drivers/gpu/nvgpu/common/ltc/ltc.c index 52aa8c167..ed81d49e1 100644 --- a/drivers/gpu/nvgpu/common/ltc/ltc.c +++ b/drivers/gpu/nvgpu/common/ltc/ltc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -189,69 +189,47 @@ fail: return err; } -void nvgpu_ltc_ecc_free(struct gk20a *g) +static void ltc_ecc_free_lts_slices(struct gk20a *g, struct nvgpu_ecc_stat **ecc_stat) { - struct nvgpu_ecc *ecc = &g->ecc; - struct nvgpu_ecc_stat *stat; u32 slices_per_ltc; u32 ltc_count; u32 ltc, lts; + struct nvgpu_ecc_stat *stat = NULL; + + ltc_count = nvgpu_ltc_get_ltc_count(g); + slices_per_ltc = nvgpu_ltc_get_slices_per_ltc(g); + + if (ecc_stat != NULL) { + for (ltc = 0; ltc < ltc_count; ltc++) { + if (ecc_stat[ltc] != NULL) { + for (lts = 0; lts < slices_per_ltc; lts++) { + stat = &ecc_stat[ltc][lts]; + nvgpu_ecc_stat_del(g, stat); + } + nvgpu_kfree(g, ecc_stat[ltc]); + } + } + nvgpu_kfree(g, ecc_stat); + } +} + +void nvgpu_ltc_ecc_free(struct gk20a *g) +{ + struct nvgpu_ecc *ecc = &g->ecc; if (g->ltc == NULL) { return; } - ltc_count = nvgpu_ltc_get_ltc_count(g); - slices_per_ltc = nvgpu_ltc_get_slices_per_ltc(g); + ltc_ecc_free_lts_slices(g, ecc->ltc.ecc_sec_count); + ltc_ecc_free_lts_slices(g, ecc->ltc.ecc_ded_count); + ltc_ecc_free_lts_slices(g, ecc->ltc.rstg_ecc_parity_count); + ltc_ecc_free_lts_slices(g, ecc->ltc.tstg_ecc_parity_count); + ltc_ecc_free_lts_slices(g, ecc->ltc.dstg_be_ecc_parity_count); - for (ltc = 0; ltc < ltc_count; ltc++) { - if (ecc->ltc.ecc_sec_count != NULL && - ecc->ltc.ecc_sec_count[ltc] != NULL) { - for (lts = 0; lts < slices_per_ltc; lts++) { - stat = &ecc->ltc.ecc_sec_count[ltc][lts]; - nvgpu_ecc_stat_del(g, stat); - } - - nvgpu_kfree(g, ecc->ltc.ecc_sec_count[ltc]); - ecc->ltc.ecc_sec_count[ltc] = NULL; - } - - if (ecc->ltc.ecc_ded_count != NULL && - ecc->ltc.ecc_ded_count[ltc] != NULL) { - for (lts = 0; lts < slices_per_ltc; lts++) { - stat = &ecc->ltc.ecc_ded_count[ltc][lts]; - nvgpu_ecc_stat_del(g, stat); - } - - nvgpu_kfree(g, ecc->ltc.ecc_ded_count[ltc]); - ecc->ltc.ecc_ded_count[ltc] = NULL; - } - - if (ecc->ltc.rstg_ecc_parity_count != NULL) { - nvgpu_kfree(g, ecc->ltc.rstg_ecc_parity_count[ltc]); - } - - if (ecc->ltc.tstg_ecc_parity_count != NULL) { - nvgpu_kfree(g, ecc->ltc.tstg_ecc_parity_count[ltc]); - } - - if (ecc->ltc.dstg_be_ecc_parity_count != NULL) { - nvgpu_kfree(g, ecc->ltc.dstg_be_ecc_parity_count[ltc]); - } - } - - nvgpu_kfree(g, ecc->ltc.ecc_sec_count); ecc->ltc.ecc_sec_count = NULL; - - nvgpu_kfree(g, ecc->ltc.ecc_ded_count); ecc->ltc.ecc_ded_count = NULL; - - nvgpu_kfree(g, ecc->ltc.rstg_ecc_parity_count); ecc->ltc.rstg_ecc_parity_count = NULL; - - nvgpu_kfree(g, ecc->ltc.tstg_ecc_parity_count); ecc->ltc.tstg_ecc_parity_count = NULL; - - nvgpu_kfree(g, ecc->ltc.dstg_be_ecc_parity_count); ecc->ltc.dstg_be_ecc_parity_count = NULL; }