diff options
Diffstat (limited to 'drivers/ras/amd/atl')
| -rw-r--r-- | drivers/ras/amd/atl/core.c | 7 | ||||
| -rw-r--r-- | drivers/ras/amd/atl/internal.h | 6 | ||||
| -rw-r--r-- | drivers/ras/amd/atl/prm.c | 4 | ||||
| -rw-r--r-- | drivers/ras/amd/atl/system.c | 30 | ||||
| -rw-r--r-- | drivers/ras/amd/atl/umc.c | 23 |
5 files changed, 38 insertions, 32 deletions
diff --git a/drivers/ras/amd/atl/core.c b/drivers/ras/amd/atl/core.c index 4197e10993ac..0f7cd6dab0b0 100644 --- a/drivers/ras/amd/atl/core.c +++ b/drivers/ras/amd/atl/core.c @@ -194,6 +194,8 @@ MODULE_DEVICE_TABLE(x86cpu, amd_atl_cpuids); static int __init amd_atl_init(void) { + int ret; + if (!x86_match_cpu(amd_atl_cpuids)) return -ENODEV; @@ -202,8 +204,9 @@ static int __init amd_atl_init(void) check_for_legacy_df_access(); - if (get_df_system_info()) - return -ENODEV; + ret = get_df_system_info(); + if (ret) + return ret; /* Increment this module's recount so that it can't be easily unloaded. */ __module_get(THIS_MODULE); diff --git a/drivers/ras/amd/atl/internal.h b/drivers/ras/amd/atl/internal.h index 2b6279d32774..82a56d9c2be1 100644 --- a/drivers/ras/amd/atl/internal.h +++ b/drivers/ras/amd/atl/internal.h @@ -138,7 +138,8 @@ struct df_flags { __u8 legacy_ficaa : 1, socket_id_shift_quirk : 1, heterogeneous : 1, - __reserved_0 : 5; + prm_only : 1, + __reserved_0 : 4; }; struct df_config { @@ -283,6 +284,9 @@ 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); +/* GUIDs for PRM handlers */ +extern const guid_t norm_to_sys_guid; + #ifdef CONFIG_AMD_ATL_PRM unsigned long prm_umc_norm_to_sys_addr(u8 socket_id, u64 umc_bank_inst_id, unsigned long addr); #else diff --git a/drivers/ras/amd/atl/prm.c b/drivers/ras/amd/atl/prm.c index 0931a20d213b..0f9bfa96e16a 100644 --- a/drivers/ras/amd/atl/prm.c +++ b/drivers/ras/amd/atl/prm.c @@ -29,10 +29,6 @@ struct norm_to_sys_param_buf { void *out_buf; } __packed; -static const guid_t norm_to_sys_guid = GUID_INIT(0xE7180659, 0xA65D, 0x451D, - 0x92, 0xCD, 0x2B, 0x56, 0xF1, - 0x2B, 0xEB, 0xA6); - unsigned long prm_umc_norm_to_sys_addr(u8 socket_id, u64 bank_id, unsigned long addr) { struct norm_to_sys_param_buf p_buf; diff --git a/drivers/ras/amd/atl/system.c b/drivers/ras/amd/atl/system.c index e18d916d5e8b..812a30e21d3a 100644 --- a/drivers/ras/amd/atl/system.c +++ b/drivers/ras/amd/atl/system.c @@ -12,6 +12,12 @@ #include "internal.h" +#include <linux/prmt.h> + +const guid_t norm_to_sys_guid = GUID_INIT(0xE7180659, 0xA65D, 0x451D, + 0x92, 0xCD, 0x2B, 0x56, 0xF1, + 0x2B, 0xEB, 0xA6); + int determine_node_id(struct addr_ctx *ctx, u8 socket_id, u8 die_id) { u16 socket_id_bits, die_id_bits; @@ -212,15 +218,17 @@ static int determine_df_rev(void) if (!rev) return determine_df_rev_legacy(); - /* - * Fail out for major revisions other than '4'. - * - * Explicit support should be added for newer systems to avoid issues. - */ if (rev == 4) return df4_determine_df_rev(reg); - return -EINVAL; + /* All other systems should have PRM handlers. */ + if (!acpi_prm_handler_available(&norm_to_sys_guid)) { + pr_debug("PRM not available\n"); + return -ENODEV; + } + + df_cfg.flags.prm_only = true; + return 0; } static int get_dram_hole_base(void) @@ -288,12 +296,18 @@ static void dump_df_cfg(void) int get_df_system_info(void) { - if (determine_df_rev()) { + int ret; + + ret = determine_df_rev(); + if (ret) { pr_warn("Failed to determine DF Revision"); df_cfg.rev = UNKNOWN; - return -EINVAL; + return ret; } + if (df_cfg.flags.prm_only) + return 0; + apply_node_id_shift(); get_num_maps(); diff --git a/drivers/ras/amd/atl/umc.c b/drivers/ras/amd/atl/umc.c index 6e072b7667e9..befc616d5e8a 100644 --- a/drivers/ras/amd/atl/umc.c +++ b/drivers/ras/amd/atl/umc.c @@ -49,17 +49,6 @@ static u8 get_coh_st_inst_id_mi300(struct atl_err *err) return i; } -/* XOR the bits in @val. */ -static u16 bitwise_xor_bits(u16 val) -{ - u16 tmp = 0; - u8 i; - - for (i = 0; i < 16; i++) - tmp ^= (val >> i) & 0x1; - - return tmp; -} struct xor_bits { bool xor_enable; @@ -250,17 +239,17 @@ static unsigned long convert_dram_to_norm_addr_mi300(unsigned long addr) if (!addr_hash.bank[i].xor_enable) continue; - temp = bitwise_xor_bits(col & addr_hash.bank[i].col_xor); - temp ^= bitwise_xor_bits(row & addr_hash.bank[i].row_xor); + temp = hweight16(col & addr_hash.bank[i].col_xor) & 1; + temp ^= hweight16(row & addr_hash.bank[i].row_xor) & 1; bank ^= temp << i; } /* Calculate hash for PC bit. */ if (addr_hash.pc.xor_enable) { - temp = bitwise_xor_bits(col & addr_hash.pc.col_xor); - temp ^= bitwise_xor_bits(row & addr_hash.pc.row_xor); + temp = hweight16(col & addr_hash.pc.col_xor) & 1; + temp ^= hweight16(row & addr_hash.pc.row_xor) & 1; /* Bits SID[1:0] act as Bank[5:4] for PC hash, so apply them here. */ - temp ^= bitwise_xor_bits((bank | sid << NUM_BANK_BITS) & addr_hash.bank_xor); + temp ^= hweight16((bank | sid << NUM_BANK_BITS) & addr_hash.bank_xor) & 1; pc ^= temp; } @@ -422,7 +411,7 @@ unsigned long convert_umc_mca_addr_to_sys_addr(struct atl_err *err) socket_id, die_id, coh_st_inst_id, addr); ret_addr = prm_umc_norm_to_sys_addr(socket_id, err->ipid, addr); - if (!IS_ERR_VALUE(ret_addr)) + if (!IS_ERR_VALUE(ret_addr) || df_cfg.flags.prm_only) return ret_addr; return norm_to_sys_addr(socket_id, die_id, coh_st_inst_id, addr); |
