aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/0038-EDAC-amd64-Add-context-struct.patch
diff options
context:
space:
mode:
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.patch229
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
+