diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0038-EDAC-amd64-Add-context-struct.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0038-EDAC-amd64-Add-context-struct.patch | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0038-EDAC-amd64-Add-context-struct.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0038-EDAC-amd64-Add-context-struct.patch new file mode 100644 index 00000000..d926db48 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0038-EDAC-amd64-Add-context-struct.patch @@ -0,0 +1,229 @@ +From 7433822f70045cce83e1f949972e03e008a5a9ec Mon Sep 17 00:00:00 2001 +From: Yazen Ghannam <yazen.ghannam@amd.com> +Date: Thu, 28 Oct 2021 17:56:59 +0000 +Subject: [PATCH 38/86] EDAC/amd64: Add context struct + +commit 70aeb807cf8649dedbcd59b70dfc38fb89bdf1bd upstream + +Define an address translation context struct. This will hold values that +will be passed between multiple functions. + +Save return address, Node ID, and the Instance ID number to start. +Currently, the UMC number is used as the Instance ID, but future DF +versions may use another value. + +Also include a "tmp" field to use when reading registers. This is to +avoid having to define a temporary variable in multiple functions. + +Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com> +Signed-off-by: Borislav Petkov <bp@suse.de> +Link: https://lkml.kernel.org/r/20211028175728.121452-5-yazen.ghannam@amd.com +Signed-off-by: Zhaolong Zhang <zhaolong.zhang@windriver.com> +--- + drivers/edac/amd64_edac.c | 97 ++++++++++++++++++++++----------------- + 1 file changed, 55 insertions(+), 42 deletions(-) + +diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c +index d41b9a02cc7d..ca0c67bc25c6 100644 +--- a/drivers/edac/amd64_edac.c ++++ b/drivers/edac/amd64_edac.c +@@ -1051,13 +1051,16 @@ static int df_indirect_read_broadcast(u16 node, u8 func, u16 reg, u32 *lo) + return __df_indirect_read(node, func, reg, DF_BROADCAST, lo); + } + ++struct addr_ctx { ++ u64 ret_addr; ++ u32 tmp; ++ u16 nid; ++ u8 inst_id; ++}; ++ + static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) + { + u64 dram_base_addr, dram_limit_addr, dram_hole_base; +- /* We start from the normalized address */ +- u64 ret_addr = norm_addr; +- +- u32 tmp; + + u8 die_id_shift, die_id_mask, socket_id_shift, socket_id_mask; + u8 intlv_num_dies, intlv_num_chan, intlv_num_sockets; +@@ -1067,35 +1070,45 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr + u8 cs_mask, cs_id = 0; + bool hash_enabled = false; + ++ struct addr_ctx ctx; ++ ++ memset(&ctx, 0, sizeof(ctx)); ++ ++ /* Start from the normalized address */ ++ ctx.ret_addr = norm_addr; ++ ++ ctx.nid = nid; ++ ctx.inst_id = umc; ++ + /* Read D18F0x1B4 (DramOffset), check if base 1 is used. */ +- if (df_indirect_read_instance(nid, 0, 0x1B4, umc, &tmp)) ++ if (df_indirect_read_instance(nid, 0, 0x1B4, umc, &ctx.tmp)) + goto out_err; + + /* Remove HiAddrOffset from normalized address, if enabled: */ +- if (tmp & BIT(0)) { +- u64 hi_addr_offset = (tmp & GENMASK_ULL(31, 20)) << 8; ++ if (ctx.tmp & BIT(0)) { ++ u64 hi_addr_offset = (ctx.tmp & GENMASK_ULL(31, 20)) << 8; + + if (norm_addr >= hi_addr_offset) { +- ret_addr -= hi_addr_offset; ++ ctx.ret_addr -= hi_addr_offset; + base = 1; + } + } + + /* Read D18F0x110 (DramBaseAddress). */ +- if (df_indirect_read_instance(nid, 0, 0x110 + (8 * base), umc, &tmp)) ++ if (df_indirect_read_instance(nid, 0, 0x110 + (8 * base), umc, &ctx.tmp)) + goto out_err; + + /* Check if address range is valid. */ +- if (!(tmp & BIT(0))) { ++ if (!(ctx.tmp & BIT(0))) { + pr_err("%s: Invalid DramBaseAddress range: 0x%x.\n", +- __func__, tmp); ++ __func__, ctx.tmp); + goto out_err; + } + +- lgcy_mmio_hole_en = tmp & BIT(1); +- intlv_num_chan = (tmp >> 4) & 0xF; +- intlv_addr_sel = (tmp >> 8) & 0x7; +- dram_base_addr = (tmp & GENMASK_ULL(31, 12)) << 16; ++ lgcy_mmio_hole_en = ctx.tmp & BIT(1); ++ intlv_num_chan = (ctx.tmp >> 4) & 0xF; ++ intlv_addr_sel = (ctx.tmp >> 8) & 0x7; ++ dram_base_addr = (ctx.tmp & GENMASK_ULL(31, 12)) << 16; + + /* {0, 1, 2, 3} map to address bits {8, 9, 10, 11} respectively */ + if (intlv_addr_sel > 3) { +@@ -1105,12 +1118,12 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr + } + + /* Read D18F0x114 (DramLimitAddress). */ +- if (df_indirect_read_instance(nid, 0, 0x114 + (8 * base), umc, &tmp)) ++ if (df_indirect_read_instance(nid, 0, 0x114 + (8 * base), umc, &ctx.tmp)) + goto out_err; + +- intlv_num_sockets = (tmp >> 8) & 0x1; +- intlv_num_dies = (tmp >> 10) & 0x3; +- dram_limit_addr = ((tmp & GENMASK_ULL(31, 12)) << 16) | GENMASK_ULL(27, 0); ++ intlv_num_sockets = (ctx.tmp >> 8) & 0x1; ++ intlv_num_dies = (ctx.tmp >> 10) & 0x3; ++ dram_limit_addr = ((ctx.tmp & GENMASK_ULL(31, 12)) << 16) | GENMASK_ULL(27, 0); + + intlv_addr_bit = intlv_addr_sel + 8; + +@@ -1161,10 +1174,10 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr + * umc/channel# as instance id of the coherent slave + * for FICAA. + */ +- if (df_indirect_read_instance(nid, 0, 0x50, umc, &tmp)) ++ if (df_indirect_read_instance(nid, 0, 0x50, umc, &ctx.tmp)) + goto out_err; + +- cs_fabric_id = (tmp >> 8) & 0xFF; ++ cs_fabric_id = (ctx.tmp >> 8) & 0xFF; + die_id_bit = 0; + + /* If interleaved over more than 1 channel: */ +@@ -1178,22 +1191,22 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr + + /* Read D18F1x208 (SystemFabricIdMask). */ + if (intlv_num_dies || intlv_num_sockets) +- if (df_indirect_read_broadcast(nid, 1, 0x208, &tmp)) ++ if (df_indirect_read_broadcast(nid, 1, 0x208, &ctx.tmp)) + goto out_err; + + /* If interleaved over more than 1 die. */ + if (intlv_num_dies) { + sock_id_bit = die_id_bit + intlv_num_dies; +- die_id_shift = (tmp >> 24) & 0xF; +- die_id_mask = (tmp >> 8) & 0xFF; ++ die_id_shift = (ctx.tmp >> 24) & 0xF; ++ die_id_mask = (ctx.tmp >> 8) & 0xFF; + + cs_id |= ((cs_fabric_id & die_id_mask) >> die_id_shift) << die_id_bit; + } + + /* If interleaved over more than 1 socket. */ + if (intlv_num_sockets) { +- socket_id_shift = (tmp >> 28) & 0xF; +- socket_id_mask = (tmp >> 16) & 0xFF; ++ socket_id_shift = (ctx.tmp >> 28) & 0xF; ++ socket_id_mask = (ctx.tmp >> 16) & 0xFF; + + cs_id |= ((cs_fabric_id & socket_id_mask) >> socket_id_shift) << sock_id_bit; + } +@@ -1206,44 +1219,44 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr + * bits there are. "intlv_addr_bit" tells us how many "Y" bits + * there are (where "I" starts). + */ +- temp_addr_y = ret_addr & GENMASK_ULL(intlv_addr_bit-1, 0); ++ temp_addr_y = ctx.ret_addr & GENMASK_ULL(intlv_addr_bit - 1, 0); + temp_addr_i = (cs_id << intlv_addr_bit); +- temp_addr_x = (ret_addr & GENMASK_ULL(63, intlv_addr_bit)) << num_intlv_bits; +- ret_addr = temp_addr_x | temp_addr_i | temp_addr_y; ++ temp_addr_x = (ctx.ret_addr & GENMASK_ULL(63, intlv_addr_bit)) << num_intlv_bits; ++ ctx.ret_addr = temp_addr_x | temp_addr_i | temp_addr_y; + } + + /* Add dram base address */ +- ret_addr += dram_base_addr; ++ ctx.ret_addr += dram_base_addr; + + /* If legacy MMIO hole enabled */ + if (lgcy_mmio_hole_en) { +- if (df_indirect_read_broadcast(nid, 0, 0x104, &tmp)) ++ if (df_indirect_read_broadcast(nid, 0, 0x104, &ctx.tmp)) + goto out_err; + +- dram_hole_base = tmp & GENMASK(31, 24); +- if (ret_addr >= dram_hole_base) +- ret_addr += (BIT_ULL(32) - dram_hole_base); ++ dram_hole_base = ctx.tmp & GENMASK(31, 24); ++ if (ctx.ret_addr >= dram_hole_base) ++ ctx.ret_addr += (BIT_ULL(32) - dram_hole_base); + } + + if (hash_enabled) { + /* Save some parentheses and grab ls-bit at the end. */ +- hashed_bit = (ret_addr >> 12) ^ +- (ret_addr >> 18) ^ +- (ret_addr >> 21) ^ +- (ret_addr >> 30) ^ ++ hashed_bit = (ctx.ret_addr >> 12) ^ ++ (ctx.ret_addr >> 18) ^ ++ (ctx.ret_addr >> 21) ^ ++ (ctx.ret_addr >> 30) ^ + cs_id; + + hashed_bit &= BIT(0); + +- if (hashed_bit != ((ret_addr >> intlv_addr_bit) & BIT(0))) +- ret_addr ^= BIT(intlv_addr_bit); ++ if (hashed_bit != ((ctx.ret_addr >> intlv_addr_bit) & BIT(0))) ++ ctx.ret_addr ^= BIT(intlv_addr_bit); + } + + /* Is calculated system address is above DRAM limit address? */ +- if (ret_addr > dram_limit_addr) ++ if (ctx.ret_addr > dram_limit_addr) + goto out_err; + +- *sys_addr = ret_addr; ++ *sys_addr = ctx.ret_addr; + return 0; + + out_err: +-- +2.37.3 + |