Blob Blame History Raw
From: Yazen Ghannam <yazen.ghannam@amd.com>
Date: Thu, 28 Oct 2021 17:56:58 +0000
Subject: EDAC/amd64: Allow for DF Indirect Broadcast reads
Git-commit: 448c3d6085b71aad58cd515469560ee76c982007
Patch-mainline: v5.17-rc1
References: jsc#PED-7615

The DF Indirect Access method allows for "Broadcast" accesses in which
case no specific instance is targeted. Add support using a reserved
instance ID of 0xFF to indicate a broadcast access. Set the FICAA
register appropriately.

Define helpers functions for instance and broadcast reads and use them
where appropriate.

Drop the "amd_" prefix since these functions are all static.

Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20211028175728.121452-4-yazen.ghannam@amd.com

Acked-by: Nikolay Borisov <nik.borisov@suse.com>
---
 arch/x86/include/asm/amd_nb.h |   12 ++++++++++++
 arch/x86/kernel/amd_nb.c      |    2 +-
 arch/x86/kernel/cpu/mce/amd.c |   12 ++++++------
 3 files changed, 19 insertions(+), 7 deletions(-)

--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -6,6 +6,8 @@
 #include <linux/pci.h>
 #include <linux/refcount.h>
 
+#define DF_BROADCAST	0xFF
+
 struct amd_nb_bus_dev_range {
 	u8 bus;
 	u8 dev_base;
@@ -26,6 +28,16 @@ extern int amd_smn_read(u16 node, u32 ad
 extern int amd_smn_write(u16 node, u32 address, u32 value);
 extern int amd_df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo);
 
+static inline int df_indirect_read_instance(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo)
+{
+	return amd_df_indirect_read(node, func, reg, instance_id, lo);
+}
+
+static inline int df_indirect_read_broadcast(u16 node, u8 func, u16 reg, u32 *lo)
+{
+	return amd_df_indirect_read(node, func, reg, DF_BROADCAST, lo);
+}
+
 struct amd_l3_cache {
 	unsigned indices;
 	u8	 subcaches[4];
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -205,7 +205,7 @@ int amd_df_indirect_read(u16 node, u8 fu
 	if (!F4)
 		goto out;
 
-	ficaa  = 1;
+	ficaa  = (instance_id == DF_BROADCAST) ? 0 : 1;
 	ficaa |= reg & 0x3FC;
 	ficaa |= (func & 0x7) << 11;
 	ficaa |= instance_id << 16;
--- a/arch/x86/kernel/cpu/mce/amd.c
+++ b/arch/x86/kernel/cpu/mce/amd.c
@@ -706,7 +706,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
 	bool hash_enabled = false;
 
 	/* Read D18F0x1B4 (DramOffset), check if base 1 is used. */
-	if (amd_df_indirect_read(nid, 0, 0x1B4, umc, &tmp))
+	if (df_indirect_read_instance(nid, 0, 0x1B4, umc, &tmp))
 		goto out_err;
 
 	/* Remove HiAddrOffset from normalized address, if enabled: */
@@ -720,7 +720,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
 	}
 
 	/* Read D18F0x110 (DramBaseAddress). */
-	if (amd_df_indirect_read(nid, 0, 0x110 + (8 * base), umc, &tmp))
+	if (df_indirect_read_instance(nid, 0, 0x110 + (8 * base), umc, &tmp))
 		goto out_err;
 
 	/* Check if address range is valid. */
@@ -743,7 +743,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
 	}
 
 	/* Read D18F0x114 (DramLimitAddress). */
-	if (amd_df_indirect_read(nid, 0, 0x114 + (8 * base), umc, &tmp))
+	if (df_indirect_read_instance(nid, 0, 0x114 + (8 * base), umc, &tmp))
 		goto out_err;
 
 	intlv_num_sockets = (tmp >> 8) & 0x1;
@@ -799,7 +799,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
 		 * umc/channel# as instance id of the coherent slave
 		 * for FICAA.
 		 */
-		if (amd_df_indirect_read(nid, 0, 0x50, umc, &tmp))
+		if (df_indirect_read_instance(nid, 0, 0x50, umc, &tmp))
 			goto out_err;
 
 		cs_fabric_id = (tmp >> 8) & 0xFF;
@@ -816,7 +816,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
 
 		/* Read D18F1x208 (SystemFabricIdMask). */
 		if (intlv_num_dies || intlv_num_sockets)
-			if (amd_df_indirect_read(nid, 1, 0x208, umc, &tmp))
+			if (df_indirect_read_broadcast(nid, 1, 0x208, &tmp))
 				goto out_err;
 
 		/* If interleaved over more than 1 die. */
@@ -855,7 +855,7 @@ int umc_normaddr_to_sysaddr(u64 norm_add
 
 	/* If legacy MMIO hole enabled */
 	if (lgcy_mmio_hole_en) {
-		if (amd_df_indirect_read(nid, 0, 0x104, umc, &tmp))
+		if (df_indirect_read_broadcast(nid, 0, 0x104, &tmp))
 			goto out_err;
 
 		dram_hole_base = tmp & GENMASK(31, 24);