diff options
author | Arvind R <arvino55@gmail.com> | 2011-01-25 12:08:53 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-02-17 10:47:04 -0500 |
commit | cb60a422694e03c2a8d5d2c551a06a3039072332 (patch) | |
tree | 6d68f21649aa638fcc2e16b63e76a23e0d2cc128 /drivers/edac | |
parent | da95b3d21f41da39ee716e0db781de4b9ffbb233 (diff) |
edac: correct i82975x error-info reported
to edac-core
fix the totally wrong info w.r.t page,row,dimm-label previously reported to
edac-core by i82975x driver
Signed-off-by: Arvind R. <arvino55@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/i82975x_edac.c | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 37849625647f..92e65e7038e9 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c | |||
@@ -278,6 +278,7 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, | |||
278 | struct i82975x_error_info *info, int handle_errors) | 278 | struct i82975x_error_info *info, int handle_errors) |
279 | { | 279 | { |
280 | int row, multi_chan, chan; | 280 | int row, multi_chan, chan; |
281 | unsigned long offst, page; | ||
281 | 282 | ||
282 | multi_chan = mci->csrows[0].nr_channels - 1; | 283 | multi_chan = mci->csrows[0].nr_channels - 1; |
283 | 284 | ||
@@ -292,17 +293,19 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci, | |||
292 | info->errsts = info->errsts2; | 293 | info->errsts = info->errsts2; |
293 | } | 294 | } |
294 | 295 | ||
295 | chan = info->eap & 1; | 296 | page = (unsigned long) info->eap; |
296 | info->eap >>= 1; | 297 | if (info->xeap & 1) |
297 | if (info->xeap ) | 298 | page |= 0x100000000ul; |
298 | info->eap |= 0x80000000; | 299 | chan = page & 1; |
299 | info->eap >>= PAGE_SHIFT; | 300 | page >>= 1; |
300 | row = edac_mc_find_csrow_by_page(mci, info->eap); | 301 | offst = page & ((1 << PAGE_SHIFT) - 1); |
302 | page >>= PAGE_SHIFT; | ||
303 | row = edac_mc_find_csrow_by_page(mci, page); | ||
301 | 304 | ||
302 | if (info->errsts & 0x0002) | 305 | if (info->errsts & 0x0002) |
303 | edac_mc_handle_ue(mci, info->eap, 0, row, "i82975x UE"); | 306 | edac_mc_handle_ue(mci, page, offst , row, "i82975x UE"); |
304 | else | 307 | else |
305 | edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, | 308 | edac_mc_handle_ce(mci, page, offst, info->derrsyn, row, |
306 | multi_chan ? chan : 0, | 309 | multi_chan ? chan : 0, |
307 | "i82975x CE"); | 310 | "i82975x CE"); |
308 | 311 | ||
@@ -352,11 +355,15 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank) | |||
352 | static void i82975x_init_csrows(struct mem_ctl_info *mci, | 355 | static void i82975x_init_csrows(struct mem_ctl_info *mci, |
353 | struct pci_dev *pdev, void __iomem *mch_window) | 356 | struct pci_dev *pdev, void __iomem *mch_window) |
354 | { | 357 | { |
358 | static const char *labels[4] = { | ||
359 | "DIMM A1", "DIMM A2", | ||
360 | "DIMM B1", "DIMM B2" | ||
361 | }; | ||
355 | struct csrow_info *csrow; | 362 | struct csrow_info *csrow; |
356 | unsigned long last_cumul_size; | 363 | unsigned long last_cumul_size; |
357 | u8 value; | 364 | u8 value; |
358 | u32 cumul_size; | 365 | u32 cumul_size; |
359 | int index; | 366 | int index, chan; |
360 | 367 | ||
361 | last_cumul_size = 0; | 368 | last_cumul_size = 0; |
362 | 369 | ||
@@ -365,11 +372,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, | |||
365 | * The dram row boundary (DRB) reg values are boundary address | 372 | * The dram row boundary (DRB) reg values are boundary address |
366 | * for each DRAM row with a granularity of 32 or 64MB (single/dual | 373 | * for each DRAM row with a granularity of 32 or 64MB (single/dual |
367 | * channel operation). DRB regs are cumulative; therefore DRB7 will | 374 | * channel operation). DRB regs are cumulative; therefore DRB7 will |
368 | * contain the total memory contained in all eight rows. | 375 | * contain the total memory contained in all rows. |
369 | * | ||
370 | * FIXME: | ||
371 | * EDAC currently works for Dual-channel Interleaved configuration. | ||
372 | * Other configurations, which the chip supports, need fixing/testing. | ||
373 | * | 376 | * |
374 | */ | 377 | */ |
375 | 378 | ||
@@ -380,8 +383,26 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, | |||
380 | ((index >= 4) ? 0x80 : 0)); | 383 | ((index >= 4) ? 0x80 : 0)); |
381 | cumul_size = value; | 384 | cumul_size = value; |
382 | cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT); | 385 | cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT); |
386 | /* | ||
387 | * Adjust cumul_size w.r.t number of channels | ||
388 | * | ||
389 | */ | ||
390 | if (csrow->nr_channels > 1) | ||
391 | cumul_size <<= 1; | ||
383 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, | 392 | debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, |
384 | cumul_size); | 393 | cumul_size); |
394 | |||
395 | /* | ||
396 | * Initialise dram labels | ||
397 | * index values: | ||
398 | * [0-7] for single-channel; i.e. csrow->nr_channels = 1 | ||
399 | * [0-3] for dual-channel; i.e. csrow->nr_channels = 2 | ||
400 | */ | ||
401 | for (chan = 0; chan < csrow->nr_channels; chan++) | ||
402 | strncpy(csrow->channels[chan].label, | ||
403 | labels[(index >> 1) + (chan * 2)], | ||
404 | EDAC_MC_LABEL_LEN); | ||
405 | |||
385 | if (cumul_size == last_cumul_size) | 406 | if (cumul_size == last_cumul_size) |
386 | continue; /* not populated */ | 407 | continue; /* not populated */ |
387 | 408 | ||
@@ -389,8 +410,8 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci, | |||
389 | csrow->last_page = cumul_size - 1; | 410 | csrow->last_page = cumul_size - 1; |
390 | csrow->nr_pages = cumul_size - last_cumul_size; | 411 | csrow->nr_pages = cumul_size - last_cumul_size; |
391 | last_cumul_size = cumul_size; | 412 | last_cumul_size = cumul_size; |
392 | csrow->grain = 1 << 7; /* I82975X_EAP has 128B resolution */ | 413 | csrow->grain = 1 << 6; /* I82975X_EAP has 64B resolution */ |
393 | csrow->mtype = MEM_DDR; /* i82975x supports only DDR2 */ | 414 | csrow->mtype = MEM_DDR2; /* I82975x supports only DDR2 */ |
394 | csrow->dtype = i82975x_dram_type(mch_window, index); | 415 | csrow->dtype = i82975x_dram_type(mch_window, index); |
395 | csrow->edac_mode = EDAC_SECDED; /* only supported */ | 416 | csrow->edac_mode = EDAC_SECDED; /* only supported */ |
396 | } | 417 | } |