Commit c498afaf authored by Robert Richter's avatar Robert Richter Committed by Borislav Petkov
Browse files

EDAC: Introduce an mci_for_each_dimm() iterator



Introduce an mci_for_each_dimm() iterator. It returns a pointer to
a struct dimm_info. This makes the declaration and use of an index
obsolete and avoids access to internal data of struct mci (direct array
access etc).

 [ bp: push the struct dimm_info *dimm; declaration into the
   CONFIG_EDAC_DEBUG block. ]

Signed-off-by: default avatarRobert Richter <rrichter@marvell.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Cc: "linux-edac@vger.kernel.org" <linux-edac@vger.kernel.org>
Cc: James Morse <james.morse@arm.com>
Cc: Tony Luck <tony.luck@intel.com>
Link: https://lkml.kernel.org/r/20191106093239.25517-4-rrichter@marvell.com
parent 977b1ce7
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -145,15 +145,18 @@ static void edac_mc_dump_channel(struct rank_info *chan)
	edac_dbg(4, "    channel->dimm = %p\n", chan->dimm);
}

static void edac_mc_dump_dimm(struct dimm_info *dimm, int number)
static void edac_mc_dump_dimm(struct dimm_info *dimm)
{
	char location[80];

	if (!dimm->nr_pages)
		return;

	edac_dimm_info_location(dimm, location, sizeof(location));

	edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n",
		 dimm->mci->csbased ? "rank" : "dimm",
		 number, location, dimm->csrow, dimm->cschannel);
		 dimm->idx, location, dimm->csrow, dimm->cschannel);
	edac_dbg(4, "  dimm = %p\n", dimm);
	edac_dbg(4, "  dimm->label = '%s'\n", dimm->label);
	edac_dbg(4, "  dimm->nr_pages = 0x%x\n", dimm->nr_pages);
@@ -712,6 +715,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
		edac_mc_dump_mci(mci);

	if (edac_debug_level >= 4) {
		struct dimm_info *dimm;
		int i;

		for (i = 0; i < mci->nr_csrows; i++) {
@@ -728,9 +732,9 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
				if (csrow->channels[j]->dimm->nr_pages)
					edac_mc_dump_channel(csrow->channels[j]);
		}
		for (i = 0; i < mci->tot_dimms; i++)
			if (mci->dimms[i]->nr_pages)
				edac_mc_dump_dimm(mci->dimms[i], i);

		mci_for_each_dimm(mci, dimm)
			edac_mc_dump_dimm(dimm);
	}
#endif
	mutex_lock(&mem_ctls_mutex);
@@ -1088,6 +1092,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
			  const char *msg,
			  const char *other_detail)
{
	struct dimm_info *dimm;
	char *p;
	int row = -1, chan = -1;
	int pos[EDAC_MAX_LAYERS] = { top_layer, mid_layer, low_layer };
@@ -1148,9 +1153,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
	p = e->label;
	*p = '\0';

	for (i = 0; i < mci->tot_dimms; i++) {
		struct dimm_info *dimm = mci->dimms[i];

	mci_for_each_dimm(mci, dimm) {
		if (top_layer >= 0 && top_layer != dimm->location[0])
			continue;
		if (mid_layer >= 0 && mid_layer != dimm->location[1])
+12 −17
Original line number Diff line number Diff line
@@ -621,8 +621,7 @@ static const struct device_type dimm_attr_type = {

/* Create a DIMM object under specifed memory controller device */
static int edac_create_dimm_object(struct mem_ctl_info *mci,
				   struct dimm_info *dimm,
				   int index)
				   struct dimm_info *dimm)
{
	int err;
	dimm->mci = mci;
@@ -632,9 +631,9 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci,

	dimm->dev.parent = &mci->dev;
	if (mci->csbased)
		dev_set_name(&dimm->dev, "rank%d", index);
		dev_set_name(&dimm->dev, "rank%d", dimm->idx);
	else
		dev_set_name(&dimm->dev, "dimm%d", index);
		dev_set_name(&dimm->dev, "dimm%d", dimm->idx);
	dev_set_drvdata(&dimm->dev, dimm);
	pm_runtime_forbid(&mci->dev);

@@ -916,7 +915,8 @@ static const struct device_type mci_attr_type = {
int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
				 const struct attribute_group **groups)
{
	int i, err;
	struct dimm_info *dimm;
	int err;

	/* get the /sys/devices/system/edac subsys reference */
	mci->dev.type = &mci_attr_type;
@@ -940,13 +940,12 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
	/*
	 * Create the dimm/rank devices
	 */
	for (i = 0; i < mci->tot_dimms; i++) {
		struct dimm_info *dimm = mci->dimms[i];
	mci_for_each_dimm(mci, dimm) {
		/* Only expose populated DIMMs */
		if (!dimm->nr_pages)
			continue;

		err = edac_create_dimm_object(mci, dimm, i);
		err = edac_create_dimm_object(mci, dimm);
		if (err)
			goto fail_unregister_dimm;
	}
@@ -961,11 +960,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
	return 0;

fail_unregister_dimm:
	for (i--; i >= 0; i--) {
		struct dimm_info *dimm = mci->dimms[i];
		if (!dimm->nr_pages)
			continue;

	mci_for_each_dimm(mci, dimm) {
		if (device_is_registered(&dimm->dev))
			device_unregister(&dimm->dev);
	}
	device_unregister(&mci->dev);
@@ -978,7 +974,7 @@ fail_unregister_dimm:
 */
void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
{
	int i;
	struct dimm_info *dimm;

	edac_dbg(0, "\n");

@@ -989,8 +985,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
	edac_delete_csrow_objects(mci);
#endif

	for (i = 0; i < mci->tot_dimms; i++) {
		struct dimm_info *dimm = mci->dimms[i];
	mci_for_each_dimm(mci, dimm) {
		if (dimm->nr_pages == 0)
			continue;
		edac_dbg(1, "unregistering device %s\n", dev_name(&dimm->dev));
+5 −4
Original line number Diff line number Diff line
@@ -90,12 +90,13 @@ static void ghes_edac_count_dimms(const struct dmi_header *dh, void *arg)

static int get_dimm_smbios_index(struct mem_ctl_info *mci, u16 handle)
{
	int i;
	struct dimm_info *dimm;

	for (i = 0; i < mci->tot_dimms; i++) {
		if (mci->dimms[i]->smbios_handle == handle)
			return i;
	mci_for_each_dimm(mci, dimm) {
		if (dimm->smbios_handle == handle)
			return dimm->idx;
	}

	return -1;
}

+5 −8
Original line number Diff line number Diff line
@@ -846,20 +846,17 @@ static void i5100_init_interleaving(struct pci_dev *pdev,

static void i5100_init_csrows(struct mem_ctl_info *mci)
{
	int i;
	struct i5100_priv *priv = mci->pvt_info;

	for (i = 0; i < mci->tot_dimms; i++) {
	struct dimm_info *dimm;
		const unsigned long npages = i5100_npages(mci, i);
		const unsigned int chan = i5100_csrow_to_chan(mci, i);
		const unsigned int rank = i5100_csrow_to_rank(mci, i);

	mci_for_each_dimm(mci, dimm) {
		const unsigned long npages = i5100_npages(mci, dimm->idx);
		const unsigned int chan = i5100_csrow_to_chan(mci, dimm->idx);
		const unsigned int rank = i5100_csrow_to_rank(mci, dimm->idx);

		if (!npages)
			continue;

		dimm = edac_get_dimm(mci, chan, rank, 0);

		dimm->nr_pages = npages;
		dimm->grain = 32;
		dimm->dtype = (priv->mtr[chan][rank].width == 4) ?
+7 −0
Original line number Diff line number Diff line
@@ -599,6 +599,13 @@ struct mem_ctl_info {
	u16 fake_inject_count;
};

#define mci_for_each_dimm(mci, dimm)				\
	for ((dimm) = (mci)->dimms[0];				\
	     (dimm);						\
	     (dimm) = (dimm)->idx + 1 < (mci)->tot_dimms	\
		     ? (mci)->dimms[(dimm)->idx + 1]		\
		     : NULL)

/**
 * edac_get_dimm_by_index - Get DIMM info at @index from a memory
 * 			    controller