[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210623192002.3671647-28-yazen.ghannam@amd.com>
Date: Wed, 23 Jun 2021 19:19:58 +0000
From: Yazen Ghannam <yazen.ghannam@....com>
To: linux-edac@...r.kernel.org
Cc: linux-kernel@...r.kernel.org, bp@...en8.de, mchehab@...nel.org,
tony.luck@...el.com, Smita.KoralahalliChannabasappa@....com,
Yazen Ghannam <yazen.ghannam@....com>
Subject: [PATCH v2 27/31] EDAC/amd64: Update CS ID calculation to match reference code
Redo the current CS ID calculations to match the reference code. Helper
functions are introduced that will be expanded for future DF versions.
Use u16 type for dst_fabric_id and component_id_mask values to
accommodate larger bitfields in future DF versions.
Signed-off-by: Yazen Ghannam <yazen.ghannam@....com>
---
Link:
https://lkml.kernel.org/r/20210507190140.18854-24-Yazen.Ghannam@amd.com
v1->v2:
* Moved from arch/x86 to EDAC.
* Added functions to data_fabric_ops.
drivers/edac/amd64_edac.c | 52 ++++++++++++++++++++++++++-------------
1 file changed, 35 insertions(+), 17 deletions(-)
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index fa8046e2b055..fc2cd288df0f 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -1112,6 +1112,8 @@ struct addr_ctx {
struct data_fabric_ops {
u64 (*get_hi_addr_offset)(struct addr_ctx *ctx);
+ u16 (*get_dst_fabric_id)(struct addr_ctx *ctx);
+ u16 (*get_component_id_mask)(struct addr_ctx *ctx);
u8 (*get_die_id_shift)(struct addr_ctx *ctx);
u8 (*get_socket_id_shift)(struct addr_ctx *ctx);
int (*get_intlv_mode)(struct addr_ctx *ctx);
@@ -1230,6 +1232,16 @@ static u8 get_socket_id_shift_df2(struct addr_ctx *ctx)
return (ctx->reg_fab_id_mask0 >> 28) & 0xF;
}
+static u16 get_dst_fabric_id_df2(struct addr_ctx *ctx)
+{
+ return ctx->reg_limit_addr & 0xFF;
+}
+
+static u16 get_component_id_mask_df2(struct addr_ctx *ctx)
+{
+ return (~(ctx->socket_id_mask | ctx->die_id_mask)) & 0xFF;
+}
+
struct data_fabric_ops df2_ops = {
.get_hi_addr_offset = &get_hi_addr_offset_df2,
.get_intlv_mode = &get_intlv_mode_df2,
@@ -1239,6 +1251,8 @@ struct data_fabric_ops df2_ops = {
.get_masks = &get_masks_df2,
.get_die_id_shift = &get_die_id_shift_df2,
.get_socket_id_shift = &get_socket_id_shift_df2,
+ .get_dst_fabric_id = &get_dst_fabric_id_df2,
+ .get_component_id_mask = &get_component_id_mask_df2,
};
struct data_fabric_ops *df_ops;
@@ -1339,38 +1353,42 @@ static void get_intlv_num_chan(struct addr_ctx *ctx)
}
}
-static int calculate_cs_id(struct addr_ctx *ctx)
+static u8 calc_level_bits(u8 id, u8 level_mask, u8 shift, u8 mask, u8 num_bits)
{
- u8 die_id_bit = 0, sock_id_bit, cs_mask = 0;
+ return (((id & level_mask) >> shift) & mask) << num_bits;
+}
- /* If interleaved over more than 1 channel: */
- if (ctx->intlv_num_chan) {
- die_id_bit = ctx->intlv_num_chan;
- cs_mask = (1 << die_id_bit) - 1;
- ctx->cs_id = ctx->cs_fabric_id & cs_mask;
- }
+static int calculate_cs_id(struct addr_ctx *ctx)
+{
+ u16 dst_fabric_id = df_ops->get_dst_fabric_id(ctx);
+ u16 mask, num_intlv_bits = ctx->intlv_num_chan;
- /* Return early if no die interleaving and no socket interleaving. */
- if (!(ctx->intlv_num_dies || ctx->intlv_num_sockets))
- return 0;
+ mask = df_ops->get_component_id_mask(ctx);
+ ctx->cs_id = (ctx->cs_fabric_id & mask) - (dst_fabric_id & mask);
- sock_id_bit = die_id_bit;
+ mask = (1 << num_intlv_bits) - 1;
+ ctx->cs_id &= mask;
/* If interleaved over more than 1 die: */
if (ctx->intlv_num_dies) {
u8 die_id_shift = df_ops->get_die_id_shift(ctx);
- sock_id_bit = die_id_bit + ctx->intlv_num_dies;
- ctx->cs_id |= ((ctx->cs_fabric_id & ctx->die_id_mask)
- >> die_id_shift) << die_id_bit;
+ mask = (1 << ctx->intlv_num_dies) - 1;
+
+ ctx->cs_id |= calc_level_bits(ctx->cs_fabric_id, ctx->die_id_mask,
+ die_id_shift, mask, num_intlv_bits);
+
+ num_intlv_bits += ctx->intlv_num_dies;
}
/* If interleaved over more than 1 socket: */
if (ctx->intlv_num_sockets) {
u8 socket_id_shift = df_ops->get_socket_id_shift(ctx);
- ctx->cs_id |= ((ctx->cs_fabric_id & ctx->socket_id_mask)
- >> socket_id_shift) << sock_id_bit;
+ mask = (1 << ctx->intlv_num_sockets) - 1;
+
+ ctx->cs_id |= calc_level_bits(ctx->cs_fabric_id, ctx->socket_id_mask,
+ socket_id_shift, mask, num_intlv_bits);
}
return 0;
--
2.25.1
Powered by blists - more mailing lists