Skip to content

Commit

Permalink
edac: move nr_pages to dimm struct
Browse files Browse the repository at this point in the history
The number of pages is a dimm property. Move it to the dimm struct.

After this change, it is possible to add sysfs nodes for the DIMM's that
will properly represent the DIMM stick properties, including its size.

A TODO fix here is to properly represent dual-rank/quad-rank DIMMs when
the memory controller represents the memory via chip select rows.

Reviewed-by: Aristeu Rozanski <arozansk@redhat.com>
Acked-by: Borislav Petkov <borislav.petkov@amd.com>
Acked-by: Chris Metcalf <cmetcalf@tilera.com>
Cc: Doug Thompson <norsk5@yahoo.com>
Cc: Mark Gross <mark.gross@intel.com>
Cc: Jason Uhlenkott <juhlenko@akamai.com>
Cc: Tim Small <tim@buttersideup.com>
Cc: Ranganathan Desikan <ravi@jetztechnologies.com>
Cc: "Arvind R." <arvino55@gmail.com>
Cc: Olof Johansson <olof@lixom.net>
Cc: Egor Martovetsky <egor@pasemi.com>
Cc: Michal Marek <mmarek@suse.cz>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Joe Perches <joe@perches.com>
Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Hitoshi Mitake <h.mitake@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: "Niklas Söderlund" <niklas.soderlund@ericsson.com>
Cc: Shaohui Xie <Shaohui.Xie@freescale.com>
Cc: Josh Boyer <jwboyer@gmail.com>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Mauro Carvalho Chehab committed May 28, 2012
1 parent 5e2af0c commit a895bf8
Show file tree
Hide file tree
Showing 28 changed files with 146 additions and 116 deletions.
10 changes: 6 additions & 4 deletions drivers/edac/amd64_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -2152,7 +2152,7 @@ static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT);

debugf0(" (csrow=%d) DBAM map index= %d\n", csrow_nr, cs_mode);
debugf0(" nr_pages= %u channel-count = %d\n",
debugf0(" nr_pages/channel= %u channel-count = %d\n",
nr_pages, pvt->channel_count);

return nr_pages;
Expand All @@ -2171,6 +2171,7 @@ static int init_csrows(struct mem_ctl_info *mci)
int i, j, empty = 1;
enum mem_type mtype;
enum edac_type edac_mode;
int nr_pages = 0;

amd64_read_pci_cfg(pvt->F3, NBCFG, &val);

Expand All @@ -2194,17 +2195,17 @@ static int init_csrows(struct mem_ctl_info *mci)

empty = 0;
if (csrow_enabled(i, 0, pvt))
csrow->nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
if (csrow_enabled(i, 1, pvt))
csrow->nr_pages += amd64_csrow_nr_pages(pvt, 1, i);
nr_pages += amd64_csrow_nr_pages(pvt, 1, i);

get_cs_base_and_mask(pvt, i, 0, &base, &mask);
/* 8 bytes of resolution */

mtype = amd64_determine_memory_type(pvt, i);

debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i);
debugf1(" nr_pages: %u\n", csrow->nr_pages);
debugf1(" nr_pages: %u\n", nr_pages * pvt->channel_count);

/*
* determine whether CHIPKILL or JUST ECC or NO ECC is operating
Expand All @@ -2218,6 +2219,7 @@ static int init_csrows(struct mem_ctl_info *mci)
for (j = 0; j < pvt->channel_count; j++) {
csrow->channels[j].dimm->mtype = mtype;
csrow->channels[j].dimm->edac_mode = edac_mode;
csrow->channels[j].dimm->nr_pages = nr_pages;
}
}

Expand Down
6 changes: 3 additions & 3 deletions drivers/edac/amd76x_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,10 @@ static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
pci_read_config_dword(pdev, AMD76X_DRAM_MODE_STATUS, &dms);
csrow->first_page = mba_base >> PAGE_SHIFT;
csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
dimm->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + dimm->nr_pages - 1;
csrow->page_mask = mba_mask >> PAGE_SHIFT;
dimm->grain = csrow->nr_pages << PAGE_SHIFT;
dimm->grain = dimm->nr_pages << PAGE_SHIFT;
dimm->mtype = MEM_RDDR;
dimm->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN;
dimm->edac_mode = edac_mode;
Expand Down
8 changes: 5 additions & 3 deletions drivers/edac/cell_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
struct cell_edac_priv *priv = mci->pvt_info;
struct device_node *np;
int j;
u32 nr_pages;

for (np = NULL;
(np = of_find_node_by_name(np, "memory")) != NULL;) {
Expand All @@ -142,19 +143,20 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
if (of_node_to_nid(np) != priv->node)
continue;
csrow->first_page = r.start >> PAGE_SHIFT;
csrow->nr_pages = resource_size(&r) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
nr_pages = resource_size(&r) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + nr_pages - 1;

for (j = 0; j < csrow->nr_channels; j++) {
dimm = csrow->channels[j].dimm;
dimm->mtype = MEM_XDR;
dimm->edac_mode = EDAC_SECDED;
dimm->nr_pages = nr_pages / csrow->nr_channels;
}
dev_dbg(mci->dev,
"Initialized on node %d, chanmask=0x%x,"
" first_page=0x%lx, nr_pages=0x%x\n",
priv->node, priv->chanmask,
csrow->first_page, csrow->nr_pages);
csrow->first_page, dimm->nr_pages);
break;
}
}
Expand Down
8 changes: 5 additions & 3 deletions drivers/edac/cpc925_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)
struct dimm_info *dimm;
int index, j;
u32 mbmr, mbbar, bba;
unsigned long row_size, last_nr_pages = 0;
unsigned long row_size, nr_pages, last_nr_pages = 0;

get_total_mem(pdata);

Expand All @@ -351,12 +351,14 @@ static void cpc925_init_csrows(struct mem_ctl_info *mci)

row_size = bba * (1UL << 28); /* 256M */
csrow->first_page = last_nr_pages;
csrow->nr_pages = row_size >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
nr_pages = row_size >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + nr_pages - 1;
last_nr_pages = csrow->last_page + 1;

for (j = 0; j < csrow->nr_channels; j++) {
dimm = csrow->channels[j].dimm;

dimm->nr_pages = nr_pages / csrow->nr_channels;
dimm->mtype = MEM_RDDR;
dimm->edac_mode = EDAC_SECDED;

Expand Down
6 changes: 4 additions & 2 deletions drivers/edac/e752x_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */
int drc_ddim; /* DRAM Data Integrity Mode 0=none, 2=edac */
u8 value;
u32 dra, drc, cumul_size, i;
u32 dra, drc, cumul_size, i, nr_pages;

dra = 0;
for (index = 0; index < 4; index++) {
Expand Down Expand Up @@ -1078,11 +1078,13 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,

csrow->first_page = last_cumul_size;
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;

for (i = 0; i < drc_chan + 1; i++) {
struct dimm_info *dimm = csrow->channels[i].dimm;

dimm->nr_pages = nr_pages / (drc_chan + 1);
dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */
dimm->mtype = MEM_RDDR; /* only one type supported */
dimm->dtype = mem_dev ? DEV_X4 : DEV_X8;
Expand Down
5 changes: 3 additions & 2 deletions drivers/edac/e7xxx_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
unsigned long last_cumul_size;
int index, j;
u8 value;
u32 dra, cumul_size;
u32 dra, cumul_size, nr_pages;
int drc_chan, drc_drbg, drc_ddim, mem_dev;
struct csrow_info *csrow;
struct dimm_info *dimm;
Expand Down Expand Up @@ -380,12 +380,13 @@ static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,

csrow->first_page = last_cumul_size;
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;

for (j = 0; j < drc_chan + 1; j++) {
dimm = csrow->channels[j].dimm;

dimm->nr_pages = nr_pages / (drc_chan + 1);
dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */
dimm->mtype = MEM_RDDR; /* only one type supported */
dimm->dtype = mem_dev ? DEV_X4 : DEV_X8;
Expand Down
16 changes: 10 additions & 6 deletions drivers/edac/edac_mc.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ static void edac_mc_dump_channel(struct rank_info *chan)
{
debugf4("\tchannel = %p\n", chan);
debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
debugf4("\tchannel->ce_count = %d\n", chan->dimm->ce_count);
debugf4("\tchannel->label = '%s'\n", chan->dimm->label);
debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
debugf4("\tdimm->ce_count = %d\n", chan->dimm->ce_count);
debugf4("\tdimm->label = '%s'\n", chan->dimm->label);
debugf4("\tdimm->nr_pages = 0x%x\n", chan->dimm->nr_pages);
}

static void edac_mc_dump_csrow(struct csrow_info *csrow)
Expand All @@ -55,7 +56,6 @@ static void edac_mc_dump_csrow(struct csrow_info *csrow)
debugf4("\tcsrow->first_page = 0x%lx\n", csrow->first_page);
debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page);
debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask);
debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages);
debugf4("\tcsrow->nr_channels = %d\n", csrow->nr_channels);
debugf4("\tcsrow->channels = %p\n", csrow->channels);
debugf4("\tcsrow->mci = %p\n\n", csrow->mci);
Expand Down Expand Up @@ -652,15 +652,19 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset,
int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page)
{
struct csrow_info *csrows = mci->csrows;
int row, i;
int row, i, j, n;

debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page);
row = -1;

for (i = 0; i < mci->nr_csrows; i++) {
struct csrow_info *csrow = &csrows[i];

if (csrow->nr_pages == 0)
n = 0;
for (j = 0; j < csrow->nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j].dimm;
n += dimm->nr_pages;
}
if (n == 0)
continue;

debugf3("MC%d: %s(): first(0x%lx) page(0x%lx) last(0x%lx) "
Expand Down
47 changes: 33 additions & 14 deletions drivers/edac/edac_mc_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,13 @@ static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data,
static ssize_t csrow_size_show(struct csrow_info *csrow, char *data,
int private)
{
return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages));
int i;
u32 nr_pages = 0;

for (i = 0; i < csrow->nr_channels; i++)
nr_pages += csrow->channels[i].dimm->nr_pages;

return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages));
}

static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data,
Expand Down Expand Up @@ -519,16 +525,16 @@ static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)

static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
{
int total_pages, csrow_idx;
int total_pages = 0, csrow_idx, j;

for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows;
csrow_idx++) {
for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) {
struct csrow_info *csrow = &mci->csrows[csrow_idx];

if (!csrow->nr_pages)
continue;
for (j = 0; j < csrow->nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j].dimm;

total_pages += csrow->nr_pages;
total_pages += dimm->nr_pages;
}
}

return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages));
Expand Down Expand Up @@ -900,7 +906,7 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
*/
int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
{
int i;
int i, j;
int err;
struct csrow_info *csrow;
struct kobject *kobj_mci = &mci->edac_mci_kobj;
Expand Down Expand Up @@ -934,10 +940,13 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
/* Make directories for each CSROW object under the mc<id> kobject
*/
for (i = 0; i < mci->nr_csrows; i++) {
int nr_pages = 0;

csrow = &mci->csrows[i];
for (j = 0; j < csrow->nr_channels; j++)
nr_pages += csrow->channels[j].dimm->nr_pages;

/* Only expose populated CSROWs */
if (csrow->nr_pages > 0) {
if (nr_pages > 0) {
err = edac_create_csrow_object(mci, csrow, i);
if (err) {
debugf1("%s() failure: create csrow %d obj\n",
Expand All @@ -949,10 +958,14 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)

return 0;

/* CSROW error: backout what has already been registered, */
fail1:
for (i--; i >= 0; i--) {
if (mci->csrows[i].nr_pages > 0)
int nr_pages = 0;

csrow = &mci->csrows[i];
for (j = 0; j < csrow->nr_channels; j++)
nr_pages += csrow->channels[j].dimm->nr_pages;
if (nr_pages > 0)
kobject_put(&mci->csrows[i].kobj);
}

Expand All @@ -972,14 +985,20 @@ 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 csrow_info *csrow;
int i, j;

debugf0("%s()\n", __func__);

/* remove all csrow kobjects */
debugf4("%s() unregister this mci kobj\n", __func__);
for (i = 0; i < mci->nr_csrows; i++) {
if (mci->csrows[i].nr_pages > 0) {
int nr_pages = 0;

csrow = &mci->csrows[i];
for (j = 0; j < csrow->nr_channels; j++)
nr_pages += csrow->channels[j].dimm->nr_pages;
if (nr_pages > 0) {
debugf0("%s() unreg csrow-%d\n", __func__, i);
kobject_put(&mci->csrows[i].kobj);
}
Expand Down
6 changes: 4 additions & 2 deletions drivers/edac/i3000_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
int rc;
int i, j;
struct mem_ctl_info *mci = NULL;
unsigned long last_cumul_size;
unsigned long last_cumul_size, nr_pages;
int interleaved, nr_channels;
unsigned char dra[I3000_RANKS / 2], drb[I3000_RANKS];
unsigned char *c0dra = dra, *c1dra = &dra[I3000_RANKS_PER_CHANNEL / 2];
Expand Down Expand Up @@ -391,11 +391,13 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)

csrow->first_page = last_cumul_size;
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;

for (j = 0; j < nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j].dimm;

dimm->nr_pages = nr_pages / nr_channels;
dimm->grain = I3000_DEAP_GRAIN;
dimm->mtype = MEM_DDR2;
dimm->dtype = DEV_UNKNOWN;
Expand Down
3 changes: 1 addition & 2 deletions drivers/edac/i3200_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,10 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
if (nr_pages == 0)
continue;

csrow->nr_pages = nr_pages;

for (j = 0; j < nr_channels; j++) {
struct dimm_info *dimm = csrow->channels[j].dimm;

dimm->nr_pages = nr_pages / nr_channels;
dimm->grain = nr_pages << PAGE_SHIFT;
dimm->mtype = MEM_DDR2;
dimm->dtype = DEV_UNKNOWN;
Expand Down
14 changes: 8 additions & 6 deletions drivers/edac/i5000_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,7 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)
{
struct i5000_pvt *pvt;
struct csrow_info *p_csrow;
struct dimm_info *dimm;
int empty, channel_count;
int max_csrows;
int mtr, mtr1;
Expand Down Expand Up @@ -1265,21 +1266,22 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)

csrow_megs = 0;
for (channel = 0; channel < pvt->maxch; channel++) {
dimm = p_csrow->channels[channel].dimm;
csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
p_csrow->channels[channel].dimm->grain = 8;
dimm->grain = 8;

/* Assume DDR2 for now */
p_csrow->channels[channel].dimm->mtype = MEM_FB_DDR2;
dimm->mtype = MEM_FB_DDR2;

/* ask what device type on this row */
if (MTR_DRAM_WIDTH(mtr))
p_csrow->channels[channel].dimm->dtype = DEV_X8;
dimm->dtype = DEV_X8;
else
p_csrow->channels[channel].dimm->dtype = DEV_X4;
dimm->dtype = DEV_X4;

p_csrow->channels[channel].dimm->edac_mode = EDAC_S8ECD8ED;
dimm->edac_mode = EDAC_S8ECD8ED;
dimm->nr_pages = (csrow_megs << 8) / pvt->maxch;
}
p_csrow->nr_pages = csrow_megs << 8;

empty = 0;
}
Expand Down
Loading

0 comments on commit a895bf8

Please sign in to comment.