From nobody Mon Jun 8 16:39:26 2026 Received: from out28-173.mail.aliyun.com (out28-173.mail.aliyun.com [115.124.28.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C52912DA749; Thu, 28 May 2026 03:58:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940729; cv=none; b=fL38EW8VIUdyWvA9CCwPquNBo+uXNpAav5kTZBRsC88LiUB64OhWWtajsedJXqWBKfXHeNgldUvsKHLIyqDqcmVvjssIeTDnwKKF6fcIqvqONROZWg6u2uS87EeBbTPhJbBybKE6kbT2iKI1jQ9SZflWXLt4G6Yah/shr6hLI8w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940729; c=relaxed/simple; bh=D+K3tdmP8edwD9ZQcd6/LSQRWobi59/Ye0cJullxJsQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mSNT4FXNRpPbvhtyPEH5BsH5kNR96Ue1wYbkE7rBF3G6W4nrPtp5WhP5O/XBHnDTjJciIGMterPRhasF453XP2mNPHItj3gC9EcOUc0aslQodypn2FossGoE7acLGNpi2DLCJ5XEcnpeTcXxmGoD3YkHV66z36hRBUO+n737BvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=115.124.28.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436261|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_alarm|0.000909366-0.00142474-0.997666;FP=10766275164307539003|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033037025160;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeBdM_1779940393; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeBdM_1779940393 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:18 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 01/11] ras/amd/atl: Add Hygon DF1 Data Fabric system information helper Date: Thu, 28 May 2026 11:52:35 +0800 Message-ID: <20260528035246.526012-2-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add Hygon Family 0x18 model 0x4/0x5 (Hygon DF1) support as the start. Add Hygon DF1 Data Fabric system information that Hygon address translation function depends on later. Prepare hygon_get_df_system_info() to be called by amd_atl_init() later. - Add is_hygon_f18h() as a static inline bool in internal.h, checking both X86_VENDOR_HYGON and x86 family 0x18, with a TODO noting it will move to in Hygon Node RFC next version. - Add hygon/reg_fields.h for Hygon-specific register field definitions with Hygon DF1 System Fabric ID Mask defined first. - Add hygon/system.c for Hygon-specific implementation similar to system.c for AMD. - Add HYGON_DF1 to enum df_revisions in internal.h. - Add hygon_determine_df_rev() to detect Hygon DF revision, guarded by is_hygon_f18h(); use hygon_f18h_model_in_range(0x4, 0x5) to identify DF1. - Use get_dram_hole_base() and dump_df_cfg() shared from system.c and exported in internal.h to avoid duplicate code. - Build hygon/system.c from the Makefile as an amd_atl object. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/Makefile | 2 + drivers/ras/amd/atl/hygon/reg_fields.h | 60 ++++++++++++++++++++ drivers/ras/amd/atl/hygon/system.c | 76 ++++++++++++++++++++++++++ drivers/ras/amd/atl/internal.h | 18 ++++++ drivers/ras/amd/atl/system.c | 4 +- 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 drivers/ras/amd/atl/hygon/reg_fields.h create mode 100644 drivers/ras/amd/atl/hygon/system.c diff --git a/drivers/ras/amd/atl/Makefile b/drivers/ras/amd/atl/Makefile index b56892c0c0d9..3716fe068eb6 100644 --- a/drivers/ras/amd/atl/Makefile +++ b/drivers/ras/amd/atl/Makefile @@ -15,6 +15,8 @@ amd_atl-y +=3D map.o amd_atl-y +=3D system.o amd_atl-y +=3D umc.o =20 +amd_atl-y +=3D hygon/system.o + amd_atl-$(CONFIG_AMD_ATL_PRM) +=3D prm.o =20 obj-$(CONFIG_AMD_ATL) +=3D amd_atl.o diff --git a/drivers/ras/amd/atl/hygon/reg_fields.h b/drivers/ras/amd/atl/h= ygon/reg_fields.h new file mode 100644 index 000000000000..b669049c46e5 --- /dev/null +++ b/drivers/ras/amd/atl/hygon/reg_fields.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * AMD Address Translation Library (for hygon) + * + * reg_fields.h : Register field definitions for Hygon + * + * Author: Aichun Shi + */ + +/* + * Die ID Mask + * + * Access type: Broadcast + * + * Register + * Rev Fieldname Bits + * + * D18F1x208 [System Fabric ID Mask] + * HYGON_DF1 DieIdMask [9:0] + */ +#define HYGON_DF1_DIE_ID_MASK GENMASK(9, 0) + +/* + * Die ID Shift + * + * Access type: Broadcast + * + * Register + * Rev Fieldname Bits + * + * D18F1x208 [System Fabric ID Mask] + * HYGON_DF1 DieIdShift [15:12] + */ +#define HYGON_DF1_DIE_ID_SHIFT GENMASK(15, 12) + +/* + * Socket ID Mask + * + * Access type: Broadcast + * + * Register + * Rev Fieldname Bits + * + * D18F1x208 [System Fabric ID Mask] + * HYGON_DF1 SocketIdMask [25:16] + */ +#define HYGON_DF1_SOCKET_ID_MASK GENMASK(25, 16) + +/* + * Socket ID Shift + * + * Access type: Broadcast + * + * Register + * Rev Fieldname Bits + * + * D18F1x208 [System Fabric ID Mask] + * HYGON_DF1 SocketIdShift [31:28] + */ +#define HYGON_DF1_SOCKET_ID_SHIFT GENMASK(31, 28) diff --git a/drivers/ras/amd/atl/hygon/system.c b/drivers/ras/amd/atl/hygon= /system.c new file mode 100644 index 000000000000..bff577a559ad --- /dev/null +++ b/drivers/ras/amd/atl/hygon/system.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD Address Translation Library (for hygon) + * + * system.c : Functions to read and save system-wide data for Hygon + * + * Author: Aichun Shi + */ + +#include "../internal.h" + +static void hygon_df_get_masks_shifts(u32 mask0) +{ + switch (df_cfg.rev) { + case HYGON_DF1: + df_cfg.socket_id_shift =3D FIELD_GET(HYGON_DF1_SOCKET_ID_SHIFT, mask0); + df_cfg.socket_id_mask =3D FIELD_GET(HYGON_DF1_SOCKET_ID_MASK, mask0); + df_cfg.die_id_shift =3D FIELD_GET(HYGON_DF1_DIE_ID_SHIFT, mask0); + df_cfg.die_id_mask =3D FIELD_GET(HYGON_DF1_DIE_ID_MASK, mask0); + break; + default: + atl_debug_on_bad_df_rev(); + return; + } +} + +static int hygon_determine_df_rev(void) +{ + u32 fabric_id_mask0; + + if (!is_hygon_f18h()) + return -EINVAL; + + if (hygon_f18h_model_in_range(0x4, 0x5)) + df_cfg.rev =3D HYGON_DF1; + + /* Read D18F1x208 (SystemFabricIdMask). */ + if (df_indirect_read_broadcast(0, 1, 0x208, &fabric_id_mask0)) + return -EINVAL; + + hygon_df_get_masks_shifts(fabric_id_mask0); + + return 0; +} + +static void hygon_get_num_maps(void) +{ + switch (df_cfg.rev) { + case HYGON_DF1: + df_cfg.num_coh_st_maps =3D 2; + break; + default: + atl_debug_on_bad_df_rev(); + } +} + +int hygon_get_df_system_info(void) +{ + int ret; + + ret =3D hygon_determine_df_rev(); + if (ret) { + pr_warn("Failed to determine DF Revision"); + df_cfg.rev =3D UNKNOWN; + return ret; + } + + hygon_get_num_maps(); + + if (get_dram_hole_base()) + pr_warn("Failed to read DRAM hole base"); + + dump_df_cfg(); + + return 0; +} diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h index 82a56d9c2be1..56008238c220 100644 --- a/drivers/ras/amd/atl/internal.h +++ b/drivers/ras/amd/atl/internal.h @@ -19,8 +19,11 @@ =20 #include #include +#include +#include =20 #include "reg_fields.h" +#include "hygon/reg_fields.h" =20 #undef pr_fmt #define pr_fmt(fmt) "amd_atl: " fmt @@ -40,8 +43,18 @@ =20 #define INVALID_SPA ~0ULL =20 +/* + * TODO: Will move to in Hygon Node RFC next version. + */ +static inline bool is_hygon_f18h(void) +{ + return boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_HYGON && + boot_cpu_data.x86 =3D=3D 0x18; +} + enum df_revisions { UNKNOWN, + HYGON_DF1, DF2, DF3, DF3p5, @@ -284,6 +297,11 @@ unsigned long convert_umc_mca_addr_to_sys_addr(struct = atl_err *err); u64 add_base_and_hole(struct addr_ctx *ctx, u64 addr); u64 remove_base_and_hole(struct addr_ctx *ctx, u64 addr); =20 +int get_dram_hole_base(void); +void dump_df_cfg(void); + +int hygon_get_df_system_info(void); + /* GUIDs for PRM handlers */ extern const guid_t norm_to_sys_guid; =20 diff --git a/drivers/ras/amd/atl/system.c b/drivers/ras/amd/atl/system.c index 812a30e21d3a..eb420978febb 100644 --- a/drivers/ras/amd/atl/system.c +++ b/drivers/ras/amd/atl/system.c @@ -231,7 +231,7 @@ static int determine_df_rev(void) return 0; } =20 -static int get_dram_hole_base(void) +int get_dram_hole_base(void) { u8 func =3D 0; =20 @@ -274,7 +274,7 @@ static void apply_node_id_shift(void) df_cfg.socket_id_shift +=3D df_cfg.node_id_shift; } =20 -static void dump_df_cfg(void) +void dump_df_cfg(void) { pr_debug("rev=3D0x%x", df_cfg.rev); =20 --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out198-20.us.a.mail.aliyun.com (out198-20.us.a.mail.aliyun.com [47.90.198.20]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5EF181DE8BE; Thu, 28 May 2026 04:09:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=47.90.198.20 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779941365; cv=none; b=Ev60ryEQUSTSclN61jAIeCvam6x162jTe8g00R63sac6BzxLfDqJ3HyY+BtldD7pjcqo//+Wuh3dXypWj/n/g3B8jfvpZW7axR+6P3noN+Sqn1JKRZQv3Yke09u++oyXY9xqfqgAonjWrNwBtHT9Bpqm5XTEGm0NfIysAoLeQow= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779941365; c=relaxed/simple; bh=8hSCcSIeOS9kHBROuPW24gTFO7ivIU8Ec7eu5qN4Siw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JYCQ8B4UXn8iKxQIENmjdk09ClsVEix+OfujDZyD5k2LUOo3MdJzpd7F75Uw1hj+pQ4NpeL36mTF9ZFg+dK8jHGMwPJBrmP54n3Wft6roJZA7fQyIb5iO2nw38r29ZbTYrUyelVoMGfqMpI/YCpevVAI27XVHYcNw34tTztPntc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=47.90.198.20 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436259|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.00432169-0.000303894-0.995374;FP=1039342469963859155|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033037022039;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeBiu_1779940399; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeBiu_1779940399 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:22 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 02/11] ras/amd/atl: Add Hygon DF1 DRAM address map decoding helper Date: Thu, 28 May 2026 11:52:36 +0800 Message-ID: <20260528035246.526012-3-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add Hygon DF1 DRAM address map decoding function that Hygon address translation pipeline depends on later. Prepare hygon_get_address_map() to be called by hygon/core.c later. - Add struct hygon_chan_intlv in addr_ctx and HYGON_DF1_3CHAN in enum intlv_modes to internal.h for Hygon DF1 three-channel interleave mode. - Add hygon/map.c for Hygon-specific implementation similar to map.c for AMD. - Get the coherent-station fabric ID, handle normalized offsets, read Hygon DF1 specific channel interleave state, and derive global interleave metadata (modes, bit positions, die/socket/channel counts). - Use df2_get_dram_addr_map(), valid_map(), and dump_address_map() shared from map.c and exported in internal.h to avoid duplicate code. - Build hygon/map.c from the Makefile as an amd_atl object. Hygon address map decoding duplicated the same loop as the AMD path for walking coherent station DRAM maps and selecting the high-address offset. Only the per-map register read differs; pass it via a callback so get_dram_offset() and hygon_get_dram_offset() share the implementation. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/Makefile | 1 + drivers/ras/amd/atl/hygon/map.c | 292 +++++++++++++++++++++++++ drivers/ras/amd/atl/hygon/reg_fields.h | 78 +++++++ drivers/ras/amd/atl/internal.h | 21 ++ drivers/ras/amd/atl/map.c | 11 +- 5 files changed, 398 insertions(+), 5 deletions(-) create mode 100644 drivers/ras/amd/atl/hygon/map.c diff --git a/drivers/ras/amd/atl/Makefile b/drivers/ras/amd/atl/Makefile index 3716fe068eb6..105c11015f4c 100644 --- a/drivers/ras/amd/atl/Makefile +++ b/drivers/ras/amd/atl/Makefile @@ -15,6 +15,7 @@ amd_atl-y +=3D map.o amd_atl-y +=3D system.o amd_atl-y +=3D umc.o =20 +amd_atl-y +=3D hygon/map.o amd_atl-y +=3D hygon/system.o =20 amd_atl-$(CONFIG_AMD_ATL_PRM) +=3D prm.o diff --git a/drivers/ras/amd/atl/hygon/map.c b/drivers/ras/amd/atl/hygon/ma= p.c new file mode 100644 index 000000000000..7d0ed942a28f --- /dev/null +++ b/drivers/ras/amd/atl/hygon/map.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD Address Translation Library (for hygon) + * + * map.c : Functions to read and decode DRAM address maps for Hygon + * + * Author: Aichun Shi + */ + +#include "../internal.h" + +static int hygon_df_get_intlv_mode(struct addr_ctx *ctx) +{ + ctx->map.intlv_mode =3D FIELD_GET(HYGON_DF1_INTLV_NUM_CHAN, ctx->map.base= ); + + if (df_cfg.rev =3D=3D HYGON_DF1 && ctx->map.intlv_mode =3D=3D 2) + ctx->map.intlv_mode =3D HYGON_DF1_3CHAN; + + if (ctx->map.intlv_mode =3D=3D 8) + ctx->map.intlv_mode =3D DF2_2CHAN_HASH; + + if (ctx->map.intlv_mode !=3D NONE && + ctx->map.intlv_mode !=3D NOHASH_2CHAN && + ctx->map.intlv_mode !=3D HYGON_DF1_3CHAN && + ctx->map.intlv_mode !=3D NOHASH_4CHAN && + ctx->map.intlv_mode !=3D NOHASH_8CHAN && + ctx->map.intlv_mode !=3D NOHASH_16CHAN && + ctx->map.intlv_mode !=3D DF2_2CHAN_HASH) + return -EINVAL; + + return 0; +} + +static u64 hygon_get_hi_addr_offset(u32 reg_dram_offset) +{ + u8 shift =3D DF_DRAM_BASE_LIMIT_LSB; + u64 hi_addr_offset; + + switch (df_cfg.rev) { + case HYGON_DF1: + hi_addr_offset =3D FIELD_GET(HYGON_DF1_HI_ADDR_OFFSET, reg_dram_offset); + break; + default: + hi_addr_offset =3D 0; + atl_debug_on_bad_df_rev(); + } + + return hi_addr_offset << shift; +} + +/* + * Returns: 0 if offset is disabled. + * 1 if offset is enabled. + * -EINVAL on error. + */ +static int hygon_get_dram_offset(struct addr_ctx *ctx, u64 *norm_offset) +{ + u32 reg_dram_offset; + u8 map_num; + + /* Should not be called for map 0. */ + if (!ctx->map.num) { + atl_debug(ctx, "Trying to find DRAM offset for map 0"); + return -EINVAL; + } + + /* + * DramOffset registers don't exist for map 0, so the base register + * actually refers to map 1. + * Adjust the map_num for the register offsets. + */ + map_num =3D ctx->map.num - 1; + + if (df_cfg.rev >=3D HYGON_DF1) { + /* Read D18F0x214 (DramOffset) */ + if (df_indirect_read_instance(ctx->node_id, 0, 0x214 + (4 * map_num), + ctx->inst_id, ®_dram_offset)) + return -EINVAL; + } else { + return -EINVAL; + } + + if (!FIELD_GET(DF_HI_ADDR_OFFSET_EN, reg_dram_offset)) + return 0; + + *norm_offset =3D hygon_get_hi_addr_offset(reg_dram_offset); + + return 1; +} + +#define HYGON_DF1_CHAN_ADDR_SEL BIT(24) +#define HYGON_DF1_CHAN_HASH_ENABLE BIT(23) +#define HYGON_DF1_DDR5_ENABLE BIT(19) +static int hygon_df1_get_dram_addr_map(struct addr_ctx *ctx) +{ + if (df2_get_dram_addr_map(ctx)) + return -EINVAL; + + if (df_indirect_read_instance(ctx->node_id, 2, 0x48, + ctx->inst_id, &ctx->map.intlv)) + return -EINVAL; + + ctx->chan_intlv_hygon.chan_addr_sel =3D + FIELD_GET(HYGON_DF1_CHAN_ADDR_SEL, ctx->map.intlv); + ctx->chan_intlv_hygon.chan_hash_enable =3D + FIELD_GET(HYGON_DF1_CHAN_HASH_ENABLE, ctx->map.intlv); + ctx->chan_intlv_hygon.ddr5_enable =3D + FIELD_GET(HYGON_DF1_DDR5_ENABLE, ctx->map.intlv); + + if (ctx->chan_intlv_hygon.ddr5_enable) { + u8 sb; + u64 low_addr, high_addr; + + ctx->chan_intlv_hygon.start_bit =3D ctx->chan_intlv_hygon.chan_addr_sel = ? 8 : 7; + sb =3D ctx->chan_intlv_hygon.start_bit; + low_addr =3D ctx->ret_addr & GENMASK_ULL(sb - 1, 0); + high_addr =3D (ctx->ret_addr & GENMASK_ULL(63, sb)) << 1; + ctx->ret_addr =3D high_addr | low_addr; + } + + return 0; +} + +static int hygon_get_dram_addr_map(struct addr_ctx *ctx) +{ + switch (df_cfg.rev) { + case HYGON_DF1: return hygon_df1_get_dram_addr_map(ctx); + default: + atl_debug_on_bad_df_rev(); + return -EINVAL; + } +} + +static int hygon_get_coh_st_fabric_id(struct addr_ctx *ctx) +{ + u32 reg; + + /* Read D18F0x50 (FabricBlockInstanceInformation3). */ + if (df_indirect_read_instance(ctx->node_id, 0, 0x50, ctx->inst_id, ®)) + return -EINVAL; + + switch (df_cfg.rev) { + case HYGON_DF1: + ctx->coh_st_fabric_id =3D FIELD_GET(HYGON_DF1_COH_ST_FABRIC_ID, reg); + break; + default: + atl_debug_on_bad_df_rev(); + return -EINVAL; + } + + return 0; +} + +static int hygon_get_address_map_common(struct addr_ctx *ctx) +{ + u64 norm_offset =3D 0; + + if (hygon_get_coh_st_fabric_id(ctx)) + return -EINVAL; + + if (find_normalized_offset(ctx, &norm_offset, hygon_get_dram_offset)) + return -EINVAL; + + ctx->ret_addr -=3D norm_offset; + + if (hygon_get_dram_addr_map(ctx)) + return -EINVAL; + + if (!valid_map(ctx)) + return -EINVAL; + + return 0; +} + +static u8 hygon_get_num_intlv_chan(struct addr_ctx *ctx) +{ + switch (ctx->map.intlv_mode) { + case NONE: + return 1; + case NOHASH_2CHAN: + return 2; + case HYGON_DF1_3CHAN: + return 3; + case NOHASH_4CHAN: + return 4; + case NOHASH_8CHAN: + return 8; + case NOHASH_16CHAN: + return 16; + case NOHASH_32CHAN: + return 32; + default: + atl_debug_on_bad_intlv_mode(ctx); + return 0; + } +} + +static void hygon_calculate_intlv_bits(struct addr_ctx *ctx) +{ + ctx->map.num_intlv_chan =3D hygon_get_num_intlv_chan(ctx); + + ctx->map.total_intlv_chan =3D ctx->map.num_intlv_chan; + ctx->map.total_intlv_chan *=3D ctx->map.num_intlv_dies; + ctx->map.total_intlv_chan *=3D ctx->map.num_intlv_sockets; + + /* + * Get the number of bits needed to cover this many channels. + * order_base_2() rounds up automatically. + */ + ctx->map.total_intlv_bits =3D order_base_2(ctx->map.total_intlv_chan); +} + +static u8 hygon_get_intlv_bit_pos(struct addr_ctx *ctx) +{ + u8 addr_sel =3D 0; + + switch (df_cfg.rev) { + case HYGON_DF1: + addr_sel =3D FIELD_GET(HYGON_DF1_INTLV_ADDR_SEL, ctx->map.base); + break; + default: + atl_debug_on_bad_df_rev(); + break; + } + + /* Add '8' to get the 'interleave bit position'. */ + return addr_sel + 8; +} + +static u8 hygon_get_num_intlv_dies(struct addr_ctx *ctx) +{ + u8 dies =3D 0; + + switch (df_cfg.rev) { + case HYGON_DF1: + dies =3D FIELD_GET(HYGON_DF1_INTLV_NUM_DIES, ctx->map.limit); + break; + default: + atl_debug_on_bad_df_rev(); + break; + } + + /* Register value is log2, e.g. 0 -> 1 die, 1 -> 2 dies, etc. */ + return 1 << dies; +} + +static u8 hygon_get_num_intlv_sockets(struct addr_ctx *ctx) +{ + u8 sockets =3D 0; + + switch (df_cfg.rev) { + case HYGON_DF1: + sockets =3D FIELD_GET(HYGON_DF1_INTLV_NUM_SOCKETS, ctx->map.base); + break; + default: + atl_debug_on_bad_df_rev(); + break; + } + + /* Register value is log2, e.g. 0 -> 1 sockets, 1 -> 2 sockets, etc. */ + return 1 << sockets; +} + +static int hygon_get_global_map_data(struct addr_ctx *ctx) +{ + if (hygon_df_get_intlv_mode(ctx)) + return -EINVAL; + + ctx->map.intlv_bit_pos =3D hygon_get_intlv_bit_pos(ctx); + ctx->map.num_intlv_dies =3D hygon_get_num_intlv_dies(ctx); + ctx->map.num_intlv_sockets =3D hygon_get_num_intlv_sockets(ctx); + hygon_calculate_intlv_bits(ctx); + + return 0; +} + +int hygon_get_address_map(struct addr_ctx *ctx) +{ + int ret; + + ret =3D hygon_get_address_map_common(ctx); + if (ret) + return ret; + + ret =3D hygon_get_global_map_data(ctx); + if (ret) + return ret; + + dump_address_map(&ctx->map); + + return ret; +} diff --git a/drivers/ras/amd/atl/hygon/reg_fields.h b/drivers/ras/amd/atl/h= ygon/reg_fields.h index b669049c46e5..b3d658bef6ad 100644 --- a/drivers/ras/amd/atl/hygon/reg_fields.h +++ b/drivers/ras/amd/atl/hygon/reg_fields.h @@ -7,6 +7,84 @@ * Author: Aichun Shi */ =20 +/* + * Coherent Station Fabric ID + * + * Access type: Instance + * + * Register + * Rev Fieldname Bits + * + * D18F0x50 [Fabric Block Instance Information 3] + * HYGON_DF1 BlockFabricId [17:8] + */ +#define HYGON_DF1_COH_ST_FABRIC_ID GENMASK(17, 8) + +/* + * Interleave Number of Sockets + * + * Access type: Instance + * + * Register + * Rev Fieldname Bits + * + * D18F0x110 [DRAM Base Address] + * HYGON_DF1 IntLvNumSockets [3:2] + */ +#define HYGON_DF1_INTLV_NUM_SOCKETS GENMASK(3, 2) + +/* + * Interleave Number of Channels + * + * Access type: Instance + * + * Register + * Rev Fieldname Bits + * + * D18F0x110 [DRAM Base Address] + * HYGON_DF1 IntLvNumChan [7:4] + */ +#define HYGON_DF1_INTLV_NUM_CHAN GENMASK(7, 4) + +/* + * Interleave Address Select + * + * Access type: Instance + * + * Register + * Rev Fieldname Bits + * + * D18F0x110 [DRAM Base Address] + * HYGON_DF1 IntLvAddrSel [10:8] + */ +#define HYGON_DF1_INTLV_ADDR_SEL GENMASK(10, 8) + +/* + * Interleave Number of Dies + * + * Access type: Instance + * + * Register + * Rev Fieldname Bits + * + * D18F0x114 [DRAM Limit Address] + * HYGON_DF1 IntLvNumDies [11:10] + */ +#define HYGON_DF1_INTLV_NUM_DIES GENMASK(11, 10) + +/* + * High Address Offset + * + * Access type: Instance + * + * Register + * Rev Fieldname Bits + * + * D18F0x214 [DRAM Offset] + * HYGON_DF1 HiAddrOffset [31:19] + */ +#define HYGON_DF1_HI_ADDR_OFFSET GENMASK(31, 19) + /* * Die ID Mask * diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h index 56008238c220..adcf94385b39 100644 --- a/drivers/ras/amd/atl/internal.h +++ b/drivers/ras/amd/atl/internal.h @@ -66,6 +66,7 @@ enum df_revisions { enum intlv_modes { NONE =3D 0x00, NOHASH_2CHAN =3D 0x01, + HYGON_DF1_3CHAN =3D 0x02, NOHASH_4CHAN =3D 0x03, NOHASH_8CHAN =3D 0x05, DF3_6CHAN =3D 0x06, @@ -257,6 +258,14 @@ struct addr_ctx_inputs { u8 coh_st_inst_id; }; =20 +struct hygon_chan_intlv { + u8 sub_channel; + u8 chan_addr_sel; + u8 chan_hash_enable; + u8 ddr5_enable; + u8 start_bit; +}; + struct addr_ctx { u64 ret_addr; =20 @@ -277,6 +286,9 @@ struct addr_ctx { * System-wide ID that includes 'node' bits. */ u16 coh_st_fabric_id; + + /* Hygon Channel Interleave */ + struct hygon_chan_intlv chan_intlv_hygon; }; =20 int df_indirect_read_instance(u16 node, u8 func, u16 reg, u8 instance_id, = u32 *lo); @@ -300,7 +312,16 @@ u64 remove_base_and_hole(struct addr_ctx *ctx, u64 add= r); int get_dram_hole_base(void); void dump_df_cfg(void); =20 +int df2_get_dram_addr_map(struct addr_ctx *ctx); +bool valid_map(struct addr_ctx *ctx); +void dump_address_map(struct dram_addr_map *map); + +typedef int (*get_dram_offset_fn)(struct addr_ctx *ctx, u64 *norm_offset); +int find_normalized_offset(struct addr_ctx *ctx, u64 *norm_offset, + get_dram_offset_fn get_dram_offset); + int hygon_get_df_system_info(void); +int hygon_get_address_map(struct addr_ctx *ctx); =20 /* GUIDs for PRM handlers */ extern const guid_t norm_to_sys_guid; diff --git a/drivers/ras/amd/atl/map.c b/drivers/ras/amd/atl/map.c index 24a05af747d5..365ad48ca68f 100644 --- a/drivers/ras/amd/atl/map.c +++ b/drivers/ras/amd/atl/map.c @@ -209,7 +209,7 @@ static int df3_6ch_get_dram_addr_map(struct addr_ctx *c= tx) return 0; } =20 -static int df2_get_dram_addr_map(struct addr_ctx *ctx) +int df2_get_dram_addr_map(struct addr_ctx *ctx) { /* Read D18F0x110 (DramBaseAddress). */ if (df_indirect_read_instance(ctx->node_id, 0, 0x110 + (8 * ctx->map.num), @@ -395,7 +395,8 @@ static int get_coh_st_fabric_id(struct addr_ctx *ctx) return 0; } =20 -static int find_normalized_offset(struct addr_ctx *ctx, u64 *norm_offset) +int find_normalized_offset(struct addr_ctx *ctx, u64 *norm_offset, + get_dram_offset_fn get_dram_offset) { u64 last_offset =3D 0; int ret; @@ -441,7 +442,7 @@ static int find_normalized_offset(struct addr_ctx *ctx,= u64 *norm_offset) return 0; } =20 -static bool valid_map(struct addr_ctx *ctx) +bool valid_map(struct addr_ctx *ctx) { if (df_cfg.rev >=3D DF4) return FIELD_GET(DF_ADDR_RANGE_VAL, ctx->map.ctl); @@ -456,7 +457,7 @@ static int get_address_map_common(struct addr_ctx *ctx) if (get_coh_st_fabric_id(ctx)) return -EINVAL; =20 - if (find_normalized_offset(ctx, &norm_offset)) + if (find_normalized_offset(ctx, &norm_offset, get_dram_offset)) return -EINVAL; =20 if (get_dram_addr_map(ctx)) @@ -735,7 +736,7 @@ static int validate_address_map(struct addr_ctx *ctx) return -EINVAL; } =20 -static void dump_address_map(struct dram_addr_map *map) +void dump_address_map(struct dram_addr_map *map) { u8 i; =20 --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out198-18.us.a.mail.aliyun.com (out198-18.us.a.mail.aliyun.com [47.90.198.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B06D0305693; Thu, 28 May 2026 03:53:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=47.90.198.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940428; cv=none; b=pjOb7PgBL016D2FyIaQ2bYWpUcYGyI3ROquLobAChb4xJDbY4lgQP+hMe1t2yZ3gf9LPD7SvcSnrYoAjL+YNVh7FZ+vMMHm1egTfqz+g6wz7bVLKix2O6Bi16yJH6mtf/i79v+HSGXaHpxpv/loAblH4zC9oGGkwhm4WjaMLzI4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940428; c=relaxed/simple; bh=BpSjuNcy5HhjUc4pF1h5wrVP95toqOglAJesPl5hNRM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Tpb9Y4ZpXl2JuiAeAr2eJyFqRGZaMTtxye6hcBwTfo74KOVrRo4PQwWyj3Syz8cs4qyQo5cGrAvJWV80/cTpGY5iMTxQ3eVFepkRl6rI697BG1taQCtbjJfeOnZFX9aSCXJtNlREdCSoLOBabCC8OwhLHreoRElbGIktjvBlw6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=47.90.198.18 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436259|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.0314781-0.0158465-0.952675;FP=15802124733323758803|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033045213054;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeBmX_1779940402; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeBmX_1779940402 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:26 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 03/11] ras/amd/atl: Add Hygon DF1 normalized address denormalization helper Date: Thu, 28 May 2026 11:52:37 +0800 Message-ID: <20260528035246.526012-4-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add Hygon DF1 normalized address denormalization function that Hygon address translation pipeline depends on later. Prepare hygon_denormalize_address() to be called by hygon/core.c later. - Add hygon/denormalize.c for Hygon-specific implementation similar to denormalize.c for AMD. - Add hygon_denormalize_address() to handle non-hashed and hashed interleave modes, including the Hygon DF1 three-channel interleave mode. - Define HYGON_CDD_DFID_BASE =3D 4 for the DFID offset at which compute dies (CDD) start; IO dies occupy DFID 0-3, with a TODO noting it will move to in Hygon Node RFC next version. - Document that ret_addr is temporarily repurposed as an intermediate in hygon_get_coh_st_id_df() for the DF1_3CHAN non-power-of-2 case. - Check the return value of hygon_calculate_coh_st_id() and propagate error before passing coh_st_id to hygon_insert_coh_st_id(). - Use make_space_for_coh_st_id_at_intlv_bit() and insert_coh_st_id_at_intlv_bit() shared from denormalize.c and exported in internal.h to avoid duplicate code. - Build hygon/denormalize.c from the Makefile as an amd_atl object. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/Makefile | 1 + drivers/ras/amd/atl/denormalize.c | 4 +- drivers/ras/amd/atl/hygon/denormalize.c | 194 ++++++++++++++++++++++++ drivers/ras/amd/atl/hygon/reg_fields.h | 13 ++ drivers/ras/amd/atl/internal.h | 4 + 5 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 drivers/ras/amd/atl/hygon/denormalize.c diff --git a/drivers/ras/amd/atl/Makefile b/drivers/ras/amd/atl/Makefile index 105c11015f4c..c4e01f3ecc7b 100644 --- a/drivers/ras/amd/atl/Makefile +++ b/drivers/ras/amd/atl/Makefile @@ -15,6 +15,7 @@ amd_atl-y +=3D map.o amd_atl-y +=3D system.o amd_atl-y +=3D umc.o =20 +amd_atl-y +=3D hygon/denormalize.o amd_atl-y +=3D hygon/map.o amd_atl-y +=3D hygon/system.o =20 diff --git a/drivers/ras/amd/atl/denormalize.c b/drivers/ras/amd/atl/denorm= alize.c index d45ce753e636..cf58cfa7ab3a 100644 --- a/drivers/ras/amd/atl/denormalize.c +++ b/drivers/ras/amd/atl/denormalize.c @@ -41,7 +41,7 @@ static u16 get_dst_fabric_id(struct addr_ctx *ctx) * expanded address bits: [20+n : n+p][n+p-1 : p][p-1 : 0] * [23 : 11][10 : 8][7 : 0] */ -static u64 make_space_for_coh_st_id_at_intlv_bit(struct addr_ctx *ctx) +u64 make_space_for_coh_st_id_at_intlv_bit(struct addr_ctx *ctx) { return expand_bits(ctx->map.intlv_bit_pos, ctx->map.total_intlv_bits, @@ -320,7 +320,7 @@ static u16 calculate_coh_st_id(struct addr_ctx *ctx) } } =20 -static u64 insert_coh_st_id_at_intlv_bit(struct addr_ctx *ctx, u64 denorm_= addr, u16 coh_st_id) +u64 insert_coh_st_id_at_intlv_bit(struct addr_ctx *ctx, u64 denorm_addr, u= 16 coh_st_id) { return denorm_addr | (coh_st_id << ctx->map.intlv_bit_pos); } diff --git a/drivers/ras/amd/atl/hygon/denormalize.c b/drivers/ras/amd/atl/= hygon/denormalize.c new file mode 100644 index 000000000000..8bf1cd1efa14 --- /dev/null +++ b/drivers/ras/amd/atl/hygon/denormalize.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD Address Translation Library (for hygon) + * + * denormalize.c : Functions to account for interleaving bits for Hygon + * + * Author: Aichun Shi + */ + +#include "../internal.h" + +/* + * TODO: Will move to in Hygon Node RFC next version. + */ +/* Hygon compute dies (CDD) start at DFID 4; IO dies occupy DFIDs 0-3. */ +#define HYGON_CDD_DFID_BASE 4 + +static u16 hygon_get_dst_fabric_id(struct addr_ctx *ctx) +{ + switch (df_cfg.rev) { + case HYGON_DF1: + return FIELD_GET(HYGON_DF1_DST_FABRIC_ID, ctx->map.limit); + default: + atl_debug_on_bad_df_rev(); + return 0; + } +} + +static u64 hygon_make_space_for_coh_st_id_df1_3chan(struct addr_ctx *ctx) +{ + return ctx->ret_addr & GENMASK_ULL(ctx->map.intlv_bit_pos - 1, 0); +} + +static u64 hygon_make_space_for_coh_st_id(struct addr_ctx *ctx) +{ + switch (ctx->map.intlv_mode) { + case NOHASH_2CHAN: + case NOHASH_4CHAN: + case NOHASH_8CHAN: + case NOHASH_16CHAN: + case NOHASH_32CHAN: + case DF2_2CHAN_HASH: + return make_space_for_coh_st_id_at_intlv_bit(ctx); + + case HYGON_DF1_3CHAN: + return hygon_make_space_for_coh_st_id_df1_3chan(ctx); + + default: + atl_debug_on_bad_intlv_mode(ctx); + return ~0ULL; + } +} + +static u16 hygon_get_coh_st_id_df(struct addr_ctx *ctx) +{ + u8 num_socket_intlv_bits =3D ilog2(ctx->map.num_intlv_sockets); + u8 num_die_intlv_bits =3D ilog2(ctx->map.num_intlv_dies); + u16 coh_st_id =3D ctx->coh_st_fabric_id; + u16 mask; + u8 intlv_bit_pos =3D ctx->map.intlv_bit_pos; + u8 num_intlv_bits =3D order_base_2(ctx->map.num_intlv_chan); + + if (ctx->map.intlv_mode =3D=3D HYGON_DF1_3CHAN) { + u8 cs_offset; + u16 dst_fabric_id =3D hygon_get_dst_fabric_id(ctx); + u64 temp_addr_x; + + cs_offset =3D (ctx->coh_st_fabric_id & 0x3) - (dst_fabric_id & 0x3); + if (cs_offset > 3) { + atl_debug(ctx, + "Invalid cs_offset: 0x%x coh_st_fabric_id: 0x%x dst_fabric_id: 0x%x.= \n", + cs_offset, ctx->coh_st_fabric_id, dst_fabric_id); + return ~0; + } + + temp_addr_x =3D (ctx->ret_addr & GENMASK_ULL(63, intlv_bit_pos)) >> + intlv_bit_pos; + temp_addr_x =3D temp_addr_x * 3 + cs_offset; + /* + * Repurpose ret_addr as a temporary to carry the non-power-of-2 + * quotient (high_bits * 3 + cs_offset) into + * hygon_insert_coh_st_id_df1_3chan(), which reads it back to + * reconstruct the physical address without an extra parameter. + */ + ctx->ret_addr =3D temp_addr_x; + + coh_st_id =3D temp_addr_x & GENMASK_ULL(num_intlv_bits - 1, 0); + } else { + mask =3D GENMASK(num_intlv_bits - 1, 0); + coh_st_id &=3D mask; + } + + /* Die interleave bits */ + if (num_die_intlv_bits) { + u16 die_bits; + + mask =3D GENMASK(num_die_intlv_bits - 1, 0); + die_bits =3D ctx->coh_st_fabric_id & df_cfg.die_id_mask; + die_bits >>=3D df_cfg.die_id_shift; + die_bits -=3D HYGON_CDD_DFID_BASE; + + coh_st_id |=3D (die_bits & mask) << num_intlv_bits; + num_intlv_bits +=3D num_die_intlv_bits; + } + + /* Socket interleave bits */ + if (num_socket_intlv_bits) { + u16 socket_bits; + + mask =3D GENMASK(num_socket_intlv_bits - 1, 0); + socket_bits =3D ctx->coh_st_fabric_id & df_cfg.socket_id_mask; + socket_bits >>=3D df_cfg.socket_id_shift; + + coh_st_id |=3D (socket_bits & mask) << num_intlv_bits; + } + + ctx->coh_st_fabric_id =3D coh_st_id; + + return coh_st_id; +} + +static u16 hygon_calculate_coh_st_id(struct addr_ctx *ctx) +{ + switch (ctx->map.intlv_mode) { + case NOHASH_2CHAN: + case HYGON_DF1_3CHAN: + case NOHASH_4CHAN: + case NOHASH_8CHAN: + case NOHASH_16CHAN: + case NOHASH_32CHAN: + case DF2_2CHAN_HASH: + return hygon_get_coh_st_id_df(ctx); + + default: + atl_debug_on_bad_intlv_mode(ctx); + return ~0; + } +} + +static u64 hygon_insert_coh_st_id_df1_3chan(struct addr_ctx *ctx, + u64 denorm_addr, u16 coh_st_id) +{ + u8 num_intlv_bits_chan =3D order_base_2(ctx->map.num_intlv_chan); + u64 temp_addr =3D ((ctx->ret_addr >> num_intlv_bits_chan) << + num_intlv_bits_chan) | coh_st_id; + + return denorm_addr | (temp_addr << ctx->map.intlv_bit_pos); +} + +static u64 hygon_insert_coh_st_id(struct addr_ctx *ctx, u64 denorm_addr, u= 16 coh_st_id) +{ + switch (ctx->map.intlv_mode) { + case NOHASH_2CHAN: + case NOHASH_4CHAN: + case NOHASH_8CHAN: + case NOHASH_16CHAN: + case NOHASH_32CHAN: + case DF2_2CHAN_HASH: + return insert_coh_st_id_at_intlv_bit(ctx, denorm_addr, coh_st_id); + + case HYGON_DF1_3CHAN: + return hygon_insert_coh_st_id_df1_3chan(ctx, denorm_addr, coh_st_id); + + default: + atl_debug_on_bad_intlv_mode(ctx); + return ~0ULL; + } +} + +static int hygon_denorm_addr_common(struct addr_ctx *ctx) +{ + u64 denorm_addr; + u16 coh_st_id; + + denorm_addr =3D hygon_make_space_for_coh_st_id(ctx); + if (denorm_addr =3D=3D ~0ULL) + return -EINVAL; + coh_st_id =3D hygon_calculate_coh_st_id(ctx); + if (coh_st_id =3D=3D (u16)~0) + return -EINVAL; + ctx->ret_addr =3D hygon_insert_coh_st_id(ctx, denorm_addr, coh_st_id); + return 0; +} + +int hygon_denormalize_address(struct addr_ctx *ctx) +{ + switch (ctx->map.intlv_mode) { + case NONE: + return 0; + + default: + return hygon_denorm_addr_common(ctx); + } +} diff --git a/drivers/ras/amd/atl/hygon/reg_fields.h b/drivers/ras/amd/atl/h= ygon/reg_fields.h index b3d658bef6ad..b48eaad4fed0 100644 --- a/drivers/ras/amd/atl/hygon/reg_fields.h +++ b/drivers/ras/amd/atl/hygon/reg_fields.h @@ -59,6 +59,19 @@ */ #define HYGON_DF1_INTLV_ADDR_SEL GENMASK(10, 8) =20 +/* + * Destination Fabric ID + * + * Access type: Instance + * + * Register + * Rev Fieldname Bits + * + * D18F0x114 [DRAM Limit Address] + * HYGON_DF1 DstFabricID [9:0] + */ +#define HYGON_DF1_DST_FABRIC_ID GENMASK(9, 0) + /* * Interleave Number of Dies * diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h index adcf94385b39..3d08c34b76cd 100644 --- a/drivers/ras/amd/atl/internal.h +++ b/drivers/ras/amd/atl/internal.h @@ -320,8 +320,12 @@ typedef int (*get_dram_offset_fn)(struct addr_ctx *ctx= , u64 *norm_offset); int find_normalized_offset(struct addr_ctx *ctx, u64 *norm_offset, get_dram_offset_fn get_dram_offset); =20 +u64 make_space_for_coh_st_id_at_intlv_bit(struct addr_ctx *ctx); +u64 insert_coh_st_id_at_intlv_bit(struct addr_ctx *ctx, u64 denorm_addr, u= 16 coh_st_id); + int hygon_get_df_system_info(void); int hygon_get_address_map(struct addr_ctx *ctx); +int hygon_denormalize_address(struct addr_ctx *ctx); =20 /* GUIDs for PRM handlers */ extern const guid_t norm_to_sys_guid; --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out198-24.us.a.mail.aliyun.com (out198-24.us.a.mail.aliyun.com [47.90.198.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D85D2310652; Thu, 28 May 2026 03:53:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=47.90.198.24 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940431; cv=none; b=EPZCw0Q0xECEEqcu8489hn2E3uFZH+TKvEs/XSeperbpmYS7M23U+9QX02u5tqPk6KfxlXt6Dc1oUmDkJuIYfmpa+lUDW9PQsuHuqKwBxeUblrC1oigMJWGrJelAqrCTkvtGFdlfkX7GHK9cWMyMVMcsT8Y1JAxp90wvsL0nSQY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940431; c=relaxed/simple; bh=SnVrbllw7Y2S15BSszvff/z5s0LuQb8oDZ6q/dRd/JY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ndZHC92Q1q86hiL8KJOnM61/jcEcjYbfFch0SI/1UHVPQ0ceC6YfGy291CIjVliuB/g7gKpRicU8MklTUFcVftFcC/3RMz63fgCkIQM58JMyPhFcItHzsEyy//V9ur077lfPlttrDTKWQJNRSEgwkiSx1ZwcCiYbX/gY9KHBCc4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=47.90.198.24 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436265|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.00426137-0.000702351-0.995036;FP=3105353133394314329|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033037032089;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeBq1_1779940406; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeBq1_1779940406 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:30 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 04/11] ras/amd/atl: Add Hygon DF1 address dehash helper Date: Thu, 28 May 2026 11:52:38 +0800 Message-ID: <20260528035246.526012-5-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add Hygon DF1 address dehash function that Hygon address translation pipeline depends on later. Prepare hygon_dehash_address() to be called by hygon/core.c later. - Add hygon/dehash.c for Hygon-specific implementation similar to dehash.c for AMD. - Add hygon_dehash_address() to do address dehashing where the DRAM map uses hashed interleave modes for Hygon DF1 including two-channel hash interleave mode and DDR5 case. - Use void return type for hygon_df_2chan_dehash_addr() as it never fails. - Use BIT_ULL() instead of BIT() when toggling the interleave bit in a u64 address to avoid truncation on bit positions >=3D 32. - Build hygon/dehash.c from the Makefile as an amd_atl object. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/Makefile | 1 + drivers/ras/amd/atl/hygon/dehash.c | 75 ++++++++++++++++++++++++++++++ drivers/ras/amd/atl/internal.h | 1 + 3 files changed, 77 insertions(+) create mode 100644 drivers/ras/amd/atl/hygon/dehash.c diff --git a/drivers/ras/amd/atl/Makefile b/drivers/ras/amd/atl/Makefile index c4e01f3ecc7b..fc12013de21f 100644 --- a/drivers/ras/amd/atl/Makefile +++ b/drivers/ras/amd/atl/Makefile @@ -15,6 +15,7 @@ amd_atl-y +=3D map.o amd_atl-y +=3D system.o amd_atl-y +=3D umc.o =20 +amd_atl-y +=3D hygon/dehash.o amd_atl-y +=3D hygon/denormalize.o amd_atl-y +=3D hygon/map.o amd_atl-y +=3D hygon/system.o diff --git a/drivers/ras/amd/atl/hygon/dehash.c b/drivers/ras/amd/atl/hygon= /dehash.c new file mode 100644 index 000000000000..9ec65888cf7b --- /dev/null +++ b/drivers/ras/amd/atl/hygon/dehash.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD Address Translation Library (for hygon) + * + * dehash.c : Functions to account for hashing bits for Hygon + * + * Author: Aichun Shi + */ + +#include "../internal.h" + +static int hygon_df1_ddr5_dehash_addr(struct addr_ctx *ctx) +{ + u8 chan_hash_enable =3D ctx->chan_intlv_hygon.chan_hash_enable; + u8 sub_channel =3D ctx->chan_intlv_hygon.sub_channel; + u8 start_bit =3D ctx->chan_intlv_hygon.start_bit; + u8 hashed_bit; + + if (chan_hash_enable) { + hashed_bit =3D (ctx->ret_addr >> 12) ^ + (ctx->ret_addr >> 21) ^ + (ctx->ret_addr >> 30) ^ + sub_channel; + hashed_bit &=3D BIT(0); + ctx->ret_addr |=3D hashed_bit << start_bit; + } else { + ctx->ret_addr |=3D sub_channel << start_bit; + } + + return 0; +} + +static void hygon_df_2chan_dehash_addr(struct addr_ctx *ctx) +{ + u8 hashed_bit; + u8 intlv_bit_pos =3D ctx->map.intlv_bit_pos; + + hashed_bit =3D (ctx->ret_addr >> 12) ^ + (ctx->ret_addr >> 18) ^ + (ctx->ret_addr >> 21) ^ + (ctx->ret_addr >> 30) ^ + ctx->coh_st_fabric_id; + + hashed_bit &=3D BIT(0); + if (hashed_bit !=3D ((ctx->ret_addr >> intlv_bit_pos) & BIT_ULL(0))) + ctx->ret_addr ^=3D BIT_ULL(intlv_bit_pos); +} + +int hygon_dehash_address(struct addr_ctx *ctx) +{ + switch (ctx->map.intlv_mode) { + /* No hashing cases. */ + case NONE: + case NOHASH_2CHAN: + case HYGON_DF1_3CHAN: + case NOHASH_4CHAN: + case NOHASH_8CHAN: + case NOHASH_16CHAN: + case NOHASH_32CHAN: + break; + + case DF2_2CHAN_HASH: + hygon_df_2chan_dehash_addr(ctx); + break; + + default: + atl_debug_on_bad_intlv_mode(ctx); + return -EINVAL; + } + + if (df_cfg.rev =3D=3D HYGON_DF1 && ctx->chan_intlv_hygon.ddr5_enable) + hygon_df1_ddr5_dehash_addr(ctx); + + return 0; +} diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h index 3d08c34b76cd..1d7f504b1164 100644 --- a/drivers/ras/amd/atl/internal.h +++ b/drivers/ras/amd/atl/internal.h @@ -326,6 +326,7 @@ u64 insert_coh_st_id_at_intlv_bit(struct addr_ctx *ctx,= u64 denorm_addr, u16 coh int hygon_get_df_system_info(void); int hygon_get_address_map(struct addr_ctx *ctx); int hygon_denormalize_address(struct addr_ctx *ctx); +int hygon_dehash_address(struct addr_ctx *ctx); =20 /* GUIDs for PRM handlers */ extern const guid_t norm_to_sys_guid; --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out28-220.mail.aliyun.com (out28-220.mail.aliyun.com [115.124.28.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F7FC3019A6; Thu, 28 May 2026 03:53:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.220 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940418; cv=none; b=pZL1NrP712Mp11dPCEyA5ScYvCqAPp/laXJNUK/c20dTZkrA4g0eaMY6PMd+NfkKUHi2a21GnczGRjjNFgkOC7aDI7AjJ/aLNba0avhCPyGtk9v8KBSLw9D/HC4WebPv5sFVruE/1Y5dnhB/JK8giA5lkiCkQYfNjdNc+EM/X7g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940418; c=relaxed/simple; bh=lNrBh1Wg6n9647cRiDZChtTe6VQ985thyLKcCUJv8Yg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bDKJuXQ+pfJp5sIKEsHU78lgK3k8tGifpFAC+CilFX3li7HWbLflC/fJMUxVJ2CS7/YhStijVJKdOf2xYnckARjmJ4fKE/JhHoZAtoppTDjiCAvUIGtfr5kyP8H8YGsQHfI8BuPH1Anl1mC1//9fUKneDzCcd4uG4kIR4i8hcmo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=115.124.28.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436259|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.00336733-0.000363507-0.996269;FP=9965760330803922687|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033037022039;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeBuW_1779940411; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeBuW_1779940411 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:34 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 05/11] ras/amd/atl: Add Hygon DF1 normalized-to-system address translation Date: Thu, 28 May 2026 11:52:39 +0800 Message-ID: <20260528035246.526012-6-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Translate a normalized UMC MCA address into a system physical address for Hygon DF1 with the following pipeline. Pipeline: - Initialize address context with socket, die, coherent-station instance, sub-channel, and normalized address. - Use the logical die_id directly as the DF node index; Hygon physical node IDs may be non-contiguous, so skip the socket/die mask shift computation used by determine_node_id(). - Call hygon_get_address_map() first to populate the address map context before checking legacy hole requirements. - Enforce legacy hole requirements when the map enables the hole without a configured hole base. - Run Hygon DRAM map decoding, denormalization, DRAM base plus legacy hole, dehash, and DRAM limit checks. Prepare hygon_norm_to_sys_addr() to be called by hygon/umc.c later. - Add hygon/core.c for Hygon-specific implementation similar to core.c for AMD. - Call hygon_get_address_map(), hygon_denormalize_address(), hygon_dehash_address() prepared previously in hygon/map.c, hygon/denormalize.c and hygon/dehash.c. - Use legacy hole_en() and addr_over_limit() shared from core.c and exported in internal.h to avoid duplicate code. - Build hygon/core.c from the Makefile as an amd_atl object. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/Makefile | 1 + drivers/ras/amd/atl/core.c | 4 +-- drivers/ras/amd/atl/hygon/core.c | 57 ++++++++++++++++++++++++++++++++ drivers/ras/amd/atl/internal.h | 6 ++++ 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 drivers/ras/amd/atl/hygon/core.c diff --git a/drivers/ras/amd/atl/Makefile b/drivers/ras/amd/atl/Makefile index fc12013de21f..0a42f2cbabc4 100644 --- a/drivers/ras/amd/atl/Makefile +++ b/drivers/ras/amd/atl/Makefile @@ -15,6 +15,7 @@ amd_atl-y +=3D map.o amd_atl-y +=3D system.o amd_atl-y +=3D umc.o =20 +amd_atl-y +=3D hygon/core.o amd_atl-y +=3D hygon/dehash.o amd_atl-y +=3D hygon/denormalize.o amd_atl-y +=3D hygon/map.o diff --git a/drivers/ras/amd/atl/core.c b/drivers/ras/amd/atl/core.c index 0f7cd6dab0b0..b7083588b46e 100644 --- a/drivers/ras/amd/atl/core.c +++ b/drivers/ras/amd/atl/core.c @@ -17,7 +17,7 @@ =20 struct df_config df_cfg __read_mostly; =20 -static int addr_over_limit(struct addr_ctx *ctx) +int addr_over_limit(struct addr_ctx *ctx) { u64 dram_limit_addr; =20 @@ -39,7 +39,7 @@ static int addr_over_limit(struct addr_ctx *ctx) return 0; } =20 -static bool legacy_hole_en(struct addr_ctx *ctx) +bool legacy_hole_en(struct addr_ctx *ctx) { u32 reg =3D ctx->map.base; =20 diff --git a/drivers/ras/amd/atl/hygon/core.c b/drivers/ras/amd/atl/hygon/c= ore.c new file mode 100644 index 000000000000..40d31458f1e2 --- /dev/null +++ b/drivers/ras/amd/atl/hygon/core.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD Address Translation Library (for hygon) + * + * core.c : Base translation functions for Hygon + * + * Author: Aichun Shi + */ + +#include "../internal.h" + +unsigned long hygon_norm_to_sys_addr(u8 socket_id, u8 die_id, u8 coh_st_in= st_id, + u8 sub_channel, unsigned long addr) +{ + struct addr_ctx ctx; + + if (df_cfg.rev =3D=3D UNKNOWN) + return -EINVAL; + + memset(&ctx, 0, sizeof(ctx)); + + /* Start from the normalized address */ + ctx.ret_addr =3D addr; + /* + * Hygon physical node IDs may be non-contiguous. Use hygon_cpu_to_df_nod= e() + * to get a contiguous DF node index instead of computing it from + * socket/die mask shifts via determine_node_id(). + */ + ctx.node_id =3D die_id; + ctx.inst_id =3D coh_st_inst_id; + + ctx.inputs.norm_addr =3D addr; + ctx.inputs.socket_id =3D socket_id; + ctx.inputs.die_id =3D die_id; + ctx.inputs.coh_st_inst_id =3D coh_st_inst_id; + + ctx.chan_intlv_hygon.sub_channel =3D sub_channel; + + if (hygon_get_address_map(&ctx)) + return -EINVAL; + + if (legacy_hole_en(&ctx) && !df_cfg.dram_hole_base) + return -EINVAL; + + if (hygon_denormalize_address(&ctx)) + return -EINVAL; + + ctx.ret_addr =3D add_base_and_hole(&ctx, ctx.ret_addr); + + if (hygon_dehash_address(&ctx)) + return -EINVAL; + + if (addr_over_limit(&ctx)) + return -EINVAL; + + return ctx.ret_addr; +} diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h index 1d7f504b1164..5648f9fdd1cb 100644 --- a/drivers/ras/amd/atl/internal.h +++ b/drivers/ras/amd/atl/internal.h @@ -308,6 +308,8 @@ unsigned long convert_umc_mca_addr_to_sys_addr(struct a= tl_err *err); =20 u64 add_base_and_hole(struct addr_ctx *ctx, u64 addr); u64 remove_base_and_hole(struct addr_ctx *ctx, u64 addr); +bool legacy_hole_en(struct addr_ctx *ctx); +int addr_over_limit(struct addr_ctx *ctx); =20 int get_dram_hole_base(void); void dump_df_cfg(void); @@ -328,6 +330,10 @@ int hygon_get_address_map(struct addr_ctx *ctx); int hygon_denormalize_address(struct addr_ctx *ctx); int hygon_dehash_address(struct addr_ctx *ctx); =20 +unsigned long hygon_norm_to_sys_addr(u8 socket_id, u8 die_id, u8 coh_st_in= st_id, + u8 sub_channel, unsigned long addr); +unsigned long hygon_convert_umc_mca_addr_to_sys_addr(struct atl_err *err); + /* GUIDs for PRM handlers */ extern const guid_t norm_to_sys_guid; =20 --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out198-27.us.a.mail.aliyun.com (out198-27.us.a.mail.aliyun.com [47.90.198.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 60DC0306B37; Thu, 28 May 2026 03:53:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=47.90.198.27 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940437; cv=none; b=EEJUu0XYezIrmQRFwSE9+zXbFfURjDz1GALXPMy/deYD+YWTzmb2hKg8kvWvreY8YTlCBJ4uNm4daBpmzPjlfR3Fbz5RfX495EuF2xTf6SmB83/0kFbZrYtAuFZjyhgtl9vIs02FC2/X5PQuBizsr/qOZuvgMi6MKa+LobQJ8mY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940437; c=relaxed/simple; bh=PIQTNLHxXCN1tndkapHFgbMOn794d2O9245/lmy28bM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gYEjQcqa9IhTBWae1IWCoL9BhE0bbm6A9r6zeP85bobgk1komjDeN1k7cOVlScwGdFCqS23J8twCzdJUoJun2bY/9eLFgbnbhaH2992NsgzXko11iRPrPR1cOtLnbDvxs2bjsRCXJSa3HO1XQanmniFwwth3QXQ2p2wB5ZIaiBM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=47.90.198.27 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436652|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_alarm|0.00302477-0.000264186-0.996711;FP=13694441621964164283|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033032023038;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeBxX_1779940414; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeBxX_1779940414 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:37 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 06/11] ras/amd/atl: Add Hygon UMC MCA to system address conversion support Date: Thu, 28 May 2026 11:52:40 +0800 Message-ID: <20260528035246.526012-7-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Prepare hygon_convert_umc_mca_addr_to_sys_addr() to be registered by amd_atl_register_decoder() in amd_atl_init() later. - Add hygon/umc.c for Hygon-specific implementation similar to umc.c for AMD. - Add hygon_convert_umc_mca_addr_to_sys_addr() to call hygon_norm_to_sys_addr() to do the address translation process. - Use hygon_cpu_to_df_node() to map the CPU to a contiguous DF node index; propagate -errno on failure. - Build hygon/umc.c from the Makefile as an amd_atl object. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/Makefile | 1 + drivers/ras/amd/atl/hygon/umc.c | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 drivers/ras/amd/atl/hygon/umc.c diff --git a/drivers/ras/amd/atl/Makefile b/drivers/ras/amd/atl/Makefile index 0a42f2cbabc4..9d65e215b87a 100644 --- a/drivers/ras/amd/atl/Makefile +++ b/drivers/ras/amd/atl/Makefile @@ -20,6 +20,7 @@ amd_atl-y +=3D hygon/dehash.o amd_atl-y +=3D hygon/denormalize.o amd_atl-y +=3D hygon/map.o amd_atl-y +=3D hygon/system.o +amd_atl-y +=3D hygon/umc.o =20 amd_atl-$(CONFIG_AMD_ATL_PRM) +=3D prm.o =20 diff --git a/drivers/ras/amd/atl/hygon/umc.c b/drivers/ras/amd/atl/hygon/um= c.c new file mode 100644 index 000000000000..0f064dd22bcc --- /dev/null +++ b/drivers/ras/amd/atl/hygon/umc.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD Address Translation Library (for hygon) + * + * umc.c : Unified Memory Controller (UMC) topology helpers for Hygon + * + * Author: Aichun Shi + */ + +#include "../internal.h" + +static int hygon_get_die_id(struct atl_err *err) +{ + return hygon_cpu_to_df_node(err->cpu); +} + +#define HYGON_IPID_SUB_CHANNEL_MASK BIT(13) +static u8 hygon_get_ipid_sub_channel(struct atl_err *err) +{ + return FIELD_GET(HYGON_IPID_SUB_CHANNEL_MASK, err->ipid); +} + +#define HYGON_UMC_CHANNEL_NUM GENMASK(23, 20) +static u8 hygon_get_coh_st_inst_id(struct atl_err *err) +{ + return FIELD_GET(HYGON_UMC_CHANNEL_NUM, err->ipid); +} + +unsigned long hygon_convert_umc_mca_addr_to_sys_addr(struct atl_err *err) +{ + u8 socket_id =3D topology_physical_package_id(err->cpu); + u8 coh_st_inst_id =3D hygon_get_coh_st_inst_id(err); + int die_id =3D hygon_get_die_id(err); + u8 sub_channel =3D hygon_get_ipid_sub_channel(err); + + if (die_id < 0) + return die_id; + + pr_debug("socket_id=3D0x%x die_id=3D0x%x coh_st_inst_id=3D0x%x addr=3D0x%= 016llx", + socket_id, die_id, coh_st_inst_id, err->addr); + + return hygon_norm_to_sys_addr(socket_id, die_id, coh_st_inst_id, + sub_channel, err->addr); +} --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out28-196.mail.aliyun.com (out28-196.mail.aliyun.com [115.124.28.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 65BC131327D; Thu, 28 May 2026 03:59:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940750; cv=none; b=XUE/LgE+QgfMV4/4j4oiZWT9h4/Mn4G5cW6hCsjhOOOINnqb9eGYkvhfVzcEco8vVhYFNRoD9GdggVNHmHGqS/kPSZLCCRSadtSHk6h4BwOZLS2T5yzPFbMrfyt76iO+uKlPu0E4X7bebGgvTYmO1HHJko2gWijePiiUymVHfvk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940750; c=relaxed/simple; bh=Ln/9CngqrVyl294T205TovUdUhW8j+gmNlh7b6KC0Ug=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kBWZ32YkYqNgLyFBm0qHRdLbETTwcITKAkIxuNQ3Uy2O4iWuj0PH/vMFfc55PNdGmBU21pOjZCYd/rbiQvQ1Yr8MLhzTRAfqQGHPMKjAqE8Dq7T2lDYglku+hdtUbIHBZtfkR9+abuZ9g0wX3Te8KBYfFnxfWDSBteWXW3uH0IA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=115.124.28.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.0745184|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.0030461-0.000431533-0.996522;FP=6929155660541054527|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033068005250;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeC.r_1779940417; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeC.r_1779940417 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:41 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 07/11] ras/amd/atl: Add Hygon DF discovery and MCA decode at initialization Date: Thu, 28 May 2026 11:52:41 +0800 Message-ID: <20260528035246.526012-8-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add node number bounds, Data Fabric discovery and UMC MCA to system address decoder for Hygon while keeping the AMD path unchanged. Address translation function is exported by amd_convert_umc_mca_addr_to_sys_addr() and used by users such as EDAC. - Use is_hygon_f18h() directly to guard Hygon-specific paths in amd_atl_init() and __df_indirect_read(); use hygon_cdd_num() as the Hygon node count. - Call hygon_get_df_system_info() to get Hygon-specific Data Fabric system information. - Register hygon_convert_umc_mca_addr_to_sys_addr() as the address translation decoder for Hygon. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/access.c | 8 +++++++- drivers/ras/amd/atl/core.c | 20 +++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/ras/amd/atl/access.c b/drivers/ras/amd/atl/access.c index c2334f8f9add..32c97de35c20 100644 --- a/drivers/ras/amd/atl/access.c +++ b/drivers/ras/amd/atl/access.c @@ -68,9 +68,15 @@ static int __df_indirect_read(u16 node, u8 func, u16 reg= , u8 instance_id, u32 *l struct pci_dev *F4; int err =3D -ENODEV; u32 ficaa =3D 0; + u16 num_nodes; =20 node =3D get_accessible_node(node); - if (node >=3D amd_nb_num()) { + if (is_hygon_f18h()) + num_nodes =3D hygon_cdd_num(); + else + num_nodes =3D amd_nb_num(); + + if (node >=3D num_nodes) { pr_debug("Node %u is out of bounds\n", node); goto out; } diff --git a/drivers/ras/amd/atl/core.c b/drivers/ras/amd/atl/core.c index b7083588b46e..ab01813eda29 100644 --- a/drivers/ras/amd/atl/core.c +++ b/drivers/ras/amd/atl/core.c @@ -195,22 +195,36 @@ MODULE_DEVICE_TABLE(x86cpu, amd_atl_cpuids); static int __init amd_atl_init(void) { int ret; + u16 num_nodes; =20 if (!x86_match_cpu(amd_atl_cpuids)) return -ENODEV; =20 - if (!amd_nb_num()) + if (is_hygon_f18h()) + num_nodes =3D hygon_cdd_num(); + else + num_nodes =3D amd_nb_num(); + + if (!num_nodes) return -ENODEV; =20 check_for_legacy_df_access(); =20 - ret =3D get_df_system_info(); + if (is_hygon_f18h()) + ret =3D hygon_get_df_system_info(); + else + ret =3D get_df_system_info(); + if (ret) return ret; =20 /* Increment this module's recount so that it can't be easily unloaded. */ __module_get(THIS_MODULE); - amd_atl_register_decoder(convert_umc_mca_addr_to_sys_addr); + + if (is_hygon_f18h()) + amd_atl_register_decoder(hygon_convert_umc_mca_addr_to_sys_addr); + else + amd_atl_register_decoder(convert_umc_mca_addr_to_sys_addr); =20 pr_info("AMD Address Translation Library initialized\n"); return 0; --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out28-98.mail.aliyun.com (out28-98.mail.aliyun.com [115.124.28.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E8843313522; Thu, 28 May 2026 03:53:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.98 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940435; cv=none; b=L4srOfyWbe3o/P3iWx7THZPaIkaRI+xEbUjGSHSwPaF/Ie6VK6eu3cpEO+jXW3vWDNbcrqbNyTS+Y62UYIAv/r8CwTgbMuO5Xnr3NezhoZ2XKyyKl6RYI9RnCfZ2gXQFwtu1fhgXDBuBOUAeR2OL68EHC+Nv3gzHI+dOHmn6AJw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940435; c=relaxed/simple; bh=qYKSPzN6EkwxryseXHyaya2jyR3bdrjjDtwQ/5UZaJo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K84RmWdYrGcx3XxD8Me7JFdhIkMHr1cEcNSVdDSJe/YAqLSBoCQYdJtfaWLk4a4/CL7ybLi3DuDIUBf/D1Kcz8Eu42l8O+m5cPfj8fHzOdGxMQnFdrmyv4FHVn/Tw5IE1OfuMsYttajJ+uBpgf7aqVApiJrL8vLIW3UaOCjBhZI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=115.124.28.98 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436259|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.00236447-0.000260808-0.997375;FP=1976337212772305938|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033037017159;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeC3j_1779940421; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeC3j_1779940421 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:44 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 08/11] ras/amd/atl: Add Hygon DF2 address translation support Date: Thu, 28 May 2026 11:52:42 +0800 Message-ID: <20260528035246.526012-9-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend address translation support for Hygon Family 0x18 model 0x6/0x8 (Hygon DF2). System detection: - Add register field definitions for Hygon DF2 in hygon/reg_fields.h. - Add HYGON_DF2 to enum df_revisions and interleave mode HYGON_DF2_4CHAN_HASH (0x22, above the 0x20 DF4.5 range to avoid aliasing with hardware values) for four-channel hash for Hygon DF2 in internal.h. - Discover Hygon DF2 socket/die mask widths and shifts; detect model 0x6/0x8 as Hygon DF2. DRAM map: - Add hygon_df2_get_dram_addr_map(): use shared AMD DF2 DRAM base/limit via df2_get_dram_addr_map(), and read Hygon-specific interleave fields. - Map hardware intlv_mode 8 to HYGON_DF2_4CHAN_HASH on DF2 and to DF2_2CHAN_HASH on other revisions; add DF2_2CHAN_HASH (2-channel) and HYGON_DF2_4CHAN_HASH (4-channel) to the channel count table. - Get die/socket interleave count for Hygon DF2. Denormalize/dehash: - Get coherent-station fabric ID for Hygon DF2 including HYGON_DF2_4CHAN_HASH case. - Add HYGON_DF2_4CHAN_HASH to make-space, calculate, and insert coherent-station ID switch cases in hygon/denormalize.c. - Add hygon_df2_4chan_dehash_addr() with void return type to support dehash for HYGON_DF2_4CHAN_HASH; it never fails. UMC: - Form the coherent-station instance ID from the channel field and sub-channel bit from MCA IPID to match Hygon DF2 UMC addressing. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/hygon/dehash.c | 21 +++++++++++++++ drivers/ras/amd/atl/hygon/denormalize.c | 5 ++++ drivers/ras/amd/atl/hygon/map.c | 36 ++++++++++++++++++++++--- drivers/ras/amd/atl/hygon/reg_fields.h | 18 +++++++++++++ drivers/ras/amd/atl/hygon/system.c | 9 +++++++ drivers/ras/amd/atl/hygon/umc.c | 8 +++++- drivers/ras/amd/atl/internal.h | 2 ++ 7 files changed, 95 insertions(+), 4 deletions(-) diff --git a/drivers/ras/amd/atl/hygon/dehash.c b/drivers/ras/amd/atl/hygon= /dehash.c index 9ec65888cf7b..e46b9acaba93 100644 --- a/drivers/ras/amd/atl/hygon/dehash.c +++ b/drivers/ras/amd/atl/hygon/dehash.c @@ -46,6 +46,23 @@ static void hygon_df_2chan_dehash_addr(struct addr_ctx *= ctx) ctx->ret_addr ^=3D BIT_ULL(intlv_bit_pos); } =20 +static void hygon_df2_4chan_dehash_addr(struct addr_ctx *ctx) +{ + u8 hashed_bit; + u8 intlv_bit_pos =3D ctx->map.intlv_bit_pos; + + hashed_bit =3D (ctx->ret_addr >> 12) ^ + (ctx->ret_addr >> 18) ^ + (ctx->ret_addr >> 21) ^ + (ctx->ret_addr >> 30) ^ + ctx->coh_st_fabric_id; + + hashed_bit &=3D 0x3; + if (hashed_bit !=3D ((ctx->ret_addr >> intlv_bit_pos) & 0x3)) + ctx->ret_addr =3D (ctx->ret_addr & ~((u64)3 << intlv_bit_pos)) | + (hashed_bit << intlv_bit_pos); +} + int hygon_dehash_address(struct addr_ctx *ctx) { switch (ctx->map.intlv_mode) { @@ -63,6 +80,10 @@ int hygon_dehash_address(struct addr_ctx *ctx) hygon_df_2chan_dehash_addr(ctx); break; =20 + case HYGON_DF2_4CHAN_HASH: + hygon_df2_4chan_dehash_addr(ctx); + break; + default: atl_debug_on_bad_intlv_mode(ctx); return -EINVAL; diff --git a/drivers/ras/amd/atl/hygon/denormalize.c b/drivers/ras/amd/atl/= hygon/denormalize.c index 8bf1cd1efa14..b64ea18aae66 100644 --- a/drivers/ras/amd/atl/hygon/denormalize.c +++ b/drivers/ras/amd/atl/hygon/denormalize.c @@ -20,6 +20,8 @@ static u16 hygon_get_dst_fabric_id(struct addr_ctx *ctx) switch (df_cfg.rev) { case HYGON_DF1: return FIELD_GET(HYGON_DF1_DST_FABRIC_ID, ctx->map.limit); + case HYGON_DF2: + return FIELD_GET(HYGON_DF2_DST_FABRIC_ID, ctx->map.limit); default: atl_debug_on_bad_df_rev(); return 0; @@ -40,6 +42,7 @@ static u64 hygon_make_space_for_coh_st_id(struct addr_ctx= *ctx) case NOHASH_16CHAN: case NOHASH_32CHAN: case DF2_2CHAN_HASH: + case HYGON_DF2_4CHAN_HASH: return make_space_for_coh_st_id_at_intlv_bit(ctx); =20 case HYGON_DF1_3CHAN: @@ -129,6 +132,7 @@ static u16 hygon_calculate_coh_st_id(struct addr_ctx *c= tx) case NOHASH_16CHAN: case NOHASH_32CHAN: case DF2_2CHAN_HASH: + case HYGON_DF2_4CHAN_HASH: return hygon_get_coh_st_id_df(ctx); =20 default: @@ -156,6 +160,7 @@ static u64 hygon_insert_coh_st_id(struct addr_ctx *ctx,= u64 denorm_addr, u16 coh case NOHASH_16CHAN: case NOHASH_32CHAN: case DF2_2CHAN_HASH: + case HYGON_DF2_4CHAN_HASH: return insert_coh_st_id_at_intlv_bit(ctx, denorm_addr, coh_st_id); =20 case HYGON_DF1_3CHAN: diff --git a/drivers/ras/amd/atl/hygon/map.c b/drivers/ras/amd/atl/hygon/ma= p.c index 7d0ed942a28f..79f23c1d4203 100644 --- a/drivers/ras/amd/atl/hygon/map.c +++ b/drivers/ras/amd/atl/hygon/map.c @@ -16,15 +16,20 @@ static int hygon_df_get_intlv_mode(struct addr_ctx *ctx) if (df_cfg.rev =3D=3D HYGON_DF1 && ctx->map.intlv_mode =3D=3D 2) ctx->map.intlv_mode =3D HYGON_DF1_3CHAN; =20 - if (ctx->map.intlv_mode =3D=3D 8) - ctx->map.intlv_mode =3D DF2_2CHAN_HASH; + if (ctx->map.intlv_mode =3D=3D 8) { + if (df_cfg.rev =3D=3D HYGON_DF2) + ctx->map.intlv_mode =3D HYGON_DF2_4CHAN_HASH; + else + ctx->map.intlv_mode =3D DF2_2CHAN_HASH; + } =20 if (ctx->map.intlv_mode !=3D NONE && ctx->map.intlv_mode !=3D NOHASH_2CHAN && - ctx->map.intlv_mode !=3D HYGON_DF1_3CHAN && + ctx->map.intlv_mode !=3D HYGON_DF1_3CHAN && ctx->map.intlv_mode !=3D NOHASH_4CHAN && ctx->map.intlv_mode !=3D NOHASH_8CHAN && ctx->map.intlv_mode !=3D NOHASH_16CHAN && + ctx->map.intlv_mode !=3D HYGON_DF2_4CHAN_HASH && ctx->map.intlv_mode !=3D DF2_2CHAN_HASH) return -EINVAL; =20 @@ -38,6 +43,7 @@ static u64 hygon_get_hi_addr_offset(u32 reg_dram_offset) =20 switch (df_cfg.rev) { case HYGON_DF1: + case HYGON_DF2: hi_addr_offset =3D FIELD_GET(HYGON_DF1_HI_ADDR_OFFSET, reg_dram_offset); break; default: @@ -121,10 +127,24 @@ static int hygon_df1_get_dram_addr_map(struct addr_ct= x *ctx) return 0; } =20 +static int hygon_df2_get_dram_addr_map(struct addr_ctx *ctx) +{ + if (df2_get_dram_addr_map(ctx)) + return -EINVAL; + + /* Read D18F0x60 */ + if (df_indirect_read_instance(ctx->node_id, 0, 0x60, + ctx->inst_id, &ctx->map.intlv)) + return -EINVAL; + + return 0; +} + static int hygon_get_dram_addr_map(struct addr_ctx *ctx) { switch (df_cfg.rev) { case HYGON_DF1: return hygon_df1_get_dram_addr_map(ctx); + case HYGON_DF2: return hygon_df2_get_dram_addr_map(ctx); default: atl_debug_on_bad_df_rev(); return -EINVAL; @@ -143,6 +163,9 @@ static int hygon_get_coh_st_fabric_id(struct addr_ctx *= ctx) case HYGON_DF1: ctx->coh_st_fabric_id =3D FIELD_GET(HYGON_DF1_COH_ST_FABRIC_ID, reg); break; + case HYGON_DF2: + ctx->coh_st_fabric_id =3D FIELD_GET(HYGON_DF2_COH_ST_FABRIC_ID, reg); + break; default: atl_debug_on_bad_df_rev(); return -EINVAL; @@ -178,9 +201,11 @@ static u8 hygon_get_num_intlv_chan(struct addr_ctx *ct= x) case NONE: return 1; case NOHASH_2CHAN: + case DF2_2CHAN_HASH: return 2; case HYGON_DF1_3CHAN: return 3; + case HYGON_DF2_4CHAN_HASH: case NOHASH_4CHAN: return 4; case NOHASH_8CHAN: @@ -216,6 +241,7 @@ static u8 hygon_get_intlv_bit_pos(struct addr_ctx *ctx) =20 switch (df_cfg.rev) { case HYGON_DF1: + case HYGON_DF2: addr_sel =3D FIELD_GET(HYGON_DF1_INTLV_ADDR_SEL, ctx->map.base); break; default: @@ -235,6 +261,9 @@ static u8 hygon_get_num_intlv_dies(struct addr_ctx *ctx) case HYGON_DF1: dies =3D FIELD_GET(HYGON_DF1_INTLV_NUM_DIES, ctx->map.limit); break; + case HYGON_DF2: + dies =3D FIELD_GET(HYGON_DF2_INTLV_NUM_DIES, ctx->map.intlv); + break; default: atl_debug_on_bad_df_rev(); break; @@ -250,6 +279,7 @@ static u8 hygon_get_num_intlv_sockets(struct addr_ctx *= ctx) =20 switch (df_cfg.rev) { case HYGON_DF1: + case HYGON_DF2: sockets =3D FIELD_GET(HYGON_DF1_INTLV_NUM_SOCKETS, ctx->map.base); break; default: diff --git a/drivers/ras/amd/atl/hygon/reg_fields.h b/drivers/ras/amd/atl/h= ygon/reg_fields.h index b48eaad4fed0..dd50fddd9402 100644 --- a/drivers/ras/amd/atl/hygon/reg_fields.h +++ b/drivers/ras/amd/atl/hygon/reg_fields.h @@ -17,8 +17,10 @@ * * D18F0x50 [Fabric Block Instance Information 3] * HYGON_DF1 BlockFabricId [17:8] + * HYGON_DF2 BlockFabricId [18:8] */ #define HYGON_DF1_COH_ST_FABRIC_ID GENMASK(17, 8) +#define HYGON_DF2_COH_ST_FABRIC_ID GENMASK(18, 8) =20 /* * Interleave Number of Sockets @@ -30,6 +32,7 @@ * * D18F0x110 [DRAM Base Address] * HYGON_DF1 IntLvNumSockets [3:2] + * HYGON_DF2 IntLvNumSockets [3:2] */ #define HYGON_DF1_INTLV_NUM_SOCKETS GENMASK(3, 2) =20 @@ -43,6 +46,7 @@ * * D18F0x110 [DRAM Base Address] * HYGON_DF1 IntLvNumChan [7:4] + * HYGON_DF2 IntLvNumChan [7:4] */ #define HYGON_DF1_INTLV_NUM_CHAN GENMASK(7, 4) =20 @@ -56,6 +60,7 @@ * * D18F0x110 [DRAM Base Address] * HYGON_DF1 IntLvAddrSel [10:8] + * HYGON_DF2 IntLvAddrSel [10:8] */ #define HYGON_DF1_INTLV_ADDR_SEL GENMASK(10, 8) =20 @@ -69,8 +74,10 @@ * * D18F0x114 [DRAM Limit Address] * HYGON_DF1 DstFabricID [9:0] + * HYGON_DF2 DstFabricID [10:0] */ #define HYGON_DF1_DST_FABRIC_ID GENMASK(9, 0) +#define HYGON_DF2_DST_FABRIC_ID GENMASK(10, 0) =20 /* * Interleave Number of Dies @@ -82,8 +89,12 @@ * * D18F0x114 [DRAM Limit Address] * HYGON_DF1 IntLvNumDies [11:10] + * + * D18F0x60 + * HYGON_DF2 IntLvNumDies [1:0] */ #define HYGON_DF1_INTLV_NUM_DIES GENMASK(11, 10) +#define HYGON_DF2_INTLV_NUM_DIES GENMASK(1, 0) =20 /* * High Address Offset @@ -95,6 +106,7 @@ * * D18F0x214 [DRAM Offset] * HYGON_DF1 HiAddrOffset [31:19] + * HYGON_DF2 HiAddrOffset [31:19] */ #define HYGON_DF1_HI_ADDR_OFFSET GENMASK(31, 19) =20 @@ -108,8 +120,10 @@ * * D18F1x208 [System Fabric ID Mask] * HYGON_DF1 DieIdMask [9:0] + * HYGON_DF2 DieIdMask [10:0] */ #define HYGON_DF1_DIE_ID_MASK GENMASK(9, 0) +#define HYGON_DF2_DIE_ID_MASK GENMASK(10, 0) =20 /* * Die ID Shift @@ -121,6 +135,7 @@ * * D18F1x208 [System Fabric ID Mask] * HYGON_DF1 DieIdShift [15:12] + * HYGON_DF2 DieIdShift [15:12] */ #define HYGON_DF1_DIE_ID_SHIFT GENMASK(15, 12) =20 @@ -134,8 +149,10 @@ * * D18F1x208 [System Fabric ID Mask] * HYGON_DF1 SocketIdMask [25:16] + * HYGON_DF2 SocketIdMask [26:16] */ #define HYGON_DF1_SOCKET_ID_MASK GENMASK(25, 16) +#define HYGON_DF2_SOCKET_ID_MASK GENMASK(26, 16) =20 /* * Socket ID Shift @@ -147,5 +164,6 @@ * * D18F1x208 [System Fabric ID Mask] * HYGON_DF1 SocketIdShift [31:28] + * HYGON_DF2 SocketIdShift [31:28] */ #define HYGON_DF1_SOCKET_ID_SHIFT GENMASK(31, 28) diff --git a/drivers/ras/amd/atl/hygon/system.c b/drivers/ras/amd/atl/hygon= /system.c index bff577a559ad..99a139acaac6 100644 --- a/drivers/ras/amd/atl/hygon/system.c +++ b/drivers/ras/amd/atl/hygon/system.c @@ -18,6 +18,12 @@ static void hygon_df_get_masks_shifts(u32 mask0) df_cfg.die_id_shift =3D FIELD_GET(HYGON_DF1_DIE_ID_SHIFT, mask0); df_cfg.die_id_mask =3D FIELD_GET(HYGON_DF1_DIE_ID_MASK, mask0); break; + case HYGON_DF2: + df_cfg.socket_id_shift =3D FIELD_GET(HYGON_DF1_SOCKET_ID_SHIFT, mask0); + df_cfg.socket_id_mask =3D FIELD_GET(HYGON_DF2_SOCKET_ID_MASK, mask0); + df_cfg.die_id_shift =3D FIELD_GET(HYGON_DF1_DIE_ID_SHIFT, mask0); + df_cfg.die_id_mask =3D FIELD_GET(HYGON_DF2_DIE_ID_MASK, mask0); + break; default: atl_debug_on_bad_df_rev(); return; @@ -33,6 +39,8 @@ static int hygon_determine_df_rev(void) =20 if (hygon_f18h_model_in_range(0x4, 0x5)) df_cfg.rev =3D HYGON_DF1; + else if (boot_cpu_data.x86_model =3D=3D 0x6 || boot_cpu_data.x86_model = =3D=3D 0x8) + df_cfg.rev =3D HYGON_DF2; =20 /* Read D18F1x208 (SystemFabricIdMask). */ if (df_indirect_read_broadcast(0, 1, 0x208, &fabric_id_mask0)) @@ -47,6 +55,7 @@ static void hygon_get_num_maps(void) { switch (df_cfg.rev) { case HYGON_DF1: + case HYGON_DF2: df_cfg.num_coh_st_maps =3D 2; break; default: diff --git a/drivers/ras/amd/atl/hygon/umc.c b/drivers/ras/amd/atl/hygon/um= c.c index 0f064dd22bcc..fd25deb843db 100644 --- a/drivers/ras/amd/atl/hygon/umc.c +++ b/drivers/ras/amd/atl/hygon/umc.c @@ -23,7 +23,13 @@ static u8 hygon_get_ipid_sub_channel(struct atl_err *err) #define HYGON_UMC_CHANNEL_NUM GENMASK(23, 20) static u8 hygon_get_coh_st_inst_id(struct atl_err *err) { - return FIELD_GET(HYGON_UMC_CHANNEL_NUM, err->ipid); + u8 sub_channel =3D hygon_get_ipid_sub_channel(err); + u8 coh_st_inst_id =3D FIELD_GET(HYGON_UMC_CHANNEL_NUM, err->ipid); + + if (df_cfg.rev =3D=3D HYGON_DF2) + coh_st_inst_id =3D (coh_st_inst_id << 1) + sub_channel; + + return coh_st_inst_id; } =20 unsigned long hygon_convert_umc_mca_addr_to_sys_addr(struct atl_err *err) diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h index 5648f9fdd1cb..bda71630b4a1 100644 --- a/drivers/ras/amd/atl/internal.h +++ b/drivers/ras/amd/atl/internal.h @@ -55,6 +55,7 @@ static inline bool is_hygon_f18h(void) enum df_revisions { UNKNOWN, HYGON_DF1, + HYGON_DF2, DF2, DF3, DF3p5, @@ -87,6 +88,7 @@ enum intlv_modes { MI3_HASH_16CHAN =3D 0x19, MI3_HASH_32CHAN =3D 0x1A, DF2_2CHAN_HASH =3D 0x21, + HYGON_DF2_4CHAN_HASH =3D 0x22, /* DF4.5 modes are all IntLvNumChan + 0x20 */ DF4p5_NPS1_16CHAN_1K_HASH =3D 0x2C, DF4p5_NPS0_24CHAN_1K_HASH =3D 0x2E, --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out28-98.mail.aliyun.com (out28-98.mail.aliyun.com [115.124.28.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8999D3101B9; Thu, 28 May 2026 03:53:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.98 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940437; cv=none; b=ln/n5geTD80XqWddbrkllXJBjE3G5mN8OnUQUTBRkTPi0zeiHlz3aDDNkcwTiC3A8MblHGXVo4EFoBbnIVUJM2h4eqP6q4AxATWb0hiWNbRjAU8OTLsUYrBs6/ZtzVu1FUD1g3qR9VN5a4UcHX8Od2Rc+Gvs7z/x1WYqlMNaJJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940437; c=relaxed/simple; bh=20z6J+rb+k3AyYIeuD0rndoBzU2aeXYnAvYonsNifv8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ds/YiiRivxxh3EKu/jx69m5/mqotiu707x9H2D6HTIKffbQx2todeorp5wJMCRsCgF6bohyZ+vyvy4Q2DmXt6E7lBZwvWw7VDXS8MrDyJ2p+rpGzJMRzT2AZZw/Bj88JfjglmTPXtMYgtA+1FBhcLbiaFktbbu+qcwM2teqh/Eg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=115.124.28.98 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436264|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_alarm|0.00501537-0.00373007-0.991255;FP=1688142016429214746|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033040074035;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeC7I_1779940424; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeC7I_1779940424 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:47 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 09/11] ras/amd/atl: Add Hygon DF3 address translation support Date: Thu, 28 May 2026 11:52:43 +0800 Message-ID: <20260528035246.526012-10-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend address translation support for Hygon Family 0x18 model 0x7 (Hygon DF3). System detection: - Add register field definitions for Hygon DF3 in hygon/reg_fields.h. - Add HYGON_DF3 to enum df_revisions in internal.h. - Discover Hygon DF3 socket/die mask widths and shifts; detect model 0x7 as Hygon DF3. - Return -EINVAL from hygon_determine_df_rev() for unrecognized models rather than silently succeeding with UNKNOWN revision. DRAM map: - Use shared AMD DF2 DRAM base/limit via df2_get_dram_addr_map(). - Map Hygon-specific HYGON_DF2_4CHAN_HASH interleave mode for Hygon DF3. - Get die/socket interleave count for Hygon DF3. - Get DRAM offset and high address offset for Hygon DF3; use explicit equality comparisons in hygon_get_dram_offset() instead of >=3D to avoid accidentally matching AMD DF revisions. Denormalize: - Get destination fabric ID for Hygon DF3. UMC: - Extend hygon_get_coh_st_inst_id() to apply the sub-channel shift for HYGON_DF3 in addition to HYGON_DF2. Signed-off-by: Aichun Shi --- drivers/ras/amd/atl/hygon/denormalize.c | 2 ++ drivers/ras/amd/atl/hygon/map.c | 21 +++++++++++++++++++-- drivers/ras/amd/atl/hygon/reg_fields.h | 22 ++++++++++++++++++++++ drivers/ras/amd/atl/hygon/system.c | 11 +++++++++++ drivers/ras/amd/atl/hygon/umc.c | 2 +- drivers/ras/amd/atl/internal.h | 1 + 6 files changed, 56 insertions(+), 3 deletions(-) diff --git a/drivers/ras/amd/atl/hygon/denormalize.c b/drivers/ras/amd/atl/= hygon/denormalize.c index b64ea18aae66..aba00e25307d 100644 --- a/drivers/ras/amd/atl/hygon/denormalize.c +++ b/drivers/ras/amd/atl/hygon/denormalize.c @@ -22,6 +22,8 @@ static u16 hygon_get_dst_fabric_id(struct addr_ctx *ctx) return FIELD_GET(HYGON_DF1_DST_FABRIC_ID, ctx->map.limit); case HYGON_DF2: return FIELD_GET(HYGON_DF2_DST_FABRIC_ID, ctx->map.limit); + case HYGON_DF3: + return FIELD_GET(HYGON_DF3_DST_FABRIC_ID, ctx->map.limit); default: atl_debug_on_bad_df_rev(); return 0; diff --git a/drivers/ras/amd/atl/hygon/map.c b/drivers/ras/amd/atl/hygon/ma= p.c index 79f23c1d4203..95d9e9b0b2e6 100644 --- a/drivers/ras/amd/atl/hygon/map.c +++ b/drivers/ras/amd/atl/hygon/map.c @@ -17,7 +17,7 @@ static int hygon_df_get_intlv_mode(struct addr_ctx *ctx) ctx->map.intlv_mode =3D HYGON_DF1_3CHAN; =20 if (ctx->map.intlv_mode =3D=3D 8) { - if (df_cfg.rev =3D=3D HYGON_DF2) + if (df_cfg.rev =3D=3D HYGON_DF2 || df_cfg.rev =3D=3D HYGON_DF3) ctx->map.intlv_mode =3D HYGON_DF2_4CHAN_HASH; else ctx->map.intlv_mode =3D DF2_2CHAN_HASH; @@ -46,6 +46,9 @@ static u64 hygon_get_hi_addr_offset(u32 reg_dram_offset) case HYGON_DF2: hi_addr_offset =3D FIELD_GET(HYGON_DF1_HI_ADDR_OFFSET, reg_dram_offset); break; + case HYGON_DF3: + hi_addr_offset =3D FIELD_GET(HYGON_DF3_HI_ADDR_OFFSET, reg_dram_offset); + break; default: hi_addr_offset =3D 0; atl_debug_on_bad_df_rev(); @@ -77,7 +80,12 @@ static int hygon_get_dram_offset(struct addr_ctx *ctx, u= 64 *norm_offset) */ map_num =3D ctx->map.num - 1; =20 - if (df_cfg.rev >=3D HYGON_DF1) { + if (df_cfg.rev =3D=3D HYGON_DF3) { + /* Read D18F0x1B4 (DramOffset) */ + if (df_indirect_read_instance(ctx->node_id, 0, 0x1B4 + (4 * map_num), + ctx->inst_id, ®_dram_offset)) + return -EINVAL; + } else if (df_cfg.rev =3D=3D HYGON_DF1 || df_cfg.rev =3D=3D HYGON_DF2) { /* Read D18F0x214 (DramOffset) */ if (df_indirect_read_instance(ctx->node_id, 0, 0x214 + (4 * map_num), ctx->inst_id, ®_dram_offset)) @@ -145,6 +153,7 @@ static int hygon_get_dram_addr_map(struct addr_ctx *ctx) switch (df_cfg.rev) { case HYGON_DF1: return hygon_df1_get_dram_addr_map(ctx); case HYGON_DF2: return hygon_df2_get_dram_addr_map(ctx); + case HYGON_DF3: return df2_get_dram_addr_map(ctx); default: atl_debug_on_bad_df_rev(); return -EINVAL; @@ -166,6 +175,9 @@ static int hygon_get_coh_st_fabric_id(struct addr_ctx *= ctx) case HYGON_DF2: ctx->coh_st_fabric_id =3D FIELD_GET(HYGON_DF2_COH_ST_FABRIC_ID, reg); break; + case HYGON_DF3: + ctx->coh_st_fabric_id =3D FIELD_GET(HYGON_DF3_COH_ST_FABRIC_ID, reg); + break; default: atl_debug_on_bad_df_rev(); return -EINVAL; @@ -242,6 +254,7 @@ static u8 hygon_get_intlv_bit_pos(struct addr_ctx *ctx) switch (df_cfg.rev) { case HYGON_DF1: case HYGON_DF2: + case HYGON_DF3: addr_sel =3D FIELD_GET(HYGON_DF1_INTLV_ADDR_SEL, ctx->map.base); break; default: @@ -259,6 +272,7 @@ static u8 hygon_get_num_intlv_dies(struct addr_ctx *ctx) =20 switch (df_cfg.rev) { case HYGON_DF1: + case HYGON_DF3: dies =3D FIELD_GET(HYGON_DF1_INTLV_NUM_DIES, ctx->map.limit); break; case HYGON_DF2: @@ -282,6 +296,9 @@ static u8 hygon_get_num_intlv_sockets(struct addr_ctx *= ctx) case HYGON_DF2: sockets =3D FIELD_GET(HYGON_DF1_INTLV_NUM_SOCKETS, ctx->map.base); break; + case HYGON_DF3: + sockets =3D FIELD_GET(HYGON_DF3_INTLV_NUM_SOCKETS, ctx->map.limit); + break; default: atl_debug_on_bad_df_rev(); break; diff --git a/drivers/ras/amd/atl/hygon/reg_fields.h b/drivers/ras/amd/atl/h= ygon/reg_fields.h index dd50fddd9402..817d95154192 100644 --- a/drivers/ras/amd/atl/hygon/reg_fields.h +++ b/drivers/ras/amd/atl/hygon/reg_fields.h @@ -18,9 +18,11 @@ * D18F0x50 [Fabric Block Instance Information 3] * HYGON_DF1 BlockFabricId [17:8] * HYGON_DF2 BlockFabricId [18:8] + * HYGON_DF3 BlockFabricId [15:8] */ #define HYGON_DF1_COH_ST_FABRIC_ID GENMASK(17, 8) #define HYGON_DF2_COH_ST_FABRIC_ID GENMASK(18, 8) +#define HYGON_DF3_COH_ST_FABRIC_ID GENMASK(15, 8) =20 /* * Interleave Number of Sockets @@ -33,8 +35,12 @@ * D18F0x110 [DRAM Base Address] * HYGON_DF1 IntLvNumSockets [3:2] * HYGON_DF2 IntLvNumSockets [3:2] + * + * D18F0x114 [DRAM Limit Address] + * HYGON_DF3 IntLvNumSockets [8] */ #define HYGON_DF1_INTLV_NUM_SOCKETS GENMASK(3, 2) +#define HYGON_DF3_INTLV_NUM_SOCKETS BIT(8) =20 /* * Interleave Number of Channels @@ -47,6 +53,7 @@ * D18F0x110 [DRAM Base Address] * HYGON_DF1 IntLvNumChan [7:4] * HYGON_DF2 IntLvNumChan [7:4] + * HYGON_DF3 IntLvNumChan [7:4] */ #define HYGON_DF1_INTLV_NUM_CHAN GENMASK(7, 4) =20 @@ -61,6 +68,7 @@ * D18F0x110 [DRAM Base Address] * HYGON_DF1 IntLvAddrSel [10:8] * HYGON_DF2 IntLvAddrSel [10:8] + * HYGON_DF3 IntLvAddrSel [10:8] */ #define HYGON_DF1_INTLV_ADDR_SEL GENMASK(10, 8) =20 @@ -75,9 +83,11 @@ * D18F0x114 [DRAM Limit Address] * HYGON_DF1 DstFabricID [9:0] * HYGON_DF2 DstFabricID [10:0] + * HYGON_DF3 DstFabricID [7:0] */ #define HYGON_DF1_DST_FABRIC_ID GENMASK(9, 0) #define HYGON_DF2_DST_FABRIC_ID GENMASK(10, 0) +#define HYGON_DF3_DST_FABRIC_ID GENMASK(7, 0) =20 /* * Interleave Number of Dies @@ -89,6 +99,7 @@ * * D18F0x114 [DRAM Limit Address] * HYGON_DF1 IntLvNumDies [11:10] + * HYGON_DF3 IntLvNumDies [11:10] * * D18F0x60 * HYGON_DF2 IntLvNumDies [1:0] @@ -107,8 +118,12 @@ * D18F0x214 [DRAM Offset] * HYGON_DF1 HiAddrOffset [31:19] * HYGON_DF2 HiAddrOffset [31:19] + * + * D18F0x1B4 [DRAM Offset] + * HYGON_DF3 HiAddrOffset [31:20] */ #define HYGON_DF1_HI_ADDR_OFFSET GENMASK(31, 19) +#define HYGON_DF3_HI_ADDR_OFFSET GENMASK(31, 20) =20 /* * Die ID Mask @@ -121,9 +136,11 @@ * D18F1x208 [System Fabric ID Mask] * HYGON_DF1 DieIdMask [9:0] * HYGON_DF2 DieIdMask [10:0] + * HYGON_DF3 DieIdMask [15:8] */ #define HYGON_DF1_DIE_ID_MASK GENMASK(9, 0) #define HYGON_DF2_DIE_ID_MASK GENMASK(10, 0) +#define HYGON_DF3_DIE_ID_MASK GENMASK(15, 8) =20 /* * Die ID Shift @@ -136,8 +153,10 @@ * D18F1x208 [System Fabric ID Mask] * HYGON_DF1 DieIdShift [15:12] * HYGON_DF2 DieIdShift [15:12] + * HYGON_DF3 DieIdShift [27:24] */ #define HYGON_DF1_DIE_ID_SHIFT GENMASK(15, 12) +#define HYGON_DF3_DIE_ID_SHIFT GENMASK(27, 24) =20 /* * Socket ID Mask @@ -150,9 +169,11 @@ * D18F1x208 [System Fabric ID Mask] * HYGON_DF1 SocketIdMask [25:16] * HYGON_DF2 SocketIdMask [26:16] + * HYGON_DF3 SocketIdMask [23:16] */ #define HYGON_DF1_SOCKET_ID_MASK GENMASK(25, 16) #define HYGON_DF2_SOCKET_ID_MASK GENMASK(26, 16) +#define HYGON_DF3_SOCKET_ID_MASK GENMASK(23, 16) =20 /* * Socket ID Shift @@ -165,5 +186,6 @@ * D18F1x208 [System Fabric ID Mask] * HYGON_DF1 SocketIdShift [31:28] * HYGON_DF2 SocketIdShift [31:28] + * HYGON_DF3 SocketIdShift [31:28] */ #define HYGON_DF1_SOCKET_ID_SHIFT GENMASK(31, 28) diff --git a/drivers/ras/amd/atl/hygon/system.c b/drivers/ras/amd/atl/hygon= /system.c index 99a139acaac6..e6ed5809eecc 100644 --- a/drivers/ras/amd/atl/hygon/system.c +++ b/drivers/ras/amd/atl/hygon/system.c @@ -24,6 +24,12 @@ static void hygon_df_get_masks_shifts(u32 mask0) df_cfg.die_id_shift =3D FIELD_GET(HYGON_DF1_DIE_ID_SHIFT, mask0); df_cfg.die_id_mask =3D FIELD_GET(HYGON_DF2_DIE_ID_MASK, mask0); break; + case HYGON_DF3: + df_cfg.socket_id_shift =3D FIELD_GET(HYGON_DF1_SOCKET_ID_SHIFT, mask0); + df_cfg.socket_id_mask =3D FIELD_GET(HYGON_DF3_SOCKET_ID_MASK, mask0); + df_cfg.die_id_shift =3D FIELD_GET(HYGON_DF3_DIE_ID_SHIFT, mask0); + df_cfg.die_id_mask =3D FIELD_GET(HYGON_DF3_DIE_ID_MASK, mask0); + break; default: atl_debug_on_bad_df_rev(); return; @@ -41,6 +47,10 @@ static int hygon_determine_df_rev(void) df_cfg.rev =3D HYGON_DF1; else if (boot_cpu_data.x86_model =3D=3D 0x6 || boot_cpu_data.x86_model = =3D=3D 0x8) df_cfg.rev =3D HYGON_DF2; + else if (boot_cpu_data.x86_model =3D=3D 0x7) + df_cfg.rev =3D HYGON_DF3; + else + return -EINVAL; =20 /* Read D18F1x208 (SystemFabricIdMask). */ if (df_indirect_read_broadcast(0, 1, 0x208, &fabric_id_mask0)) @@ -56,6 +66,7 @@ static void hygon_get_num_maps(void) switch (df_cfg.rev) { case HYGON_DF1: case HYGON_DF2: + case HYGON_DF3: df_cfg.num_coh_st_maps =3D 2; break; default: diff --git a/drivers/ras/amd/atl/hygon/umc.c b/drivers/ras/amd/atl/hygon/um= c.c index fd25deb843db..063c4e87a58c 100644 --- a/drivers/ras/amd/atl/hygon/umc.c +++ b/drivers/ras/amd/atl/hygon/umc.c @@ -26,7 +26,7 @@ static u8 hygon_get_coh_st_inst_id(struct atl_err *err) u8 sub_channel =3D hygon_get_ipid_sub_channel(err); u8 coh_st_inst_id =3D FIELD_GET(HYGON_UMC_CHANNEL_NUM, err->ipid); =20 - if (df_cfg.rev =3D=3D HYGON_DF2) + if (df_cfg.rev =3D=3D HYGON_DF2 || df_cfg.rev =3D=3D HYGON_DF3) coh_st_inst_id =3D (coh_st_inst_id << 1) + sub_channel; =20 return coh_st_inst_id; diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h index bda71630b4a1..6a1640d3b30b 100644 --- a/drivers/ras/amd/atl/internal.h +++ b/drivers/ras/amd/atl/internal.h @@ -56,6 +56,7 @@ enum df_revisions { UNKNOWN, HYGON_DF1, HYGON_DF2, + HYGON_DF3, DF2, DF3, DF3p5, --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out28-2.mail.aliyun.com (out28-2.mail.aliyun.com [115.124.28.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA4702DA749; Thu, 28 May 2026 03:59:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940762; cv=none; b=pgVkQ4W1p5TdPtvqUIix+DkEXkgen/T61JOq6P7FjKWVRpjUB6jRxAcYVFcJ90bU6XlMTb4ykpzTnG8Rlt/qaXDaqG/m0EYcn8hW15VSA4qfNMgoCSM92zPO4HvJpHBfGkYtZYal0AvFB+AalB2WVcLGdir3HMY4yHE8bfjtCL0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940762; c=relaxed/simple; bh=Yy7H8afrj0+EYn6ozWUAd6VUhE9TwkVrAhwOzh0d1aw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hCFo2VWeMmPXGBlJVcQX/Q6qFaINlfsrBBWSvz8wsxAXMnL6GLI4paKYKO1aaNTZx9/cU+G9V3Xaay+FF8BfwIYUNk6QopqE3qbz6SaQ9XnyVmpTs9seludkd262iiKXcAe8noYsDupWLf/+lLesvN9/xHBkHcQyvKrXhMOJsfE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=115.124.28.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436259|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.00552353-0.000629855-0.993847;FP=17812137783631348919|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033032023038;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeCAb_1779940428; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeCAb_1779940428 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:52 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 10/11] EDAC/amd64: Add Hygon Family 0x18 models 0x4-0x8 support Date: Thu, 28 May 2026 11:52:44 +0800 Message-ID: <20260528035246.526012-11-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add UMC base support for Hygon Family 0x18 models 0x4-0x8. Add error channel fields from MCA IPID for Hygon. Add distinct memory-controller counts for Hygon models 0x4/0x5. - Factor Hygon-specific code into hygon_edac.c and hygon_edac.h. - Add is_hygon_f18h() as a static inline bool in hygon_edac.h, checking both X86_VENDOR_HYGON and x86 family 0x18, with a TODO noting it will move to in Hygon Node RFC next version. - Separate UMC base computation into hygon_get_umc_base() in hygon_edac.c. - Add get_umc_base_addr() dispatching to hygon_get_umc_base() on Hygon. - Add system_supports_ddr5() to include Hygon models 0x4-0x8 alongside the existing zn_regs_v2 path. - Add get_num_nodes() returning hygon_cdd_num() on Hygon and amd_nb_num() on AMD; use in init, exit, and allocation. - Extract error channel from IPID bits [23:20] on Hygon vs [31:20] on AMD to match the Hygon UMC IPID layout. Signed-off-by: Aichun Shi --- drivers/edac/Makefile | 5 +++ drivers/edac/amd64_edac.c | 58 ++++++++++++++++++++++++------- drivers/edac/amd64_edac.h | 5 +++ drivers/edac/hygon_edac.c | 73 +++++++++++++++++++++++++++++++++++++++ drivers/edac/hygon_edac.h | 24 +++++++++++++ 5 files changed, 153 insertions(+), 12 deletions(-) create mode 100644 drivers/edac/hygon_edac.c create mode 100644 drivers/edac/hygon_edac.h diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index a37534300ab9..1d58af106420 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -47,6 +47,11 @@ obj-$(CONFIG_EDAC_X38) +=3D x38_edac.o obj-$(CONFIG_EDAC_I82860) +=3D i82860_edac.o obj-$(CONFIG_EDAC_AMD64) +=3D amd64_edac.o =20 +amd64_edac-y :=3D amd64_edac_core.o hygon_edac.o + +$(obj)/amd64_edac_core.o: $(src)/amd64_edac.c FORCE + $(call if_changed_rule,cc_o_c) + obj-$(CONFIG_EDAC_PASEMI) +=3D pasemi_edac.o =20 mpc85xx_edac_mod-y :=3D fsl_ddr_edac.o mpc85xx_edac.o diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 8908ab881c85..d9050f368d4e 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2,8 +2,10 @@ #include #include #include "amd64_edac.h" +#include "hygon_edac.h" #include #include +#include =20 static struct edac_pci_ctl_info *pci_ctl; =20 @@ -98,6 +100,27 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, i= nt offset, return pcibios_err_to_errno(err); } =20 +static u32 get_umc_base_addr(struct amd64_pvt *pvt, u8 channel) +{ + if (is_hygon_f18h()) + return hygon_get_umc_base(pvt, channel); + + return get_umc_base(channel); +} + +static bool system_supports_ddr5(struct amd64_pvt *pvt) +{ + return pvt->flags.zn_regs_v2 || hygon_supports_ddr5(); +} + +static u16 get_num_nodes(void) +{ + if (is_hygon_f18h()) + return hygon_cdd_num(); + + return amd_nb_num(); +} + /* * Select DCT to which PCI cfg accesses are routed */ @@ -1453,11 +1476,13 @@ static void umc_read_base_mask(struct amd64_pvt *pv= t) u32 *base, *base_sec; u32 *mask, *mask_sec; int cs, umc; + u32 umc_base; u32 tmp; =20 for_each_umc(umc) { - umc_base_reg =3D get_umc_base(umc) + UMCCH_BASE_ADDR; - umc_base_reg_sec =3D get_umc_base(umc) + UMCCH_BASE_ADDR_SEC; + umc_base =3D get_umc_base_addr(pvt, umc); + umc_base_reg =3D umc_base + UMCCH_BASE_ADDR; + umc_base_reg_sec =3D umc_base + UMCCH_BASE_ADDR_SEC; =20 for_each_chip_select(cs, umc, pvt) { base =3D &pvt->csels[umc].csbases[cs]; @@ -1479,8 +1504,8 @@ static void umc_read_base_mask(struct amd64_pvt *pvt) } } =20 - umc_mask_reg =3D get_umc_base(umc) + UMCCH_ADDR_MASK; - umc_mask_reg_sec =3D get_umc_base(umc) + get_umc_reg(pvt, UMCCH_ADDR_MAS= K_SEC); + umc_mask_reg =3D umc_base + UMCCH_ADDR_MASK; + umc_mask_reg_sec =3D umc_base + get_umc_reg(pvt, UMCCH_ADDR_MASK_SEC); =20 for_each_chip_select_mask(cs, umc, pvt) { mask =3D &pvt->csels[umc].csmasks[cs]; @@ -1554,6 +1579,7 @@ static void umc_determine_memory_type(struct amd64_pv= t *pvt) { struct amd64_umc *umc; u32 i; + bool ddr5_supported =3D system_supports_ddr5(pvt); =20 for_each_umc(i) { umc =3D &pvt->umc[i]; @@ -1567,7 +1593,7 @@ static void umc_determine_memory_type(struct amd64_pv= t *pvt) * Check if the system supports the "DDR Type" field in UMC Config * and has DDR5 DIMMs in use. */ - if (pvt->flags.zn_regs_v2 && ((umc->umc_cfg & GENMASK(2, 0)) =3D=3D 0x1)= ) { + if (ddr5_supported && ((umc->umc_cfg & GENMASK(2, 0)) =3D=3D 0x1)) { if (umc->dimm_cfg & BIT(5)) umc->dram_type =3D MEM_LRDDR5; else if (umc->dimm_cfg & BIT(4)) @@ -2801,7 +2827,11 @@ static inline void decode_bus_error(int node_id, str= uct mce *m) */ static void umc_get_err_info(struct mce *m, struct err_info *err) { - err->channel =3D (m->ipid & GENMASK(31, 0)) >> 20; + if (is_hygon_f18h()) + err->channel =3D hygon_get_umc_channel(m->ipid); + else + err->channel =3D FIELD_GET(GENMASK(31, 20), m->ipid); + err->csrow =3D m->synd & 0x7; } =20 @@ -2922,8 +2952,7 @@ static void umc_read_mc_regs(struct amd64_pvt *pvt) =20 /* Read registers from each UMC */ for_each_umc(i) { - - umc_base =3D get_umc_base(i); + umc_base =3D get_umc_base_addr(pvt, i); umc =3D &pvt->umc[i]; =20 if (!amd_smn_read(nid, umc_base + get_umc_reg(pvt, UMCCH_DIMM_CFG), &tmp= )) @@ -3841,6 +3870,7 @@ static int per_family_init(struct amd64_pvt *pvt) break; =20 case 0x18: + hygon_per_family_init(pvt); break; =20 case 0x19: @@ -4128,6 +4158,7 @@ static int __init amd64_edac_init(void) { const char *owner; int err =3D -ENODEV; + u16 node_num; int i; =20 if (ghes_get_devices()) @@ -4140,13 +4171,15 @@ static int __init amd64_edac_init(void) if (!x86_match_cpu(amd64_cpuids)) return -ENODEV; =20 - if (!amd_nb_num()) + node_num =3D get_num_nodes(); + + if (!node_num) return -ENODEV; =20 opstate_init(); =20 err =3D -ENOMEM; - ecc_stngs =3D kzalloc_objs(ecc_stngs[0], amd_nb_num()); + ecc_stngs =3D kzalloc_objs(ecc_stngs[0], node_num); if (!ecc_stngs) goto err_free; =20 @@ -4154,7 +4187,7 @@ static int __init amd64_edac_init(void) if (!msrs) goto err_free; =20 - for (i =3D 0; i < amd_nb_num(); i++) { + for (i =3D 0; i < node_num; i++) { err =3D probe_one_instance(i); if (err) { /* unwind properly */ @@ -4200,6 +4233,7 @@ static int __init amd64_edac_init(void) static void __exit amd64_edac_exit(void) { int i; + u16 node_num =3D get_num_nodes(); =20 if (pci_ctl) edac_pci_release_generic_ctl(pci_ctl); @@ -4210,7 +4244,7 @@ static void __exit amd64_edac_exit(void) else amd_unregister_ecc_decoder(decode_bus_error); =20 - for (i =3D 0; i < amd_nb_num(); i++) + for (i =3D 0; i < node_num; i++) remove_one_instance(i); =20 kfree(ecc_stngs); diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 1757c1b99fc8..d6a068dffb36 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -8,6 +8,9 @@ * GNU General Public License. */ =20 +#ifndef _AMD64_EDAC_H +#define _AMD64_EDAC_H + #include #include #include @@ -524,3 +527,5 @@ static inline u32 dct_sel_baseaddr(struct amd64_pvt *pv= t) } return (pvt)->dct_sel_lo & 0xFFFFF800; } + +#endif /* _AMD64_EDAC_H */ diff --git a/drivers/edac/hygon_edac.c b/drivers/edac/hygon_edac.c new file mode 100644 index 000000000000..92504edac1f9 --- /dev/null +++ b/drivers/edac/hygon_edac.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Hygon Family 0x18 memory-controller support for amd64_edac. + * + * Vendor-specific UMC addressing, node counts, MCA decode, and family init + * live here so the core amd64_edac.c AMD paths stay unchanged aside from + * thin hook calls. + * + * Linked into amd64_edac.ko together with amd64_edac_core.o (compiled from + * amd64_edac.c; see drivers/edac/Makefile). + */ + +#include +#include +#include + +#include "amd64_edac.h" +#include "hygon_edac.h" + +/* + * Hygon Family 0x18 models 0x4-0x8: UMC config is behind an SMN window de= rived + * from the compute-die DFID. + */ +u32 hygon_get_umc_base(struct amd64_pvt *pvt, u8 channel) +{ + struct amd_northbridge *nb =3D node_to_amd_nb(pvt->mc_node_id); + u32 base =3D get_umc_base(channel); + u8 df_id; + + if (!hygon_f18h_model_in_range(0x4, 0x8)) + return base; + + if (hygon_get_dfid(nb->misc, &df_id)) + return base; + + return base + (0x80000000U + (0x10000000U * (df_id - 4))); +} + +/* + * Hygon Family 0x18 UMC channel is encoded in IPID bits [23:20], unlike A= MD + * which uses bits [31:20]. + */ +u8 hygon_get_umc_channel(u64 ipid) +{ + return FIELD_GET(GENMASK_ULL(23, 20), ipid); +} + +bool hygon_supports_ddr5(void) +{ + return hygon_f18h_model_in_range(0x4, 0x8); +} + +void hygon_per_family_init(struct amd64_pvt *pvt) +{ + if (!is_hygon_f18h()) + return; + + switch (pvt->model) { + case 0x4: + pvt->max_mcs =3D 3; + break; + case 0x5: + pvt->max_mcs =3D 1; + break; + case 0x6: + case 0x7: + case 0x8: + pvt->max_mcs =3D 2; + break; + default: + break; + } +} diff --git a/drivers/edac/hygon_edac.h b/drivers/edac/hygon_edac.h new file mode 100644 index 000000000000..80f952209b95 --- /dev/null +++ b/drivers/edac/hygon_edac.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _HYGON_EDAC_H +#define _HYGON_EDAC_H + +#include +#include + +struct amd64_pvt; + +/* + * TODO: Will move to in Hygon Node RFC next version. + */ +static inline bool is_hygon_f18h(void) +{ + return boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_HYGON && + boot_cpu_data.x86 =3D=3D 0x18; +} + +u32 hygon_get_umc_base(struct amd64_pvt *pvt, u8 channel); +u8 hygon_get_umc_channel(u64 ipid); +bool hygon_supports_ddr5(void); +void hygon_per_family_init(struct amd64_pvt *pvt); + +#endif /* _HYGON_EDAC_H */ --=20 2.47.3 From nobody Mon Jun 8 16:39:26 2026 Received: from out198-22.us.a.mail.aliyun.com (out198-22.us.a.mail.aliyun.com [47.90.198.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CB5CB3126D0; Thu, 28 May 2026 03:54:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=47.90.198.22 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940450; cv=none; b=Z8/dycBYavD6OBmnlJl73Tk8FPzwug8QB1Ofmn2EpC3QO4Ho9grcpqFX931ufQSLRr//3VV313VNjnTh9lrIppdbJfKzOBPpU/O2nFcsN89lDBMA3yDTprgzDWq98mmv7bPFl15z/tBu1I6g0slQl4QhRUuMbfO4Rd5QEKjU+uk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779940450; c=relaxed/simple; bh=stguw2RtEW5fKiw22OpkQyFhblUjUm8mZDxUGSHT/MI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LiIKFdao2LepOIWObOydI3dq8+zhNTa6CrlA3jVoymXk18brfpKSB+Rs2M/kG0UsISzIdhExv0yCCx3IsCfNNjYn3/JFTL+gsv1dtFsl26c9WY7+XecTWo6CW2UjynwgG9L7FuEF1u70YsTyQcNc3k/Oi8gp/1pt9hJ7FkqYHKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=47.90.198.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.1322343|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_regular_dialog|0.00720156-6.86753e-05-0.99273;FP=6361688190859692242|1|1|2|0|-1|-1|-1;HT=maildocker-contentspam033037028158;MF=shiaichun@open-hieco.net;NM=1;PH=DS;RN=6;RT=6;SR=0;TI=SMTPD_---.hieeCFG_1779940432; Received: from localhost.localdomain(mailfrom:shiaichun@open-hieco.net fp:SMTPD_---.hieeCFG_1779940432 cluster:ay29) by smtp.aliyun-inc.com; Thu, 28 May 2026 11:53:55 +0800 From: Aichun Shi To: yazen.ghannam@amd.com, bp@alien8.de, tony.luck@intel.com Cc: linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org, shiaichun@open-hieco.net Subject: [RFC PATCH v2 11/11] EDAC/amd64: Harden Hygon Family 0x18 UMC SMN base against bad DFID Date: Thu, 28 May 2026 11:52:45 +0800 Message-ID: <20260528035246.526012-12-shiaichun@open-hieco.net> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260528035246.526012-1-shiaichun@open-hieco.net> References: <20260528035246.526012-1-shiaichun@open-hieco.net> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" hygon_get_umc_base() uses hygon_get_dfid() to place the UMC register block on compute dies (DFID >=3D 4). On read failure the DFID was left uninitialized, and DFID < 4 (I/O die) would underflow (df_id - 4) and produce a bogus SMN window. Validate NB misc, check hygon_get_dfid() return, and reject DFID < 4 with a warning; fall back to the default UMC base without the Hygon offset. Use unsigned arithmetic to avoid signed integer overflow when computing the base offset for DFID values >=3D 12. - Define HYGON_CDD_DFID_BASE in hygon_edac.c with a TODO noting it will move to in Hygon Node RFC next version. Signed-off-by: Aichun Shi --- drivers/edac/hygon_edac.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/edac/hygon_edac.c b/drivers/edac/hygon_edac.c index 92504edac1f9..f4d25841fecd 100644 --- a/drivers/edac/hygon_edac.c +++ b/drivers/edac/hygon_edac.c @@ -11,29 +11,55 @@ */ =20 #include -#include #include =20 #include "amd64_edac.h" #include "hygon_edac.h" =20 +/* + * TODO: Will move to in Hygon Node RFC next version. + */ +/* Hygon compute dies (CDD) start at DFID 4; IO dies occupy DFIDs 0-3. */ +#define HYGON_CDD_DFID_BASE 4 + /* * Hygon Family 0x18 models 0x4-0x8: UMC config is behind an SMN window de= rived * from the compute-die DFID. */ u32 hygon_get_umc_base(struct amd64_pvt *pvt, u8 channel) { - struct amd_northbridge *nb =3D node_to_amd_nb(pvt->mc_node_id); + u8 df_id =3D 0; + int ret; u32 base =3D get_umc_base(channel); - u8 df_id; =20 if (!hygon_f18h_model_in_range(0x4, 0x8)) return base; =20 - if (hygon_get_dfid(nb->misc, &df_id)) + if (!pvt->F3) { + amd64_warn("Hygon: no DF misc for MC node %u, using default UMC base\n", + pvt->mc_node_id); + return base; + } + + ret =3D hygon_get_dfid(pvt->F3, &df_id); + if (ret) { + amd64_warn("Hygon: hygon_get_dfid failed for %s (node %u): %d, using def= ault UMC base\n", + pci_name(pvt->F3), pvt->mc_node_id, ret); return base; + } + + /* + * UMCs exist only on compute dies (CDD), DFID >=3D HYGON_CDD_DFID_BASE. + * I/O dies use DFID < HYGON_CDD_DFID_BASE; the UMC base offset + * calculation must not run on I/O dies. + */ + if (df_id < HYGON_CDD_DFID_BASE) { + amd64_warn("Hygon: DFID %u on %s (node %u) is not a compute die, using d= efault UMC base\n", + df_id, pci_name(pvt->F3), pvt->mc_node_id); + return base; + } =20 - return base + (0x80000000U + (0x10000000U * (df_id - 4))); + return base + (0x80000000U + (0x10000000U * (df_id - HYGON_CDD_DFID_BASE)= )); } =20 /* --=20 2.47.3