EDAC/amd64: Allow for DF Indirect Broadcast reads
authorYazen Ghannam <yazen.ghannam@amd.com>
Thu, 28 Oct 2021 17:56:58 +0000 (17:56 +0000)
committerBorislav Petkov <bp@suse.de>
Mon, 15 Nov 2021 11:48:55 +0000 (12:48 +0100)
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
drivers/edac/amd64_edac.c

index 034d9863bcf989e5a53dca0f07910b3be45bd566..d41b9a02cc7dde540e8ae43ac1eb689b73e3bae4 100644 (file)
@@ -1000,8 +1000,11 @@ static DEFINE_MUTEX(df_indirect_mutex);
  *
  * Fabric Indirect Configuration Access Data (FICAD): There are FICAD LO
  * and FICAD HI registers but so far we only need the LO register.
+ *
+ * Use Instance Id 0xFF to indicate a broadcast read.
  */
-static int amd_df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo)
+#define DF_BROADCAST   0xFF
+static int __df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo)
 {
        struct pci_dev *F4;
        u32 ficaa;
@@ -1014,7 +1017,7 @@ static int amd_df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32
        if (!F4)
                goto out;
 
-       ficaa  = 1;
+       ficaa  = (instance_id == DF_BROADCAST) ? 0 : 1;
        ficaa |= reg & 0x3FC;
        ficaa |= (func & 0x7) << 11;
        ficaa |= instance_id << 16;
@@ -1038,6 +1041,16 @@ out:
        return err;
 }
 
+static int df_indirect_read_instance(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo)
+{
+       return __df_indirect_read(node, func, reg, instance_id, lo);
+}
+
+static int df_indirect_read_broadcast(u16 node, u8 func, u16 reg, u32 *lo)
+{
+       return __df_indirect_read(node, func, reg, DF_BROADCAST, lo);
+}
+
 static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr)
 {
        u64 dram_base_addr, dram_limit_addr, dram_hole_base;
@@ -1055,7 +1068,7 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr
        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: */
@@ -1069,7 +1082,7 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr
        }
 
        /* 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. */
@@ -1092,7 +1105,7 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr
        }
 
        /* 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;
@@ -1148,7 +1161,7 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr
                 * 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;
@@ -1165,7 +1178,7 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr
 
                /* 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. */
@@ -1204,7 +1217,7 @@ static int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr
 
        /* 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);