Messages in this thread Patch in this message | | | From | Yazen Ghannam <> | Subject | [PATCH v2 22/31] EDAC/amd64: Define function to make space for CS ID | Date | Wed, 23 Jun 2021 19:19:53 +0000 |
| |
Move code that makes a gap for the CS ID into a separate helper function. The exact bits to use vary based on interleaving mode. New interleaving modes in future DF versions will be added as new cases.
Also, introduce a helper function that does the bit manipulation to make the gap. The current version of this function is "simple", and future interleaving modes may reuse this or use a more advanced function.
Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com> --- Link: https://lkml.kernel.org/r/20210507190140.18854-19-Yazen.Ghannam@amd.com
v1->v2: * Moved from arch/x86 to EDAC. * Added new function pointer to ctx struct.
drivers/edac/amd64_edac.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index e5c296b00f5c..b497af7c3561 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1102,6 +1102,7 @@ struct addr_ctx { u8 intlv_num_sockets; u8 cs_id; int (*dehash_addr)(struct addr_ctx *ctx); + void (*make_space_for_cs_id)(struct addr_ctx *ctx); }; struct data_fabric_ops { @@ -1111,6 +1112,29 @@ struct data_fabric_ops { void (*get_intlv_num_sockets)(struct addr_ctx *ctx); }; +static void expand_bits(u8 start_bit, u8 num_bits, u64 *value) +{ + u64 temp1, temp2; + + if (start_bit == 0) { + *value <<= num_bits; + return; + } + + temp1 = *value & GENMASK_ULL(start_bit - 1, 0); + temp2 = (*value & GENMASK_ULL(63, start_bit)) << num_bits; + *value = temp1 | temp2; +} + +static void make_space_for_cs_id_simple(struct addr_ctx *ctx) +{ + u8 num_intlv_bits = ctx->intlv_num_chan; + + num_intlv_bits += ctx->intlv_num_dies; + num_intlv_bits += ctx->intlv_num_sockets; + expand_bits(ctx->intlv_addr_bit, num_intlv_bits, &ctx->ret_addr); +} + static u64 get_hi_addr_offset_df2(struct addr_ctx *ctx) { return (ctx->reg_dram_offset & GENMASK_ULL(31, 20)) << 8; @@ -1141,6 +1165,8 @@ static int get_intlv_mode_df2(struct addr_ctx *ctx) ctx->dehash_addr = &dehash_addr_df2; } + ctx->make_space_for_cs_id = &make_space_for_cs_id_simple; + if (ctx->intlv_mode != NONE && ctx->intlv_mode != NOHASH_2CH && ctx->intlv_mode != DF2_HASH_2CH) @@ -1278,13 +1304,11 @@ static int denormalize_addr(struct addr_ctx *ctx) df_ops->get_intlv_num_dies(ctx); df_ops->get_intlv_num_sockets(ctx); - num_intlv_bits = ctx->intlv_num_chan; - num_intlv_bits += ctx->intlv_num_dies; - num_intlv_bits += ctx->intlv_num_sockets; + ctx->make_space_for_cs_id(ctx); if (num_intlv_bits > 0) { - u64 temp_addr_x, temp_addr_i, temp_addr_y; u8 die_id_bit, sock_id_bit, cs_fabric_id; + u64 temp_addr_i; /* * Read FabricBlockInstanceInformation3_CS[BlockFabricID]. @@ -1340,11 +1364,8 @@ static int denormalize_addr(struct addr_ctx *ctx) * bits there are. "intlv_addr_bit" tells us how many "Y" bits * there are (where "I" starts). */ - temp_addr_y = ctx->ret_addr & GENMASK_ULL(ctx->intlv_addr_bit - 1, 0); temp_addr_i = (ctx->cs_id << ctx->intlv_addr_bit); - temp_addr_x = (ctx->ret_addr & GENMASK_ULL(63, ctx->intlv_addr_bit)) - << num_intlv_bits; - ctx->ret_addr = temp_addr_x | temp_addr_i | temp_addr_y; + ctx->ret_addr |= temp_addr_i; } return 0; -- 2.25.1
| |