@@ -725,6 +725,7 @@ struct addr_ctx {
u32 reg_dram_offset;
u32 reg_base_addr;
u32 reg_limit_addr;
+ u32 reg_fab_id_mask0;
u16 nid;
u8 umc;
u8 map_num;
@@ -734,6 +735,8 @@ struct addr_ctx {
u8 intlv_num_sockets;
u8 cs_id;
u8 cs_fabric_id;
+ u8 die_id_mask;
+ u8 socket_id_mask;
bool hash_enabled;
};
@@ -905,15 +908,31 @@ static int get_cs_fabric_id(struct addr_ctx *ctx)
return 0;
}
+static void get_masks(struct addr_ctx *ctx)
+{
+ ctx->die_id_mask = (ctx->reg_fab_id_mask0 >> 8) & 0xFF;
+ ctx->socket_id_mask = (ctx->reg_fab_id_mask0 >> 16) & 0xFF;
+}
+
+static u8 get_die_id_shift(struct addr_ctx *ctx)
+{
+ return (ctx->reg_fab_id_mask0 >> 24) & 0xF;
+}
+
+static u8 get_socket_id_shift(struct addr_ctx *ctx)
+{
+ return (ctx->reg_fab_id_mask0 >> 28) & 0xF;
+}
+
static int calculate_cs_id(struct addr_ctx *ctx)
{
- u8 die_id_shift, die_id_mask, socket_id_shift, socket_id_mask;
u8 die_id_bit, sock_id_bit, cs_mask = 0;
- u32 tmp;
if (get_cs_fabric_id(ctx))
return -EINVAL;
+ get_masks(ctx);
+
die_id_bit = 0;
/* If interleaved over more than 1 channel: */
@@ -923,27 +942,26 @@ static int calculate_cs_id(struct addr_ctx *ctx)
ctx->cs_id = ctx->cs_fabric_id & cs_mask;
}
- sock_id_bit = die_id_bit;
+ /* Return early if no die interleaving and no socket interleaving. */
+ if (!(ctx->intlv_num_dies || ctx->intlv_num_sockets))
+ return 0;
- if (ctx->intlv_num_dies || ctx->intlv_num_sockets)
- if (amd_df_indirect_read(ctx->nid, df_regs[SYS_FAB_ID_MASK], ctx->umc, &tmp))
- return -EINVAL;
+ sock_id_bit = die_id_bit;
/* If interleaved over more than 1 die: */
if (ctx->intlv_num_dies) {
- sock_id_bit = die_id_bit + ctx->intlv_num_dies;
- die_id_shift = (tmp >> 24) & 0xF;
- die_id_mask = (tmp >> 8) & 0xFF;
+ u8 die_id_shift = get_die_id_shift(ctx);
- ctx->cs_id |= ((ctx->cs_fabric_id & die_id_mask) >> die_id_shift) << die_id_bit;
+ 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;
}
/* If interleaved over more than 1 socket: */
if (ctx->intlv_num_sockets) {
- socket_id_shift = (tmp >> 28) & 0xF;
- socket_id_mask = (tmp >> 16) & 0xFF;
+ u8 socket_id_shift = get_socket_id_shift(ctx);
- ctx->cs_id |= ((ctx->cs_fabric_id & socket_id_mask)
+ ctx->cs_id |= ((ctx->cs_fabric_id & ctx->socket_id_mask)
>> socket_id_shift) << sock_id_bit;
}
@@ -1037,6 +1055,15 @@ static int addr_over_limit(struct addr_ctx *ctx)
return 0;
}
+static int get_fabric_id_mask_reg(struct addr_ctx *ctx)
+{
+ if (amd_df_indirect_read(ctx->nid, df_regs[SYS_FAB_ID_MASK],
+ ctx->umc, &ctx->reg_fab_id_mask0))
+ return -EINVAL;
+
+ return 0;
+}
+
int umc_normaddr_to_sysaddr(u64 *addr, u16 nid, u8 umc)
{
struct addr_ctx ctx;
@@ -1049,6 +1076,9 @@ int umc_normaddr_to_sysaddr(u64 *addr, u16 nid, u8 umc)
ctx.nid = nid;
ctx.umc = umc;
+ if (get_fabric_id_mask_reg(&ctx))
+ return -EINVAL;
+
ctx.df_type = get_df_type(&ctx);
if (remove_dram_offset(&ctx))