[PATCH 023/109] drm/amd/ras: Support querying RAS driver capabilities
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: YiPeng Chai <[email protected]> Support querying RAS driver capabilities: 1. Generate ras block bitmask for HW. -- Read ras hw capabilities from registers. -- Convert hw ras block bitmask to driver ras block bitmask. 2. Generate ras block bitmask for SW. 3. Add interfaces to query RAS capabilities. Signed-off-by: YiPeng Chai <[email protected]> Reviewed-by: Hawking Zhang <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/ras/core/aca.c | 10 +++++ drivers/gpu/drm/amd/ras/core/aca.h | 2 + drivers/gpu/drm/amd/ras/core/aca_v1_0.c | 13 ++++++ drivers/gpu/drm/amd/ras/core/core.c | 23 ++++++++++ drivers/gpu/drm/amd/ras/core/ras.h | 5 ++- drivers/gpu/drm/amd/ras/core/ras_aca_v5_0.c | 13 ++++++ drivers/gpu/drm/amd/ras/core/ras_psp.c | 26 ++++++++++++ drivers/gpu/drm/amd/ras/core/ras_psp.h | 25 +++++++++++ drivers/gpu/drm/amd/ras/core/ras_psp_v13_0.c | 42 +++++++++++++++++++ drivers/gpu/drm/amd/ras/core/ras_psp_v15_0.c | 41 ++++++++++++++++++ .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c | 10 ++--- 11 files changed, 204 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/ras/core/aca.c b/drivers/gpu/drm/amd/ras/core/aca.c index 8bb93ca61b18a..6d7cfef543622 100644 --- a/drivers/gpu/drm/amd/ras/core/aca.c +++ b/drivers/gpu/drm/amd/ras/core/aca.c @@ -701,3 +701,13 @@ int ras_aca_parse_bank(struct ras_core_context *ras_core, return ret; } + +u64 ras_aca_get_parser_caps(struct ras_core_context *ras_core) +{ + struct ras_aca *ras_aca = &ras_core->ras_aca; + + if (ras_aca->ip_func && ras_aca->ip_func->aca_parse_ras_caps) + return ras_aca->ip_func->aca_parse_ras_caps(ras_core); + + return 0; +} diff --git a/drivers/gpu/drm/amd/ras/core/aca.h b/drivers/gpu/drm/amd/ras/core/aca.h index a9538e64d7d53..b19b6e7089f28 100644 --- a/drivers/gpu/drm/amd/ras/core/aca.h +++ b/drivers/gpu/drm/amd/ras/core/aca.h @@ -145,6 +145,7 @@ struct aca_block { struct ras_aca_ip_func { uint32_t block_num; const struct aca_block_info **block_info; + u64 (*aca_parse_ras_caps)(struct ras_core_context *ras_core); }; struct ras_aca { @@ -169,4 +170,5 @@ void ras_aca_clear_fatal_flag(struct ras_core_context *ras_core); int ras_aca_parse_bank(struct ras_core_context *ras_core, struct aca_bank_reg *bank, struct aca_bank_ecc *ecc); +u64 ras_aca_get_parser_caps(struct ras_core_context *ras_core); #endif diff --git a/drivers/gpu/drm/amd/ras/core/aca_v1_0.c b/drivers/gpu/drm/amd/ras/core/aca_v1_0.c index a8b413270de37..c2fba818a4629 100644 --- a/drivers/gpu/drm/amd/ras/core/aca_v1_0.c +++ b/drivers/gpu/drm/amd/ras/core/aca_v1_0.c @@ -372,7 +372,20 @@ static const struct aca_block_info *aca_block_info_v1_0[] = { &aca_v1_0_xgmi, }; +static u64 aca_parse_ras_caps_v1_0(struct ras_core_context *ras_core) +{ + u64 parser_supported_mask = 0; + u32 i; + + for (i = 0; i < ARRAY_SIZE(aca_block_info_v1_0); i++) + parser_supported_mask |= + BIT_ULL(aca_block_info_v1_0[i]->ras_block_id); + + return parser_supported_mask; +} + const struct ras_aca_ip_func ras_aca_func_v1_0 = { .block_num = ARRAY_SIZE(aca_block_info_v1_0), .block_info = aca_block_info_v1_0, + .aca_parse_ras_caps = aca_parse_ras_caps_v1_0, }; diff --git a/drivers/gpu/drm/amd/ras/core/core.c b/drivers/gpu/drm/amd/ras/core/core.c index aad95bf3fa180..079032433a916 100644 --- a/drivers/gpu/drm/amd/ras/core/core.c +++ b/drivers/gpu/drm/amd/ras/core/core.c @@ -761,3 +761,26 @@ int ras_core_get_eeprom_version(struct ras_core_context *ras_core, { return ras_eeprom_get_version(ras_core, version); } + +uint64_t ras_core_get_ras_caps(struct ras_core_context *ras_core) +{ + uint64_t ras_hw_caps, ras_drv_caps; + + if (!ras_core) + return 0; + + ras_hw_caps = ras_psp_get_hw_ras_caps(ras_core); + ras_drv_caps = ras_aca_get_parser_caps(ras_core); + + return ras_hw_caps & ras_drv_caps; +} + +bool ras_core_poison_supported(struct ras_core_context *ras_core) +{ + if (!ras_core) + return false; + + /* For some ASICs, poison flag is detected externally by uniras module. */ + return ras_core->poison_supported ? true : + ras_psp_poison_supported(ras_core); +} diff --git a/drivers/gpu/drm/amd/ras/core/ras.h b/drivers/gpu/drm/amd/ras/core/ras.h index dc590867d82a3..e28d51b1992ef 100644 --- a/drivers/gpu/drm/amd/ras/core/ras.h +++ b/drivers/gpu/drm/amd/ras/core/ras.h @@ -103,7 +103,8 @@ enum ras_block_id { RAS_BLOCK_ID__SSBDCI, RAS_BLOCK_ID__UCIE_PCS, - RAS_BLOCK_ID__LAST + RAS_BLOCK_ID__LAST, + MAX_SUPPORTED_RAS_BLOCK_ID = MAX_RAS_BLOCK_MASK_BITS }; enum ras_ecc_err_type { @@ -448,4 +449,6 @@ int ras_core_get_eeprom_version(struct ras_core_context *ras_core, uint32_t *version); int ras_core_get_ip_version(struct ras_core_context *ras_core, enum ras_unit_id unit_id, uint32_t *version); +uint64_t ras_core_get_ras_caps(struct ras_core_context *ras_core); +bool ras_core_poison_supported(struct ras_core_context *ras_core); #endif diff --git a/drivers/gpu/drm/amd/ras/core/ras_aca_v5_0.c b/drivers/gpu/drm/amd/ras/core/ras_aca_v5_0.c index 15e72d4b492d0..3074f8c3f3164 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_aca_v5_0.c +++ b/drivers/gpu/drm/amd/ras/core/ras_aca_v5_0.c @@ -348,7 +348,20 @@ static const struct aca_block_info *aca_block_info_v5_0[] = { &aca_v5_0_xgmi, }; +static u64 aca_parse_ras_caps_v5_0(struct ras_core_context *ras_core) +{ + u64 parser_supported_mask = 0; + u32 i; + + for (i = 0; i < ARRAY_SIZE(aca_block_info_v5_0); i++) + parser_supported_mask |= + BIT_ULL(aca_block_info_v5_0[i]->ras_block_id); + + return parser_supported_mask; +} + const struct ras_aca_ip_func ras_aca_func_v5_0 = { .block_num = ARRAY_SIZE(aca_block_info_v5_0), .block_info = aca_block_info_v5_0, + .aca_parse_ras_caps = aca_parse_ras_caps_v5_0, }; diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp.c b/drivers/gpu/drm/amd/ras/core/ras_psp.c index 5628b384a7333..da49ee79711d9 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_psp.c +++ b/drivers/gpu/drm/amd/ras/core/ras_psp.c @@ -720,6 +720,11 @@ int ras_psp_hw_init(struct ras_core_context *ras_core) psp->ip_func->get_ras_block_maps(ras_core, &psp->blk_maps, &psp->maps_size)) return -EINVAL; + + if (psp->ip_func->get_ras_hw_caps && + psp->ip_func->get_ras_hw_caps(ras_core, &psp->ras_hw_caps)) + return -EINVAL; + /* After GPU reset, the system RAS PSP status may change. * therefore, it is necessary to synchronize the system status again. */ @@ -783,3 +788,24 @@ int ras_psp_get_block_ta_id(struct ras_core_context *ras_core, return -RAS_CORE_NOT_SUPPORTED; } + +bool ras_psp_poison_supported(struct ras_core_context *ras_core) +{ + struct ras_psp *psp = &ras_core->ras_psp; + + return psp->ras_hw_caps.poison_supported; +} + +bool ras_psp_flex_mca_enabled(struct ras_core_context *ras_core) +{ + struct ras_psp *psp = &ras_core->ras_psp; + + return psp->ras_hw_caps.flex_mca_enabled; +} + +uint64_t ras_psp_get_hw_ras_caps(struct ras_core_context *ras_core) +{ + struct ras_psp *psp = &ras_core->ras_psp; + + return psp->ras_hw_caps.features.block_mask; +} diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp.h b/drivers/gpu/drm/amd/ras/core/ras_psp.h index 5265408ddafea..dbc06c85d4aec 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_psp.h +++ b/drivers/gpu/drm/amd/ras/core/ras_psp.h @@ -26,6 +26,8 @@ #include "ras.h" #include "ta_if.h" +#define MAX_RAS_BLOCK_MASK_BITS 56 + struct ras_core_context; struct ras_ta_trigger_error_input; struct ras_ta_query_address_input; @@ -68,11 +70,30 @@ struct ras_block_map { uint32_t ras_id; uint32_t ta_id; }; + +union ras_feature { + struct { + uint64_t block_mask : MAX_RAS_BLOCK_MASK_BITS; + uint64_t rsv: 4; + uint64_t tag: 3; + uint64_t en : 1; + }; + uint64_t value; +}; + +struct ras_hw_caps { + bool poison_supported; + bool flex_mca_enabled; + union ras_feature features; +}; + struct ras_psp_ip_func { uint32_t (*psp_ras_ring_wptr_get)(struct ras_core_context *ras_core); int (*psp_ras_ring_wptr_set)(struct ras_core_context *ras_core, uint32_t wptr); int (*get_ras_block_maps)(struct ras_core_context *ras_core, struct ras_block_map **blk_maps, uint32_t *maps_size); + int (*get_ras_hw_caps)(struct ras_core_context *ras_core, + struct ras_hw_caps *ras_cap); }; struct ras_psp_ring { @@ -116,6 +137,7 @@ struct ras_psp { uint32_t psp_ip_version; struct ras_block_map *blk_maps; uint32_t maps_size; + struct ras_hw_caps ras_hw_caps; struct ras_psp_ring psp_ring; struct ras_psp_ctx psp_ctx; struct ras_ta_ctx ta_ctx; @@ -153,4 +175,7 @@ bool ras_psp_check_supported_cmd(struct ras_core_context *ras_core, enum ras_ta_cmd_id cmd_id); int ras_psp_get_block_ta_id(struct ras_core_context *ras_core, uint32_t ras_id, uint32_t *ta_id); +bool ras_psp_poison_supported(struct ras_core_context *ras_core); +bool ras_psp_flex_mca_enabled(struct ras_core_context *ras_core); +uint64_t ras_psp_get_hw_ras_caps(struct ras_core_context *ras_core); #endif diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp_v13_0.c b/drivers/gpu/drm/amd/ras/core/ras_psp_v13_0.c index 92e617eca8791..49ba57f58878c 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_psp_v13_0.c +++ b/drivers/gpu/drm/amd/ras/core/ras_psp_v13_0.c @@ -27,6 +27,9 @@ #define regMP0_SMN_C2PMSG_67 0x0083 #define regMP0_SMN_C2PMSG_67_BASE_IDX 0 +#define regMP0_SMN_C2PMSG_127 0x00bf +#define regMP0_SMN_C2PMSG_127_BASE_IDX 0 + static struct ras_block_map ras_block_maps_v13_0[] = { {RAS_BLOCK_ID__UMC, RAS_TA_BLOCK__UMC}, {RAS_BLOCK_ID__SDMA, RAS_TA_BLOCK__SDMA}, @@ -73,8 +76,47 @@ static int ras_psp_v13_0_get_ras_block_maps(struct ras_core_context *ras_core, return 0; } + +static int ras_psp_v13_0_get_ras_hw_caps(struct ras_core_context *ras_core, + struct ras_hw_caps *ras_cap) +{ + uint32_t ras_hw_cap, bit; + uint32_t i; + + if (!ras_cap) + return -EINVAL; + + ras_hw_cap = RAS_DEV_RREG32_SOC15(ras_core->dev, MP0, 0, regMP0_SMN_C2PMSG_127); + + ras_cap->poison_supported = true; + ras_cap->flex_mca_enabled = false; + + ras_cap->features.value = 0; + for (bit = 0; bit <= 29; bit++) { + if (!(ras_hw_cap & BIT_ULL(bit))) + continue; + + for (i = 0; i < ARRAY_SIZE(ras_block_maps_v13_0); i++) { + if (ras_block_maps_v13_0[i].ta_id == bit) { + if (ras_block_maps_v13_0[i].ras_id < MAX_SUPPORTED_RAS_BLOCK_ID) + ras_cap->features.block_mask |= + BIT_ULL(ras_block_maps_v13_0[i].ras_id); + else + RAS_DEV_WARN(ras_core->dev, + "RAS block maps v13 error: invalid ras block id %u\n", + ras_block_maps_v13_0[i].ras_id); + + break; + } + } + } + + return 0; +} + const struct ras_psp_ip_func ras_psp_v13_0 = { .psp_ras_ring_wptr_get = ras_psp_v13_0_ring_wptr_get, .psp_ras_ring_wptr_set = ras_psp_v13_0_ring_wptr_set, .get_ras_block_maps = ras_psp_v13_0_get_ras_block_maps, + .get_ras_hw_caps = ras_psp_v13_0_get_ras_hw_caps, }; diff --git a/drivers/gpu/drm/amd/ras/core/ras_psp_v15_0.c b/drivers/gpu/drm/amd/ras/core/ras_psp_v15_0.c index 74f00eec40782..e3cae8c94b28f 100644 --- a/drivers/gpu/drm/amd/ras/core/ras_psp_v15_0.c +++ b/drivers/gpu/drm/amd/ras/core/ras_psp_v15_0.c @@ -28,6 +28,8 @@ #define regMPASP_SMN_C2PMSG_67 0x0083 #define regMPASP_SMN_C2PMSG_67_BASE_IDX 1 +#define regMPASP_SMN_C2PMSG_127 0x00bf +#define regMPASP_SMN_C2PMSG_127_BASE_IDX 1 static struct ras_block_map ras_block_maps_v15_0[] = { {RAS_BLOCK_ID__UMC, RAS_TA_MPASP_BLOCK__UMC}, @@ -85,8 +87,47 @@ static int ras_psp_v15_0_get_ras_block_maps(struct ras_core_context *ras_core, return 0; } + +static int ras_psp_v15_0_get_ras_hw_caps(struct ras_core_context *ras_core, + struct ras_hw_caps *ras_cap) +{ + uint32_t ras_hw_cap, bit; + uint32_t i; + + if (!ras_cap) + return -EINVAL; + + ras_hw_cap = RAS_DEV_RREG32_SOC15(ras_core->dev, + MP0, 0, regMPASP_SMN_C2PMSG_127); + + ras_cap->poison_supported = (ras_hw_cap & BIT_ULL(31)) ? true : false; + ras_cap->flex_mca_enabled = (ras_hw_cap & BIT_ULL(30)) ? true : false; + + ras_cap->features.value = 0; + for (bit = 0; bit <= 29; bit++) { + if (!(ras_hw_cap & BIT_ULL(bit))) + continue; + + for (i = 0; i < ARRAY_SIZE(ras_block_maps_v15_0); i++) { + if (ras_block_maps_v15_0[i].ta_id == bit) { + if (ras_block_maps_v15_0[i].ras_id < MAX_SUPPORTED_RAS_BLOCK_ID) + ras_cap->features.block_mask |= + BIT_ULL(ras_block_maps_v15_0[i].ras_id); + else + RAS_DEV_WARN(ras_core->dev, + "RAS block maps v15 error: invalid ras block id %u\n", + ras_block_maps_v15_0[i].ras_id); + break; + } + } + } + + return 0; +} + const struct ras_psp_ip_func ras_psp_v15_0 = { .psp_ras_ring_wptr_get = ras_psp_v15_0_ring_wptr_get, .psp_ras_ring_wptr_set = ras_psp_v15_0_ring_wptr_set, .get_ras_block_maps = ras_psp_v15_0_get_ras_block_maps, + .get_ras_hw_caps = ras_psp_v15_0_get_ras_hw_caps, }; diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c index 1b23ffffc415c..3b8d61785a897 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_mgr.c @@ -269,7 +269,7 @@ static int amdgpu_ras_mgr_get_ras_ta_init_param(struct ras_core_context *ras_cor struct amdgpu_device *adev = (struct amdgpu_device *)ras_core->dev; uint32_t nps_mode; - if (amdgpu_ras_is_poison_mode_supported(adev)) + if (ras_core_poison_supported(ras_core)) ras_ta_param->poison_mode_en = 1; if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) @@ -624,7 +624,7 @@ int amdgpu_ras_mgr_handle_controller_interrupt(struct amdgpu_device *adev, void return -EPERM; if (ih_info && (ih_info->block == AMDGPU_RAS_BLOCK__UMC)) { - if (ras_mgr->ras_core->poison_supported) { + if (ras_core_poison_supported(ras_mgr->ras_core)) { seq_no = amdgpu_ras_mgr_gen_ras_event_seqno(adev, RAS_SEQNO_TYPE_DE); RAS_DEV_INFO(adev, "{%llu} RAS poison is created, no user action is needed.\n", @@ -632,7 +632,7 @@ int amdgpu_ras_mgr_handle_controller_interrupt(struct amdgpu_device *adev, void } ret = amdgpu_ras_process_handle_umc_interrupt(adev, ih_info); - } else if (ras_mgr->ras_core->poison_supported) { + } else if (ras_core_poison_supported(ras_mgr->ras_core)) { ret = amdgpu_ras_process_handle_unexpected_interrupt(adev, ih_info); } else { RAS_DEV_WARN(adev, @@ -655,7 +655,7 @@ int amdgpu_ras_mgr_dispatch_interrupt(struct amdgpu_device *adev, struct ras_ih_ return 0; if (ih_info->block == RAS_BLOCK_ID__UMC) { - if (ras_mgr->ras_core->poison_supported) { + if (ras_core_poison_supported(ras_mgr->ras_core)) { seq_no = amdgpu_ras_mgr_gen_ras_event_seqno(adev, RAS_SEQNO_TYPE_DE); RAS_DEV_INFO(adev, "{%llu} RAS poison is created, no user action is needed.\n", @@ -663,7 +663,7 @@ int amdgpu_ras_mgr_dispatch_interrupt(struct amdgpu_device *adev, struct ras_ih_ } ret = amdgpu_ras_process_handle_umc_interrupt(adev, ih_info); - } else if (ras_mgr->ras_core->poison_supported) { + } else if (ras_core_poison_supported(ras_mgr->ras_core)) { ret = amdgpu_ras_process_handle_consumption_interrupt(adev, ih_info); } else { RAS_DEV_WARN(adev, -- 2.55.0