#define DID_MTL_P_SKU2 0x7d02
#define DID_MTL_P_SKU3 0x7d14
+ /* Compute die IDs for Arrow Lake-UH with IBECC */
+ #define DID_ARL_UH_SKU1 0x7d06
+ #define DID_ARL_UH_SKU2 0x7d20
+ #define DID_ARL_UH_SKU3 0x7d30
+
static int get_mchbar(struct pci_dev *pdev, u64 *mchbar)
{
union {
{ PCI_VDEVICE(INTEL, DID_MTL_P_SKU1), (kernel_ulong_t)&mtl_p_cfg },
{ PCI_VDEVICE(INTEL, DID_MTL_P_SKU2), (kernel_ulong_t)&mtl_p_cfg },
{ PCI_VDEVICE(INTEL, DID_MTL_P_SKU3), (kernel_ulong_t)&mtl_p_cfg },
+ { PCI_VDEVICE(INTEL, DID_ARL_UH_SKU1), (kernel_ulong_t)&mtl_p_cfg },
+ { PCI_VDEVICE(INTEL, DID_ARL_UH_SKU2), (kernel_ulong_t)&mtl_p_cfg },
+ { PCI_VDEVICE(INTEL, DID_ARL_UH_SKU3), (kernel_ulong_t)&mtl_p_cfg },
{ },
};
MODULE_DEVICE_TABLE(pci, igen6_pci_tbl);
rc = pci_read_config_word(imc->pdev, ERRCMD_OFFSET, &errcmd);
if (rc)
- return rc;
+ return pcibios_err_to_errno(rc);
if (enable)
errcmd |= ERRCMD_CE | ERRSTS_UE;
rc = pci_write_config_word(imc->pdev, ERRCMD_OFFSET, errcmd);
if (rc)
- return rc;
+ return pcibios_err_to_errno(rc);
return 0;
}
#include "reg_fields.h"
+ #undef pr_fmt
+ #define pr_fmt(fmt) "amd_atl: " fmt
+
/* Maximum possible number of Coherent Stations within a single Data Fabric. */
#define MAX_COH_ST_CHANNELS 32
#define DF_DRAM_BASE_LIMIT_LSB 28
#define MI300_DRAM_LIMIT_LSB 20
+ #define INVALID_SPA ~0ULL
+
enum df_revisions {
UNKNOWN,
DF2,
DF4p5_NPS1_10CHAN_2K_HASH = 0x49,
};
+ struct df4p5_denorm_ctx {
+ /* Indicates the number of "lost" bits. This will be 1, 2, or 3. */
+ u8 perm_shift;
+
+ /* A mask indicating the bits that need to be rehashed. */
+ u16 rehash_vector;
+
+ /*
+ * Represents the value that the high bits of the normalized address
+ * are divided by during normalization. This value will be 3 for
+ * interleave modes with a number of channels divisible by 3 or the
+ * value will be 5 for interleave modes with a number of channels
+ * divisible by 5. Power-of-two interleave modes are handled
+ * separately.
+ */
+ u8 mod_value;
+
+ /*
+ * Represents the bits that can be directly pulled from the normalized
+ * address. In each case, pass through bits [7:0] of the normalized
+ * address. The other bits depend on the interleave bit position which
+ * will be bit 10 for 1K interleave stripe cases and bit 11 for 2K
+ * interleave stripe cases.
+ */
+ u64 base_denorm_addr;
+
+ /*
+ * Represents the high bits of the physical address that have been
+ * divided by the mod_value.
+ */
+ u64 div_addr;
+
+ u64 current_spa;
+ u64 resolved_spa;
+
+ u16 coh_st_fabric_id;
+ };
+
struct df_flags {
__u8 legacy_ficaa : 1,
socket_id_shift_quirk : 1,
/* Number of DRAM Address maps visible in a Coherent Station. */
u8 num_coh_st_maps;
+ u32 dram_hole_base;
+
/* Global flags to handle special cases. */
struct df_flags flags;
};
int get_df_system_info(void);
int determine_node_id(struct addr_ctx *ctx, u8 socket_num, u8 die_num);
-int get_addr_hash_mi300(void);
+int get_umc_info_mi300(void);
int get_address_map(struct addr_ctx *ctx);
unsigned long norm_to_sys_addr(u8 socket_id, u8 die_id, u8 coh_st_inst_id, unsigned long addr);
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);
+
/*
* Make a gap in @data that is @num_bits long starting at @bit_num.
* e.g. data = 11111111'b
if (reg == DF_FUNC0_ID_MI300) {
df_cfg.flags.heterogeneous = 1;
- if (get_addr_hash_mi300())
+ if (get_umc_info_mi300())
return -EINVAL;
}
return -EINVAL;
}
+ static int get_dram_hole_base(void)
+ {
+ u8 func = 0;
+
+ if (df_cfg.rev >= DF4)
+ func = 7;
+
+ if (df_indirect_read_broadcast(0, func, 0x104, &df_cfg.dram_hole_base))
+ return -EINVAL;
+
+ df_cfg.dram_hole_base &= DF_DRAM_HOLE_BASE_MASK;
+
+ return 0;
+ }
+
static void get_num_maps(void)
{
switch (df_cfg.rev) {
pr_debug("num_coh_st_maps=%u", df_cfg.num_coh_st_maps);
+ pr_debug("dram_hole_base=0x%x", df_cfg.dram_hole_base);
pr_debug("flags.legacy_ficaa=%u", df_cfg.flags.legacy_ficaa);
pr_debug("flags.socket_id_shift_quirk=%u", df_cfg.flags.socket_id_shift_quirk);
}
int get_df_system_info(void)
{
if (determine_df_rev()) {
- pr_warn("amd_atl: Failed to determine DF Revision");
+ pr_warn("Failed to determine DF Revision");
df_cfg.rev = UNKNOWN;
return -EINVAL;
}
get_num_maps();
+ if (get_dram_hole_base())
+ pr_warn("Failed to read DRAM hole base");
+
dump_df_cfg();
return 0;