Message ID | 20190624150758.6695-9-rrichter@marvell.com |
---|---|
State | New |
Headers | show |
Series | EDAC, mc, ghes: Fixes and updates to improve memory error reporting | expand |
On Mon, Jun 24, 2019 at 03:09:11PM +0000, Robert Richter wrote: > Make code more readable by introducing a mci_for_each_dimm() iterator. > Now, we just get a pointer to a struct dimm_info. Direct array access > using an index is no longer needed to iterate. > > Signed-off-by: Robert Richter <rrichter@marvell.com> > --- > drivers/edac/edac_mc.c | 18 ++++++++++-------- > drivers/edac/edac_mc_sysfs.c | 34 +++++++++++++++------------------- > drivers/edac/ghes_edac.c | 8 ++++---- > drivers/edac/i5100_edac.c | 11 +++++------ > include/linux/edac.h | 7 +++++++ > 5 files changed, 41 insertions(+), 37 deletions(-) > > diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c > index c44bc83e8502..27277ca46ab3 100644 > --- a/drivers/edac/edac_mc.c > +++ b/drivers/edac/edac_mc.c > @@ -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; > + What's that for? > 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); > @@ -703,6 +706,7 @@ EXPORT_SYMBOL_GPL(edac_get_owner); > int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, > const struct attribute_group **groups) > { > + struct dimm_info *dimm; > int ret = -EINVAL; > edac_dbg(0, "\n"); > > @@ -727,9 +731,8 @@ 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); <---- newline here. > + mci_for_each_dimm(mci, dimm) > + edac_mc_dump_dimm(dimm); > } > #endif > mutex_lock(&mem_ctls_mutex); ... > @@ -950,9 +949,10 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, > printk(KERN_CONT "\n"); > } > #endif > - err = edac_create_dimm_object(mci, dimm, i); > + err = edac_create_dimm_object(mci, dimm); > if (err) { > - edac_dbg(1, "failure: create dimm %d obj\n", i); > + edac_dbg(1, "failure: create dimm %d obj\n", > + dimm->idx); > goto fail_unregister_dimm; > } > } Since you're touching this, pls do s/dimm/DIMM/g in the user-visible strings because it is an abbreviation. > @@ -967,12 +967,9 @@ 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; > - > - device_unregister(&dimm->dev); > + mci_for_each_dimm(mci, dimm) { > + if (device_is_registered(&dimm->dev)) > + device_unregister(&dimm->dev); > } > device_unregister(&mci->dev); > > @@ -984,7 +981,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, > */ > void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) > { > - int i; > + struct dimm_info *dimm; > > edac_dbg(0, "\n"); > > @@ -995,8 +992,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(0, "removing device %s\n", dev_name(&dimm->dev)); > diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c > index 8050f9577fe6..72e75ea5526c 100644 > --- a/drivers/edac/ghes_edac.c > +++ b/drivers/edac/ghes_edac.c > @@ -81,11 +81,11 @@ static void ghes_edac_count_dimms(const struct dmi_header *dh, void *arg) > static int get_dimm_smbios_index(u16 handle) > { > struct mem_ctl_info *mci = ghes_pvt->mci; > - 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; > } > diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c > index 39ba7f2414ae..7ec42b26a716 100644 > --- a/drivers/edac/i5100_edac.c > +++ b/drivers/edac/i5100_edac.c > @@ -846,14 +846,13 @@ 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; > + struct dimm_info *dimm; > > - for (i = 0; i < mci->tot_dimms; i++) { > - struct dimm_info *dimm; > - const unsigned long npages = i5100_npages(mci, i); > - const unsigned chan = i5100_csrow_to_chan(mci, i); > - const unsigned rank = i5100_csrow_to_rank(mci, i); > + mci_for_each_dimm(mci, dimm) { > + const unsigned long npages = i5100_npages(mci, dimm->idx); > + const unsigned chan = i5100_csrow_to_chan(mci, dimm->idx); > + const unsigned rank = i5100_csrow_to_rank(mci, dimm->idx); > > if (!npages) > continue; This cannot be right: the code here under this does now: dimm = edac_get_dimm(mci, chan, rank, 0); but dimm is already set. It used to get the DIMM using chan and rank but now you're iterating over the already initialized pointers. So I think you don't need the edac_get_dimm() anymore. Also fix those up too, while at it pls: WARNING: Prefer 'unsigned int' to bare use of 'unsigned' #235: FILE: drivers/edac/i5100_edac.c:854: + const unsigned chan = i5100_csrow_to_chan(mci, dimm->idx); WARNING: Prefer 'unsigned int' to bare use of 'unsigned' #236: FILE: drivers/edac/i5100_edac.c:855: + const unsigned rank = i5100_csrow_to_rank(mci, dimm->idx); > diff --git a/include/linux/edac.h b/include/linux/edac.h > index 2ee9b8598ae0..20a04f48616c 100644 > --- a/include/linux/edac.h > +++ b/include/linux/edac.h > @@ -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 < (mci)->tot_dimms \ > + ? (mci)->dimms[(dimm)->idx + 1] \ > + : NULL) > + > /** > * edac_get_dimm_by_index - Get DIMM info from a memory controller > * given by an index > -- Thx. -- Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply.
On 14.08.19 17:18:24, Borislav Petkov wrote: > On Mon, Jun 24, 2019 at 03:09:11PM +0000, Robert Richter wrote: > > Make code more readable by introducing a mci_for_each_dimm() iterator. > > Now, we just get a pointer to a struct dimm_info. Direct array access > > using an index is no longer needed to iterate. > > > > Signed-off-by: Robert Richter <rrichter@marvell.com> > > --- > > drivers/edac/edac_mc.c | 18 ++++++++++-------- > > drivers/edac/edac_mc_sysfs.c | 34 +++++++++++++++------------------- > > drivers/edac/ghes_edac.c | 8 ++++---- > > drivers/edac/i5100_edac.c | 11 +++++------ > > include/linux/edac.h | 7 +++++++ > > 5 files changed, 41 insertions(+), 37 deletions(-) > > > > diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c > > index c44bc83e8502..27277ca46ab3 100644 > > --- a/drivers/edac/edac_mc.c > > +++ b/drivers/edac/edac_mc.c > > @@ -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; > > + > > What's that for? This is moved from the iterator loop below to here. It limits the dump to only populated dimm slots. > > > 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); > > diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c > > index 39ba7f2414ae..7ec42b26a716 100644 > > --- a/drivers/edac/i5100_edac.c > > +++ b/drivers/edac/i5100_edac.c > > @@ -846,14 +846,13 @@ 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; > > + struct dimm_info *dimm; > > > > - for (i = 0; i < mci->tot_dimms; i++) { > > - struct dimm_info *dimm; > > - const unsigned long npages = i5100_npages(mci, i); > > - const unsigned chan = i5100_csrow_to_chan(mci, i); > > - const unsigned rank = i5100_csrow_to_rank(mci, i); > > + mci_for_each_dimm(mci, dimm) { > > + const unsigned long npages = i5100_npages(mci, dimm->idx); > > + const unsigned chan = i5100_csrow_to_chan(mci, dimm->idx); > > + const unsigned rank = i5100_csrow_to_rank(mci, dimm->idx); > > > > if (!npages) > > continue; > > This cannot be right: the code here under this does now: > > dimm = edac_get_dimm(mci, chan, rank, 0); > > but dimm is already set. It used to get the DIMM using chan and rank but > now you're iterating over the already initialized pointers. So I think > you don't need the edac_get_dimm() anymore. Right, it should calculate to the same pointer we already have and can be removed. Good catch. > > Also fix those up too, while at it pls: > > WARNING: Prefer 'unsigned int' to bare use of 'unsigned' > #235: FILE: drivers/edac/i5100_edac.c:854: > + const unsigned chan = i5100_csrow_to_chan(mci, dimm->idx); > > WARNING: Prefer 'unsigned int' to bare use of 'unsigned' > #236: FILE: drivers/edac/i5100_edac.c:855: > + const unsigned rank = i5100_csrow_to_rank(mci, dimm->idx); I am going to fix this is a separate patch, though I will exclude rework of struct i5100_priv. I have reworked the patch according to all your other comments. Thanks for review. -Robert
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index c44bc83e8502..27277ca46ab3 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -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); @@ -703,6 +706,7 @@ EXPORT_SYMBOL_GPL(edac_get_owner); int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, const struct attribute_group **groups) { + struct dimm_info *dimm; int ret = -EINVAL; edac_dbg(0, "\n"); @@ -727,9 +731,8 @@ 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); @@ -1104,6 +1107,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 }; @@ -1163,9 +1167,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]) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index a69e99206a6f..4d15c88a52cd 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -623,8 +623,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; @@ -634,9 +633,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); @@ -910,7 +909,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; @@ -933,14 +933,13 @@ 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; #ifdef CONFIG_EDAC_DEBUG - edac_dbg(1, "creating dimm%d, located at ", i); + edac_dbg(1, "creating dimm%d, located at ", dimm->idx); if (edac_debug_level >= 1) { int lay; for (lay = 0; lay < mci->n_layers; lay++) @@ -950,9 +949,10 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, printk(KERN_CONT "\n"); } #endif - err = edac_create_dimm_object(mci, dimm, i); + err = edac_create_dimm_object(mci, dimm); if (err) { - edac_dbg(1, "failure: create dimm %d obj\n", i); + edac_dbg(1, "failure: create dimm %d obj\n", + dimm->idx); goto fail_unregister_dimm; } } @@ -967,12 +967,9 @@ 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; - - device_unregister(&dimm->dev); + mci_for_each_dimm(mci, dimm) { + if (device_is_registered(&dimm->dev)) + device_unregister(&dimm->dev); } device_unregister(&mci->dev); @@ -984,7 +981,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, */ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) { - int i; + struct dimm_info *dimm; edac_dbg(0, "\n"); @@ -995,8 +992,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(0, "removing device %s\n", dev_name(&dimm->dev)); diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index 8050f9577fe6..72e75ea5526c 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c @@ -81,11 +81,11 @@ static void ghes_edac_count_dimms(const struct dmi_header *dh, void *arg) static int get_dimm_smbios_index(u16 handle) { struct mem_ctl_info *mci = ghes_pvt->mci; - 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; } diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index 39ba7f2414ae..7ec42b26a716 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c @@ -846,14 +846,13 @@ 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; + struct dimm_info *dimm; - for (i = 0; i < mci->tot_dimms; i++) { - struct dimm_info *dimm; - const unsigned long npages = i5100_npages(mci, i); - const unsigned chan = i5100_csrow_to_chan(mci, i); - const unsigned rank = i5100_csrow_to_rank(mci, i); + mci_for_each_dimm(mci, dimm) { + const unsigned long npages = i5100_npages(mci, dimm->idx); + const unsigned chan = i5100_csrow_to_chan(mci, dimm->idx); + const unsigned rank = i5100_csrow_to_rank(mci, dimm->idx); if (!npages) continue; diff --git a/include/linux/edac.h b/include/linux/edac.h index 2ee9b8598ae0..20a04f48616c 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h @@ -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 < (mci)->tot_dimms \ + ? (mci)->dimms[(dimm)->idx + 1] \ + : NULL) + /** * edac_get_dimm_by_index - Get DIMM info from a memory controller * given by an index
Make code more readable by introducing a mci_for_each_dimm() iterator. Now, we just get a pointer to a struct dimm_info. Direct array access using an index is no longer needed to iterate. Signed-off-by: Robert Richter <rrichter@marvell.com> --- drivers/edac/edac_mc.c | 18 ++++++++++-------- drivers/edac/edac_mc_sysfs.c | 34 +++++++++++++++------------------- drivers/edac/ghes_edac.c | 8 ++++---- drivers/edac/i5100_edac.c | 11 +++++------ include/linux/edac.h | 7 +++++++ 5 files changed, 41 insertions(+), 37 deletions(-) -- 2.20.1