EDAC/mc: Split edac_mc_alloc() into smaller functions
authorRobert Richter <rrichter@marvell.com>
Thu, 23 Jan 2020 09:02:49 +0000 (09:02 +0000)
committerBorislav Petkov <bp@suse.de>
Mon, 17 Feb 2020 11:47:50 +0000 (12:47 +0100)
edac_mc_alloc() is huge. Factor out code by moving it to the two new
functions edac_mc_alloc_csrows() and edac_mc_alloc_dimms(). Do not
move code yet for better review.

 [ bp: sort local args in reversed fir tree order. ]

Signed-off-by: Robert Richter <rrichter@marvell.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Acked-by: Aristeu Rozanski <aris@redhat.com>
Link: https://lkml.kernel.org/r/20200123090210.26933-2-rrichter@marvell.com
drivers/edac/edac_mc.c

index 64785e6..71777b4 100644 (file)
@@ -311,6 +311,9 @@ static void mci_release(struct device *dev)
        kfree(mci);
 }
 
+static int edac_mc_alloc_csrows(struct mem_ctl_info *mci);
+static int edac_mc_alloc_dimms(struct mem_ctl_info *mci);
+
 struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
                                   unsigned int n_layers,
                                   struct edac_mc_layer *layers,
@@ -318,15 +321,11 @@ struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
 {
        struct mem_ctl_info *mci;
        struct edac_mc_layer *layer;
-       struct csrow_info *csr;
-       struct rank_info *chan;
-       struct dimm_info *dimm;
        u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS];
-       unsigned int pos[EDAC_MAX_LAYERS];
        unsigned int idx, size, tot_dimms = 1, count = 1;
        unsigned int tot_csrows = 1, tot_channels = 1, tot_errcount = 0;
-       void *pvt, *p, *ptr = NULL;
-       int i, j, row, chn, n, len;
+       void *pvt, *ptr = NULL;
+       int i;
        bool per_rank = false;
 
        if (WARN_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0))
@@ -401,16 +400,43 @@ struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
        mci->num_cschannel = tot_channels;
        mci->csbased = per_rank;
 
+       if (edac_mc_alloc_csrows(mci))
+               goto error;
+
+       if (edac_mc_alloc_dimms(mci))
+               goto error;
+
+       mci->op_state = OP_ALLOC;
+
+       return mci;
+
+error:
+       _edac_mc_free(mci);
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(edac_mc_alloc);
+
+static int edac_mc_alloc_csrows(struct mem_ctl_info *mci)
+{
+       unsigned int tot_channels = mci->num_cschannel;
+       unsigned int tot_csrows = mci->nr_csrows;
+       unsigned int row, chn;
+
        /*
         * Alocate and fill the csrow/channels structs
         */
        mci->csrows = kcalloc(tot_csrows, sizeof(*mci->csrows), GFP_KERNEL);
        if (!mci->csrows)
-               goto error;
+               return -ENOMEM;
+
        for (row = 0; row < tot_csrows; row++) {
+               struct csrow_info *csr;
+
                csr = kzalloc(sizeof(**mci->csrows), GFP_KERNEL);
                if (!csr)
-                       goto error;
+                       return -ENOMEM;
+
                mci->csrows[row] = csr;
                csr->csrow_idx = row;
                csr->mci = mci;
@@ -418,34 +444,51 @@ struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
                csr->channels = kcalloc(tot_channels, sizeof(*csr->channels),
                                        GFP_KERNEL);
                if (!csr->channels)
-                       goto error;
+                       return -ENOMEM;
 
                for (chn = 0; chn < tot_channels; chn++) {
+                       struct rank_info *chan;
+
                        chan = kzalloc(sizeof(**csr->channels), GFP_KERNEL);
                        if (!chan)
-                               goto error;
+                               return -ENOMEM;
+
                        csr->channels[chn] = chan;
                        chan->chan_idx = chn;
                        chan->csrow = csr;
                }
        }
 
+       return 0;
+}
+
+static int edac_mc_alloc_dimms(struct mem_ctl_info *mci)
+{
+       unsigned int pos[EDAC_MAX_LAYERS];
+       unsigned int row, chn, idx;
+       int layer;
+       void *p;
+
        /*
         * Allocate and fill the dimm structs
         */
-       mci->dimms  = kcalloc(tot_dimms, sizeof(*mci->dimms), GFP_KERNEL);
+       mci->dimms  = kcalloc(mci->tot_dimms, sizeof(*mci->dimms), GFP_KERNEL);
        if (!mci->dimms)
-               goto error;
+               return -ENOMEM;
 
        memset(&pos, 0, sizeof(pos));
        row = 0;
        chn = 0;
-       for (idx = 0; idx < tot_dimms; idx++) {
+       for (idx = 0; idx < mci->tot_dimms; idx++) {
+               struct dimm_info *dimm;
+               struct rank_info *chan;
+               int n, len;
+
                chan = mci->csrows[row]->channels[chn];
 
                dimm = kzalloc(sizeof(**mci->dimms), GFP_KERNEL);
                if (!dimm)
-                       goto error;
+                       return -ENOMEM;
                mci->dimms[idx] = dimm;
                dimm->mci = mci;
                dimm->idx = idx;
@@ -455,16 +498,16 @@ struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
                 */
                len = sizeof(dimm->label);
                p = dimm->label;
-               n = snprintf(p, len, "mc#%u", mc_num);
+               n = snprintf(p, len, "mc#%u", mci->mc_idx);
                p += n;
                len -= n;
-               for (j = 0; j < n_layers; j++) {
+               for (layer = 0; layer < mci->n_layers; layer++) {
                        n = snprintf(p, len, "%s#%u",
-                                    edac_layer_name[layers[j].type],
-                                    pos[j]);
+                                    edac_layer_name[mci->layers[layer].type],
+                                    pos[layer]);
                        p += n;
                        len -= n;
-                       dimm->location[j] = pos[j];
+                       dimm->location[layer] = pos[layer];
 
                        if (len <= 0)
                                break;
@@ -476,39 +519,31 @@ struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
                dimm->cschannel = chn;
 
                /* Increment csrow location */
-               if (layers[0].is_virt_csrow) {
+               if (mci->layers[0].is_virt_csrow) {
                        chn++;
-                       if (chn == tot_channels) {
+                       if (chn == mci->num_cschannel) {
                                chn = 0;
                                row++;
                        }
                } else {
                        row++;
-                       if (row == tot_csrows) {
+                       if (row == mci->nr_csrows) {
                                row = 0;
                                chn++;
                        }
                }
 
                /* Increment dimm location */
-               for (j = n_layers - 1; j >= 0; j--) {
-                       pos[j]++;
-                       if (pos[j] < layers[j].size)
+               for (layer = mci->n_layers - 1; layer >= 0; layer--) {
+                       pos[layer]++;
+                       if (pos[layer] < mci->layers[layer].size)
                                break;
-                       pos[j] = 0;
+                       pos[layer] = 0;
                }
        }
 
-       mci->op_state = OP_ALLOC;
-
-       return mci;
-
-error:
-       _edac_mc_free(mci);
-
-       return NULL;
+       return 0;
 }
-EXPORT_SYMBOL_GPL(edac_mc_alloc);
 
 void edac_mc_free(struct mem_ctl_info *mci)
 {