From dc0a50a8411e2a3a3ca5a9d97581bbc5420c2687 Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Wed, 3 Aug 2016 10:59:15 -0400 Subject: [PATCH] EDAC, amd64: Fix channel decode on Fam15hMod60h systems Fam15hMod60h systems are using the channel decode of Fam15hMod30h which gives incorrect results. Fam15hMod60h systems should use the generic channel decode method plus a couple more cases. Signed-off-by: Yazen Ghannam Cc: Aravind Gopalakrishnan Cc: linux-edac Link: http://lkml.kernel.org/r/1470236355-30039-1-git-send-email-Yazen.Ghannam@amd.com Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 8c0ec2128907..da43404dbd0c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1425,11 +1425,17 @@ static u8 f1x_determine_channel(struct amd64_pvt *pvt, u64 sys_addr, if (intlv_addr & 0x2) { u8 shift = intlv_addr & 0x1 ? 9 : 6; - u32 temp = hweight_long((u32) ((sys_addr >> 16) & 0x1F)) % 2; + u32 temp = hweight_long((u32) ((sys_addr >> 16) & 0x1F)) & 1; return ((sys_addr >> shift) & 1) ^ temp; } + if (intlv_addr & 0x4) { + u8 shift = intlv_addr & 0x1 ? 9 : 8; + + return (sys_addr >> shift) & 1; + } + return (sys_addr >> (12 + hweight8(intlv_en))) & 1; } @@ -1726,8 +1732,11 @@ static int f15_m30h_match_to_this_node(struct amd64_pvt *pvt, unsigned range, if (!(num_dcts_intlv % 2 == 0) || (num_dcts_intlv > 4)) return -EINVAL; - channel = f15_m30h_determine_channel(pvt, sys_addr, intlv_en, - num_dcts_intlv, dct_sel); + if (pvt->model >= 0x60) + channel = f1x_determine_channel(pvt, sys_addr, false, intlv_en); + else + channel = f15_m30h_determine_channel(pvt, sys_addr, intlv_en, + num_dcts_intlv, dct_sel); /* Verify we stay within the MAX number of channels allowed */ if (channel > 3) -- 2.39.5