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 <ddutta@nvidia.com>
Change-Id: I1ec5a7d7e57580bc75b7679c922d1e3af8418f6b
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2652684
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: Sagar Kamble <skamble@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
Debarshi Dutta
2022-01-11 15:07:10 +05:30
committed by mobile promotions
parent 878235e914
commit 1b3ae7eb92

View File

@@ -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 * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -189,69 +189,47 @@ fail:
return err; 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 slices_per_ltc;
u32 ltc_count; u32 ltc_count;
u32 ltc, lts; 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) { if (g->ltc == NULL) {
return; return;
} }
ltc_count = nvgpu_ltc_get_ltc_count(g); ltc_ecc_free_lts_slices(g, ecc->ltc.ecc_sec_count);
slices_per_ltc = nvgpu_ltc_get_slices_per_ltc(g); 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; ecc->ltc.ecc_sec_count = NULL;
nvgpu_kfree(g, ecc->ltc.ecc_ded_count);
ecc->ltc.ecc_ded_count = NULL; ecc->ltc.ecc_ded_count = NULL;
nvgpu_kfree(g, ecc->ltc.rstg_ecc_parity_count);
ecc->ltc.rstg_ecc_parity_count = NULL; ecc->ltc.rstg_ecc_parity_count = NULL;
nvgpu_kfree(g, ecc->ltc.tstg_ecc_parity_count);
ecc->ltc.tstg_ecc_parity_count = NULL; 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; ecc->ltc.dstg_be_ecc_parity_count = NULL;
} }