aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-09-20 12:09:30 -0300
committerBen Hutchings <ben@decadent.org.uk>2012-10-10 03:31:05 +0100
commitb39bfb4cc09a0663d13b537e69e8241e6cc8ce71 (patch)
tree9330ed8dbeeb71692dea0f928d4e3da14d7fda62 /drivers/edac
parent247a9ca13ccd0e1cfd81b481e91d365950eaeaaf (diff)
downloadkernel_samsung_smdk4412-b39bfb4cc09a0663d13b537e69e8241e6cc8ce71.zip
kernel_samsung_smdk4412-b39bfb4cc09a0663d13b537e69e8241e6cc8ce71.tar.gz
kernel_samsung_smdk4412-b39bfb4cc09a0663d13b537e69e8241e6cc8ce71.tar.bz2
sb_edac: Avoid overflow errors at memory size calculation
commit deb09ddaff1435f72dd598d38f9b58354c68a5ec upstream. Sandy bridge EDAC is calculating the memory size with overflow. Basically, the size field and the integer calculation is using 32 bits. More bits are needed, when the DIMM memories have high density. The net result is that memories are improperly reported there, when high-density DIMMs are used: EDAC DEBUG: in drivers/edac/sb_edac.c, line at 591: mc#0: channel 0, dimm 0, -16384 Mb (-4194304 pages) bank: 8, rank: 2, row: 0x10000, col: 0x800 EDAC DEBUG: in drivers/edac/sb_edac.c, line at 591: mc#0: channel 1, dimm 0, -16384 Mb (-4194304 pages) bank: 8, rank: 2, row: 0x10000, col: 0x800 As the number of pages value is handled at the EDAC core as unsigned ints, the driver shows the 16 GB memories at sysfs interface as 16760832 MB! The fix is simple: calculate the number of pages as unsigned 64-bits integer. After the patch, the memory size (16 GB) is properly detected: EDAC DEBUG: in drivers/edac/sb_edac.c, line at 592: mc#0: channel 0, dimm 0, 16384 Mb (4194304 pages) bank: 8, rank: 2, row: 0x10000, col: 0x800 EDAC DEBUG: in drivers/edac/sb_edac.c, line at 592: mc#0: channel 1, dimm 0, 16384 Mb (4194304 pages) bank: 8, rank: 2, row: 0x10000, col: 0x800 Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> [bwh: Backported to 3.2: - Adjust context - Debug log function is debugf0(), not edac_dbg()] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/sb_edac.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 0db57b5..da71881 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -554,7 +554,8 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
{
struct sbridge_pvt *pvt = mci->pvt_info;
struct csrow_info *csr;
- int i, j, banks, ranks, rows, cols, size, npages;
+ unsigned i, j, banks, ranks, rows, cols, npages;
+ u64 size;
int csrow = 0;
unsigned long last_page = 0;
u32 reg;
@@ -626,10 +627,10 @@ static int get_dimm_config(const struct mem_ctl_info *mci)
cols = numcol(mtr);
/* DDR3 has 8 I/O banks */
- size = (rows * cols * banks * ranks) >> (20 - 3);
+ size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
npages = MiB_TO_PAGES(size);
- debugf0("mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+ debugf0("mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
pvt->sbridge_dev->mc, i, j,
size, npages,
banks, ranks, rows, cols);