Use a flexible array member to combine allocations to avoid separate freeing. Also emded the actual array to avoid separate allocations.
Add __counted_by for extra runtime analysis with UBSAN. Move tot_channels assignment to after allocations. kzalloc_flex() does this already for GCC >= 15. Signed-off-by: Rosen Penev <[email protected]> --- drivers/edac/edac_mc.c | 33 ++++++++++----------------------- include/linux/edac.h | 2 +- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index fd70caa85574..0fff56ce21b4 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -179,7 +179,7 @@ static void mci_release(struct device *dev) { struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev); struct csrow_info *csr; - int i, chn, row; + int i, row; if (mci->dimms) { for (i = 0; i < mci->tot_dimms; i++) @@ -193,11 +193,6 @@ static void mci_release(struct device *dev) if (!csr) continue; - if (csr->channels) { - for (chn = 0; chn < mci->num_cschannel; chn++) - kfree(csr->channels[chn]); - kfree(csr->channels); - } kfree(csr); } kfree(mci->csrows); @@ -222,26 +217,18 @@ static int edac_mc_alloc_csrows(struct mem_ctl_info *mci) for (row = 0; row < tot_csrows; row++) { struct csrow_info *csr; - csr = kzalloc_obj(**mci->csrows); + csr = kzalloc_flex(*csr, channels, tot_channels); if (!csr) return -ENOMEM; + csr->nr_channels = tot_channels; mci->csrows[row] = csr; csr->csrow_idx = row; csr->mci = mci; - csr->nr_channels = tot_channels; - csr->channels = kzalloc_objs(*csr->channels, tot_channels); - if (!csr->channels) - return -ENOMEM; for (chn = 0; chn < tot_channels; chn++) { - struct rank_info *chan; - - chan = kzalloc_obj(**csr->channels); - if (!chan) - return -ENOMEM; + struct rank_info *chan = &csr->channels[chn]; - csr->channels[chn] = chan; chan->chan_idx = chn; chan->csrow = csr; } @@ -272,7 +259,7 @@ static int edac_mc_alloc_dimms(struct mem_ctl_info *mci) struct rank_info *chan; int n, len; - chan = mci->csrows[row]->channels[chn]; + chan = &mci->csrows[row]->channels[chn]; dimm = kzalloc_obj(**mci->dimms); if (!dimm) @@ -613,13 +600,13 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, int j; for (j = 0; j < csrow->nr_channels; j++) - nr_pages += csrow->channels[j]->dimm->nr_pages; + nr_pages += csrow->channels[j].dimm->nr_pages; if (!nr_pages) continue; edac_mc_dump_csrow(csrow); for (j = 0; j < csrow->nr_channels; j++) - if (csrow->channels[j]->dimm->nr_pages) - edac_mc_dump_channel(csrow->channels[j]); + if (csrow->channels[j].dimm->nr_pages) + edac_mc_dump_channel(&csrow->channels[j]); } mci_for_each_dimm(mci, dimm) @@ -758,7 +745,7 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) struct csrow_info *csrow = csrows[i]; n = 0; for (j = 0; j < csrow->nr_channels; j++) { - struct dimm_info *dimm = csrow->channels[j]->dimm; + struct dimm_info *dimm = csrow->channels[j].dimm; n += dimm->nr_pages; } if (n == 0) @@ -904,7 +891,7 @@ static void edac_inc_csrow(struct edac_raw_error_desc *e, int row, int chan) if (type == HW_EVENT_ERR_CORRECTED) { mci->csrows[row]->ce_count += count; if (chan >= 0) - mci->csrows[row]->channels[chan]->ce_count += count; + mci->csrows[row]->channels[chan].ce_count += count; } else { mci->csrows[row]->ue_count += count; } diff --git a/include/linux/edac.h b/include/linux/edac.h index 3902c3789510..3d8ee12c11be 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -448,7 +448,7 @@ struct csrow_info { /* channel information for this csrow */ u32 nr_channels; - struct rank_info **channels; + struct rank_info channels[] __counted_by(nr_channels); }; /* -- 2.55.0

