Messages in this thread Patch in this message | | | From | Yazen Ghannam <> | Subject | [PATCH v4 21/24] EDAC/amd64: Update CS ID calculation to match reference code | Date | Thu, 27 Jan 2022 20:41:12 +0000 |
| |
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@amd.com> --- Link: https://lore.kernel.org/r/20211028175728.121452-27-yazen.ghannam@amd.com
v3->v4: * Remove leading whitespace in function pointers.
v2->v3: * Was patch 27 in v2.
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 ac7919010063..e293aefd486e 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1092,6 +1092,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); @@ -1213,6 +1215,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, @@ -1222,6 +1234,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; @@ -1310,38 +1324,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
| |