Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 309133
b: refs/heads/master
c: 64e1fda
h: refs/heads/master
i:
  309131: 433a731
v: v3
  • Loading branch information
Mauro Carvalho Chehab committed May 28, 2012
1 parent 87ca15b commit 3a7992c
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 72 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 68d086f89b8064d5576f8c1e47fa7ecb4fd6f141
refs/heads/master: 64e1fdaf55d61eb79ae970f78bb00edf6aa696fb
150 changes: 79 additions & 71 deletions trunk/drivers/edac/i5000_edac.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@
#define MTR3 0x8C

#define NUM_MTRS 4
#define CHANNELS_PER_BRANCH (2)
#define CHANNELS_PER_BRANCH 2
#define MAX_BRANCHES 2

/* Defines to extract the vaious fields from the
* MTRx - Memory Technology Registers
Expand Down Expand Up @@ -962,14 +963,14 @@ static int determine_amb_present_reg(struct i5000_pvt *pvt, int channel)
*
* return the proper MTR register as determine by the csrow and channel desired
*/
static int determine_mtr(struct i5000_pvt *pvt, int csrow, int channel)
static int determine_mtr(struct i5000_pvt *pvt, int slot, int channel)
{
int mtr;

if (channel < CHANNELS_PER_BRANCH)
mtr = pvt->b0_mtr[csrow >> 1];
mtr = pvt->b0_mtr[slot];
else
mtr = pvt->b1_mtr[csrow >> 1];
mtr = pvt->b1_mtr[slot];

return mtr;
}
Expand All @@ -994,37 +995,34 @@ static void decode_mtr(int slot_row, u16 mtr)
debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]);
}

static void handle_channel(struct i5000_pvt *pvt, int csrow, int channel,
static void handle_channel(struct i5000_pvt *pvt, int slot, int channel,
struct i5000_dimm_info *dinfo)
{
int mtr;
int amb_present_reg;
int addrBits;

mtr = determine_mtr(pvt, csrow, channel);
mtr = determine_mtr(pvt, slot, channel);
if (MTR_DIMMS_PRESENT(mtr)) {
amb_present_reg = determine_amb_present_reg(pvt, channel);

/* Determine if there is a DIMM present in this DIMM slot */
if (amb_present_reg & (1 << (csrow >> 1))) {
/* Determine if there is a DIMM present in this DIMM slot */
if (amb_present_reg) {
dinfo->dual_rank = MTR_DIMM_RANK(mtr);

if (!((dinfo->dual_rank == 0) &&
((csrow & 0x1) == 0x1))) {
/* Start with the number of bits for a Bank
* on the DRAM */
addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
/* Add thenumber of ROW bits */
addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
/* add the number of COLUMN bits */
addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);

addrBits += 6; /* add 64 bits per DIMM */
addrBits -= 20; /* divide by 2^^20 */
addrBits -= 3; /* 8 bits per bytes */

dinfo->megabytes = 1 << addrBits;
}
/* Start with the number of bits for a Bank
* on the DRAM */
addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
/* Add the number of ROW bits */
addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
/* add the number of COLUMN bits */
addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);

addrBits += 6; /* add 64 bits per DIMM */
addrBits -= 20; /* divide by 2^^20 */
addrBits -= 3; /* 8 bits per bytes */

dinfo->megabytes = 1 << addrBits;
}
}
}
Expand All @@ -1038,10 +1036,9 @@ static void handle_channel(struct i5000_pvt *pvt, int csrow, int channel,
static void calculate_dimm_size(struct i5000_pvt *pvt)
{
struct i5000_dimm_info *dinfo;
int csrow, max_csrows;
int slot, channel, branch;
char *p, *mem_buffer;
int space, n;
int channel;

/* ================= Generate some debug output ================= */
space = PAGE_SIZE;
Expand All @@ -1052,63 +1049,75 @@ static void calculate_dimm_size(struct i5000_pvt *pvt)
return;
}

n = snprintf(p, space, "\n");
p += n;
space -= n;

/* Scan all the actual CSROWS (which is # of DIMMS * 2)
/* Scan all the actual slots
* and calculate the information for each DIMM
* Start with the highest csrow first, to display it first
* and work toward the 0th csrow
* Start with the highest slot first, to display it first
* and work toward the 0th slot
*/
max_csrows = pvt->maxdimmperch * 2;
for (csrow = max_csrows - 1; csrow >= 0; csrow--) {
for (slot = pvt->maxdimmperch - 1; slot >= 0; slot--) {

/* on an odd csrow, first output a 'boundary' marker,
/* on an odd slot, first output a 'boundary' marker,
* then reset the message buffer */
if (csrow & 0x1) {
n = snprintf(p, space, "---------------------------"
if (slot & 0x1) {
n = snprintf(p, space, "--------------------------"
"--------------------------------");
p += n;
space -= n;
debugf2("%s\n", mem_buffer);
p = mem_buffer;
space = PAGE_SIZE;
}
n = snprintf(p, space, "csrow %2d ", csrow);
n = snprintf(p, space, "slot %2d ", slot);
p += n;
space -= n;

for (channel = 0; channel < pvt->maxch; channel++) {
dinfo = &pvt->dimm_info[csrow][channel];
handle_channel(pvt, csrow, channel, dinfo);
n = snprintf(p, space, "%4d MB | ", dinfo->megabytes);
dinfo = &pvt->dimm_info[slot][channel];
handle_channel(pvt, slot, channel, dinfo);
if (dinfo->megabytes)
n = snprintf(p, space, "%4d MB %dR| ",
dinfo->megabytes, dinfo->dual_rank + 1);
else
n = snprintf(p, space, "%4d MB | ", 0);
p += n;
space -= n;
}
n = snprintf(p, space, "\n");
p += n;
space -= n;
debugf2("%s\n", mem_buffer);
p = mem_buffer;
space = PAGE_SIZE;
}

/* Output the last bottom 'boundary' marker */
n = snprintf(p, space, "---------------------------"
"--------------------------------\n");
n = snprintf(p, space, "--------------------------"
"--------------------------------");
p += n;
space -= n;
debugf2("%s\n", mem_buffer);
p = mem_buffer;
space = PAGE_SIZE;

/* now output the 'channel' labels */
n = snprintf(p, space, " ");
n = snprintf(p, space, " ");
p += n;
space -= n;
for (channel = 0; channel < pvt->maxch; channel++) {
n = snprintf(p, space, "channel %d | ", channel);
p += n;
space -= n;
}
n = snprintf(p, space, "\n");
debugf2("%s\n", mem_buffer);
p = mem_buffer;
space = PAGE_SIZE;

n = snprintf(p, space, " ");
p += n;
space -= n;
for (branch = 0; branch < MAX_BRANCHES; branch++) {
n = snprintf(p, space, " branch %d | ", branch);
p += n;
space -= n;
}

/* output the last message and free buffer */
debugf2("%s\n", mem_buffer);
Expand Down Expand Up @@ -1241,14 +1250,13 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci)
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;
int mtr;
int csrow_megs;
int channel;
int csrow;
int slot;

pvt = mci->pvt_info;

Expand All @@ -1258,26 +1266,25 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)
empty = 1; /* Assume NO memory */

/*
* TODO: it would be better to not use csrow here, filling
* directly the dimm_info structs, based on branch, channel, dim number
* FIXME: The memory layout used to map slot/channel into the
* real memory architecture is weird: branch+slot are "csrows"
* and channel is channel. That required an extra array (dimm_info)
* to map the dimms. A good cleanup would be to remove this array,
* and do a loop here with branch, channel, slot
*/
for (csrow = 0; csrow < max_csrows; csrow++) {
p_csrow = &mci->csrows[csrow];
for (slot = 0; slot < max_csrows; slot++) {
for (channel = 0; channel < pvt->maxch; channel++) {

p_csrow->csrow_idx = csrow;
mtr = determine_mtr(pvt, slot, channel);

/* use branch 0 for the basis */
mtr = pvt->b0_mtr[csrow >> 1];
mtr1 = pvt->b1_mtr[csrow >> 1];
if (!MTR_DIMMS_PRESENT(mtr))
continue;

/* if no DIMMS on this row, continue */
if (!MTR_DIMMS_PRESENT(mtr) && !MTR_DIMMS_PRESENT(mtr1))
continue;
dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers,
channel / MAX_BRANCHES,
channel % MAX_BRANCHES, slot);

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

/* Assume DDR2 for now */
Expand All @@ -1290,7 +1297,7 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)
dimm->dtype = DEV_X4;

dimm->edac_mode = EDAC_S8ECD8ED;
dimm->nr_pages = (csrow_megs << 8) / pvt->maxch;
dimm->nr_pages = csrow_megs << 8;
}

empty = 0;
Expand Down Expand Up @@ -1337,7 +1344,7 @@ static void i5000_get_dimm_and_channel_counts(struct pci_dev *pdev,
* supported on this memory controller
*/
pci_read_config_byte(pdev, MAXDIMMPERCH, &value);
*num_dimms_per_channel = (int)value *2;
*num_dimms_per_channel = (int)value;

pci_read_config_byte(pdev, MAXCH, &value);
*num_channels = (int)value;
Expand Down Expand Up @@ -1387,11 +1394,12 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
__func__, num_channels, num_dimms_per_channel);

/* allocate a new MC control structure */

layers[0].type = EDAC_MC_LAYER_BRANCH;
layers[0].size = 2;
layers[0].is_virt_csrow = true;
layers[0].size = MAX_BRANCHES;
layers[0].is_virt_csrow = false;
layers[1].type = EDAC_MC_LAYER_CHANNEL;
layers[1].size = num_channels;
layers[1].size = num_channels / MAX_BRANCHES;
layers[1].is_virt_csrow = false;
layers[2].type = EDAC_MC_LAYER_SLOT;
layers[2].size = num_dimms_per_channel;
Expand Down

0 comments on commit 3a7992c

Please sign in to comment.