diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index f7e6a751f309..bdeb9fd08249 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -303,10 +303,11 @@ static void _edac_mc_free(struct mem_ctl_info *mci)
 	kfree(mci);
 }
 
-struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
-				   unsigned n_layers,
-				   struct edac_mc_layer *layers,
-				   unsigned sz_pvt)
+struct mem_ctl_info *__edac_mc_alloc(unsigned mc_num,
+				unsigned dimm_num,
+				unsigned n_layers,
+				struct edac_mc_layer *layers,
+				unsigned sz_pvt)
 {
 	struct mem_ctl_info *mci;
 	struct edac_mc_layer *layer;
@@ -321,6 +322,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 	bool per_rank = false;
 
 	BUG_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0);
+
 	/*
 	 * Calculate the total amount of dimms and csrows/cschannels while
 	 * in the old API emulation mode
@@ -336,6 +338,26 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 			per_rank = true;
 	}
 
+	/* allocate dimm_num DIMMS, layer size must be zero */
+	if (dimm_num) {
+		if (dimm_num <= 0 ||
+			layers[0].size ||
+			(n_layers > 1 && layers[1].size) ||
+			(n_layers > 2 && layers[2].size)) {
+			edac_printk(KERN_WARNING, EDAC_MC,
+				"invalid layer data\n");
+			return NULL;
+		}
+
+		/*
+		 * Assume 1 csrow per dimm which also means 1 channel
+		 * per csrow.
+		 */
+		tot_dimms	= dimm_num;
+		tot_csrows	= dimm_num;
+		tot_channels	= 1;
+	}
+
 	/* Figure out the offsets of the various items from the start of an mc
 	 * structure.  We want the alignment of each item to be at least as
 	 * stringent as what the compiler would provide if we could simply
@@ -422,25 +444,10 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 		dimm->mci = mci;
 		dimm->idx = idx;
 
-		/*
-		 * Copy DIMM location and initialize it.
-		 */
-		len = sizeof(dimm->label);
-		p = dimm->label;
-		n = snprintf(p, len, "mc#%u", mc_num);
-		p += n;
-		len -= n;
-		for (j = 0; j < n_layers; j++) {
-			n = snprintf(p, len, "%s#%u",
-				     edac_layer_name[layers[j].type],
-				     pos[j]);
-			p += n;
-			len -= n;
-			dimm->location[j] = pos[j];
-
-			if (len <= 0)
-				break;
-		}
+		/* unknown location */
+		dimm->location[0] = -1;
+		dimm->location[1] = -1;
+		dimm->location[2] = -1;
 
 		/* Link it to the csrows old API data */
 		chan->dimm = dimm;
@@ -462,6 +469,34 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 			}
 		}
 
+		/*
+		 * Copy DIMM location and initialize it.
+		 */
+		len = sizeof(dimm->label);
+		p = dimm->label;
+		n = snprintf(p, len, "mc#%u", mc_num);
+		p += n;
+		len -= n;
+
+		if (dimm_num) {
+			n = snprintf(p, len, "dimm#%u", idx);
+			p += n;
+			len -= n;
+			continue;
+		}
+
+		for (j = 0; j < n_layers; j++) {
+			n = snprintf(p, len, "%s#%u",
+				     edac_layer_name[layers[j].type],
+				     pos[j]);
+			p += n;
+			len -= n;
+			dimm->location[j] = pos[j];
+
+			if (len <= 0)
+				break;
+		}
+
 		/* Increment dimm location */
 		for (j = n_layers - 1; j >= 0; j--) {
 			pos[j]++;
@@ -480,7 +515,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(edac_mc_alloc);
+EXPORT_SYMBOL_GPL(__edac_mc_alloc);
 
 void edac_mc_free(struct mem_ctl_info *mci)
 {
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index c4ddd5c1e24c..e8215847f853 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -99,6 +99,10 @@ do {									\
  * edac_mc_alloc() - Allocate and partially fill a struct &mem_ctl_info.
  *
  * @mc_num:		Memory controller number
+ * @dimm_num:		Number of DIMMs to allocate. If non-zero the
+ *			@layers' size parameter must be zero. Useful
+ *			if the MC hierarchy is unknown but the number
+ *			of DIMMs is known.
  * @n_layers:		Number of MC hierarchy layers
  * @layers:		Describes each layer as seen by the Memory Controller
  * @sz_pvt:		size of private storage needed
@@ -122,10 +126,15 @@ do {									\
  *	On success, return a pointer to struct mem_ctl_info pointer;
  *	%NULL otherwise
  */
-struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
-				   unsigned n_layers,
-				   struct edac_mc_layer *layers,
-				   unsigned sz_pvt);
+struct mem_ctl_info *__edac_mc_alloc(unsigned mc_num,
+				unsigned dimm_num,
+				unsigned n_layers,
+				struct edac_mc_layer *layers,
+				unsigned sz_pvt);
+#define edac_mc_alloc(mc_num, n_layers, layers, sz_pvt) \
+	__edac_mc_alloc(mc_num, 0, n_layers, layers, sz_pvt)
+#define edac_mc_alloc_by_dimm(mc_num, dimm_num, n_layers, layers, sz_pvt) \
+	__edac_mc_alloc(mc_num, dimm_num, n_layers, layers, sz_pvt)
 
 /**
  * edac_get_owner - Return the owner's mod_name of EDAC MC
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index b8878ff498d1..4bac643d3404 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -707,11 +707,12 @@ ghes_edac_register_one(int nid, struct ghes *ghes, struct device *parent)
 	struct edac_mc_layer layers[1];
 
 	layers[0].type = EDAC_MC_LAYER_ALL_MEM;
-	layers[0].size = mem_info.num_per_node[nid];
+	layers[0].size = 0;
 	layers[0].is_virt_csrow = true;
 
-	mci = edac_mc_alloc(nid, ARRAY_SIZE(layers), layers,
-			sizeof(struct ghes_edac_pvt));
+	mci = edac_mc_alloc_by_dimm(nid, mem_info.num_per_node[nid],
+				ARRAY_SIZE(layers), layers,
+				sizeof(struct ghes_edac_pvt));
 	if (!mci) {
 		pr_err("Can't allocate memory for EDAC data\n");
 		return -ENOMEM;
