From e3a895e050be494551039227820e269f45761479 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Jul 2026 14:18:36 -0400 Subject: [PATCH 01/51] drm/amdkfd: drop duplicate kfd_queue_acquire_buffers() Duplicated code from the merge. Drop it. Fixes: 0461ba9a7994 ("Merge tag 'amd-drm-next-7.3-2026-07-02' of https://gitlab.freedesktop.org/agd5f/linux into drm-next") Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index acbdca91cde5..d723b07379b3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -1048,12 +1048,6 @@ int kfd_criu_restore_queue(struct kfd_process *p, goto exit; } - ret = kfd_queue_acquire_buffers(pdd, &qp); - if (ret) { - pr_debug("failed to acquire user queue buffers for CRIU\n"); - goto exit; - } - print_queue_properties(&qp); ret = pqm_create_queue(&p->pqm, pdd->dev, &qp, &queue_id, q_data, mqd, ctl_stack, NULL); From 3dbf9b502bed00248ed07fcf63b22a0a4ec16331 Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Fri, 3 Apr 2026 10:55:22 +0800 Subject: [PATCH 02/51] drm/amdgpu: retire legacy pmfw eeprom interface wrapper retire legacy pmfw eeprom interface wrapper functions Reviewed-by: Hawking Zhang Signed-off-by: Ce Sun Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 98 ------------------- .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 21 ---- 2 files changed, 119 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index baa8cc3646d5..8c398c2e6709 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -1740,104 +1740,6 @@ bool amdgpu_ras_smu_eeprom_supported(struct amdgpu_device *adev) return !!(flags & RAS_SMU_FEATURE_BIT__RAS_EEPROM); } -int amdgpu_ras_smu_get_table_version(struct amdgpu_device *adev, - uint32_t *table_version) -{ - const struct ras_smu_drv *smu_ras_drv = amdgpu_ras_get_smu_ras_drv(adev); - - if (!amdgpu_ras_smu_eeprom_supported(adev)) - return -EOPNOTSUPP; - - if (smu_ras_drv->smu_eeprom_funcs->get_ras_table_version) - return smu_ras_drv->smu_eeprom_funcs->get_ras_table_version(adev, - table_version); - return -EOPNOTSUPP; -} - -int amdgpu_ras_smu_get_badpage_count(struct amdgpu_device *adev, - uint32_t *count, uint32_t timeout) -{ - const struct ras_smu_drv *smu_ras_drv = amdgpu_ras_get_smu_ras_drv(adev); - - if (!amdgpu_ras_smu_eeprom_supported(adev)) - return -EOPNOTSUPP; - - if (smu_ras_drv->smu_eeprom_funcs->get_badpage_count) - return smu_ras_drv->smu_eeprom_funcs->get_badpage_count(adev, - count, timeout); - return -EOPNOTSUPP; -} - -int amdgpu_ras_smu_get_badpage_mca_addr(struct amdgpu_device *adev, - uint16_t index, uint64_t *mca_addr) -{ - const struct ras_smu_drv *smu_ras_drv = amdgpu_ras_get_smu_ras_drv(adev); - - if (!amdgpu_ras_smu_eeprom_supported(adev)) - return -EOPNOTSUPP; - - if (smu_ras_drv->smu_eeprom_funcs->get_badpage_mca_addr) - return smu_ras_drv->smu_eeprom_funcs->get_badpage_mca_addr(adev, - index, mca_addr); - return -EOPNOTSUPP; -} - -int amdgpu_ras_smu_set_timestamp(struct amdgpu_device *adev, - uint64_t timestamp) -{ - const struct ras_smu_drv *smu_ras_drv = amdgpu_ras_get_smu_ras_drv(adev); - - if (!amdgpu_ras_smu_eeprom_supported(adev)) - return -EOPNOTSUPP; - - if (smu_ras_drv->smu_eeprom_funcs->set_timestamp) - return smu_ras_drv->smu_eeprom_funcs->set_timestamp(adev, - timestamp); - return -EOPNOTSUPP; -} - -int amdgpu_ras_smu_get_timestamp(struct amdgpu_device *adev, - uint16_t index, uint64_t *timestamp) -{ - const struct ras_smu_drv *smu_ras_drv = amdgpu_ras_get_smu_ras_drv(adev); - - if (!amdgpu_ras_smu_eeprom_supported(adev)) - return -EOPNOTSUPP; - - if (smu_ras_drv->smu_eeprom_funcs->get_timestamp) - return smu_ras_drv->smu_eeprom_funcs->get_timestamp(adev, - index, timestamp); - return -EOPNOTSUPP; -} - -int amdgpu_ras_smu_get_badpage_ipid(struct amdgpu_device *adev, - uint16_t index, uint64_t *ipid) -{ - const struct ras_smu_drv *smu_ras_drv = amdgpu_ras_get_smu_ras_drv(adev); - - if (!amdgpu_ras_smu_eeprom_supported(adev)) - return -EOPNOTSUPP; - - if (smu_ras_drv->smu_eeprom_funcs->get_badpage_ipid) - return smu_ras_drv->smu_eeprom_funcs->get_badpage_ipid(adev, - index, ipid); - return -EOPNOTSUPP; -} - -int amdgpu_ras_smu_erase_ras_table(struct amdgpu_device *adev, - uint32_t *result) -{ - const struct ras_smu_drv *smu_ras_drv = amdgpu_ras_get_smu_ras_drv(adev); - - if (!amdgpu_ras_smu_eeprom_supported(adev)) - return -EOPNOTSUPP; - - if (smu_ras_drv->smu_eeprom_funcs->erase_ras_table) - return smu_ras_drv->smu_eeprom_funcs->erase_ras_table(adev, - result); - return -EOPNOTSUPP; -} - void amdgpu_ras_check_bad_page_status(struct amdgpu_device *adev) { struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 3c7fcce5fe8b..5e5275ae7aab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -165,27 +165,6 @@ void amdgpu_ras_eeprom_check_and_recover(struct amdgpu_device *adev); bool amdgpu_ras_smu_eeprom_supported(struct amdgpu_device *adev); -int amdgpu_ras_smu_get_table_version(struct amdgpu_device *adev, - uint32_t *table_version); - -int amdgpu_ras_smu_get_badpage_count(struct amdgpu_device *adev, - uint32_t *count, uint32_t timeout); - -int amdgpu_ras_smu_get_badpage_mca_addr(struct amdgpu_device *adev, - uint16_t index, uint64_t *mca_addr); - -int amdgpu_ras_smu_set_timestamp(struct amdgpu_device *adev, - uint64_t timestamp); - -int amdgpu_ras_smu_get_timestamp(struct amdgpu_device *adev, - uint16_t index, uint64_t *timestamp); - -int amdgpu_ras_smu_get_badpage_ipid(struct amdgpu_device *adev, - uint16_t index, uint64_t *ipid); - -int amdgpu_ras_smu_erase_ras_table(struct amdgpu_device *adev, - uint32_t *result); - int amdgpu_ras_eeprom_read_idx(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *record, u32 rec_idx, const u32 num); From ef71f00173228904763552b7405169023f8034a8 Mon Sep 17 00:00:00 2001 From: Kanala Ramalingeswara Reddy Date: Wed, 17 Jun 2026 18:04:36 +0530 Subject: [PATCH 03/51] drm/amdgpu: add support for PSP version 15.0.9 Initialize PSP Version 15_0_9 Signed-off-by: Kanala Ramalingeswara Reddy Signed-off-by: Granthali Vinodkumar Dhandar Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index a015d55aa158..396098e8bce1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2529,6 +2529,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev) amdgpu_device_ip_block_add(adev, &psp_v14_0_ip_block); break; case IP_VERSION(15, 0, 0): + case IP_VERSION(15, 0, 9): amdgpu_device_ip_block_add(adev, &psp_v15_0_ip_block); break; case IP_VERSION(15, 0, 8): diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 96e1b72b9e1c..e0c0d7872e45 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -275,6 +275,7 @@ static int psp_early_init(struct amdgpu_ip_block *ip_block) psp->boot_time_tmr = false; break; case IP_VERSION(15, 0, 0): + case IP_VERSION(15, 0, 9): psp_v15_0_0_set_psp_funcs(psp); psp->boot_time_tmr = false; break; @@ -3475,7 +3476,9 @@ static int psp_load_non_psp_fw(struct psp_context *psp) amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(15, 0, 0) || amdgpu_ip_version(adev, MP0_HWIP, 0) == - IP_VERSION(15, 0, 8)) && + IP_VERSION(15, 0, 8) || + amdgpu_ip_version(adev, MP0_HWIP, 0) == + IP_VERSION(15, 0, 9)) && (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3)) From 1dfd4e84b5beec353a81d61af9eaf4e5a56e0c57 Mon Sep 17 00:00:00 2001 From: Kanala Ramalingeswara Reddy Date: Wed, 17 Jun 2026 18:04:53 +0530 Subject: [PATCH 04/51] drm/amdgpu: add support for SMU version 15.0.9 Initialize SMU Version 15_0_9 Signed-off-by: Kanala Ramalingeswara Reddy Signed-off-by: Granthali Vinodkumar Dhandar Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c | 3 ++- 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 396098e8bce1..d9edac5f321d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2601,6 +2601,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(15, 0, 0): case IP_VERSION(15, 0, 5): case IP_VERSION(15, 0, 8): + case IP_VERSION(15, 0, 9): amdgpu_device_ip_block_add(adev, &smu_v15_0_ip_block); break; default: diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 09f28dbd60ee..5a3d6c7a8d6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -406,6 +406,7 @@ soc21_asic_reset_method(struct amdgpu_device *adev) case IP_VERSION(14, 0, 4): case IP_VERSION(14, 0, 5): case IP_VERSION(15, 0, 0): + case IP_VERSION(15, 0, 9): return AMD_RESET_METHOD_MODE2; default: if (amdgpu_dpm_is_baco_supported(adev)) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 541cf0a985eb..0caea992d3fb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -801,6 +801,7 @@ static int smu_set_funcs(struct amdgpu_device *adev) break; case IP_VERSION(15, 0, 0): case IP_VERSION(15, 0, 5): + case IP_VERSION(15, 0, 9): smu_v15_0_0_set_ppt_funcs(smu); break; case IP_VERSION(15, 0, 8): diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c index f3fb6ed4bc95..046069e93854 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0.c @@ -583,6 +583,7 @@ int smu_v15_0_gfx_off_control(struct smu_context *smu, bool enable) switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { case IP_VERSION(15, 0, 0): + case IP_VERSION(15, 0, 9): if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c index a214ddbd4c86..bb8d09e73c7d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_0_ppt.c @@ -1177,7 +1177,8 @@ static int smu_v15_0_common_get_dpm_profile_freq(struct smu_context *smu, smu_v15_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &clk_limit); break; case SMU_FCLK: - if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(15, 0, 0)) + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(15, 0, 0) || + amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(15, 0, 9)) smu_v15_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &clk_limit); else clk_limit = SMU_15_0_UMD_PSTATE_FCLK; From ea3fdd1eda088030d8925f023613728969f55955 Mon Sep 17 00:00:00 2001 From: Suresh Guttula Date: Fri, 26 Jun 2026 11:39:51 +0530 Subject: [PATCH 05/51] drm/amdgpu: Disable JDPG on VCN5_3 JDPG does not support on VCN5 This patch will disable JDPG, because DPG is not correctly copying the JRBC Read/Write Pointers (R/WPTR) from the PG (Power Gating) block to JRBC. Signed-off-by: Suresh Guttula Reviewed-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc21.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 5a3d6c7a8d6c..1b667be8c5d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -850,7 +850,6 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block) AMD_CG_SUPPORT_BIF_LS; adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG | AMD_PG_SUPPORT_VCN | - AMD_PG_SUPPORT_JPEG_DPG | AMD_PG_SUPPORT_JPEG | AMD_PG_SUPPORT_GFX_PG; adev->external_rev_id = adev->rev_id + 0xF; @@ -878,7 +877,6 @@ static int soc21_common_early_init(struct amdgpu_ip_block *ip_block) AMD_CG_SUPPORT_BIF_LS; adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG | AMD_PG_SUPPORT_VCN | - AMD_PG_SUPPORT_JPEG_DPG | AMD_PG_SUPPORT_JPEG | AMD_PG_SUPPORT_GFX_PG; adev->external_rev_id = adev->rev_id + 0x40; From aaa1d1ea6f2185144b474ce9b969a91dacf961e6 Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Fri, 3 Apr 2026 10:58:22 +0800 Subject: [PATCH 06/51] drm/amdgpu: retire legacy pmfw eeprom support check Remove the legacy function to check pmfw eeprom support Reviewed-by: Hawking Zhang Signed-off-by: Ce Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 1 - .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 48 +------------------ .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 2 +- 4 files changed, 2 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 148bb4cb0a2d..82175a84875f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -3205,7 +3205,6 @@ int amdgpu_ras_init_badpage_info(struct amdgpu_device *adev) return 0; control = &con->eeprom_control; - con->ras_smu_drv = amdgpu_dpm_get_ras_smu_driver(adev); ret = amdgpu_ras_eeprom_init(control); control->is_eeprom_valid = !ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 8c398c2e6709..95468b9463fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -1156,10 +1156,6 @@ static ssize_t amdgpu_ras_debugfs_table_read(struct file *f, char __user *buf, int res = -EFAULT; size_t data_len; - /* pmfw manages eeprom data by itself */ - if (amdgpu_ras_smu_eeprom_supported(adev)) - return 0; - mutex_lock(&control->ras_tbl_mutex); /* We want *pos - data_len > 0, which means there's @@ -1676,8 +1672,7 @@ void amdgpu_ras_eeprom_check_and_recover(struct amdgpu_device *adev) struct amdgpu_ras_eeprom_control *control; int res; - if (!__is_ras_eeprom_supported(adev) || !ras || - amdgpu_ras_smu_eeprom_supported(adev)) + if (!__is_ras_eeprom_supported(adev) || !ras) return; control = &ras->eeprom_control; if (!control->is_eeprom_valid) @@ -1699,47 +1694,6 @@ void amdgpu_ras_eeprom_check_and_recover(struct amdgpu_device *adev) return; } -static const struct ras_smu_drv *amdgpu_ras_get_smu_ras_drv(struct amdgpu_device *adev) -{ - struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - - if (!ras) - return NULL; - - return ras->ras_smu_drv; -} - -static uint64_t amdgpu_ras_smu_get_feature_flags(struct amdgpu_device *adev) -{ - const struct ras_smu_drv *ras_smu_drv = amdgpu_ras_get_smu_ras_drv(adev); - uint64_t flags = 0ULL; - - if (!ras_smu_drv) - goto out; - - if (ras_smu_drv->ras_smu_feature_flags) - ras_smu_drv->ras_smu_feature_flags(adev, &flags); - -out: - return flags; -} - -bool amdgpu_ras_smu_eeprom_supported(struct amdgpu_device *adev) -{ - const struct ras_smu_drv *smu_ras_drv = amdgpu_ras_get_smu_ras_drv(adev); - uint64_t flags = 0ULL; - - if (!__is_ras_eeprom_supported(adev) || !smu_ras_drv) - return false; - - if (!smu_ras_drv->smu_eeprom_funcs) - return false; - - flags = amdgpu_ras_smu_get_feature_flags(adev); - - return !!(flags & RAS_SMU_FEATURE_BIT__RAS_EEPROM); -} - void amdgpu_ras_check_bad_page_status(struct amdgpu_device *adev) { struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 5e5275ae7aab..6e50b9f0569d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -163,8 +163,6 @@ int amdgpu_ras_eeprom_check(struct amdgpu_ras_eeprom_control *control); void amdgpu_ras_eeprom_check_and_recover(struct amdgpu_device *adev); -bool amdgpu_ras_smu_eeprom_supported(struct amdgpu_device *adev); - int amdgpu_ras_eeprom_read_idx(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *record, u32 rec_idx, const u32 num); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 2a5f5e6188bb..33b02f794095 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -186,7 +186,7 @@ void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, if ((amdgpu_bad_page_threshold != 0) && err_data->err_addr_cnt) { amdgpu_ras_add_bad_pages(adev, err_data->err_addr, - err_data->err_addr_cnt, amdgpu_ras_smu_eeprom_supported(adev)); + err_data->err_addr_cnt, false); amdgpu_ras_save_bad_pages(adev, &err_count); amdgpu_dpm_send_hbm_bad_pages_num(adev, From 958430a1f068f6be6c9376e07014a9e8c63ae24e Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Fri, 3 Apr 2026 11:06:05 +0800 Subject: [PATCH 07/51] drm/amd/pm: retire legacy smu ras driver framework Remove the legacy smu ras driver framework Reviewed-by: Hawking Zhang Signed-off-by: Ce Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 1 - drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 7 ------- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 1 - drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 11 ---------- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 8 ------- .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 21 ------------------- drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 - 7 files changed, 50 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index a44aed7f169e..822abb638d58 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -598,7 +598,6 @@ struct amdgpu_ras { /* Disable/Enable uniras switch */ bool uniras_enabled; - const struct ras_smu_drv *ras_smu_drv; }; struct ras_fs_data { diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index f76ba6753551..c09c60ad3f38 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -2110,10 +2110,3 @@ ssize_t amdgpu_dpm_get_xcp_metrics(struct amdgpu_device *adev, int xcp_id, return ret; } - -const struct ras_smu_drv *amdgpu_dpm_get_ras_smu_driver(struct amdgpu_device *adev) -{ - void *pp_handle = adev->powerplay.pp_handle; - - return smu_get_ras_smu_driver(pp_handle); -} diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index aa3f427819a0..c7ea29385682 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -612,6 +612,5 @@ int amdgpu_dpm_reset_vcn(struct amdgpu_device *adev, uint32_t inst_mask); bool amdgpu_dpm_reset_vcn_is_supported(struct amdgpu_device *adev); bool amdgpu_dpm_is_temp_metrics_supported(struct amdgpu_device *adev, enum smu_temp_metric_type type); -const struct ras_smu_drv *amdgpu_dpm_get_ras_smu_driver(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 0caea992d3fb..504fd9762a8e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2818,17 +2818,6 @@ const struct amdgpu_ip_block_version smu_v15_0_ip_block = { .funcs = &smu_ip_funcs, }; -const struct ras_smu_drv *smu_get_ras_smu_driver(void *handle) -{ - struct smu_context *smu = (struct smu_context *)handle; - const struct ras_smu_drv *tmp = NULL; - int ret; - - ret = smu_get_ras_smu_drv(smu, &tmp); - - return ret ? NULL : tmp; -} - static int smu_load_microcode(void *handle) { struct smu_context *smu = handle; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 378781c05bea..f8fd93999617 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -1618,13 +1618,6 @@ struct pptable_funcs { */ int (*ras_send_msg)(struct smu_context *smu, enum smu_message_type msg, uint32_t param, uint32_t *read_arg); - - - /** - * @get_ras_smu_drv: Get RAS smu driver interface - * Return: ras_smu_drv * - */ - int (*get_ras_smu_drv)(struct smu_context *smu, const struct ras_smu_drv **ras_smu_drv); }; typedef enum { @@ -1972,7 +1965,6 @@ int smu_set_pm_policy(struct smu_context *smu, enum pp_pm_policy p_type, int level); ssize_t smu_get_pm_policy_info(struct smu_context *smu, enum pp_pm_policy p_type, char *sysbuf); -const struct ras_smu_drv *smu_get_ras_smu_driver(void *handle); int amdgpu_smu_ras_send_msg(struct amdgpu_device *adev, enum smu_message_type msg, uint32_t param, uint32_t *readarg); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 334c92a28994..64db62a8d642 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -3273,26 +3273,6 @@ static void smu_v13_0_6_set_temp_funcs(struct smu_context *smu) == IP_VERSION(13, 0, 12)) ? &smu_v13_0_12_temp_funcs : NULL; } -static int smu_v13_0_6_get_ras_smu_drv(struct smu_context *smu, const struct ras_smu_drv **ras_smu_drv) -{ - if (!ras_smu_drv) - return -EINVAL; - - if (amdgpu_sriov_vf(smu->adev)) - return -EOPNOTSUPP; - - switch (amdgpu_ip_version(smu->adev, MP1_HWIP, 0)) { - case IP_VERSION(13, 0, 12): - *ras_smu_drv = &smu_v13_0_12_ras_smu_drv; - break; - default: - *ras_smu_drv = NULL; - break; - } - - return 0; -} - static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { /* init dpm */ .init_allowed_features = smu_v13_0_6_init_allowed_features, @@ -3351,7 +3331,6 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { .dpm_reset_vcn = smu_v13_0_6_reset_vcn, .post_init = smu_v13_0_6_post_init, .ras_send_msg = smu_v13_0_6_ras_send_msg, - .get_ras_smu_drv = smu_v13_0_6_get_ras_smu_drv, }; void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 24848da90234..45e3758e9ed8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -98,7 +98,6 @@ #define smu_is_asic_wbrf_supported(smu) smu_ppt_funcs(is_asic_wbrf_supported, false, smu) #define smu_enable_uclk_shadow(smu, enable) smu_ppt_funcs(enable_uclk_shadow, 0, smu, enable) #define smu_set_wbrf_exclusion_ranges(smu, freq_band_range) smu_ppt_funcs(set_wbrf_exclusion_ranges, -EOPNOTSUPP, smu, freq_band_range) -#define smu_get_ras_smu_drv(smu, ras_smu_drv) smu_ppt_funcs(get_ras_smu_drv, -EOPNOTSUPP, smu, ras_smu_drv) #endif #endif From dc04b407200d8c7642960afcd3cb64c9c3859f29 Mon Sep 17 00:00:00 2001 From: Tiago Dourado Date: Thu, 25 Jun 2026 23:59:12 -0300 Subject: [PATCH 08/51] drm/amdgpu/jpeg: deduplicate jpeg_v3_0 process_interrupt The jpeg_v3_0_process_interrupt function is identical to jpeg_v2_0_process_interrupt. Remove the duplicate implementation in jpeg_v3_0 and assign the jpeg_v2_0 version directly to the irq_funcs struct. Export jpeg_v2_0_process_interrupt through jpeg_v2_0.h to allow cross-version reuse. Signed-off-by: Tiago Dourado Co-developed-by: Luiz Fernandes Signed-off-by: Luiz Fernandes Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h | 4 ++++ drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 21 +-------------------- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c index cffb1e6bab35..a9c00adcfe41 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c @@ -747,7 +747,7 @@ static int jpeg_v2_0_set_interrupt_state(struct amdgpu_device *adev, return 0; } -static int jpeg_v2_0_process_interrupt(struct amdgpu_device *adev, +int jpeg_v2_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h index 654e43e83e2c..4f400fb476f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.h @@ -58,6 +58,10 @@ void jpeg_v2_0_dec_ring_emit_vm_flush(struct amdgpu_ring *ring, void jpeg_v2_0_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val); void jpeg_v2_0_dec_ring_nop(struct amdgpu_ring *ring, uint32_t count); +int jpeg_v2_0_process_interrupt(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry); + extern const struct amdgpu_ip_block_version jpeg_v2_0_ip_block; #endif /* __JPEG_V2_0_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c index d0445df39d2c..e9ccadeb7696 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c @@ -539,25 +539,6 @@ static int jpeg_v3_0_set_interrupt_state(struct amdgpu_device *adev, return 0; } -static int jpeg_v3_0_process_interrupt(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) -{ - DRM_DEBUG("IH: JPEG TRAP\n"); - - switch (entry->src_id) { - case VCN_2_0__SRCID__JPEG_DECODE: - amdgpu_fence_process(adev->jpeg.inst->ring_dec); - break; - default: - DRM_ERROR("Unhandled interrupt: %d %d\n", - entry->src_id, entry->src_data[0]); - break; - } - - return 0; -} - static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid, struct amdgpu_fence *timedout_fence) @@ -630,7 +611,7 @@ static void jpeg_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev) static const struct amdgpu_irq_src_funcs jpeg_v3_0_irq_funcs = { .set = jpeg_v3_0_set_interrupt_state, - .process = jpeg_v3_0_process_interrupt, + .process = jpeg_v2_0_process_interrupt, }; static void jpeg_v3_0_set_irq_funcs(struct amdgpu_device *adev) From f4c7d8293f019bccb7211ce312559715b51c5094 Mon Sep 17 00:00:00 2001 From: Tiago Dourado Date: Thu, 25 Jun 2026 23:59:13 -0300 Subject: [PATCH 09/51] drm/amdgpu/jpeg: deduplicate jpeg_v5_3_0 process_interrupt The jpeg_v5_3_0_process_interrupt function is identical to jpeg_v5_0_0_process_interrupt. Remove the duplicate implementation in jpeg_v5_3_0 and assign the jpeg_v5_0_0 version directly to the irq_funcs struct. Export jpeg_v5_0_0_process_interrupt through jpeg_v5_0_0.h to allow cross-version reuse. Signed-off-by: Tiago Dourado Co-developed-by: Luiz Fernandes Signed-off-by: Luiz Fernandes Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h | 4 ++++ drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c | 22 ++-------------------- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c index 72a4b2d0676f..1cdbe353ae40 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c @@ -625,7 +625,7 @@ static int jpeg_v5_0_0_set_interrupt_state(struct amdgpu_device *adev, return 0; } -static int jpeg_v5_0_0_process_interrupt(struct amdgpu_device *adev, +int jpeg_v5_0_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h index 5abb96159814..4eeb0c14702c 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.h @@ -32,4 +32,8 @@ extern const struct amdgpu_ip_block_version jpeg_v5_0_0_ip_block; +int jpeg_v5_0_0_process_interrupt(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry); + #endif /* __JPEG_V5_0_0_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c index e7546816baba..66d4c487eee5 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_3_0.c @@ -32,6 +32,7 @@ #include "vcn/vcn_5_3_0_offset.h" #include "vcn/vcn_5_3_0_sh_mask.h" #include "ivsrcid/vcn/irqsrcs_vcn_5_0.h" +#include "jpeg_v5_0_0.h" #include "jpeg_v5_3_0.h" static void jpeg_v5_3_0_set_dec_ring_funcs(struct amdgpu_device *adev); @@ -608,25 +609,6 @@ static int jpeg_v5_3_0_set_interrupt_state(struct amdgpu_device *adev, return 0; } -static int jpeg_v5_3_0_process_interrupt(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) -{ - DRM_DEBUG("IH: JPEG TRAP\n"); - - switch (entry->src_id) { - case VCN_5_0__SRCID__JPEG_DECODE: - amdgpu_fence_process(adev->jpeg.inst->ring_dec); - break; - default: - DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n", - entry->src_id, entry->src_data[0]); - break; - } - - return 0; -} - static int jpeg_v5_3_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid, struct amdgpu_fence *timedout_fence) @@ -697,7 +679,7 @@ static void jpeg_v5_3_0_set_dec_ring_funcs(struct amdgpu_device *adev) static const struct amdgpu_irq_src_funcs jpeg_v5_3_0_irq_funcs = { .set = jpeg_v5_3_0_set_interrupt_state, - .process = jpeg_v5_3_0_process_interrupt, + .process = jpeg_v5_0_0_process_interrupt, }; static void jpeg_v5_3_0_set_irq_funcs(struct amdgpu_device *adev) From f3f622b43edc86a4ae00f521789a5d24bb71a761 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sun, 28 Jun 2026 16:17:01 +1000 Subject: [PATCH 10/51] drm/amdgpu/mes: Add NULL check for mes_hung_db_array allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kcalloc but does not check for failure. If the allocation fails, the pointer remains NULL but the function returns success. Subsequent code using this buffer will dereference a NULL pointer, causing a kernel oops. Add a check to return -ENOMEM if the allocation fails. Signed-off-by: Geoffrey McRae Reviewed-by: Alex Deucher Cc: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index 6c0dde3786e3..261ddc19c840 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -250,11 +250,16 @@ int amdgpu_mes_init(struct amdgpu_device *adev) goto error_doorbell; } } - } - adev->gfx.mec.mes_hung_db_array = - kcalloc(amdgpu_mes_get_hung_queue_db_array_size(adev), - sizeof(u32), GFP_KERNEL); + adev->gfx.mec.mes_hung_db_array = + kcalloc(amdgpu_mes_get_hung_queue_db_array_size(adev), + sizeof(u32), GFP_KERNEL); + + if (!adev->gfx.mec.mes_hung_db_array) { + r = -ENOMEM; + goto error_doorbell; + } + } return 0; From 3d4e5f211e04f71e08ab27d9bb30b10072796a96 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Sun, 28 Jun 2026 09:02:07 -0400 Subject: [PATCH 11/51] drm/amdkfd: use iosys_map for CWSR buffer access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After moving TBA/TMA from GTT to VRAM for GFX9.4.2+ in commit 5088a1ba6d6d ("drm/amdkfd: move TBA/TMA from system to device memory"), direct pointer dereferences to CWSR buffers became unsafe because VRAM is accessed via MMIO (PCI BAR mappings). Direct writes like 'tma[2] = enabled' and memcpy() can fail or produce incorrect results on non-x86 architectures because: - MMIO requires specific accessor functions (writeq/readq) - Compiler optimizations may generate invalid instruction sequences - No guarantee of proper memory barriers or atomic access This patch converts CWSR buffer access to use struct iosys_map, which automatically handles both system memory (GTT) and MMIO (VRAM) correctly by: - Using writeq/writel/memcpy_toio for MMIO regions - Using WRITE_ONCE/memcpy for system memory - Providing proper memory barriers and access guarantees Changes: - Replace void *cwsr_kaddr with struct iosys_map cwsr_map - Detect MMIO vs system memory using TTM_BO_MAP_IOMEM_MASK - Use iosys_map_wr() for writing trap handler addresses and flags - Use iosys_map_memcpy_to() for copying CWSR ISA code This ensures correct operation on all architectures while maintaining backward compatibility with older GPUs and APUs that use GTT. Assisted-by: Claude:Claude-Opus-4.6 Signed-off-by: James Zhu Acked-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 3 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 66 +++++++++++++++++------- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 90f010cbe54e..86a944d36aaf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -710,7 +711,7 @@ struct qcm_process_device { /* CWSR memory */ struct kgd_mem *cwsr_mem; - void *cwsr_kaddr; + struct iosys_map cwsr_map; uint64_t cwsr_base; uint64_t tba_addr; uint64_t tma_addr; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 767c2cc8e29e..7a604b8c8886 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "amdgpu_amdkfd.h" #include "amdgpu.h" #include "amdgpu_reset.h" @@ -745,6 +746,22 @@ static void kfd_process_free_gpuvm(struct kgd_mem *mem, NULL); } +static void kfd_process_free_gpuvm_map(struct kgd_mem *mem, + struct kfd_process_device *pdd, + struct iosys_map *map) +{ + struct kfd_node *dev = pdd->dev; + + if (map && !iosys_map_is_null(map)) { + amdgpu_amdkfd_gpuvm_unmap_bo_from_kernel(mem); + iosys_map_clear(map); + } + + amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(dev->adev, mem, pdd->drm_priv); + amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, mem, pdd->drm_priv, + NULL); +} + /* kfd_process_alloc_gpuvm - Allocate GPU VM for the KFD process * This function should be only called right after the process * is created and when kfd_processes_mutex is still being held @@ -1186,9 +1203,9 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) if (pdd->drm_file) fput(pdd->drm_file); - if (pdd->qpd.cwsr_kaddr && !pdd->qpd.cwsr_base) - free_pages((unsigned long)pdd->qpd.cwsr_kaddr, - get_order(KFD_CWSR_TBA_TMA_SIZE)); + if (!iosys_map_is_null(&pdd->qpd.cwsr_map) && !pdd->qpd.cwsr_base) + free_pages((unsigned long)pdd->qpd.cwsr_map.vaddr, + get_order(KFD_CWSR_TBA_TMA_SIZE)); idr_destroy(&pdd->alloc_idr); @@ -1495,7 +1512,7 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd) void *kaddr; int ret; - if (!dev->kfd->cwsr_enabled || qpd->cwsr_kaddr || !qpd->cwsr_base) + if (!dev->kfd->cwsr_enabled || !iosys_map_is_null(&qpd->cwsr_map) || !qpd->cwsr_base) return 0; if (KFD_GC_VERSION(dev) >= IP_VERSION(9, 4, 2) && !dev->adev->apu_prefer_gtt) @@ -1510,17 +1527,28 @@ static int kfd_process_device_init_cwsr_dgpu(struct kfd_process_device *pdd) return ret; qpd->cwsr_mem = mem; - qpd->cwsr_kaddr = kaddr; + + /* Set up iosys_map based on whether memory is MMIO or system memory */ + if (mem->bo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK) + iosys_map_set_vaddr_iomem(&qpd->cwsr_map, kaddr); + else + iosys_map_set_vaddr(&qpd->cwsr_map, kaddr); + qpd->tba_addr = qpd->cwsr_base; - memcpy(qpd->cwsr_kaddr, dev->kfd->cwsr_isa, dev->kfd->cwsr_isa_size); + /* Copy CWSR ISA to buffer using appropriate accessor */ + iosys_map_memcpy_to(&qpd->cwsr_map, 0, dev->kfd->cwsr_isa, + dev->kfd->cwsr_isa_size); kfd_process_set_trap_debug_flag(&pdd->qpd, pdd->process->debug_trap_enabled); qpd->tma_addr = qpd->tba_addr + KFD_CWSR_TMA_OFFSET; - pr_debug("set tba :0x%llx, tma:0x%llx, cwsr_kaddr:%p for pqm.\n", - qpd->tba_addr, qpd->tma_addr, qpd->cwsr_kaddr); + pr_debug("set tba :0x%llx, tma:0x%llx, cwsr_map:%s at %p for pqm.\n", + qpd->tba_addr, qpd->tma_addr, + qpd->cwsr_map.is_iomem ? "iomem" : "system", + qpd->cwsr_map.is_iomem ? (void *)qpd->cwsr_map.vaddr_iomem : + qpd->cwsr_map.vaddr); return 0; } @@ -1530,24 +1558,24 @@ static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd) struct kfd_node *dev = pdd->dev; struct qcm_process_device *qpd = &pdd->qpd; - if (!dev->kfd->cwsr_enabled || !qpd->cwsr_kaddr || !qpd->cwsr_base) + if (!dev->kfd->cwsr_enabled || iosys_map_is_null(&qpd->cwsr_map) || !qpd->cwsr_base) return; - kfd_process_free_gpuvm(qpd->cwsr_mem, pdd, &qpd->cwsr_kaddr); + kfd_process_free_gpuvm_map(qpd->cwsr_mem, pdd, &qpd->cwsr_map); } void kfd_process_set_trap_handler(struct qcm_process_device *qpd, uint64_t tba_addr, uint64_t tma_addr) { - if (qpd->cwsr_kaddr) { + if (!iosys_map_is_null(&qpd->cwsr_map)) { /* KFD trap handler is bound, record as second-level TBA/TMA * in first-level TMA. First-level trap will jump to second. */ - uint64_t *tma = - (uint64_t *)(qpd->cwsr_kaddr + KFD_CWSR_TMA_OFFSET); - tma[0] = tba_addr; - tma[1] = tma_addr; + iosys_map_wr(&qpd->cwsr_map, KFD_CWSR_TMA_OFFSET, + uint64_t, tba_addr); + iosys_map_wr(&qpd->cwsr_map, KFD_CWSR_TMA_OFFSET + sizeof(uint64_t), + uint64_t, tma_addr); } else { /* No trap handler bound, bind as first-level TBA/TMA. */ qpd->tba_addr = tba_addr; @@ -1613,10 +1641,10 @@ bool kfd_process_xnack_mode(struct kfd_process *p, bool supported) void kfd_process_set_trap_debug_flag(struct qcm_process_device *qpd, bool enabled) { - if (qpd->cwsr_kaddr) { - uint64_t *tma = - (uint64_t *)(qpd->cwsr_kaddr + KFD_CWSR_TMA_OFFSET); - tma[2] = enabled; + if (!iosys_map_is_null(&qpd->cwsr_map)) { + iosys_map_wr(&qpd->cwsr_map, + KFD_CWSR_TMA_OFFSET + 2 * sizeof(uint64_t), + uint64_t, enabled); } } From 2c256086a363f01f9840a57949506eccf5c990a6 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sun, 28 Jun 2026 15:37:02 +1000 Subject: [PATCH 12/51] drm/amdgpu/mes: Fix hung_queue_db_array loop limit for multi-XCC The loop iterated only AMDGPU_MAX_MES_PIPES times, leaving entries uninitialized for multi-XCC GPUs. This causes null pointer dereferences when accessing arrays indexed by XCC ID >= 2. Extend the loop to cover all XCCs (AMDGPU_MAX_MES_PIPES * num_xcc), matching other per-XCC arrays. Fixes: a132fc9bc2f8 ("drm/amdgpu: Fixup boost mes detect hang array size") Signed-off-by: Geoffrey McRae Reviewed-by: Amber Lin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index 261ddc19c840..c2b9479f4ca6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -237,7 +237,7 @@ int amdgpu_mes_init(struct amdgpu_device *adev) } if (adev->mes.hung_queue_db_array_size) { - for (i = 0; i < AMDGPU_MAX_MES_PIPES; i++) { + for (i = 0; i < AMDGPU_MAX_MES_PIPES * num_xcc; i++) { r = amdgpu_bo_create_kernel(adev, adev->mes.hung_queue_db_array_size * sizeof(u32), PAGE_SIZE, From 7a3706b47553069d835f04da522fc6aca943cda0 Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Wed, 25 Mar 2026 10:37:04 +0800 Subject: [PATCH 13/51] drm/amd/pm: retire legacy ras_smu_drv interface for smu v13.0.12 Remove the legacy ras_smu_drv interface implementation for SMU v13.0.12 Reviewed-by: Hawking Zhang Signed-off-by: Ce Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 26 ---- .../drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c | 130 ------------------ .../drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h | 1 - 3 files changed, 157 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 822abb638d58..739da6e1d495 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -492,32 +492,6 @@ struct ras_critical_region { uint64_t size; }; -struct ras_eeprom_table_version { - uint32_t minor : 16; - uint32_t major : 16; -}; - -struct ras_eeprom_smu_funcs { - int (*get_ras_table_version)(struct amdgpu_device *adev, - uint32_t *table_version); - int (*get_badpage_count)(struct amdgpu_device *adev, uint32_t *count, uint32_t timeout); - int (*get_badpage_mca_addr)(struct amdgpu_device *adev, uint16_t index, uint64_t *mca_addr); - int (*set_timestamp)(struct amdgpu_device *adev, uint64_t timestamp); - int (*get_timestamp)(struct amdgpu_device *adev, - uint16_t index, uint64_t *timestamp); - int (*get_badpage_ipid)(struct amdgpu_device *adev, uint16_t index, uint64_t *ipid); - int (*erase_ras_table)(struct amdgpu_device *adev, uint32_t *result); -}; - -enum ras_smu_feature_flags { - RAS_SMU_FEATURE_BIT__RAS_EEPROM = BIT_ULL(0), -}; - -struct ras_smu_drv { - const struct ras_eeprom_smu_funcs *smu_eeprom_funcs; - void (*ras_smu_feature_flags)(struct amdgpu_device *adev, uint64_t *flags); -}; - struct amdgpu_ras { void *ras_mgr; /* ras infrastructure */ diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c index dea27fcb2b20..ecdbf9bb8eb7 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_12_ppt.c @@ -1017,133 +1017,3 @@ const struct smu_temp_funcs smu_v13_0_12_temp_funcs = { .temp_metrics_is_supported = smu_v13_0_12_is_temp_metrics_supported, .get_temp_metrics = smu_v13_0_12_get_temp_metrics, }; - -static int smu_v13_0_12_get_ras_table_version(struct amdgpu_device *adev, - uint32_t *table_version) -{ - struct smu_context *smu = adev->powerplay.pp_handle; - - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetRASTableVersion, 0, table_version); -} - -static int smu_v13_0_12_get_badpage_count(struct amdgpu_device *adev, uint32_t *count, - uint32_t timeout) -{ - struct smu_context *smu = adev->powerplay.pp_handle; - uint64_t end, now; - int ret = 0; - - now = (uint64_t)ktime_to_ms(ktime_get()); - end = now + timeout; - do { - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetBadPageCount, 0, count); - /* eeprom is not ready */ - if (ret != -EBUSY) - return ret; - usleep_range(10000, 15000); - now = (uint64_t)ktime_to_ms(ktime_get()); - } while (now < end); - - dev_err(adev->dev, - "smu get bad page count timeout!\n"); - return ret; -} - -static int smu_v13_0_12_set_timestamp(struct amdgpu_device *adev, uint64_t timestamp) -{ - struct smu_context *smu = adev->powerplay.pp_handle; - - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetTimestamp, (uint32_t)timestamp, 0); -} - -static int smu_v13_0_12_get_timestamp(struct amdgpu_device *adev, - uint16_t index, uint64_t *timestamp) -{ - struct smu_context *smu = adev->powerplay.pp_handle; - uint32_t temp; - int ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetTimestamp, index, &temp); - if (!ret) - *timestamp = temp; - - return ret; -} - -static int smu_v13_0_12_get_badpage_ipid(struct amdgpu_device *adev, - uint16_t index, uint64_t *ipid) -{ - struct smu_context *smu = adev->powerplay.pp_handle; - uint32_t temp_arg, temp_ipid_lo, temp_ipid_high; - int ret; - - temp_arg = index | (1 << 16); - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetBadPageIpid, temp_arg, &temp_ipid_lo); - if (ret) - return ret; - - temp_arg = index | (2 << 16); - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetBadPageIpid, temp_arg, &temp_ipid_high); - if (!ret) - *ipid = (uint64_t)temp_ipid_high << 32 | temp_ipid_lo; - return ret; -} - -static int smu_v13_0_12_erase_ras_table(struct amdgpu_device *adev, - uint32_t *result) -{ - struct smu_context *smu = adev->powerplay.pp_handle; - - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_EraseRasTable, 0, result); -} - -static int smu_v13_0_12_get_badpage_mca_addr(struct amdgpu_device *adev, - uint16_t index, uint64_t *mca_addr) -{ - struct smu_context *smu = adev->powerplay.pp_handle; - uint32_t temp_arg, temp_addr_lo, temp_addr_high; - int ret; - - temp_arg = index | (1 << 16); - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetBadPageMcaAddr, temp_arg, &temp_addr_lo); - if (ret) - return ret; - - temp_arg = index | (2 << 16); - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetBadPageMcaAddr, temp_arg, &temp_addr_high); - if (!ret) - *mca_addr = (uint64_t)temp_addr_high << 32 | temp_addr_lo; - return ret; -} - -static const struct ras_eeprom_smu_funcs smu_v13_0_12_eeprom_smu_funcs = { - .get_ras_table_version = smu_v13_0_12_get_ras_table_version, - .get_badpage_count = smu_v13_0_12_get_badpage_count, - .get_badpage_mca_addr = smu_v13_0_12_get_badpage_mca_addr, - .set_timestamp = smu_v13_0_12_set_timestamp, - .get_timestamp = smu_v13_0_12_get_timestamp, - .get_badpage_ipid = smu_v13_0_12_get_badpage_ipid, - .erase_ras_table = smu_v13_0_12_erase_ras_table, -}; - -static void smu_v13_0_12_ras_smu_feature_flags(struct amdgpu_device *adev, uint64_t *flags) -{ - if (!flags) - return; - - *flags = 0ULL; -} - -const struct ras_smu_drv smu_v13_0_12_ras_smu_drv = { - .smu_eeprom_funcs = &smu_v13_0_12_eeprom_smu_funcs, - .ras_smu_feature_flags = smu_v13_0_12_ras_smu_feature_flags, -}; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h index a150fc88902c..a66bf33dbb58 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.h @@ -117,7 +117,6 @@ int smu_v13_0_12_get_system_power(struct smu_context *smu, extern const struct cmn2asic_mapping smu_v13_0_12_feature_mask_map[]; extern const struct cmn2asic_msg_mapping smu_v13_0_12_message_map[]; extern const struct smu_temp_funcs smu_v13_0_12_temp_funcs; -extern const struct ras_smu_drv smu_v13_0_12_ras_smu_drv; #if defined(SWSMU_CODE_LAYER_L2) #include "smu_cmn.h" From 26004caf89391254f2b7fef912c0d5e52a45a59d Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Wed, 25 Mar 2026 10:47:38 +0800 Subject: [PATCH 14/51] drm/amdgpu: retire legacy mca umc status check interface Remove the legacy interface to check mca umc status Reviewed-by: Hawking Zhang Signed-off-by: Ce Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 3 --- drivers/gpu/drm/amd/amdgpu/umc_v12_0.c | 20 -------------------- 3 files changed, 24 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h index 6d12f8a516d5..8ad47c5ab022 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h @@ -26,7 +26,6 @@ enum amdgpu_mca_error_type { AMDGPU_MCA_ERROR_TYPE_UE = 0, AMDGPU_MCA_ERROR_TYPE_CE, - AMDGPU_MCA_ERROR_TYPE_DE, }; struct amdgpu_mca_ras_block { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index cf06d5f856f9..46c42997d314 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -21,7 +21,6 @@ #ifndef __AMDGPU_UMC_H__ #define __AMDGPU_UMC_H__ #include "amdgpu_ras.h" -#include "amdgpu_mca.h" /* * (addr / 256) * 4096, the higher 26 bits in ErrorAddr * is the index of 4KB block @@ -101,8 +100,6 @@ struct amdgpu_umc_ras { void *ras_error_status); void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev, void *ras_error_status); - bool (*check_ecc_err_status)(struct amdgpu_device *adev, - enum amdgpu_mca_error_type type, void *ras_error_status); void (*get_retire_flip_bits)(struct amdgpu_device *adev); }; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c index 67bdf7303e6b..d62712324940 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c @@ -178,30 +178,10 @@ static void umc_v12_0_get_retire_flip_bits(struct amdgpu_device *adev) adev->umc.retire_unit = 0x1 << flip_bits->bit_num; } -static bool umc_v12_0_check_ecc_err_status(struct amdgpu_device *adev, - enum amdgpu_mca_error_type type, void *ras_error_status) -{ - uint64_t mc_umc_status = *(uint64_t *)ras_error_status; - - switch (type) { - case AMDGPU_MCA_ERROR_TYPE_UE: - return umc_v12_0_is_uncorrectable_error(adev, mc_umc_status); - case AMDGPU_MCA_ERROR_TYPE_CE: - return umc_v12_0_is_correctable_error(adev, mc_umc_status); - case AMDGPU_MCA_ERROR_TYPE_DE: - return umc_v12_0_is_deferred_error(adev, mc_umc_status); - default: - return false; - } - - return false; -} - struct amdgpu_umc_ras umc_v12_0_ras = { .ras_block = { .hw_ops = NULL, }, - .check_ecc_err_status = umc_v12_0_check_ecc_err_status, .get_retire_flip_bits = umc_v12_0_get_retire_flip_bits, }; From 656fecdc68bad6583377c82433ebda012f4c80a4 Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Fri, 3 Apr 2026 11:08:29 +0800 Subject: [PATCH 15/51] drm/amdgpu: retire legacy get_retire_flip_bits for UMC Remove the legacy get_retire_flip_bits implementation for UMC v12 Reviewed-by: Hawking Zhang Signed-off-by: Ce Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v12_0.c | 106 ------------------------- 1 file changed, 106 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c index d62712324940..d3eeaead7ca2 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c @@ -73,115 +73,9 @@ bool umc_v12_0_is_correctable_error(struct amdgpu_device *adev, uint64_t mc_umc_ !(umc_v12_0_is_uncorrectable_error(adev, mc_umc_status))))); } -static void umc_v12_0_get_retire_flip_bits(struct amdgpu_device *adev) -{ - enum amdgpu_memory_partition nps = AMDGPU_NPS1_PARTITION_MODE; - uint32_t vram_type = adev->gmc.vram_type; - struct amdgpu_umc_flip_bits *flip_bits = &(adev->umc.flip_bits); - - if (adev->gmc.gmc_funcs->query_mem_partition_mode) - nps = adev->gmc.gmc_funcs->query_mem_partition_mode(adev); - - if (adev->gmc.num_umc == 16) { - /* default setting */ - flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_C2_BIT; - flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C3_BIT; - flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_C4_BIT; - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R13_BIT; - flip_bits->flip_row_bit = 13; - flip_bits->bit_num = 4; - flip_bits->r13_in_pa = UMC_V12_0_PA_R13_BIT; - - if (nps == AMDGPU_NPS2_PARTITION_MODE) { - flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH5_BIT; - flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C2_BIT; - flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B1_BIT; - flip_bits->r13_in_pa = UMC_V12_0_PA_R12_BIT; - } else if (nps == AMDGPU_NPS4_PARTITION_MODE) { - flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH4_BIT; - flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_CH5_BIT; - flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B0_BIT; - flip_bits->r13_in_pa = UMC_V12_0_PA_R11_BIT; - } - - switch (vram_type) { - case AMDGPU_VRAM_TYPE_HBM: - /* other nps modes are taken as nps1 */ - if (nps == AMDGPU_NPS2_PARTITION_MODE) - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT; - else if (nps == AMDGPU_NPS4_PARTITION_MODE) - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT; - - break; - case AMDGPU_VRAM_TYPE_HBM3E: - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT; - flip_bits->flip_row_bit = 12; - - if (nps == AMDGPU_NPS2_PARTITION_MODE) - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT; - else if (nps == AMDGPU_NPS4_PARTITION_MODE) - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R10_BIT; - - break; - default: - dev_warn(adev->dev, - "Unknown HBM type, set RAS retire flip bits to the value in NPS1 mode.\n"); - break; - } - } else if (adev->gmc.num_umc == 8) { - /* default setting */ - flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH5_BIT; - flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_C2_BIT; - flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B1_BIT; - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT; - flip_bits->flip_row_bit = 12; - flip_bits->bit_num = 4; - flip_bits->r13_in_pa = UMC_V12_0_PA_R12_BIT; - - if (nps == AMDGPU_NPS2_PARTITION_MODE) { - flip_bits->flip_bits_in_pa[0] = UMC_V12_0_PA_CH4_BIT; - flip_bits->flip_bits_in_pa[1] = UMC_V12_0_PA_CH5_BIT; - flip_bits->flip_bits_in_pa[2] = UMC_V12_0_PA_B0_BIT; - flip_bits->r13_in_pa = UMC_V12_0_PA_R11_BIT; - } - - switch (vram_type) { - case AMDGPU_VRAM_TYPE_HBM: - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R12_BIT; - - /* other nps modes are taken as nps1 */ - if (nps == AMDGPU_NPS2_PARTITION_MODE) - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT; - - break; - case AMDGPU_VRAM_TYPE_HBM3E: - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R11_BIT; - flip_bits->flip_row_bit = 12; - - if (nps == AMDGPU_NPS2_PARTITION_MODE) - flip_bits->flip_bits_in_pa[3] = UMC_V12_0_PA_R10_BIT; - - break; - default: - dev_warn(adev->dev, - "Unknown HBM type, set RAS retire flip bits to the value in NPS1 mode.\n"); - break; - } - } else { - dev_warn(adev->dev, - "Unsupported UMC number(%d), failed to set RAS flip bits.\n", - adev->gmc.num_umc); - - return; - } - - adev->umc.retire_unit = 0x1 << flip_bits->bit_num; -} - struct amdgpu_umc_ras umc_v12_0_ras = { .ras_block = { .hw_ops = NULL, }, - .get_retire_flip_bits = umc_v12_0_get_retire_flip_bits, }; From 8d3feba033faf8dfad647758fec79018f91a48d8 Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Wed, 25 Mar 2026 11:11:03 +0800 Subject: [PATCH 16/51] drm/amdgpu: retire legacy get_retire_flip_bits interface for UMC Remove the legacy general get_retire_flip_bits interface for UMC Reviewed-by: Hawking Zhang Signed-off-by: Ce Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 ---- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 15 --------------- 2 files changed, 19 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 82175a84875f..ff1524fdb35f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -3209,10 +3209,6 @@ int amdgpu_ras_init_badpage_info(struct amdgpu_device *adev) ret = amdgpu_ras_eeprom_init(control); control->is_eeprom_valid = !ret; - if (adev->umc.ras && - adev->umc.ras->get_retire_flip_bits) - adev->umc.ras->get_retire_flip_bits(adev); - if (control->ras_num_recs && control->is_eeprom_valid) { ret = amdgpu_ras_load_bad_pages(adev); if (ret) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index 46c42997d314..b2a3db60d231 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -77,18 +77,6 @@ #define UMC_NPS_SHIFT 40 #define UMC_NPS_MASK 0xffULL -/* three column bits and one row bit in MCA address flip - * in bad page retirement - */ -#define RETIRE_FLIP_BITS_NUM 4 - -struct amdgpu_umc_flip_bits { - uint32_t flip_bits_in_pa[RETIRE_FLIP_BITS_NUM]; - uint32_t flip_row_bit; - uint32_t r13_in_pa; - uint32_t bit_num; -}; - typedef int (*umc_func)(struct amdgpu_device *adev, uint32_t node_inst, uint32_t umc_inst, uint32_t ch_inst, void *data); @@ -100,7 +88,6 @@ struct amdgpu_umc_ras { void *ras_error_status); void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev, void *ras_error_status); - void (*get_retire_flip_bits)(struct amdgpu_device *adev); }; struct amdgpu_umc_funcs { @@ -132,8 +119,6 @@ struct amdgpu_umc { /* active mask for umc node instance */ unsigned long active_mask; - struct amdgpu_umc_flip_bits flip_bits; - unsigned long err_addr_cnt; }; From 9e03530cc93422bf898ed3e4818556efc6c5fab2 Mon Sep 17 00:00:00 2001 From: Ce Sun Date: Wed, 25 Mar 2026 12:06:48 +0800 Subject: [PATCH 17/51] drm/amdgpu: retire legacy deferred error separate logging Remove the legacy logic that logs deferred errors separately Reviewed-by: Hawking Zhang Signed-off-by: Ce Sun Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 122 +++++------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 - drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 1 - drivers/gpu/drm/amd/amdgpu/umc_v12_0.c | 25 ----- drivers/gpu/drm/amd/amdgpu/umc_v12_0.h | 3 - 5 files changed, 23 insertions(+), 131 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index ff1524fdb35f..fd2c0cc1b958 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1137,8 +1137,7 @@ static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev, struct ras_err_data *err_data, struct ras_query_context *qctx, const char *blk_name, - bool is_ue, - bool is_de) + bool is_ue) { struct amdgpu_smuio_mcm_config_info *mcm_info; struct ras_err_node *err_node; @@ -1168,53 +1167,29 @@ static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev, } } else { - if (is_de) { - for_each_ras_error(err_node, err_data) { - err_info = &err_node->err_info; - mcm_info = &err_info->mcm_info; - if (err_info->de_count) { - RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " - "%lld new deferred hardware errors detected in %s block\n", - mcm_info->socket_id, - mcm_info->die_id, - err_info->de_count, - blk_name); - } - } + if (adev->debug_disable_ce_logs) + return; - for_each_ras_error(err_node, &ras_mgr->err_data) { - err_info = &err_node->err_info; - mcm_info = &err_info->mcm_info; + for_each_ras_error(err_node, err_data) { + err_info = &err_node->err_info; + mcm_info = &err_info->mcm_info; + if (err_info->ce_count) { RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " - "%lld deferred hardware errors detected in total in %s block\n", - mcm_info->socket_id, mcm_info->die_id, - err_info->de_count, blk_name); + "%lld new correctable hardware errors detected in %s block\n", + mcm_info->socket_id, + mcm_info->die_id, + err_info->ce_count, + blk_name); } - } else { - if (adev->debug_disable_ce_logs) - return; + } - for_each_ras_error(err_node, err_data) { - err_info = &err_node->err_info; - mcm_info = &err_info->mcm_info; - if (err_info->ce_count) { - RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " - "%lld new correctable hardware errors detected in %s block\n", - mcm_info->socket_id, - mcm_info->die_id, - err_info->ce_count, - blk_name); - } - } - - for_each_ras_error(err_node, &ras_mgr->err_data) { - err_info = &err_node->err_info; - mcm_info = &err_info->mcm_info; - RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " - "%lld correctable hardware errors detected in total in %s block\n", - mcm_info->socket_id, mcm_info->die_id, - err_info->ce_count, blk_name); - } + for_each_ras_error(err_node, &ras_mgr->err_data) { + err_info = &err_node->err_info; + mcm_info = &err_info->mcm_info; + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " + "%lld correctable hardware errors detected in total in %s block\n", + mcm_info->socket_id, mcm_info->die_id, + err_info->ce_count, blk_name); } } } @@ -1235,8 +1210,7 @@ static void amdgpu_ras_error_generate_report(struct amdgpu_device *adev, if (err_data->ce_count) { if (err_data_has_source_info(err_data)) { - amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx, - blk_name, false, false); + amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx, blk_name, false); } else if (!adev->aid_mask && adev->smuio.funcs && adev->smuio.funcs->get_socket_id && @@ -1258,8 +1232,7 @@ static void amdgpu_ras_error_generate_report(struct amdgpu_device *adev, if (err_data->ue_count) { if (err_data_has_source_info(err_data)) { - amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx, - blk_name, true, false); + amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx, blk_name, true); } else if (!adev->aid_mask && adev->smuio.funcs && adev->smuio.funcs->get_socket_id && @@ -1278,29 +1251,6 @@ static void amdgpu_ras_error_generate_report(struct amdgpu_device *adev, blk_name); } } - - if (err_data->de_count) { - if (err_data_has_source_info(err_data)) { - amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx, - blk_name, false, true); - } else if (!adev->aid_mask && - adev->smuio.funcs && - adev->smuio.funcs->get_socket_id && - adev->smuio.funcs->get_die_id) { - RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d " - "%ld deferred hardware errors " - "detected in %s block\n", - adev->smuio.funcs->get_socket_id(adev), - adev->smuio.funcs->get_die_id(adev), - ras_mgr->err_data.de_count, - blk_name); - } else { - RAS_EVENT_LOG(adev, event_id, "%ld deferred hardware errors " - "detected in %s block\n", - ras_mgr->err_data.de_count, - blk_name); - } - } } static void amdgpu_ras_virt_error_generate_report(struct amdgpu_device *adev, @@ -1347,8 +1297,7 @@ static void amdgpu_rasmgr_error_data_statistic_update(struct ras_manager *obj, s if (err_data_has_source_info(err_data)) { for_each_ras_error(err_node, err_data) { err_info = &err_node->err_info; - amdgpu_ras_error_statistic_de_count(&obj->err_data, - &err_info->mcm_info, err_info->de_count); + amdgpu_ras_error_statistic_ce_count(&obj->err_data, &err_info->mcm_info, err_info->ce_count); amdgpu_ras_error_statistic_ue_count(&obj->err_data, @@ -1358,7 +1307,6 @@ static void amdgpu_rasmgr_error_data_statistic_update(struct ras_manager *obj, s /* for legacy asic path which doesn't has error source info */ obj->err_data.ue_count += err_data->ue_count; obj->err_data.ce_count += err_data->ce_count; - obj->err_data.de_count += err_data->de_count; } } @@ -1466,7 +1414,6 @@ static int amdgpu_ras_query_error_status_with_event(struct amdgpu_device *adev, info->ue_count = obj->err_data.ue_count; info->ce_count = obj->err_data.ce_count; - info->de_count = obj->err_data.de_count; out_fini_err_data: amdgpu_ras_error_data_fini(&err_data); @@ -2385,7 +2332,6 @@ static void amdgpu_ras_interrupt_umc_handler(struct ras_manager *obj, */ obj->err_data.ue_count += err_data.ue_count; obj->err_data.ce_count += err_data.ce_count; - obj->err_data.de_count += err_data.de_count; } amdgpu_ras_error_data_fini(&err_data); @@ -4773,28 +4719,6 @@ int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data, return 0; } -int amdgpu_ras_error_statistic_de_count(struct ras_err_data *err_data, - struct amdgpu_smuio_mcm_config_info *mcm_info, - u64 count) -{ - struct ras_err_info *err_info; - - if (!err_data || !mcm_info) - return -EINVAL; - - if (!count) - return 0; - - err_info = amdgpu_ras_error_get_info(err_data, mcm_info); - if (!err_info) - return -EINVAL; - - err_info->de_count += count; - err_data->de_count += count; - - return 0; -} - #define mmMP0_SMN_C2PMSG_92 0x1609C #define mmMP0_SMN_C2PMSG_126 0x160BE static void amdgpu_ras_boot_time_error_reporting(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 739da6e1d495..23bff7a0f35b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -950,9 +950,6 @@ int amdgpu_ras_error_statistic_ce_count(struct ras_err_data *err_data, int amdgpu_ras_error_statistic_ue_count(struct ras_err_data *err_data, struct amdgpu_smuio_mcm_config_info *mcm_info, u64 count); -int amdgpu_ras_error_statistic_de_count(struct ras_err_data *err_data, - struct amdgpu_smuio_mcm_config_info *mcm_info, - u64 count); void amdgpu_ras_query_boot_status(struct amdgpu_device *adev, u32 num_instances); void amdgpu_ras_set_fed(struct amdgpu_device *adev, bool status); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 33b02f794095..a98a6cfd4fba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -260,7 +260,6 @@ int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev, if (ret == AMDGPU_RAS_SUCCESS && obj) { obj->err_data.ue_count += err_data.ue_count; obj->err_data.ce_count += err_data.ce_count; - obj->err_data.de_count += err_data.de_count; } amdgpu_ras_error_data_fini(&err_data); diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c index d3eeaead7ca2..99d19de42525 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c @@ -28,30 +28,8 @@ #include "umc/umc_12_0_0_sh_mask.h" #include "mp/mp_13_0_6_sh_mask.h" -bool umc_v12_0_is_deferred_error(struct amdgpu_device *adev, uint64_t mc_umc_status) -{ - dev_dbg(adev->dev, - "MCA_UMC_STATUS(0x%llx): Val:%llu, Poison:%llu, Deferred:%llu, PCC:%llu, UC:%llu, TCC:%llu\n", - mc_umc_status, - REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val), - REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Poison), - REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred), - REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC), - REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC), - REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) - ); - - return (amdgpu_ras_is_poison_mode_supported(adev) && - (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && - ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1) || - (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Poison) == 1))); -} - bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_umc_status) { - if (umc_v12_0_is_deferred_error(adev, mc_umc_status)) - return false; - return ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 || REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 || @@ -60,9 +38,6 @@ bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_um bool umc_v12_0_is_correctable_error(struct amdgpu_device *adev, uint64_t mc_umc_status) { - if (umc_v12_0_is_deferred_error(adev, mc_umc_status)) - return false; - return (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1 || (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 && diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h index 9d9e84d8d3bb..906dc7fa1008 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h @@ -66,12 +66,9 @@ (((REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdLo) & 0x1) << 2) | \ (REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdHi) & 0x03)) -bool umc_v12_0_is_deferred_error(struct amdgpu_device *adev, uint64_t mc_umc_status); bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_umc_status); bool umc_v12_0_is_correctable_error(struct amdgpu_device *adev, uint64_t mc_umc_status); -typedef bool (*check_error_type_func)(struct amdgpu_device *adev, uint64_t mc_umc_status); - extern struct amdgpu_umc_ras umc_v12_0_ras; #endif From 873a8d6b3c0a386408c891e4ff1c684fa11783e1 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 25 Jun 2026 17:48:22 +0800 Subject: [PATCH 18/51] drm/amd/amdgpu: disable ASPM on VI if pcie dpm is disabled Disable ASPM on VI if PCIE dpm is disabled. Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5370 Signed-off-by: Kenneth Feng Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 78c96c7102e4..631c49f568db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1334,7 +1334,8 @@ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev) * It's unclear if this is a platform-specific or GPU-specific issue. * Disable ASPM on SI for the time being. */ - if (adev->family == AMDGPU_FAMILY_SI) + if (adev->family == AMDGPU_FAMILY_SI || + (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK) && adev->family == AMDGPU_FAMILY_VI)) return true; #if IS_ENABLED(CONFIG_X86) From 8396b9de4198a54ec4760a94a179347540a9764d Mon Sep 17 00:00:00 2001 From: Jesse Zhang Date: Wed, 1 Jul 2026 18:17:03 +0800 Subject: [PATCH 19/51] drm/amdgpu: trigger GPU recovery when userq destroy fails to unmap a hung queue Destroying a hung user queue issues a MES REMOVE_QUEUE that times out, The destroy path only logged the error and freed the queue, so the next userq submission failed and forced a GPU reset attributed to an innocent workload. Kick the userq reset work when unmap fails so the GPU is recovered at destroy time. Acked-by: Alex Deucher Signed-off-by: Jesse Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index 82c8809d1d9c..9cc71a3a5362 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -540,6 +540,15 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que amdgpu_userq_cleanup(queue); mutex_unlock(&uq_mgr->userq_mutex); + /* + * A failed unmap means MES could not remove the hung queue and is now + * unresponsive. Recover the GPU here so the wedged MES does not fail + * the next, unrelated queue submission and trigger a reset attributed + * to an innocent workload. + */ + if (r) + queue_work(adev->reset_domain->wq, &uq_mgr->reset_work); + cancel_delayed_work_sync(&queue->hang_detect_work); uq_funcs->mqd_destroy(queue); queue->userq_mgr = NULL; From 679c6f09d9d58e0debec19ab46bf28e48bf76788 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Fri, 3 Jul 2026 18:18:26 +0530 Subject: [PATCH 20/51] drm/amdgpu/mes12: Remove MES self test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MES self test is no longer needed. Other MES versions already dropped their self tests since IGT now covers this functionality. Remove the MES v12 self test as well. Cc: Alex Deucher Suggested-by: Christian König Signed-off-by: Srinivasan Shanmugam Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mes_v12_1.c | 334 +------------------------ 1 file changed, 1 insertion(+), 333 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c index f7d5879c6e44..e7d7160f8fc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c @@ -43,7 +43,6 @@ static int mes_v12_1_xcc_hw_init(struct amdgpu_ip_block *ip_block, int xcc_id); static int mes_v12_1_hw_fini(struct amdgpu_ip_block *ip_block); static int mes_v12_1_kiq_hw_init(struct amdgpu_device *adev, uint32_t xcc_id); static int mes_v12_1_kiq_hw_fini(struct amdgpu_device *adev, uint32_t xcc_id); -static int mes_v12_1_self_test(struct amdgpu_device *adev, int xcc_id); static int mes_v12_1_setup_coop_mode(struct amdgpu_device *adev, int xcc_id); #define MES_EOP_SIZE 2048 @@ -1994,31 +1993,10 @@ static int mes_v12_1_early_init(struct amdgpu_ip_block *ip_block) return 0; } -static int mes_v12_1_late_init(struct amdgpu_ip_block *ip_block) -{ - struct amdgpu_device *adev = ip_block->adev; - int xcc_id, num_xcc = NUM_XCC(adev->gfx.xcc_mask); - - /* TODO: remove it if issue fixed. */ - if (adev->mes.enable_coop_mode) - return 0; - - for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) { - /* for COOP mode, only test master xcc. */ - if (adev->mes.enable_coop_mode && - adev->mes.master_xcc_ids[xcc_id] != xcc_id) - continue; - - mes_v12_1_self_test(adev, xcc_id); - } - - return 0; -} - static const struct amd_ip_funcs mes_v12_1_ip_funcs = { .name = "mes_v12_1", .early_init = mes_v12_1_early_init, - .late_init = mes_v12_1_late_init, + .late_init = NULL, .sw_init = mes_v12_1_sw_init, .sw_fini = mes_v12_1_sw_fini, .hw_init = mes_v12_1_hw_init, @@ -2034,313 +2012,3 @@ const struct amdgpu_ip_block_version mes_v12_1_ip_block = { .rev = 0, .funcs = &mes_v12_1_ip_funcs, }; - -static int mes_v12_1_alloc_test_buf(struct amdgpu_device *adev, - struct amdgpu_bo **bo, uint64_t *addr, - void **ptr, int size) -{ - amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, - bo, addr, ptr); - if (!*bo) { - dev_err(adev->dev, "failed to allocate test buffer bo\n"); - return -ENOMEM; - } - memset(*ptr, 0, size); - return 0; -} - -static int mes_v12_1_map_test_bo(struct amdgpu_device *adev, - struct amdgpu_bo *bo, struct amdgpu_vm *vm, - struct amdgpu_bo_va **bo_va, u64 va, int size) -{ - struct amdgpu_sync sync; - int r; - - r = amdgpu_map_static_csa(adev, vm, bo, bo_va, va, size); - if (r) - return r; - - amdgpu_sync_create(&sync); - - r = amdgpu_vm_bo_update(adev, *bo_va, false); - if (r) { - dev_err(adev->dev, "failed to do vm_bo_update on meta data\n"); - goto error; - } - amdgpu_sync_fence(&sync, (*bo_va)->last_pt_update, GFP_KERNEL); - - r = amdgpu_vm_update_pdes(adev, vm, false); - if (r) { - dev_err(adev->dev, "failed to update pdes on meta data\n"); - goto error; - } - amdgpu_sync_fence(&sync, vm->last_update, GFP_KERNEL); - amdgpu_sync_wait(&sync, false); - -error: - amdgpu_sync_free(&sync); - return r; -} - -static int mes_v12_1_test_ring(struct amdgpu_device *adev, int xcc_id, - u32 *queue_ptr, u64 fence_gpu_addr, - void *fence_cpu_ptr, void *wptr_cpu_addr, - u64 doorbell_idx, int queue_type) -{ - volatile uint32_t *cpu_ptr = fence_cpu_ptr; - int num_xcc = NUM_XCC(adev->gfx.xcc_mask); - int sdma_ring_align = 0x10, compute_ring_align = 0x100; - uint32_t tmp, xcc_offset; - int r = 0, i, j, wptr = 0; - - if (queue_type == AMDGPU_RING_TYPE_COMPUTE) { - if (!adev->mes.enable_coop_mode) { - WREG32_SOC15(GC, GET_INST(GC, xcc_id), - regSCRATCH_REG0, 0xCAFEDEAD); - } else { - for (i = 0; i < num_xcc; i++) { - if (adev->mes.master_xcc_ids[i] == xcc_id) - WREG32_SOC15(GC, GET_INST(GC, i), - regSCRATCH_REG0, 0xCAFEDEAD); - } - } - - xcc_offset = SOC15_REG_OFFSET(GC, 0, regSCRATCH_REG0); - queue_ptr[wptr++] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); - queue_ptr[wptr++] = xcc_offset - PACKET3_SET_UCONFIG_REG_START; - queue_ptr[wptr++] = 0xDEADBEEF; - - for (i = wptr; i < compute_ring_align; i++) - queue_ptr[wptr++] = PACKET3(PACKET3_NOP, 0x3FFF); - - } else if (queue_type == AMDGPU_RING_TYPE_SDMA) { - *cpu_ptr = 0xCAFEDEAD; - - queue_ptr[wptr++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_WRITE) | - SDMA_PKT_COPY_LINEAR_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR); - queue_ptr[wptr++] = lower_32_bits(fence_gpu_addr); - queue_ptr[wptr++] = upper_32_bits(fence_gpu_addr); - queue_ptr[wptr++] = SDMA_PKT_WRITE_UNTILED_DW_3_COUNT(0); - queue_ptr[wptr++] = 0xDEADBEEF; - - for (i = wptr; i < sdma_ring_align; i++) - queue_ptr[wptr++] = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP); - - wptr <<= 2; - } - - atomic64_set((atomic64_t *)wptr_cpu_addr, wptr); - WDOORBELL64(doorbell_idx, wptr); - - for (i = 0; i < adev->usec_timeout; i++) { - if (queue_type == AMDGPU_RING_TYPE_SDMA) { - tmp = le32_to_cpu(*cpu_ptr); - } else { - if (!adev->mes.enable_coop_mode) { - tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id), - regSCRATCH_REG0); - } else { - for (j = 0; j < num_xcc; j++) { - if (xcc_id != adev->mes.master_xcc_ids[j]) - continue; - - tmp = RREG32_SOC15(GC, GET_INST(GC, j), - regSCRATCH_REG0); - if (tmp != 0xDEADBEEF) - break; - } - } - } - - if (tmp == 0xDEADBEEF) - break; - - if (amdgpu_emu_mode == 1) - msleep(1); - else - udelay(1); - } - - if (i >= adev->usec_timeout) { - dev_err(adev->dev, "xcc%d: mes self test (%s) failed\n", xcc_id, - queue_type == AMDGPU_RING_TYPE_SDMA ? "sdma" : "compute"); - - while (halt_if_hws_hang) - schedule(); - - r = -ETIMEDOUT; - } else { - dev_info(adev->dev, "xcc%d: mes self test (%s) pass\n", xcc_id, - queue_type == AMDGPU_RING_TYPE_SDMA ? "sdma" : "compute"); - } - - return r; -} - -#define USER_CTX_SIZE (PAGE_SIZE * 2) -#define USER_CTX_VA AMDGPU_VA_RESERVED_BOTTOM -#define RING_OFFSET(addr) ((addr)) -#define EOP_OFFSET(addr) ((addr) + PAGE_SIZE) -#define WPTR_OFFSET(addr) ((addr) + USER_CTX_SIZE - sizeof(u64)) -#define RPTR_OFFSET(addr) ((addr) + USER_CTX_SIZE - sizeof(u64) * 2) -#define FENCE_OFFSET(addr) ((addr) + USER_CTX_SIZE - sizeof(u64) * 3) - -static int mes_v12_1_test_queue(struct amdgpu_device *adev, int xcc_id, - int pasid, struct amdgpu_vm *vm, u64 meta_gpu_addr, - u64 queue_gpu_addr, void *ctx_ptr, int queue_type) -{ - struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)]; - struct amdgpu_mqd *mqd_mgr = &adev->mqds[queue_type]; - struct amdgpu_mqd_prop mqd_prop = {0}; - struct mes_add_queue_input add_queue = {0}; - struct mes_remove_queue_input remove_queue = {0}; - struct amdgpu_bo *mqd_bo = NULL; - int num_xcc = NUM_XCC(adev->gfx.xcc_mask); - int i, r, off, mqd_size, mqd_count = 1; - void *mqd_ptr = NULL; - u64 mqd_gpu_addr, doorbell_idx; - - /* extra one page size padding for mes fw */ - mqd_size = mqd_mgr->mqd_size + PAGE_SIZE; - - if (queue_type == AMDGPU_RING_TYPE_SDMA) { - doorbell_idx = adev->mes.db_start_dw_offset + \ - adev->doorbell_index.sdma_engine[0]; - } else { - doorbell_idx = adev->mes.db_start_dw_offset + \ - adev->doorbell_index.userqueue_start; - } - - if (adev->mes.enable_coop_mode && - queue_type == AMDGPU_RING_TYPE_COMPUTE) { - for (i = 0, mqd_count = 0; i < num_xcc; i++) { - if (adev->mes.master_xcc_ids[i] == xcc_id) - mqd_count++; - } - mqd_size *= mqd_count; - } - - r = mes_v12_1_alloc_test_buf(adev, &mqd_bo, &mqd_gpu_addr, - &mqd_ptr, mqd_size * mqd_count); - if (r < 0) - return r; - - mqd_prop.mqd_gpu_addr = mqd_gpu_addr; - mqd_prop.hqd_base_gpu_addr = RING_OFFSET(USER_CTX_VA); - mqd_prop.eop_gpu_addr = EOP_OFFSET(USER_CTX_VA); - mqd_prop.wptr_gpu_addr = WPTR_OFFSET(USER_CTX_VA); - mqd_prop.rptr_gpu_addr = RPTR_OFFSET(USER_CTX_VA); - mqd_prop.doorbell_index = doorbell_idx; - mqd_prop.queue_size = PAGE_SIZE; - mqd_prop.mqd_stride_size = mqd_size; - mqd_prop.use_doorbell = true; - mqd_prop.hqd_active = false; - - mqd_mgr->init_mqd(adev, mqd_ptr, &mqd_prop); - if (mqd_count > 1) { - for (i = 1; i < mqd_count; i++) { - off = mqd_size * i; - mqd_prop.mqd_gpu_addr = mqd_gpu_addr + off; - mqd_mgr->init_mqd(adev, (char *)mqd_ptr + off, - &mqd_prop); - } - } - - add_queue.xcc_id = xcc_id; - add_queue.process_id = pasid; - add_queue.page_table_base_addr = adev->vm_manager.vram_base_offset + - amdgpu_bo_gpu_offset(vm->root.bo) - adev->gmc.vram_start; - add_queue.process_va_start = 0; - add_queue.process_va_end = adev->vm_manager.max_pfn - 1; - add_queue.process_context_addr = meta_gpu_addr; - add_queue.gang_context_addr = meta_gpu_addr + AMDGPU_MES_PROC_CTX_SIZE; - add_queue.doorbell_offset = doorbell_idx; - add_queue.mqd_addr = mqd_gpu_addr; - add_queue.wptr_addr = mqd_prop.wptr_gpu_addr; - add_queue.wptr_mc_addr = WPTR_OFFSET(queue_gpu_addr); - add_queue.queue_type = queue_type; - add_queue.vm_cntx_cntl = hub->vm_cntx_cntl; - - r = mes_v12_1_add_hw_queue(&adev->mes, &add_queue); - if (r) - goto error; - - mes_v12_1_test_ring(adev, xcc_id, (u32 *)RING_OFFSET((char *)ctx_ptr), - FENCE_OFFSET(USER_CTX_VA), - FENCE_OFFSET((char *)ctx_ptr), - WPTR_OFFSET((char *)ctx_ptr), - doorbell_idx, queue_type); - - remove_queue.xcc_id = xcc_id; - remove_queue.doorbell_offset = doorbell_idx; - remove_queue.gang_context_addr = add_queue.gang_context_addr; - remove_queue.queue_type = queue_type; - r = mes_v12_1_remove_hw_queue(&adev->mes, &remove_queue); - -error: - amdgpu_bo_free_kernel(&mqd_bo, &mqd_gpu_addr, &mqd_ptr); - return r; -} - -static int mes_v12_1_self_test(struct amdgpu_device *adev, int xcc_id) -{ - int queue_types[] = { AMDGPU_RING_TYPE_COMPUTE, - /* AMDGPU_RING_TYPE_SDMA */ }; - struct amdgpu_bo_va *bo_va = NULL; - struct amdgpu_vm *vm = NULL; - struct amdgpu_bo *meta_bo = NULL, *ctx_bo = NULL; - void *meta_ptr = NULL, *ctx_ptr = NULL; - u64 meta_gpu_addr, ctx_gpu_addr; - int size, i, r, pasid; - - pasid = amdgpu_pasid_alloc(16); - if (pasid < 0) - pasid = 0; - - size = AMDGPU_MES_PROC_CTX_SIZE + AMDGPU_MES_GANG_CTX_SIZE; - r = mes_v12_1_alloc_test_buf(adev, &meta_bo, &meta_gpu_addr, - &meta_ptr, size); - if (r < 0) - goto err2; - - r = mes_v12_1_alloc_test_buf(adev, &ctx_bo, &ctx_gpu_addr, - &ctx_ptr, USER_CTX_SIZE); - if (r < 0) - goto err2; - - vm = kzalloc(sizeof(*vm), GFP_KERNEL); - if (!vm) { - r = -ENOMEM; - goto err2; - } - - r = amdgpu_vm_init(adev, vm, -1, pasid); - if (r) - goto err1; - - r = mes_v12_1_map_test_bo(adev, ctx_bo, vm, &bo_va, - USER_CTX_VA, USER_CTX_SIZE); - if (r) - goto err0; - - for (i = 0; i < ARRAY_SIZE(queue_types); i++) { - memset(ctx_ptr, 0, USER_CTX_SIZE); - - r = mes_v12_1_test_queue(adev, xcc_id, pasid, vm, meta_gpu_addr, - ctx_gpu_addr, ctx_ptr, queue_types[i]); - if (r) - break; - } - - amdgpu_unmap_static_csa(adev, vm, ctx_bo, bo_va, USER_CTX_VA); -err0: - amdgpu_vm_fini(adev, vm); -err1: - kfree(vm); -err2: - amdgpu_bo_free_kernel(&meta_bo, &meta_gpu_addr, &meta_ptr); - amdgpu_bo_free_kernel(&ctx_bo, &ctx_gpu_addr, &ctx_ptr); - amdgpu_pasid_free(pasid); - return r; -} - From fbf41e05119f43e9d69307272ced4ed3b82ad371 Mon Sep 17 00:00:00 2001 From: Shahyan Soltani Date: Wed, 3 Jun 2026 09:23:04 -0400 Subject: [PATCH 21/51] drm/amdgpu: move struct amdgpu_wb and helpers into separate files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move struct amdgpu_wb and helpers out of the monolithic header amdgpu.h into its own dedicated header amdgpu_wb.h. Add amdgpu_wb_init() and amdgpu_wb_fini() into amdgpu_wb.h. Move functions amdgpu_device_wb_get(), amdgpu_device_wb_free(), amdgpu_device_wb_init(), and amdgpu_device_wb_fini() out of amdgpu_device.c into new dedicated amdgpu_wb.c file. Removed static from functions amdgpu_device_wb_init() and amdgpu_device_wb_fini(). Rename functions amdgpu_device_wb_get(), amdgpu_device_wb_free(), amdgpu_device_wb_init(), and amdgpu_device_wb_fini() into amdgpu_wb_get(), amdgpu_wb_free(), amdgpu_wb_init(), and amdgpu_wb_fini(). Update amdgpu/Makefile to build amdgpu_wb.o. This is part of the ongoing effort to reduce the size of amdgpu.h into their own respective separate headers. Signed-off-by: Shahyan Soltani Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 68 +--------- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 110 +--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 16 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 18 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_wb.c | 129 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_wb.h | 102 +++++++++++++++ drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 8 +- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c | 4 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 4 +- drivers/gpu/drm/amd/amdgpu/mes_userqueue.c | 4 +- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/mes_v12_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/mes_v12_1.c | 6 +- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 8 +- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 8 +- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 8 +- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 8 +- drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 10 +- drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c | 10 +- drivers/gpu/drm/amd/amdgpu/si_dma.c | 8 +- 33 files changed, 349 insertions(+), 285 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_wb.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_wb.h diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 5100e35027ec..105b9dcc19a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -71,7 +71,8 @@ amdgpu-y += amdgpu_device.o amdgpu_reg_access.o amdgpu_doorbell_mgr.o amdgpu_kms amdgpu_fw_attestation.o amdgpu_securedisplay.o \ amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o amdgpu_lockdep.o \ amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_dev_coredump.o \ - amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o amdgpu_ip.o + amdgpu_cper.o amdgpu_userq_fence.o amdgpu_eviction_fence.o amdgpu_ip.o \ + amdgpu_wb.o amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index dd8ea71077af..ccf187d0b706 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -112,6 +112,7 @@ #include "amdgpu_reg_state.h" #include "amdgpu_userq.h" #include "amdgpu_eviction_fence.h" +#include "amdgpu_wb.h" #include "amdgpu_ip.h" #include "amdgpu_sa.h" #if defined(CONFIG_DRM_AMD_ISP) @@ -429,73 +430,6 @@ struct amdgpu_fpriv { int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv); -/* - * Writeback - */ -#define AMDGPU_MAX_WB 1024 /* Reserve at most 1024 WB slots for amdgpu-owned rings. */ - -/** - * struct amdgpu_wb - This struct is used for small GPU memory allocation. - * - * This struct is used to allocate a small amount of GPU memory that can be - * used to shadow certain states into the memory. This is especially useful for - * providing easy CPU access to some states without requiring register access - * (e.g., if some block is power gated, reading register may be problematic). - * - * Note: the term writeback was initially used because many of the amdgpu - * components had some level of writeback memory, and this struct initially - * described those components. - */ -struct amdgpu_wb { - - /** - * @wb_obj: - * - * Buffer Object used for the writeback memory. - */ - struct amdgpu_bo *wb_obj; - - /** - * @wb: - * - * Pointer to the first writeback slot. In terms of CPU address - * this value can be accessed directly by using the offset as an index. - * For the GPU address, it is necessary to use gpu_addr and the offset. - */ - uint32_t *wb; - - /** - * @gpu_addr: - * - * Writeback base address in the GPU. - */ - uint64_t gpu_addr; - - /** - * @num_wb: - * - * Number of writeback slots reserved for amdgpu. - */ - u32 num_wb; - - /** - * @used: - * - * Track the writeback slot already used. - */ - unsigned long used[DIV_ROUND_UP(AMDGPU_MAX_WB, BITS_PER_LONG)]; - - /** - * @lock: - * - * Protects read and write of the used field array. - */ - spinlock_t lock; -}; - -int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb); -void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb); - /* * Benchmarking */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 631c49f568db..b39ec5ed6242 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -72,6 +72,7 @@ #include "amdgpu_xgmi.h" #include "amdgpu_ras.h" +#include "amdgpu_wb.h" #include "amdgpu_ras_mgr.h" #include "amdgpu_pmu.h" #include "amdgpu_smu.h" @@ -1006,109 +1007,6 @@ int amdgpu_device_pci_reset(struct amdgpu_device *adev) return pci_reset_function(adev->pdev); } -/* - * amdgpu_device_wb_*() - * Writeback is the method by which the GPU updates special pages in memory - * with the status of certain GPU events (fences, ring pointers,etc.). - */ - -/** - * amdgpu_device_wb_fini - Disable Writeback and free memory - * - * @adev: amdgpu_device pointer - * - * Disables Writeback and frees the Writeback memory (all asics). - * Used at driver shutdown. - */ -static void amdgpu_device_wb_fini(struct amdgpu_device *adev) -{ - if (adev->wb.wb_obj) { - amdgpu_bo_free_kernel(&adev->wb.wb_obj, - &adev->wb.gpu_addr, - (void **)&adev->wb.wb); - adev->wb.wb_obj = NULL; - } -} - -/** - * amdgpu_device_wb_init - Init Writeback driver info and allocate memory - * - * @adev: amdgpu_device pointer - * - * Initializes writeback and allocates writeback memory (all asics). - * Used at driver startup. - * Returns 0 on success or an -error on failure. - */ -static int amdgpu_device_wb_init(struct amdgpu_device *adev) -{ - int r; - - if (adev->wb.wb_obj == NULL) { - /* AMDGPU_MAX_WB * sizeof(uint32_t) * 8 = AMDGPU_MAX_WB 256bit slots */ - r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t) * 8, - PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, - &adev->wb.wb_obj, &adev->wb.gpu_addr, - (void **)&adev->wb.wb); - if (r) { - dev_warn(adev->dev, "(%d) create WB bo failed\n", r); - return r; - } - - adev->wb.num_wb = AMDGPU_MAX_WB; - memset(&adev->wb.used, 0, sizeof(adev->wb.used)); - - /* clear wb memory */ - memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8); - } - - return 0; -} - -/** - * amdgpu_device_wb_get - Allocate a wb entry - * - * @adev: amdgpu_device pointer - * @wb: wb index - * - * Allocate a wb slot for use by the driver (all asics). - * Returns 0 on success or -EINVAL on failure. - */ -int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb) -{ - unsigned long flags, offset; - - spin_lock_irqsave(&adev->wb.lock, flags); - offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb); - if (offset < adev->wb.num_wb) { - __set_bit(offset, adev->wb.used); - spin_unlock_irqrestore(&adev->wb.lock, flags); - *wb = offset << 3; /* convert to dw offset */ - return 0; - } else { - spin_unlock_irqrestore(&adev->wb.lock, flags); - return -EINVAL; - } -} - -/** - * amdgpu_device_wb_free - Free a wb entry - * - * @adev: amdgpu_device pointer - * @wb: wb index - * - * Free a wb slot allocated for use by the driver (all asics) - */ -void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb) -{ - unsigned long flags; - - wb >>= 3; - spin_lock_irqsave(&adev->wb.lock, flags); - if (wb < adev->wb.num_wb) - __clear_bit(wb, adev->wb.used); - spin_unlock_irqrestore(&adev->wb.lock, flags); -} - /** * amdgpu_device_resize_fb_bar - try to resize FB BAR * @@ -2374,10 +2272,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) r); goto init_failed; } - r = amdgpu_device_wb_init(adev); + r = amdgpu_wb_init(adev); if (r) { dev_err(adev->dev, - "amdgpu_device_wb_init failed %d\n", r); + "amdgpu_wb_init failed %d\n", r); goto init_failed; } adev->ip_blocks[i].status.hw = true; @@ -2909,7 +2807,7 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) { amdgpu_ucode_free_bo(adev); amdgpu_free_static_csa(&adev->virt.csa_obj); - amdgpu_device_wb_fini(adev); + amdgpu_wb_fini(adev); amdgpu_device_mem_scratch_fini(adev); amdgpu_ib_pool_fini(adev); amdgpu_seq64_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 96c9d4f00b27..1e275c2e7dd3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -1170,7 +1170,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_ BUG_ON(!ring->funcs->emit_rreg); spin_lock_irqsave(&kiq->ring_lock, flags); - if (amdgpu_device_wb_get(adev, ®_val_offs)) { + if (amdgpu_wb_get(adev, ®_val_offs)) { pr_err("critical bug! too many kiq readers\n"); goto failed_unlock; } @@ -1213,7 +1213,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_ mb(); value = adev->wb.wb[reg_val_offs]; - amdgpu_device_wb_free(adev, reg_val_offs); + amdgpu_wb_free(adev, reg_val_offs); return value; failed_undo: @@ -1222,7 +1222,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg, uint32_t xcc_ spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq_read: if (reg_val_offs) - amdgpu_device_wb_free(adev, reg_val_offs); + amdgpu_wb_free(adev, reg_val_offs); dev_err(adev->dev, "failed to read reg:%x\n", reg); return ~0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c index a6419246e9c2..c2a10b41804a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c @@ -75,13 +75,13 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih, } else { unsigned wptr_offs, rptr_offs; - r = amdgpu_device_wb_get(adev, &wptr_offs); + r = amdgpu_wb_get(adev, &wptr_offs); if (r) return r; - r = amdgpu_device_wb_get(adev, &rptr_offs); + r = amdgpu_wb_get(adev, &rptr_offs); if (r) { - amdgpu_device_wb_free(adev, wptr_offs); + amdgpu_wb_free(adev, wptr_offs); return r; } @@ -90,8 +90,8 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih, &ih->ring_obj, &ih->gpu_addr, (void **)&ih->ring); if (r) { - amdgpu_device_wb_free(adev, rptr_offs); - amdgpu_device_wb_free(adev, wptr_offs); + amdgpu_wb_free(adev, rptr_offs); + amdgpu_wb_free(adev, wptr_offs); return r; } @@ -131,8 +131,8 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih) } else { amdgpu_bo_free_kernel(&ih->ring_obj, &ih->gpu_addr, (void **)&ih->ring); - amdgpu_device_wb_free(adev, (ih->wptr_addr - ih->gpu_addr) / 4); - amdgpu_device_wb_free(adev, (ih->rptr_addr - ih->gpu_addr) / 4); + amdgpu_wb_free(adev, (ih->wptr_addr - ih->gpu_addr) / 4); + amdgpu_wb_free(adev, (ih->rptr_addr - ih->gpu_addr) / 4); } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index c2b9479f4ca6..c66e69b62361 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -183,7 +183,7 @@ int amdgpu_mes_init(struct amdgpu_device *adev) adev->mes.sdma_hqd_mask[0]); for (i = 0; i < AMDGPU_MAX_MES_PIPES * num_xcc; i++) { - r = amdgpu_device_wb_get(adev, &adev->mes.sch_ctx_offs[i]); + r = amdgpu_wb_get(adev, &adev->mes.sch_ctx_offs[i]); if (r) { dev_err(adev->dev, "(%d) ring trail_fence_offs wb alloc failed\n", @@ -195,7 +195,7 @@ int amdgpu_mes_init(struct amdgpu_device *adev) adev->mes.sch_ctx_ptr[i] = (uint64_t *)&adev->wb.wb[adev->mes.sch_ctx_offs[i]]; - r = amdgpu_device_wb_get(adev, + r = amdgpu_wb_get(adev, &adev->mes.query_status_fence_offs[i]); if (r) { dev_err(adev->dev, @@ -268,9 +268,9 @@ int amdgpu_mes_init(struct amdgpu_device *adev) error: for (i = 0; i < AMDGPU_MAX_MES_PIPES * num_xcc; i++) { if (adev->mes.sch_ctx_ptr[i]) - amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs[i]); + amdgpu_wb_free(adev, adev->mes.sch_ctx_offs[i]); if (adev->mes.query_status_fence_ptr[i]) - amdgpu_device_wb_free(adev, + amdgpu_wb_free(adev, adev->mes.query_status_fence_offs[i]); if (adev->mes.hung_queue_db_array_gpu_obj[i]) amdgpu_bo_free_kernel(&adev->mes.hung_queue_db_array_gpu_obj[i], @@ -300,9 +300,9 @@ void amdgpu_mes_fini(struct amdgpu_device *adev) &adev->mes.hung_queue_db_array_gpu_addr[i], &adev->mes.hung_queue_db_array_cpu_addr[i]); if (adev->mes.sch_ctx_ptr[i]) - amdgpu_device_wb_free(adev, adev->mes.sch_ctx_offs[i]); + amdgpu_wb_free(adev, adev->mes.sch_ctx_offs[i]); if (adev->mes.query_status_fence_ptr[i]) - amdgpu_device_wb_free(adev, + amdgpu_wb_free(adev, adev->mes.query_status_fence_offs[i]); } @@ -572,7 +572,7 @@ uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg, uint64_t read_val_gpu_addr; uint32_t *read_val_ptr; - if (amdgpu_device_wb_get(adev, &addr_offset)) { + if (amdgpu_wb_get(adev, &addr_offset)) { dev_err(adev->dev, "critical bug! too many mes readers\n"); goto error; } @@ -598,7 +598,7 @@ uint32_t amdgpu_mes_rreg(struct amdgpu_device *adev, uint32_t reg, error: if (addr_offset) - amdgpu_device_wb_free(adev, addr_offset); + amdgpu_wb_free(adev, addr_offset); return val; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 4d417c4a5cd2..0d34f0eca991 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -264,31 +264,31 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, return r; } - r = amdgpu_device_wb_get(adev, &ring->rptr_offs); + r = amdgpu_wb_get(adev, &ring->rptr_offs); if (r) { dev_err(adev->dev, "(%d) ring rptr_offs wb alloc failed\n", r); return r; } - r = amdgpu_device_wb_get(adev, &ring->wptr_offs); + r = amdgpu_wb_get(adev, &ring->wptr_offs); if (r) { dev_err(adev->dev, "(%d) ring wptr_offs wb alloc failed\n", r); return r; } - r = amdgpu_device_wb_get(adev, &ring->fence_offs); + r = amdgpu_wb_get(adev, &ring->fence_offs); if (r) { dev_err(adev->dev, "(%d) ring fence_offs wb alloc failed\n", r); return r; } - r = amdgpu_device_wb_get(adev, &ring->trail_fence_offs); + r = amdgpu_wb_get(adev, &ring->trail_fence_offs); if (r) { dev_err(adev->dev, "(%d) ring trail_fence_offs wb alloc failed\n", r); return r; } - r = amdgpu_device_wb_get(adev, &ring->cond_exe_offs); + r = amdgpu_wb_get(adev, &ring->cond_exe_offs); if (r) { dev_err(adev->dev, "(%d) ring cond_exec_polling wb alloc failed\n", r); return r; @@ -401,11 +401,11 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring) ring->sched.ready = false; - amdgpu_device_wb_free(ring->adev, ring->rptr_offs); - amdgpu_device_wb_free(ring->adev, ring->wptr_offs); + amdgpu_wb_free(ring->adev, ring->rptr_offs); + amdgpu_wb_free(ring->adev, ring->wptr_offs); - amdgpu_device_wb_free(ring->adev, ring->cond_exe_offs); - amdgpu_device_wb_free(ring->adev, ring->fence_offs); + amdgpu_wb_free(ring->adev, ring->cond_exe_offs); + amdgpu_wb_free(ring->adev, ring->fence_offs); amdgpu_bo_free_kernel(&ring->ring_obj, &ring->gpu_addr, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c index cd707d70a0bf..3985d56008cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c @@ -272,7 +272,7 @@ static int umsch_mm_init(struct amdgpu_device *adev) adev->umsch_mm.engine_mask = (1 << UMSCH_SWIP_ENGINE_TYPE_VPE); adev->umsch_mm.vpe_hqd_mask = 0xfe; - r = amdgpu_device_wb_get(adev, &adev->umsch_mm.wb_index); + r = amdgpu_wb_get(adev, &adev->umsch_mm.wb_index); if (r) { dev_err(adev->dev, "failed to alloc wb for umsch: %d\n", r); return r; @@ -288,7 +288,7 @@ static int umsch_mm_init(struct amdgpu_device *adev) (void **)&adev->umsch_mm.cmd_buf_ptr); if (r) { dev_err(adev->dev, "failed to allocate cmdbuf bo %d\n", r); - amdgpu_device_wb_free(adev, adev->umsch_mm.wb_index); + amdgpu_wb_free(adev, adev->umsch_mm.wb_index); return r; } @@ -380,7 +380,7 @@ static int umsch_mm_sw_fini(struct amdgpu_ip_block *ip_block) &adev->umsch_mm.log_gpu_addr, (void **)&adev->umsch_mm.log_cpu_addr); - amdgpu_device_wb_free(adev, adev->umsch_mm.wb_index); + amdgpu_wb_free(adev, adev->umsch_mm.wb_index); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c index 7bf74ff93fbd..2b45010b7ebe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c @@ -789,7 +789,7 @@ static int vpe_ring_test_ring(struct amdgpu_ring *ring) uint64_t wb_addr; int ret; - ret = amdgpu_device_wb_get(adev, &index); + ret = amdgpu_wb_get(adev, &index); if (ret) { dev_err(adev->dev, "(%d) failed to allocate wb slot\n", ret); return ret; @@ -818,7 +818,7 @@ static int vpe_ring_test_ring(struct amdgpu_ring *ring) ret = -ETIMEDOUT; out: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return ret; } @@ -833,7 +833,7 @@ static int vpe_ring_test_ib(struct amdgpu_ring *ring, long timeout) uint64_t wb_addr; int ret; - ret = amdgpu_device_wb_get(adev, &index); + ret = amdgpu_wb_get(adev, &index); if (ret) { dev_err(adev->dev, "(%d) failed to allocate wb slot\n", ret); return ret; @@ -872,7 +872,7 @@ static int vpe_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_wb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_wb.c new file mode 100644 index 000000000000..8b7061c94ccd --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_wb.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Copyright 2026 Advanced Micro Devices, Inc. + + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include + +#include "amdgpu.h" +#include "amdgpu_wb.h" + +/* + * amdgpu_wb_*() + * Writeback is the method by which the GPU updates special pages in memory + * with the status of certain GPU events (fences, ring pointers,etc.). + */ + +/** + * amdgpu_wb_fini - Disable Writeback and free memory + * + * @adev: amdgpu_device pointer + * + * Disables Writeback and frees the Writeback memory (all asics). + * Used at driver shutdown. + */ +void amdgpu_wb_fini(struct amdgpu_device *adev) +{ + if (adev->wb.wb_obj) { + amdgpu_bo_free_kernel(&adev->wb.wb_obj, + &adev->wb.gpu_addr, + (void **)&adev->wb.wb); + adev->wb.wb_obj = NULL; + } +} + +/** + * amdgpu_wb_init - Init Writeback driver info and allocate memory + * + * @adev: amdgpu_device pointer + * + * Initializes writeback and allocates writeback memory (all asics). + * Used at driver startup. + * Returns 0 on success or an -error on failure. + */ +int amdgpu_wb_init(struct amdgpu_device *adev) +{ + int r; + + if (adev->wb.wb_obj == NULL) { + /* AMDGPU_MAX_WB * sizeof(uint32_t) * 8 = AMDGPU_MAX_WB 256bit slots */ + r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t) * 8, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, + &adev->wb.wb_obj, &adev->wb.gpu_addr, + (void **)&adev->wb.wb); + if (r) { + dev_warn(adev->dev, "(%d) create WB bo failed\n", r); + return r; + } + + adev->wb.num_wb = AMDGPU_MAX_WB; + memset(&adev->wb.used, 0, sizeof(adev->wb.used)); + + /* clear wb memory */ + memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8); + } + + return 0; +} + +/** + * amdgpu_wb_get - Allocate a wb entry + * + * @adev: amdgpu_device pointer + * @wb: wb index + * + * Allocate a wb slot for use by the driver (all asics). + * Returns 0 on success or -EINVAL on failure. + */ +int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb) +{ + unsigned long flags, offset; + + spin_lock_irqsave(&adev->wb.lock, flags); + offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb); + if (offset < adev->wb.num_wb) { + __set_bit(offset, adev->wb.used); + spin_unlock_irqrestore(&adev->wb.lock, flags); + *wb = offset << 3; /* convert to dw offset */ + return 0; + } else { + spin_unlock_irqrestore(&adev->wb.lock, flags); + return -EINVAL; + } +} + +/** + * amdgpu_wb_free - Free a wb entry + * + * @adev: amdgpu_device pointer + * @wb: wb index + * + * Free a wb slot allocated for use by the driver (all asics) + */ +void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb) +{ + unsigned long flags; + + wb >>= 3; + spin_lock_irqsave(&adev->wb.lock, flags); + if (wb < adev->wb.num_wb) + __clear_bit(wb, adev->wb.used); + spin_unlock_irqrestore(&adev->wb.lock, flags); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_wb.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_wb.h new file mode 100644 index 000000000000..7b8efa6a639c --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_wb.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT + * + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __AMDGPU_WB_H__ +#define __AMDGPU_WB_H__ + +#include +#include +#include + +/* + * Writeback + */ +#define AMDGPU_MAX_WB 1024 /* Reserve at most 1024 WB slots for amdgpu-owned rings. */ + +/** + * struct amdgpu_wb - This struct is used for small GPU memory allocation. + * + * This struct is used to allocate a small amount of GPU memory that can be + * used to shadow certain states into the memory. This is especially useful for + * providing easy CPU access to some states without requiring register access + * (e.g., if some block is power gated, reading register may be problematic). + * + * Note: the term writeback was initially used because many of the amdgpu + * components had some level of writeback memory, and this struct initially + * described those components. + */ + +struct amdgpu_bo; +struct amdgpu_device; + +struct amdgpu_wb { + + /** + * @wb_obj: + * + * Buffer Object used for the writeback memory. + */ + struct amdgpu_bo *wb_obj; + + /** + * @wb: + * + * Pointer to the first writeback slot. In terms of CPU address + * this value can be accessed directly by using the offset as an index. + * For the GPU address, it is necessary to use gpu_addr and the offset. + */ + uint32_t *wb; + + /** + * @gpu_addr: + * + * Writeback base address in the GPU. + */ + uint64_t gpu_addr; + + /** + * @num_wb: + * + * Number of writeback slots reserved for amdgpu. + */ + u32 num_wb; + + /** + * @used: + * + * Track the writeback slot already used. + */ + unsigned long used[DIV_ROUND_UP(AMDGPU_MAX_WB, BITS_PER_LONG)]; + + /** + * @lock: + * + * Protects read and write of the used field array. + */ + spinlock_t lock; +}; + +void amdgpu_wb_fini(struct amdgpu_device *adev); +int amdgpu_wb_init(struct amdgpu_device *adev); +int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb); +void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb); +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index 120da838ac28..b703ef1fe340 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -605,7 +605,7 @@ static int cik_sdma_ring_test_ring(struct amdgpu_ring *ring) u32 tmp; u64 gpu_addr; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -635,7 +635,7 @@ static int cik_sdma_ring_test_ring(struct amdgpu_ring *ring) r = -ETIMEDOUT; error_free_wb: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -658,7 +658,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout) u64 gpu_addr; long r; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -699,7 +699,7 @@ static int cik_sdma_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index ddf190672530..9d325867a1aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -4080,7 +4080,7 @@ static int gfx_v10_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -4121,7 +4121,7 @@ static int gfx_v10_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err1: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 2a121df90574..254a72f26ec5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -635,7 +635,7 @@ static int gfx_v11_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -676,7 +676,7 @@ static int gfx_v11_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err1: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index c765af54669c..8221a77b6b75 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -507,7 +507,7 @@ static int gfx_v12_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -548,7 +548,7 @@ static int gfx_v12_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err1: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c index e87f1baf5cb6..b19a4956c222 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c @@ -320,7 +320,7 @@ static int gfx_v12_1_ring_test_ib(struct amdgpu_ring *ring, long timeout) memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -361,7 +361,7 @@ static int gfx_v12_1_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err1: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index bee2ff6865f9..9e0840df8849 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -876,7 +876,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) uint32_t tmp; long r; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -917,7 +917,7 @@ static int gfx_v8_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err1: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 9f81fd715418..556e5cb3f4cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1232,7 +1232,7 @@ static int gfx_v9_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) uint32_t tmp; long r; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -1273,7 +1273,7 @@ static int gfx_v9_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err1: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -4267,7 +4267,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev) BUG_ON(!ring->funcs->emit_rreg); spin_lock_irqsave(&kiq->ring_lock, flags); - if (amdgpu_device_wb_get(adev, ®_val_offs)) { + if (amdgpu_wb_get(adev, ®_val_offs)) { pr_err("critical bug! too many kiq readers\n"); goto failed_unlock; } @@ -4315,7 +4315,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev) mb(); value = (uint64_t)adev->wb.wb[reg_val_offs] | (uint64_t)adev->wb.wb[reg_val_offs + 1 ] << 32ULL; - amdgpu_device_wb_free(adev, reg_val_offs); + amdgpu_wb_free(adev, reg_val_offs); return value; failed_undo: @@ -4324,7 +4324,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev) spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq_read: if (reg_val_offs) - amdgpu_device_wb_free(adev, reg_val_offs); + amdgpu_wb_free(adev, reg_val_offs); pr_err("failed to read gpu clock\n"); return ~0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index b89cbc2df951..44d38b76cb4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -458,7 +458,7 @@ static int gfx_v9_4_3_ring_test_ib(struct amdgpu_ring *ring, long timeout) uint32_t tmp; long r; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -499,7 +499,7 @@ static int gfx_v9_4_3_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err1: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c index e947c16e694d..defa050fd871 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c @@ -521,7 +521,7 @@ static int mes_userq_preempt(struct amdgpu_usermode_queue *queue) if (queue->state != AMDGPU_USERQ_STATE_MAPPED) return 0; - r = amdgpu_device_wb_get(adev, &fence_offset); + r = amdgpu_wb_get(adev, &fence_offset); if (r) return r; @@ -549,7 +549,7 @@ static int mes_userq_preempt(struct amdgpu_usermode_queue *queue) r = -ETIMEDOUT; out: - amdgpu_device_wb_free(adev, fence_offset); + amdgpu_wb_free(adev, fence_offset); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 8f136ff7d96f..72ca7302bbfb 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -198,7 +198,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, timeout = 15 * 600 * 1000; } - ret = amdgpu_device_wb_get(adev, &status_offset); + ret = amdgpu_wb_get(adev, &status_offset); if (ret) return ret; @@ -270,7 +270,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, goto error_wb_free; } - amdgpu_device_wb_free(adev, status_offset); + amdgpu_wb_free(adev, status_offset); return 0; error_undo: @@ -281,7 +281,7 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, spin_unlock_irqrestore(&mes->ring_lock[0], flags); error_wb_free: - amdgpu_device_wb_free(adev, status_offset); + amdgpu_wb_free(adev, status_offset); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c index ce5064200743..04465804c254 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c @@ -175,7 +175,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, timeout = 15 * 600 * 1000; } - ret = amdgpu_device_wb_get(adev, &status_offset); + ret = amdgpu_wb_get(adev, &status_offset); if (ret) return ret; @@ -253,7 +253,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, goto error_wb_free; } - amdgpu_device_wb_free(adev, status_offset); + amdgpu_wb_free(adev, status_offset); return 0; error_undo: @@ -264,7 +264,7 @@ static int mes_v12_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, spin_unlock_irqrestore(ring_lock, flags); error_wb_free: - amdgpu_device_wb_free(adev, status_offset); + amdgpu_wb_free(adev, status_offset); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c index e7d7160f8fc7..dbdb9ba02a5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c @@ -177,7 +177,7 @@ static int mes_v12_1_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, timeout = 15 * 600 * 1000; } - ret = amdgpu_device_wb_get(adev, &status_offset); + ret = amdgpu_wb_get(adev, &status_offset); if (ret) return ret; @@ -252,7 +252,7 @@ static int mes_v12_1_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, goto error_wb_free; } - amdgpu_device_wb_free(adev, status_offset); + amdgpu_wb_free(adev, status_offset); return 0; error_undo: @@ -263,7 +263,7 @@ static int mes_v12_1_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, spin_unlock_irqrestore(ring_lock, flags); error_wb_free: - amdgpu_device_wb_free(adev, status_offset); + amdgpu_wb_free(adev, status_offset); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 93ec52c1f367..397b08c7173a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -536,7 +536,7 @@ static int sdma_v2_4_ring_test_ring(struct amdgpu_ring *ring) u32 tmp; u64 gpu_addr; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -567,7 +567,7 @@ static int sdma_v2_4_ring_test_ring(struct amdgpu_ring *ring) r = -ETIMEDOUT; error_free_wb: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -590,7 +590,7 @@ static int sdma_v2_4_ring_test_ib(struct amdgpu_ring *ring, long timeout) u64 gpu_addr; long r; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -635,7 +635,7 @@ static int sdma_v2_4_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index c2d098cd72ce..8ac1c9dae72e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -810,7 +810,7 @@ static int sdma_v3_0_ring_test_ring(struct amdgpu_ring *ring) u32 tmp; u64 gpu_addr; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -841,7 +841,7 @@ static int sdma_v3_0_ring_test_ring(struct amdgpu_ring *ring) r = -ETIMEDOUT; error_free_wb: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -864,7 +864,7 @@ static int sdma_v3_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) u64 gpu_addr; long r; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -908,7 +908,7 @@ static int sdma_v3_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index cb64d17000df..20c8ebf0e159 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -1468,7 +1468,7 @@ static int sdma_v4_0_ring_test_ring(struct amdgpu_ring *ring) u32 tmp; u64 gpu_addr; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -1499,7 +1499,7 @@ static int sdma_v4_0_ring_test_ring(struct amdgpu_ring *ring) r = -ETIMEDOUT; error_free_wb: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -1522,7 +1522,7 @@ static int sdma_v4_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) u32 tmp = 0; u64 gpu_addr; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -1567,7 +1567,7 @@ static int sdma_v4_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 484f1a6b5fbc..6fe3d3d56c40 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -1062,7 +1062,7 @@ static int sdma_v4_4_2_ring_test_ring(struct amdgpu_ring *ring) u32 tmp; u64 gpu_addr; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -1093,7 +1093,7 @@ static int sdma_v4_4_2_ring_test_ring(struct amdgpu_ring *ring) r = -ETIMEDOUT; error_free_wb: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -1116,7 +1116,7 @@ static int sdma_v4_4_2_ring_test_ib(struct amdgpu_ring *ring, long timeout) u32 tmp = 0; u64 gpu_addr; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -1161,7 +1161,7 @@ static int sdma_v4_4_2_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index b809942b1eb7..1ca0e7f65442 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -1019,7 +1019,7 @@ static int sdma_v5_0_ring_test_ring(struct amdgpu_ring *ring) tmp = 0xCAFEDEAD; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%d) failed to allocate wb slot\n", r); return r; @@ -1031,7 +1031,7 @@ static int sdma_v5_0_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 20); if (r) { drm_err(adev_to_drm(adev), "dma failed to lock ring %d (%d).\n", ring->idx, r); - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -1056,7 +1056,7 @@ static int sdma_v5_0_ring_test_ring(struct amdgpu_ring *ring) if (i >= adev->usec_timeout) r = -ETIMEDOUT; - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -1083,7 +1083,7 @@ static int sdma_v5_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) tmp = 0xCAFEDEAD; memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%ld) failed to allocate wb slot\n", r); return r; @@ -1135,7 +1135,7 @@ static int sdma_v5_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 87c1e29fd298..81f1e9882177 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -919,7 +919,7 @@ static int sdma_v5_2_ring_test_ring(struct amdgpu_ring *ring) tmp = 0xCAFEDEAD; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%d) failed to allocate wb slot\n", r); return r; @@ -931,7 +931,7 @@ static int sdma_v5_2_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 20); if (r) { drm_err(adev_to_drm(adev), "dma failed to lock ring %d (%d).\n", ring->idx, r); - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -956,7 +956,7 @@ static int sdma_v5_2_ring_test_ring(struct amdgpu_ring *ring) if (i >= adev->usec_timeout) r = -ETIMEDOUT; - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -983,7 +983,7 @@ static int sdma_v5_2_ring_test_ib(struct amdgpu_ring *ring, long timeout) tmp = 0xCAFEDEAD; memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%ld) failed to allocate wb slot\n", r); return r; @@ -1034,7 +1034,7 @@ static int sdma_v5_2_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c index 7a3f1a60b014..cf3d2997fff8 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c @@ -910,7 +910,7 @@ static int sdma_v6_0_ring_test_ring(struct amdgpu_ring *ring) tmp = 0xCAFEDEAD; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%d) failed to allocate wb slot\n", r); return r; @@ -922,7 +922,7 @@ static int sdma_v6_0_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 5); if (r) { drm_err(adev_to_drm(adev), "dma failed to lock ring %d (%d).\n", ring->idx, r); - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -947,7 +947,7 @@ static int sdma_v6_0_ring_test_ring(struct amdgpu_ring *ring) if (i >= adev->usec_timeout) r = -ETIMEDOUT; - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -974,7 +974,7 @@ static int sdma_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) tmp = 0xCAFEDEAD; memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%ld) failed to allocate wb slot\n", r); return r; @@ -1025,7 +1025,7 @@ static int sdma_v6_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c index 84305b6800fe..69cb89298a3e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c @@ -925,7 +925,7 @@ static int sdma_v7_0_ring_test_ring(struct amdgpu_ring *ring) tmp = 0xCAFEDEAD; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%d) failed to allocate wb slot\n", r); return r; @@ -937,7 +937,7 @@ static int sdma_v7_0_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 5); if (r) { drm_err(adev_to_drm(adev), "dma failed to lock ring %d (%d).\n", ring->idx, r); - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -962,7 +962,7 @@ static int sdma_v7_0_ring_test_ring(struct amdgpu_ring *ring) if (i >= adev->usec_timeout) r = -ETIMEDOUT; - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -989,7 +989,7 @@ static int sdma_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) tmp = 0xCAFEDEAD; memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%ld) failed to allocate wb slot\n", r); return r; @@ -1040,7 +1040,7 @@ static int sdma_v7_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c index 322e6f4dd121..18366e16ef3f 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c @@ -915,7 +915,7 @@ static int sdma_v7_1_ring_test_ring(struct amdgpu_ring *ring) tmp = 0xCAFEDEAD; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%d) failed to allocate wb slot\n", r); return r; @@ -927,7 +927,7 @@ static int sdma_v7_1_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 5); if (r) { DRM_ERROR("amdgpu: dma failed to lock ring %d (%d).\n", ring->idx, r); - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -952,7 +952,7 @@ static int sdma_v7_1_ring_test_ring(struct amdgpu_ring *ring) if (i >= adev->usec_timeout) r = -ETIMEDOUT; - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -979,7 +979,7 @@ static int sdma_v7_1_ring_test_ib(struct amdgpu_ring *ring, long timeout) tmp = 0xCAFEDEAD; memset(&ib, 0, sizeof(ib)); - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) { dev_err(adev->dev, "(%ld) failed to allocate wb slot\n", r); return r; @@ -1030,7 +1030,7 @@ static int sdma_v7_1_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 549708075eb4..47f1d325bd1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -213,7 +213,7 @@ static int si_dma_ring_test_ring(struct amdgpu_ring *ring) u32 tmp; u64 gpu_addr; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -242,7 +242,7 @@ static int si_dma_ring_test_ring(struct amdgpu_ring *ring) r = -ETIMEDOUT; error_free_wb: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } @@ -265,7 +265,7 @@ static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout) u64 gpu_addr; long r; - r = amdgpu_device_wb_get(adev, &index); + r = amdgpu_wb_get(adev, &index); if (r) return r; @@ -304,7 +304,7 @@ static int si_dma_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_ib_free(&ib, NULL); dma_fence_put(f); err0: - amdgpu_device_wb_free(adev, index); + amdgpu_wb_free(adev, index); return r; } From 7513c35eacda4a300830ccef1119e16b670e5cdf Mon Sep 17 00:00:00 2001 From: Shahyan Soltani Date: Wed, 3 Jun 2026 09:43:12 -0400 Subject: [PATCH 22/51] drm/amdgpu: move struct amdgpu_video_codecs and helpers into header file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move struct amdgpu_video_codec_info, struct amdgpu_video_codecs, and helpers into a new amdgpu_video_codecs.h file. This is part of the ongoing effort to reduce the size of amdgpu.h into their own respective separate headers. Signed-off-by: Shahyan Soltani Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 21 +-------- .../gpu/drm/amd/amdgpu/amdgpu_video_codecs.h | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_video_codecs.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ccf187d0b706..3aef99a6d053 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -115,6 +115,7 @@ #include "amdgpu_wb.h" #include "amdgpu_ip.h" #include "amdgpu_sa.h" +#include "amdgpu_video_codecs.h" #if defined(CONFIG_DRM_AMD_ISP) #include "amdgpu_isp.h" #endif @@ -443,26 +444,6 @@ struct amdgpu_allowed_register_entry { bool grbm_indexed; }; -struct amdgpu_video_codec_info { - u32 codec_type; - u32 max_width; - u32 max_height; - u32 max_pixels_per_frame; - u32 max_level; -}; - -#define codec_info_build(type, width, height, level) \ - .codec_type = type,\ - .max_width = width,\ - .max_height = height,\ - .max_pixels_per_frame = height * width,\ - .max_level = level, - -struct amdgpu_video_codecs { - const u32 codec_count; - const struct amdgpu_video_codec_info *codec_array; -}; - /* * ASIC specific functions. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_video_codecs.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_video_codecs.h new file mode 100644 index 000000000000..3b2a6cb8632d --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_video_codecs.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT + * + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __AMDGPU_VIDEO_CODECS_H__ +#define __AMDGPU_VIDEO_CODECS_H__ + +#include + +#define codec_info_build(type, width, height, level) \ + .codec_type = type,\ + .max_width = width,\ + .max_height = height,\ + .max_pixels_per_frame = height * width,\ + .max_level = level, + +struct amdgpu_video_codec_info { + u32 codec_type; + u32 max_width; + u32 max_height; + u32 max_pixels_per_frame; + u32 max_level; +}; + +struct amdgpu_video_codecs { + const u32 codec_count; + const struct amdgpu_video_codec_info *codec_array; +}; +#endif From 6d9cea05db72476ea11a72a8e1e67161e5e48b01 Mon Sep 17 00:00:00 2001 From: Shahyan Soltani Date: Wed, 3 Jun 2026 09:57:18 -0400 Subject: [PATCH 23/51] drm/amdgpu: move struct amdgpu_mqd and helpers into header file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move struct amdgpu_mqd_prop, struct amdgpu_mqd, and helpers from the monolithic amdgpu.h into existing amdgpu_mes.h file. This is part of the ongoing effort to reduce the size of amdgpu.h into their own respective separate headers. Signed-off-by: Shahyan Soltani Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 48 +------------------------ drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 46 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3aef99a6d053..0b84f4c8f7ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -96,7 +96,6 @@ #include "amdgpu_doorbell.h" #include "amdgpu_amdkfd.h" #include "amdgpu_discovery.h" -#include "amdgpu_mes.h" #include "amdgpu_umc.h" #include "amdgpu_mmhub.h" #include "amdgpu_gfxhub.h" @@ -114,6 +113,7 @@ #include "amdgpu_eviction_fence.h" #include "amdgpu_wb.h" #include "amdgpu_ip.h" +#include "amdgpu_mes.h" #include "amdgpu_sa.h" #include "amdgpu_video_codecs.h" #if defined(CONFIG_DRM_AMD_ISP) @@ -623,44 +623,6 @@ struct amd_powerplay { (rid == 0x01) || \ (rid == 0x10)))) -enum amdgpu_mqd_update_flag { - AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE = 1, - AMDGPU_UPDATE_FLAG_DBG_WA_DISABLE = 2, - AMDGPU_UPDATE_FLAG_IS_GWS = 4, /* quirk for gfx9 IP */ -}; - -struct amdgpu_mqd_prop { - uint64_t mqd_gpu_addr; - uint64_t hqd_base_gpu_addr; - uint64_t rptr_gpu_addr; - uint64_t wptr_gpu_addr; - uint32_t queue_size; - bool use_doorbell; - uint32_t doorbell_index; - uint64_t eop_gpu_addr; - uint32_t hqd_pipe_priority; - uint32_t hqd_queue_priority; - uint32_t mqd_stride_size; - bool allow_tunneling; - bool hqd_active; - uint64_t shadow_addr; - uint64_t gds_bkup_addr; - uint64_t csa_addr; - uint64_t fence_address; - bool tmz_queue; - bool kernel_queue; - uint32_t *cu_mask; - uint32_t cu_mask_count; - uint32_t cu_flags; - bool is_user_cu_masked; -}; - -struct amdgpu_mqd { - unsigned mqd_size; - int (*init_mqd)(struct amdgpu_device *adev, void *mqd, - struct amdgpu_mqd_prop *p); -}; - struct amdgpu_pcie_reset_ctx { bool in_link_reset; bool occurs_dpc; @@ -1047,14 +1009,6 @@ struct amdgpu_device { struct amdgpu_kfd_dev kfd; }; -/* - * MES FW uses address(mqd_addr + sizeof(struct mqd) + 3*sizeof(uint32_t)) - * as fence address and writes a 32 bit fence value to this address. - * Driver needs to allocate at least 4 DWs extra memory in addition to - * sizeof(struct mqd). Add 8 DWs and align to AMDGPU_GPU_PAGE_SIZE for safety. - */ -#define AMDGPU_MQD_SIZE_ALIGN(mqd_size) AMDGPU_GPU_PAGE_ALIGN(((mqd_size) + 32)) - static inline uint32_t amdgpu_ip_version(const struct amdgpu_device *adev, uint8_t ip, uint8_t inst) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index f25cffad8efe..389e3324caea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -441,6 +441,52 @@ struct amdgpu_mes_funcs { struct mes_inv_tlbs_pasid_input *input); }; +enum amdgpu_mqd_update_flag { + AMDGPU_UPDATE_FLAG_DBG_WA_ENABLE = 1, + AMDGPU_UPDATE_FLAG_DBG_WA_DISABLE = 2, + AMDGPU_UPDATE_FLAG_IS_GWS = 4, /* quirk for gfx9 IP */ +}; + +struct amdgpu_mqd_prop { + uint64_t mqd_gpu_addr; + uint64_t hqd_base_gpu_addr; + uint64_t rptr_gpu_addr; + uint64_t wptr_gpu_addr; + uint32_t queue_size; + bool use_doorbell; + uint32_t doorbell_index; + uint64_t eop_gpu_addr; + uint32_t hqd_pipe_priority; + uint32_t hqd_queue_priority; + uint32_t mqd_stride_size; + bool allow_tunneling; + bool hqd_active; + uint64_t shadow_addr; + uint64_t gds_bkup_addr; + uint64_t csa_addr; + uint64_t fence_address; + bool tmz_queue; + bool kernel_queue; + uint32_t *cu_mask; + uint32_t cu_mask_count; + uint32_t cu_flags; + bool is_user_cu_masked; +}; + +struct amdgpu_mqd { + unsigned mqd_size; + int (*init_mqd)(struct amdgpu_device *adev, void *mqd, + struct amdgpu_mqd_prop *p); +}; + +/* + * MES FW uses address(mqd_addr + sizeof(struct mqd) + 3*sizeof(uint32_t)) + * as fence address and writes a 32 bit fence value to this address. + * Driver needs to allocate at least 4 DWs extra memory in addition to + * sizeof(struct mqd). Add 8 DWs and align to AMDGPU_GPU_PAGE_SIZE for safety. + */ +#define AMDGPU_MQD_SIZE_ALIGN(mqd_size) AMDGPU_GPU_PAGE_ALIGN(((mqd_size) + 32)) + #define amdgpu_mes_kiq_hw_init(adev, xcc_id) \ (adev)->mes.kiq_hw_init((adev), (xcc_id)) #define amdgpu_mes_kiq_hw_fini(adev, xcc_id) \ From a733b7bee13c6f1085979819a3154d6d12aa220b Mon Sep 17 00:00:00 2001 From: George Zhang Date: Fri, 3 Jul 2026 09:44:45 -0400 Subject: [PATCH 24/51] drm/amd/display: Fix sign mismatch warning Using mismatched signedness (int and uint32_t) causes a -Wsign-compare warning. Fix it by changing the min macro to min_t to explicitly cast. Fixes: 8cbe3648aa86 ("drm/amd/display: clamp DMUB AUX reply length to payload buffer") Signed-off-by: George Zhang Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c index 0aa99d1a542f..2692d1890ba2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c @@ -799,8 +799,8 @@ int amdgpu_dm_process_dmub_aux_transfer_sync( /*write req may receive a byte indicating partially written number as well*/ if (p_notify->aux_reply.length && payload->data) { /* Bound the reply to the scratch buffer it was read into. */ - ret = min((uint32_t)p_notify->aux_reply.length, - (uint32_t)sizeof(p_notify->aux_reply.data)); + ret = min_t(uint32_t, p_notify->aux_reply.length, + sizeof(p_notify->aux_reply.data)); /* * During a write-status-update retry the caller zeroes @@ -809,7 +809,7 @@ int amdgpu_dm_process_dmub_aux_transfer_sync( * so only clamp to payload->length for regular transfers. */ if (!payload->write_status_update) - ret = min(ret, payload->length); + ret = min_t(int, ret, payload->length); memcpy(payload->data, p_notify->aux_reply.data, ret); } else { From 45c0a9ee90f7bf91bc42d6bbe454bd31e267554d Mon Sep 17 00:00:00 2001 From: Shahyan Soltani Date: Wed, 3 Jun 2026 11:18:59 -0400 Subject: [PATCH 25/51] drm/amdgpu: move amdgpu_acpi helpers into new header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move struct amdgpu_uma_carveout_option, struct amdgpu_uma_carveout_info, struct amdgpu_numa_info, and relevant acpi helpers from the monolithic amdgpu.h header file into a new amdgpu_acpi.h file. This is part of the ongoing effort to reduce the size of amdgpu.h into their own respective separate headers. Signed-off-by: Shahyan Soltani Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 122 +----------------- drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h | 151 +++++++++++++++++++++++ 2 files changed, 152 insertions(+), 121 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 0b84f4c8f7ad..aee555519cb2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -115,6 +115,7 @@ #include "amdgpu_ip.h" #include "amdgpu_mes.h" #include "amdgpu_sa.h" +#include "amdgpu_acpi.h" #include "amdgpu_video_codecs.h" #if defined(CONFIG_DRM_AMD_ISP) #include "amdgpu_isp.h" @@ -137,13 +138,6 @@ struct amdgpu_mgpu_info { uint32_t num_apu; }; -enum amdgpu_ss { - AMDGPU_SS_DRV_LOAD, - AMDGPU_SS_DEV_D0, - AMDGPU_SS_DEV_D3, - AMDGPU_SS_DRV_UNLOAD -}; - struct amdgpu_hwip_reg_entry { u32 hwip; u32 inst; @@ -547,38 +541,6 @@ struct amdgpu_uid { struct amdgpu_device *adev; }; -#define MAX_UMA_OPTION_NAME 28 -#define MAX_UMA_OPTION_ENTRIES 19 - -#define AMDGPU_UMA_FLAG_AUTO BIT(1) -#define AMDGPU_UMA_FLAG_CUSTOM BIT(0) - -/** - * struct amdgpu_uma_carveout_option - single UMA carveout option - * @name: Name of the carveout option - * @memory_carved_mb: Amount of memory carved in MB - * @flags: ATCS flags supported by this option - */ -struct amdgpu_uma_carveout_option { - char name[MAX_UMA_OPTION_NAME]; - uint32_t memory_carved_mb; - uint8_t flags; -}; - -/** - * struct amdgpu_uma_carveout_info - table of available UMA carveout options - * @num_entries: Number of available options - * @uma_option_index: The index of the option currently applied - * @update_lock: Lock to serialize changes to the option - * @entries: The array of carveout options - */ -struct amdgpu_uma_carveout_info { - uint8_t num_entries; - uint8_t uma_option_index; - struct mutex update_lock; - struct amdgpu_uma_carveout_option entries[MAX_UMA_OPTION_ENTRIES]; -}; - struct amd_powerplay { void *pp_handle; const struct amd_pm_funcs *pp_funcs; @@ -1325,88 +1287,6 @@ struct amdgpu_afmt_acr { struct amdgpu_afmt_acr amdgpu_afmt_acr(uint32_t clock); -/* amdgpu_acpi.c */ - -struct amdgpu_numa_info { - uint64_t size; - int pxm; - int nid; -}; - -/* ATCS Device/Driver State */ -#define AMDGPU_ATCS_PSC_DEV_STATE_D0 0 -#define AMDGPU_ATCS_PSC_DEV_STATE_D3_HOT 3 -#define AMDGPU_ATCS_PSC_DRV_STATE_OPR 0 -#define AMDGPU_ATCS_PSC_DRV_STATE_NOT_OPR 1 - -#if defined(CONFIG_ACPI) -int amdgpu_acpi_init(struct amdgpu_device *adev); -void amdgpu_acpi_fini(struct amdgpu_device *adev); -bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev); -bool amdgpu_acpi_is_power_shift_control_supported(void); -bool amdgpu_acpi_is_set_uma_allocation_size_supported(void); -int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, - u8 perf_req, bool advertise); -int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, - u8 dev_state, bool drv_state); -int amdgpu_acpi_smart_shift_update(struct amdgpu_device *adev, - enum amdgpu_ss ss_state); -int amdgpu_acpi_set_uma_allocation_size(struct amdgpu_device *adev, u8 index, u8 type); -int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); -int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset, - u64 *tmr_size); -int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, int xcc_id, - struct amdgpu_numa_info *numa_info); - -void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); -bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev); -void amdgpu_acpi_detect(void); -void amdgpu_acpi_release(void); -#else -static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } -static inline int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, - u64 *tmr_offset, u64 *tmr_size) -{ - return -EINVAL; -} -static inline int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, - int xcc_id, - struct amdgpu_numa_info *numa_info) -{ - return -EINVAL; -} -static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } -static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; } -static inline void amdgpu_acpi_detect(void) { } -static inline void amdgpu_acpi_release(void) { } -static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } -static inline bool amdgpu_acpi_is_set_uma_allocation_size_supported(void) { return false; } -static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, - u8 dev_state, bool drv_state) { return 0; } -static inline int amdgpu_acpi_smart_shift_update(struct amdgpu_device *adev, - enum amdgpu_ss ss_state) -{ - return 0; -} -static inline int amdgpu_acpi_set_uma_allocation_size(struct amdgpu_device *adev, u8 index, u8 type) -{ - return -EINVAL; -} -static inline void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps) { } -#endif - -#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND) -bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev); -bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); -#else -static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } -static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; } -#endif - -#if defined(CONFIG_DRM_AMD_ISP) -int amdgpu_acpi_get_isp4_dev(struct acpi_device **dev); -#endif - void amdgpu_register_gpu_instance(struct amdgpu_device *adev); void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h new file mode 100644 index 000000000000..6569a4db5dae --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT + * + * Copyright 2026 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __AMDGPU_ACPI_H__ +#define __AMDGPU_ACPI_H__ + +#include +#include + +struct amdgpu_device; +struct acpi_device; +struct amdgpu_dm_backlight_caps; + +#define MAX_UMA_OPTION_NAME 28 +#define MAX_UMA_OPTION_ENTRIES 19 + +#define AMDGPU_UMA_FLAG_AUTO BIT(1) +#define AMDGPU_UMA_FLAG_CUSTOM BIT(0) + +/* ATCS Device/Driver State */ +#define AMDGPU_ATCS_PSC_DEV_STATE_D0 0 +#define AMDGPU_ATCS_PSC_DEV_STATE_D3_HOT 3 +#define AMDGPU_ATCS_PSC_DRV_STATE_OPR 0 +#define AMDGPU_ATCS_PSC_DRV_STATE_NOT_OPR 1 + +enum amdgpu_ss { + AMDGPU_SS_DRV_LOAD, + AMDGPU_SS_DEV_D0, + AMDGPU_SS_DEV_D3, + AMDGPU_SS_DRV_UNLOAD +}; + +/** + * struct amdgpu_uma_carveout_option - single UMA carveout option + * @name: Name of the carveout option + * @memory_carved_mb: Amount of memory carved in MB + * @flags: ATCS flags supported by this option + */ +struct amdgpu_uma_carveout_option { + char name[MAX_UMA_OPTION_NAME]; + uint32_t memory_carved_mb; + uint8_t flags; +}; + +/** + * struct amdgpu_uma_carveout_info - table of available UMA carveout options + * @num_entries: Number of available options + * @uma_option_index: The index of the option currently applied + * @update_lock: Lock to serialize changes to the option + * @entries: The array of carveout options + */ +struct amdgpu_uma_carveout_info { + uint8_t num_entries; + uint8_t uma_option_index; + struct mutex update_lock; + struct amdgpu_uma_carveout_option entries[MAX_UMA_OPTION_ENTRIES]; +}; + +struct amdgpu_numa_info { + uint64_t size; + int pxm; + int nid; +}; + +#if defined(CONFIG_ACPI) +int amdgpu_acpi_init(struct amdgpu_device *adev); +void amdgpu_acpi_fini(struct amdgpu_device *adev); +bool amdgpu_acpi_is_pcie_performance_request_supported(struct amdgpu_device *adev); +bool amdgpu_acpi_is_power_shift_control_supported(void); +bool amdgpu_acpi_is_set_uma_allocation_size_supported(void); +int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, + u8 perf_req, bool advertise); +int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, + u8 dev_state, bool drv_state); +int amdgpu_acpi_smart_shift_update(struct amdgpu_device *adev, + enum amdgpu_ss ss_state); +int amdgpu_acpi_set_uma_allocation_size(struct amdgpu_device *adev, u8 index, u8 type); +int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); +int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, u64 *tmr_offset, + u64 *tmr_size); +int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, int xcc_id, + struct amdgpu_numa_info *numa_info); + +void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); +bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev); +void amdgpu_acpi_detect(void); +void amdgpu_acpi_release(void); +#else +static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } +static inline int amdgpu_acpi_get_tmr_info(struct amdgpu_device *adev, + u64 *tmr_offset, u64 *tmr_size) +{ + return -EINVAL; +} +static inline int amdgpu_acpi_get_mem_info(struct amdgpu_device *adev, + int xcc_id, + struct amdgpu_numa_info *numa_info) +{ + return -EINVAL; +} +static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } +static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; } +static inline void amdgpu_acpi_detect(void) { } +static inline void amdgpu_acpi_release(void) { } +static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } +static inline bool amdgpu_acpi_is_set_uma_allocation_size_supported(void) { return false; } +static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, + u8 dev_state, bool drv_state) { return 0; } +static inline int amdgpu_acpi_smart_shift_update(struct amdgpu_device *adev, + enum amdgpu_ss ss_state) +{ + return 0; +} +static inline int amdgpu_acpi_set_uma_allocation_size(struct amdgpu_device *adev, u8 index, u8 type) +{ + return -EINVAL; +} +static inline void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps) { } +#endif + +#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND) +bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev); +bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); +#else +static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } +static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; } +#endif + +#if defined(CONFIG_DRM_AMD_ISP) +int amdgpu_acpi_get_isp4_dev(struct acpi_device **dev); +#endif +#endif /* __AMDGPU_ACPI_H__ */ From f9371b8a315e5b8bee593535cf07ce94c0a18dda Mon Sep 17 00:00:00 2001 From: Shahyan Soltani Date: Wed, 3 Jun 2026 11:28:54 -0400 Subject: [PATCH 26/51] drm/amdgpu: move amdgpu_allowed_register_entry into amdgpu_reg_access.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move struct amdgpu_allowed_register_entry from monolithic amdgpu.h file into existing amdgpu_reg_access.h file. This is part of the ongoing effort to reduce the size of amdgpu.h into their own respective separate headers. Signed-off-by: Shahyan Soltani Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 -------- drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.h | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index aee555519cb2..d72930adebb0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -430,14 +430,6 @@ int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv); */ int amdgpu_benchmark(struct amdgpu_device *adev, int test_number); -/* - * ASIC specific register table accessible by UMD - */ -struct amdgpu_allowed_register_entry { - uint32_t reg_offset; - bool grbm_indexed; -}; - /* * ASIC specific functions. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.h index a1011af6b52b..320c30ce4a62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reg_access.h @@ -89,6 +89,14 @@ struct amdgpu_reg_access { struct amdgpu_reg_smn_ext smn; }; +/* + * ASIC specific register table accessible by UMD + */ +struct amdgpu_allowed_register_entry { + uint32_t reg_offset; + bool grbm_indexed; +}; + void amdgpu_reg_access_init(struct amdgpu_device *adev); uint32_t amdgpu_reg_smc_rd32(struct amdgpu_device *adev, uint32_t reg); void amdgpu_reg_smc_wr32(struct amdgpu_device *adev, uint32_t reg, uint32_t v); From fff648aec5e2790d117a0ec5c849a284d9d33d70 Mon Sep 17 00:00:00 2001 From: Shahyan Soltani Date: Mon, 8 Jun 2026 13:42:21 -0400 Subject: [PATCH 27/51] drm/amdgpu: include amdgpu_video_codecs.h only where needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove #include "amdgpu_video_codecs.h" from amdgpu.h and add forward declaration of struct amdgpu_video_codecs. Add #include "amdgpu_video_codecs.h" into files amdgpu_kms.c, amdgpu_virt.c, cik.c, nv.c, si.c, soc15.c, soc21.c, soc24.c, soc_v1_0.c, and vi.c. Signed-off-by: Shahyan Soltani Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 1 + drivers/gpu/drm/amd/amdgpu/cik.c | 1 + drivers/gpu/drm/amd/amdgpu/nv.c | 1 + drivers/gpu/drm/amd/amdgpu/si.c | 1 + drivers/gpu/drm/amd/amdgpu/soc15.c | 1 + drivers/gpu/drm/amd/amdgpu/soc21.c | 1 + drivers/gpu/drm/amd/amdgpu/soc24.c | 1 + drivers/gpu/drm/amd/amdgpu/soc_v1_0.c | 1 + drivers/gpu/drm/amd/amdgpu/vi.c | 1 + 11 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index d72930adebb0..8339ab6f5d32 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -116,7 +116,6 @@ #include "amdgpu_mes.h" #include "amdgpu_sa.h" #include "amdgpu_acpi.h" -#include "amdgpu_video_codecs.h" #if defined(CONFIG_DRM_AMD_ISP) #include "amdgpu_isp.h" #endif @@ -327,6 +326,7 @@ struct amdgpu_hive_info; struct amdgpu_reset_context; struct amdgpu_reset_control; struct amdgpu_coredump_info; +struct amdgpu_video_codecs; enum amdgpu_cp_irq { AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP = 0, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 215aa678d1d0..287ede40cd91 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -46,6 +46,7 @@ #include "amdgpu_reset.h" #include "amd_pcie.h" #include "amdgpu_userq.h" +#include "amdgpu_video_codecs.h" void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 9e8f7d2b898c..8f4b86063507 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -34,6 +34,7 @@ #include "amdgpu_ras.h" #include "amdgpu_reset.h" #include "amdgpu_dpm.h" +#include "amdgpu_video_codecs.h" #include "vi.h" #include "soc15.h" #include "nv.h" diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 77e120a72815..e037c08c8547 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -36,6 +36,7 @@ #include "cikd.h" #include "atom.h" #include "amd_pcie.h" +#include "amdgpu_video_codecs.h" #include "cik.h" #include "gmc_v7_0.h" diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 77557ee3ca16..96faaf8c5737 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -36,6 +36,7 @@ #include "amdgpu_psp.h" #include "atom.h" #include "amd_pcie.h" +#include "amdgpu_video_codecs.h" #include "gc/gc_10_1_0_offset.h" #include "gc/gc_10_1_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index b104469c38ec..6e455ad66d62 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -35,6 +35,7 @@ #include "amdgpu_vce.h" #include "atom.h" #include "amd_pcie.h" +#include "amdgpu_video_codecs.h" #include "si_dpm.h" #include "sid.h" diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index ed3fd58b78d0..3d4573d93742 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -77,6 +77,7 @@ #include "mxgpu_ai.h" #include "amdgpu_ras.h" #include "amdgpu_xgmi.h" +#include "amdgpu_video_codecs.h" #include #define mmMP0_MISC_CGTT_CTRL0 0x01b9 diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 1b667be8c5d3..713746a75d1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -33,6 +33,7 @@ #include "amdgpu_ucode.h" #include "amdgpu_psp.h" #include "amdgpu_smu.h" +#include "amdgpu_video_codecs.h" #include "atom.h" #include "amd_pcie.h" diff --git a/drivers/gpu/drm/amd/amdgpu/soc24.c b/drivers/gpu/drm/amd/amdgpu/soc24.c index e5e3a460e486..9a658e4837f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc24.c +++ b/drivers/gpu/drm/amd/amdgpu/soc24.c @@ -34,6 +34,7 @@ #include "amdgpu_smu.h" #include "atom.h" #include "amd_pcie.h" +#include "amdgpu_video_codecs.h" #include "gc/gc_12_0_0_offset.h" #include "gc/gc_12_0_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c index a9039fb1a77b..43e92e2a85e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/soc_v1_0.c @@ -29,6 +29,7 @@ #include "gfxhub_v12_1.h" #include "sdma_v7_1.h" #include "gfx_v12_1.h" +#include "amdgpu_video_codecs.h" #include "gc/gc_12_1_0_offset.h" #include "gc/gc_12_1_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 5715b6b596af..514715793f78 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -34,6 +34,7 @@ #include "amdgpu_ucode.h" #include "atom.h" #include "amd_pcie.h" +#include "amdgpu_video_codecs.h" #include "gmc/gmc_8_1_d.h" #include "gmc/gmc_8_1_sh_mask.h" From 9d01579f3f868b333acc901815972685989092c7 Mon Sep 17 00:00:00 2001 From: Shahyan Soltani Date: Mon, 6 Jul 2026 08:15:21 -0400 Subject: [PATCH 28/51] drm/amdgpu: fix lifetime issue of amdgpu_vm_get_task_info_pasid() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vm pointer returned from amdgpu_vm_get_vm_from_pasid() is only valid while the lock is still being held. Once xa_unlock_irqrestore is called and returned, the pointer is no longer under lock and is subject to modification. Since, the caller still dereferences vm->task_info in amdgpu_vm_get_task_info_vm() after the lock is removed, this causes a use after unlock problem. Remove the lifetime issue present in amdgpu_vm_get_task_info_pasid() through removing the amdgpu_vm_get_vm_from_pasid() function from amdgpu_vm.c and making the relevant code inline to hold the lock while it is still in use. Signed-off-by: Shahyan Soltani Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f317f888b59f..f1dcf4f5bb78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2460,19 +2460,6 @@ static void amdgpu_vm_destroy_task_info(struct kref *kref) kfree(ti); } -static inline struct amdgpu_vm * -amdgpu_vm_get_vm_from_pasid(struct amdgpu_device *adev, u32 pasid) -{ - struct amdgpu_vm *vm; - unsigned long flags; - - xa_lock_irqsave(&adev->vm_manager.pasids, flags); - vm = xa_load(&adev->vm_manager.pasids, pasid); - xa_unlock_irqrestore(&adev->vm_manager.pasids, flags); - - return vm; -} - /** * amdgpu_vm_put_task_info - reference down the vm task_info ptr * @@ -2519,8 +2506,16 @@ amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm) struct amdgpu_task_info * amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid) { - return amdgpu_vm_get_task_info_vm( - amdgpu_vm_get_vm_from_pasid(adev, pasid)); + struct amdgpu_task_info *ti; + struct amdgpu_vm *vm; + unsigned long flags; + + xa_lock_irqsave(&adev->vm_manager.pasids, flags); + vm = xa_load(&adev->vm_manager.pasids, pasid); + ti = amdgpu_vm_get_task_info_vm(vm); + xa_unlock_irqrestore(&adev->vm_manager.pasids, flags); + + return ti; } static int amdgpu_vm_create_task_info(struct amdgpu_vm *vm) From f19d8086f6644083c913d70bfdeee20e1b6f46a5 Mon Sep 17 00:00:00 2001 From: David Francis Date: Mon, 6 Jul 2026 10:19:04 -0400 Subject: [PATCH 29/51] drm/amdkfd: Check bounds on CRIU restore queue type and mqd size We weren't checking whether the values provided in the private data in kfd CRIU restore were within bounds. For queue type, add a KFD_QUEUE_TYPE_MAX and ensure the provided type is less than it. For mqd_size, add new function mqd_size_from_queue_type and confirm that the provided mqd_size matches expectations. Reviewed-by: David Yat Sin Signed-off-by: David Francis Signed-off-by: Alex Deucher --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 6 +++++ .../drm/amd/amdkfd/kfd_device_queue_manager.h | 2 ++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 3 ++- .../amd/amdkfd/kfd_process_queue_manager.c | 24 +++++++++++++------ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 97402e6c8f83..cc42feb24277 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -3777,6 +3777,12 @@ bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm, dqm_unlock(dqm); return r; } + +size_t mqd_size_from_queue_type(struct device_queue_manager *dqm, enum kfd_queue_type type) +{ + return dqm->mqd_mgrs[get_mqd_type_from_queue_type(type)]->mqd_size; +} + #if defined(CONFIG_DEBUG_FS) static void seq_reg_dump(struct seq_file *m, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 2229f8b2f446..c9f9f7a87111 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -335,6 +335,8 @@ bool kfd_dqm_is_queue_in_process(struct device_queue_manager *dqm, int doorbell_off, u32 *queue_format); int kfd_reset_queue_mes(struct device_queue_manager *dqm, int queue_type, int pipe, int queue, unsigned int db); +size_t mqd_size_from_queue_type(struct device_queue_manager *dqm, + enum kfd_queue_type type); static inline unsigned int get_sh_mem_bases_32(struct kfd_process_device *pdd) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 86a944d36aaf..a55f119ecf4c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -441,7 +441,8 @@ enum kfd_queue_type { KFD_QUEUE_TYPE_SDMA, KFD_QUEUE_TYPE_HIQ, KFD_QUEUE_TYPE_SDMA_XGMI, - KFD_QUEUE_TYPE_SDMA_BY_ENG_ID + KFD_QUEUE_TYPE_SDMA_BY_ENG_ID, + KFD_QUEUE_TYPE_MAX, }; enum kfd_queue_format { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index d723b07379b3..002a374d224c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -1003,6 +1003,23 @@ int kfd_criu_restore_queue(struct kfd_process *p, goto exit; } + pdd = kfd_process_device_data_by_id(p, q_data->gpu_id); + if (!pdd) { + pr_err("Failed to get pdd\n"); + ret = -EINVAL; + goto exit; + } + + if (q_data->type >= KFD_QUEUE_TYPE_MAX) { + ret = -EINVAL; + goto exit; + } + + if (q_data->mqd_size != mqd_size_from_queue_type(pdd->dev->dqm, q_data->type)) { + ret = -EINVAL; + goto exit; + } + *priv_data_offset += sizeof(*q_data); q_extra_data_size = (uint64_t)q_data->ctl_stack_size + q_data->mqd_size; @@ -1025,13 +1042,6 @@ int kfd_criu_restore_queue(struct kfd_process *p, *priv_data_offset += q_extra_data_size; - pdd = kfd_process_device_data_by_id(p, q_data->gpu_id); - if (!pdd) { - pr_err("Failed to get pdd\n"); - ret = -EINVAL; - goto exit; - } - /* * data stored in this order: * mqd[xcc0], mqd[xcc1],..., ctl_stack[xcc0], ctl_stack[xcc1]... From 1cafa8b29e029eac3ddf64604f891b35dbf6262b Mon Sep 17 00:00:00 2001 From: David Francis Date: Tue, 30 Jun 2026 09:58:18 -0400 Subject: [PATCH 30/51] drm/amdkfd: Don't acquire buffers during CRIU queue restore. kfd_criu_restore_queue's call of kfd_queue_acquire_buffers was failing for multiple reasons - The ctl_stack_size set by the CRIU plugin doesn't match what is expected by acquire_buffers - The svm buffer cannot be acquired at this point because CRIU may not have restored it, or may have restored it to a different address. The only reason acquire_buffers was necessary here was to avoid a null ptr dereference in init_user_queue. Just put in a check for that dereference; it doesn't appear to come up in real use cases right now. That is, there is no usage of CRIU with shared MES. This is a partial revert of commit 20a5e7ffdfec ("drm/amdkfd: Properly acquire queue buffers in CRIU restore") Fixes: 20a5e7ffdfec ("drm/amdkfd: Properly acquire queue buffers in CRIU restore") Reviewed-by: David Yat Sin Signed-off-by: David Francis Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 002a374d224c..97e77a5a35e5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -265,6 +265,11 @@ static int init_user_queue(struct process_queue_manager *pqm, (*q)->process = pqm->process; if (dev->kfd->shared_resources.enable_mes) { + if (!q_properties->wptr_bo) { + pr_debug("Queue initialization with shared MES requires queue buffers to be initialized\n"); + return -EINVAL; + } + retval = amdgpu_amdkfd_alloc_kernel_mem(dev->adev, AMDGPU_MES_GANG_CTX_SIZE, AMDGPU_GEM_DOMAIN_GTT, @@ -1052,18 +1057,10 @@ int kfd_criu_restore_queue(struct kfd_process *p, memset(&qp, 0, sizeof(qp)); set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->xcc_mask)); - ret = kfd_queue_acquire_buffers(pdd, &qp); - if (ret) { - pr_debug("failed to acquire user queue buffers for CRIU\n"); - goto exit; - } - print_queue_properties(&qp); ret = pqm_create_queue(&p->pqm, pdd->dev, &qp, &queue_id, q_data, mqd, ctl_stack, NULL); if (ret) { - kfd_queue_unref_bo_vas(pdd, &qp); - kfd_queue_release_buffers(pdd, &qp); pr_err("Failed to create new queue err:%d\n", ret); goto exit; } From 8799ba6fb6a48438aea20c82e74c2f2a3d2b2e7a Mon Sep 17 00:00:00 2001 From: Zhu Lingshan Date: Wed, 1 Jul 2026 16:08:12 +0800 Subject: [PATCH 31/51] amdkfd: properly free secondary context id Function kfd_process_free_id() should skip over the primary kfd process because its context id is fixed assigned, not allocated through the ida table. This function should only work on secondary contexts. Fixes: fac682a1d1af ("amdkfd: identify a secondary kfd process by its id") Signed-off-by: Zhu Lingshan Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 7a604b8c8886..da4257c9aae0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -948,7 +948,7 @@ static void kfd_process_free_id(struct kfd_process *process) { struct kfd_process *primary_process; - if (process->context_id != KFD_CONTEXT_ID_PRIMARY) + if (process->context_id == KFD_CONTEXT_ID_PRIMARY) return; primary_process = kfd_lookup_process_by_mm(process->lead_thread->mm); From 6853f1f6cbbeb3f53ebbbd7286536aeb2c5d5f50 Mon Sep 17 00:00:00 2001 From: David Francis Date: Thu, 21 May 2026 09:18:59 -0400 Subject: [PATCH 32/51] drm/amdkfd: Check bounds in allocate_event_notification_slot The valid event ids go from 0 to KFD_SIGNAL_EVENT_LIMIT allocate_event_notification_slot has an option to specify an event id to allocate at, used by CRIU. We weren't checking the bounds on that value. Check them. v2: Lower bounds check is unecessary because of idr_alloc already rejecting negative numbers. Upper bounds check should be KFD_SIGNAL_EVENT_LIMIT since the signal mode mappings might not yet exist Signed-off-by: David Francis Reviewed-by: David Yat Sin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index dae01e2bb464..08532e9ff4a6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -61,6 +61,9 @@ static int allocate_event_notification_slot(struct kfd_process *p, return -ENOMEM; if (restore_id) { + if (*restore_id >= KFD_SIGNAL_EVENT_LIMIT) + return -EINVAL; + id = idr_alloc(&p->event_idr, ev, *restore_id, *restore_id + 1, GFP_KERNEL); } else { From 6807352cbabb74b61ba42888769283af72191f66 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 26 Jun 2026 16:29:13 -0400 Subject: [PATCH 33/51] drm/gfx10: Program DB_RING_CONTROL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed to allocate occlusion counters across both gfx pipes. Fixes: b7a1a0ef12b8 ("drm/amd/amdgpu: add pipe1 hardware support") Reviewed-by: Timur Kristóf Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 9d325867a1aa..55342962422b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -5350,6 +5350,15 @@ static void gfx_v10_0_constants_init(struct amdgpu_device *adev) gfx_v10_0_get_tcc_info(adev); adev->gfx.config.pa_sc_tile_steering_override = gfx_v10_0_init_pa_sc_tile_steering_override(adev); + /* Program DB_RING_CONTROL for multiple GFX pipes + * Default power up value is 1. + * Possible values: + * 0 - split occlusion counters between gfx pipes + * 1 - all occlusion counters to pipe 0 + * 2 - all occlusion counters to pipe 1 + */ + WREG32_FIELD15(GC, 0, DB_RING_CONTROL, COUNTER_CONTROL, + (adev->gfx.me.num_pipe_per_me > 1) ? 0 : 1); /* XXX SH_MEM regs */ /* where to put LDS, scratch, GPUVM in FSA64 space */ From aa087b5d2903df15a8a802e862f20b2309fc5de8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 26 Jun 2026 16:33:40 -0400 Subject: [PATCH 34/51] drm/gfx11: Program DB_RING_CONTROL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed to allocate occlusion counters across both gfx pipes. No functional change since we only use one gfx pipe at the moment (default value is 1). Reviewed-by: Timur Kristóf Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 254a72f26ec5..8214ef61ca92 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -2191,6 +2191,15 @@ static void gfx_v11_0_constants_init(struct amdgpu_device *adev) tmp = RREG32_SOC15(GC, 0, regTA_CNTL2); adev->gfx.config.ta_cntl2_truncate_coord_mode = REG_GET_FIELD(tmp, TA_CNTL2, TRUNCATE_COORD_MODE); + /* Program DB_RING_CONTROL for multiple GFX pipes + * Default power up value is 1. + * Possible values: + * 0 - split occlusion counters between gfx pipes + * 1 - all occlusion counters to pipe 0 + * 2 - all occlusion counters to pipe 1 + */ + WREG32_FIELD15_PREREG(GC, 0, DB_RING_CONTROL, COUNTER_CONTROL, + (adev->gfx.me.num_pipe_per_me > 1) ? 0 : 1); /* XXX SH_MEM regs */ /* where to put LDS, scratch, GPUVM in FSA64 space */ From 402ebe22b267783f3b05b714df224fad0223b278 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 26 Jun 2026 16:33:56 -0400 Subject: [PATCH 35/51] drm/gfx12: Program DB_RING_CONTROL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed to allocate occlusion counters across both gfx pipes. GFX 12 only has one gfx pipe, so no functional change since the default value is 1. Reviewed-by: Timur Kristóf Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index 8221a77b6b75..6fedb6df8db9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -1827,6 +1827,15 @@ static void gfx_v12_0_constants_init(struct amdgpu_device *adev) gfx_v12_0_get_cu_info(adev, &adev->gfx.cu_info); gfx_v12_0_get_tcc_info(adev); adev->gfx.config.pa_sc_tile_steering_override = 0; + /* Program DB_RING_CONTROL for multiple GFX pipes + * Default power up value is 1. + * Possible values: + * 0 - split occlusion counters between gfx pipes + * 1 - all occlusion counters to pipe 0 + * 2 - all occlusion counters to pipe 1 + */ + WREG32_FIELD15_PREREG(GC, 0, DB_RING_CONTROL, COUNTER_CONTROL, + (adev->gfx.me.num_pipe_per_me > 1) ? 0 : 1); /* XXX SH_MEM regs */ /* where to put LDS, scratch, GPUVM in FSA64 space */ From fec62b5e14254a7ce545f7a098c0b4aff88c6732 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 3 Feb 2026 11:31:48 -0500 Subject: [PATCH 36/51] drm/amdgpu/gfx11: enable gfx pipe1 hardware support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable gfx pipe1 hardware support. This is only available on gfx11 chips using the F32 microcontroller. Chips using the RS64 microcontroller are not able to use the second gfx pipe. In practice this means the second pipe is only available on APUs. This explains the stability issues Pierre-Eric saw previously with this on Navi33. Reviewed-by: Timur Kristóf Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 8214ef61ca92..2ef6bc818aba 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -51,7 +51,7 @@ #include "mes_userqueue.h" #include "amdgpu_userq_fence.h" -#define GFX11_NUM_GFX_RINGS 1 +#define GFX11_NUM_GFX_RINGS 2 #define GFX11_MEC_HPD_SIZE 2048 #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L @@ -1625,7 +1625,10 @@ static int gfx_v11_0_sw_init(struct amdgpu_ip_block *ip_block) case IP_VERSION(11, 7, 0): case IP_VERSION(11, 7, 1): adev->gfx.me.num_me = 1; - adev->gfx.me.num_pipe_per_me = 1; + if (adev->gfx.rs64_enable) + adev->gfx.me.num_pipe_per_me = 1; + else + adev->gfx.me.num_pipe_per_me = 2; adev->gfx.me.num_queue_per_pipe = 2; adev->gfx.mec.num_mec = 1; adev->gfx.mec.num_pipe_per_mec = 4; @@ -5366,6 +5369,7 @@ static void gfx_v11_0_ring_emit_gds_switch(struct amdgpu_ring *ring, static int gfx_v11_0_early_init(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; + int r; switch (amdgpu_user_queue) { case -1: @@ -5386,6 +5390,11 @@ static int gfx_v11_0_early_init(struct amdgpu_ip_block *ip_block) adev->gfx.funcs = &gfx_v11_0_gfx_funcs; + gfx_v11_0_set_imu_funcs(adev); + r = gfx_v11_0_init_microcode(adev); + if (r) + return r; + if (adev->gfx.disable_kq) { /* We need one GFX ring temporarily to set up * the clear state. @@ -5393,7 +5402,11 @@ static int gfx_v11_0_early_init(struct amdgpu_ip_block *ip_block) adev->gfx.num_gfx_rings = 1; adev->gfx.num_compute_rings = 0; } else { - adev->gfx.num_gfx_rings = GFX11_NUM_GFX_RINGS; + /* rs64 only supports one gfx pipe */ + if (adev->gfx.rs64_enable) + adev->gfx.num_gfx_rings = 1; + else + adev->gfx.num_gfx_rings = GFX11_NUM_GFX_RINGS; adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev), AMDGPU_MAX_COMPUTE_RINGS); } @@ -5404,13 +5417,12 @@ static int gfx_v11_0_early_init(struct amdgpu_ip_block *ip_block) gfx_v11_0_set_gds_init(adev); gfx_v11_0_set_rlc_funcs(adev); gfx_v11_0_set_mqd_funcs(adev); - gfx_v11_0_set_imu_funcs(adev); gfx_v11_0_init_rlcg_reg_access_ctrl(adev); amdgpu_init_rlc_reg_funcs(adev); - return gfx_v11_0_init_microcode(adev); + return 0; } static bool gfx_v11_0_is_rlc_enabled(struct amdgpu_device *adev) From 9af115ad50707b0471d1dd2a6c96f4dafa8f9346 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 18:40:49 -0400 Subject: [PATCH 37/51] drm/amdgpu: return an error instead of BUG() for CSA bo_va If the bo_va is not present, return an error rather than crashing the kernel. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index d777375e5350..d58701908158 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1118,7 +1118,8 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (fpriv->csa_va) { bo_va = fpriv->csa_va; - BUG_ON(!bo_va); + if (!bo_va) + return -ENOMEM; r = amdgpu_vm_bo_update(adev, bo_va, false); if (r) return r; From c24edbd5ae0e4f24e0179e8c9f22a867016177bb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 18:55:21 -0400 Subject: [PATCH 38/51] drm/amdgpu/gfx11: WARN() rather than BUG() for invalid SDMA engine There's no need to crash the kernel for these cases. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c index 8aa068a4d3e3..724beb96ed1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c @@ -139,7 +139,8 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev, regSDMA1_QUEUE0_RB_CNTL) - regSDMA0_QUEUE0_RB_CNTL; break; default: - BUG(); + WARN(1, "Invalid SDMA engine id %d\n", engine_id); + break; } sdma_rlc_reg_offset = sdma_engine_reg_base From 28cc342e2455c2c8f573bb0f0d8427a8199c1515 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 18:56:14 -0400 Subject: [PATCH 39/51] drm/amdgpu/gfx12: WARN() rather than BUG() for invalid SDMA engine There's no need to crash the kernel for these cases. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c index bf0bd7688ee4..e11ba3e91841 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12.c @@ -90,7 +90,8 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev, regSDMA1_QUEUE0_RB_CNTL) - regSDMA0_QUEUE0_RB_CNTL; break; default: - BUG(); + WARN(1, "Invalid SDMA engine id %d\n", engine_id); + break; } sdma_rlc_reg_offset = sdma_engine_reg_base From 9f8032604b9736cb484324432a6fcbda34acca17 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 18:56:39 -0400 Subject: [PATCH 40/51] drm/amdgpu/gfx12.1: WARN() rather than BUG() for invalid SDMA engine There's no need to crash the kernel for these cases. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c index bcb180f9d3ff..38ca1aea33b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v12_1.c @@ -93,7 +93,8 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev, regSDMA1_SDMA_QUEUE0_RB_CNTL) - regSDMA0_SDMA_QUEUE0_RB_CNTL; break; default: - BUG(); + WARN(1, "Invalid SDMA engine id %d\n", engine_id); + break; } sdma_rlc_reg_offset = sdma_engine_reg_base From d7c595044965c826e6f3ce30590d3ec4399cd633 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 18:57:29 -0400 Subject: [PATCH 41/51] drm/amdgpu/atomfirmware: WARN() rather than BUG() There's no need to crash the kernel for this case. Just return an error. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 6860a3a4d466..1e21e3444802 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -917,8 +917,6 @@ int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev) (crev != 6)) { spll->reference_freq = le32_to_cpu(gfx_info->v22.rlc_gpu_timer_refclk); ret = 0; - } else { - BUG(); } } } From 07359ed21ec48ebb6ef9819da72c12b0b858b311 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 18:58:33 -0400 Subject: [PATCH 42/51] drm/amdgpu/cgs: WARN() rather than BUG() There's no need to crash the kernel for these cases. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index babd23e5a27e..9bbe60968352 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -76,10 +76,9 @@ static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device, DRM_ERROR("audio endpt register access not implemented.\n"); return 0; default: - BUG(); + WARN(1, "Invalid indirect register space"); + return 0; } - WARN(1, "Invalid indirect register space"); - return 0; } static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device, @@ -104,9 +103,8 @@ static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device, DRM_ERROR("audio endpt register access not implemented.\n"); return; default: - BUG(); + WARN(1, "Invalid indirect register space"); } - WARN(1, "Invalid indirect register space"); } static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type) From c6b4a5080156e50a7cdca75a7ff3531e8efcc5d3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 19:02:37 -0400 Subject: [PATCH 43/51] drm/amdgpu/ucode: WARN() rather than BUG() There's no need to crash the kernel for this case. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 6d9e96fabd58..4f1c711df5bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -1478,7 +1478,8 @@ void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, ip_name = "isp"; break; default: - BUG(); + WARN(1, "invalid HWIP %d\n", block_type); + return; } maj = IP_VERSION_MAJ(version); From 1804cde52d4e0ecd1c75d4670ec6e813425c18d3 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 19:03:27 -0400 Subject: [PATCH 44/51] drm/amdgpu/cik_sdma: replace BUG() with an error There's no need to crash the kernel for this case. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik_sdma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index b703ef1fe340..b951328d94cf 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -125,7 +125,8 @@ static int cik_sdma_init_microcode(struct amdgpu_device *adev) case CHIP_MULLINS: chip_name = "mullins"; break; - default: BUG(); + default: + return -EINVAL; } for (i = 0; i < adev->sdma.num_instances; i++) { From 8fe5f5e2da26e9e8f2ddd639c5caad9cf215108b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 19:06:11 -0400 Subject: [PATCH 45/51] drm/amdgpu/sdma2.4: replace BUG() with an error There's no need to crash the kernel for this case. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 397b08c7173a..c7253b908351 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -138,7 +138,7 @@ static int sdma_v2_4_init_microcode(struct amdgpu_device *adev) chip_name = "topaz"; break; default: - BUG(); + return -EINVAL; } for (i = 0; i < adev->sdma.num_instances; i++) { From 9599e82b19a582ffa2d781a98a786a0d0822b041 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 19:06:42 -0400 Subject: [PATCH 46/51] drm/amdgpu/sdma3.0: replace BUG() with an error There's no need to crash the kernel for this case. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 8ac1c9dae72e..05cce4bde73e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -298,7 +298,8 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev) case CHIP_STONEY: chip_name = "stoney"; break; - default: BUG(); + default: + return -EINVAL; } for (i = 0; i < adev->sdma.num_instances; i++) { From af0e4c0eaf86b2b853ed12b994239cb21cebcda5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 19:09:39 -0400 Subject: [PATCH 47/51] drm/amdgpu/si: drop BUG()s There's no need to crash the kernel for these cases. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 6e455ad66d62..7100f30ffeff 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -2218,7 +2218,7 @@ static void si_init_golden_registers(struct amdgpu_device *adev) default: - BUG(); + break; } } @@ -2735,7 +2735,7 @@ int si_set_ip_blocks(struct amdgpu_device *adev) amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); break; default: - BUG(); + break; } return 0; } From 22b19c575e8e750ccee5d88b39c0ac2efc8c5870 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 15 Jun 2026 19:14:01 -0400 Subject: [PATCH 48/51] drm/amdgpu/gmc6: replace BUG() with an error There's no need to crash the kernel for this case. Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index a914dd8183b5..b49098931d19 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -124,7 +124,7 @@ static int gmc_v6_0_init_microcode(struct amdgpu_device *adev) chip_name = "hainan"; break; default: - BUG(); + return -EINVAL; } /* this memory configuration requires special firmware */ From c936b8126b444401318fcbeb1828488cc5312dee Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Mon, 6 Jul 2026 09:29:24 +0800 Subject: [PATCH 49/51] drm/amd/pm: fix smu14 power limit range calculation SMU14 derives the default PPT limit from SocketPowerLimitAc/Dc, but MsgLimits.Power may expose a different firmware limit for the same PPT0 throttler. Using those values independently as fixed min/max bases can report an incorrect configurable power range. Keep the socket power limit as the default value and as the fallback for current-limit queries. Calculate the reported range from both firmware values instead, using the lower value as the minimum base and the higher value as the maximum base before applying OD percentages. Signed-off-by: Yang Wang Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- .../drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c index d6cf643205ab..0fbcaf884419 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -1621,19 +1621,23 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu, table_context->power_play_table; PPTable_t *pptable = table_context->driver_pptable; CustomSkuTable_t *skutable = &pptable->CustomSkuTable; - int16_t od_percent_upper = 0, od_percent_lower = 0; + uint32_t pp_limit = smu->adev->pm.ac_power ? + skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] : + skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0]; uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; - uint32_t power_limit; + uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit); + uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit); + int16_t od_percent_upper = 0, od_percent_lower = 0; + int ret; - if (smu_v14_0_get_current_power_limit(smu, &power_limit)) - power_limit = smu->adev->pm.ac_power ? - skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] : - skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0]; + if (current_power_limit) { + ret = smu_v14_0_get_current_power_limit(smu, current_power_limit); + if (ret) + *current_power_limit = pp_limit; + } - if (current_power_limit) - *current_power_limit = power_limit; if (default_power_limit) - *default_power_limit = power_limit; + *default_power_limit = pp_limit; if (powerplay_table) { if (smu->od_enabled && @@ -1647,15 +1651,15 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu, } dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n", - od_percent_upper, od_percent_lower, power_limit); + od_percent_upper, od_percent_lower, pp_limit); if (max_power_limit) { - *max_power_limit = msg_limit * (100 + od_percent_upper); + *max_power_limit = max_limit * (100 + od_percent_upper); *max_power_limit /= 100; } if (min_power_limit) { - *min_power_limit = power_limit * (100 + od_percent_lower); + *min_power_limit = min_limit * (100 + od_percent_lower); *min_power_limit /= 100; } From 325de6bf3328efd5acf5072337fc196928753de8 Mon Sep 17 00:00:00 2001 From: Zhu Lingshan Date: Wed, 1 Jul 2026 11:03:09 +0800 Subject: [PATCH 50/51] drm/amdkfd: expose pasid of secondary contexts by debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current kfd debugfs interfaces only expose pasid of the primary process, this commit exposes pasid of secondary contexts by debugfs Just like entries under sysfs, the secondary contexts are named as context_ under its primary kfd process. The layout: /sys/kernel/debug/kfd/proc# tree . └── 5802 ├── context_0 │   ├── pasid_1025 │   └── pasid_63266 ├── context_1 │   ├── pasid_1025 │   └── pasid_63266 ├── pasid_1025 └── pasid_63266 Another fix is, kfd_debugfs_add_process may fail, this commit change it to return a meaningful value other than void Signed-off-by: Zhu Lingshan Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 5 + drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c | 119 ++++++++++++++++++----- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 5 +- 4 files changed, 107 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 411ee894f623..2c1a936459ac 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -3303,6 +3303,11 @@ static int kfd_ioctl_create_process(struct file *filep, struct kfd_process *p, v } filep->private_data = process; + ret = kfd_debugfs_add_process(process); + if (ret) + pr_warn("Failed to create debugfs entry for the kfd_process, ret = %d\n", + ret); + mutex_unlock(&kfd_processes_mutex); ret = kfd_create_process_sysfs(process); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c b/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c index 7d4e07452cdb..464836f2a53f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c @@ -33,6 +33,7 @@ static struct list_head procs; struct debugfs_proc_entry { struct list_head list; struct dentry *proc_dentry; + struct kfd_process *process; pid_t pid; }; @@ -140,34 +141,97 @@ static const struct file_operations kfd_debugfs_pasid_fops = { .read = kfd_debugfs_pasid_read, }; -void kfd_debugfs_add_process(struct kfd_process *p) +/* This helper locates the debugfs entry of a kfd process */ +static struct debugfs_proc_entry *kfd_debugfs_find_process_entry(struct kfd_process *p) { - int i; - char name[MAX_DEBUGFS_FILENAME_LEN]; struct debugfs_proc_entry *entry; + list_for_each_entry(entry, &procs, list) { + if (entry->process == p) + return entry; + } + + return NULL; +} + +/* This helper creates pasid file of a kfd process under debugfs */ +static void kfd_debugfs_create_pasid_files(struct kfd_process *p, + struct dentry *dir) +{ + char name[MAX_DEBUGFS_FILENAME_LEN]; + struct kfd_process_device *pdd; + int i; + + /* create pasid file for each GPU */ + for (i = 0; i < p->n_pdds; i++) { + pdd = p->pdds[i]; + snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "pasid_%u", pdd->dev->id); + debugfs_create_file((const char *)name, S_IFREG | 0444, + dir, pdd, &kfd_debugfs_pasid_fops); + } +} + +int kfd_debugfs_add_process(struct kfd_process *p) +{ + struct debugfs_proc_entry *primary_entry; + char name[MAX_DEBUGFS_FILENAME_LEN]; + struct kfd_process *primary_process; + struct debugfs_proc_entry *entry; + int ret; + entry = kzalloc_obj(*entry); if (!entry) - return; + return -ENOMEM; + + entry->process = p; + entry->pid = p->lead_thread->pid; + + if (p->context_id == KFD_CONTEXT_ID_PRIMARY) { + snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "%d", + (int)entry->pid); + entry->proc_dentry = debugfs_create_dir(name, debugfs_proc); + } else { + primary_process = kfd_lookup_process_by_mm(p->lead_thread->mm); + if (!primary_process) { + ret = -ESRCH; + goto err_free_entry; + } + + primary_entry = kfd_debugfs_find_process_entry(primary_process); + kfd_unref_process(primary_process); + if (!primary_entry) { + pr_warn("Failed to find the primary debugfs entry for pid %d\n", + entry->pid); + ret = -ENOENT; + goto err_free_entry; + } + + snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "context_%u", + p->context_id); + entry->proc_dentry = debugfs_create_dir(name, + primary_entry->proc_dentry); + } + if (IS_ERR_OR_NULL(entry->proc_dentry)) { + ret = entry->proc_dentry ? PTR_ERR(entry->proc_dentry) : -ENOMEM; + goto err_free_entry; + } list_add(&entry->list, &procs); - entry->pid = p->lead_thread->pid; - snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "%d", - (int)entry->pid); - entry->proc_dentry = debugfs_create_dir(name, debugfs_proc); + kfd_debugfs_create_pasid_files(p, entry->proc_dentry); - /* Create debugfs files for each GPU: - * - proc//pasid_ - */ - for (i = 0; i < p->n_pdds; i++) { - struct kfd_process_device *pdd = p->pdds[i]; + return 0; - snprintf(name, MAX_DEBUGFS_FILENAME_LEN, "pasid_%u", - pdd->dev->id); - debugfs_create_file((const char *)name, S_IFREG | 0444, - entry->proc_dentry, pdd, - &kfd_debugfs_pasid_fops); - } +err_free_entry: + kfree(entry); + return ret; +} + +/* This helper removes a debugfs entry and its sub-entries */ +static void kfd_debugfs_remove_entry(struct debugfs_proc_entry *entry) +{ + debugfs_remove(entry->proc_dentry); + list_del(&entry->list); + kfree(entry); } void kfd_debugfs_remove_process(struct kfd_process *p) @@ -175,13 +239,22 @@ void kfd_debugfs_remove_process(struct kfd_process *p) struct debugfs_proc_entry *entry, *next; mutex_lock(&kfd_processes_mutex); + if (p->context_id == KFD_CONTEXT_ID_PRIMARY) { + /* remove entries of secondary contexts */ + list_for_each_entry_safe(entry, next, &procs, list) { + if (entry->pid != p->lead_thread->pid || entry->process == p) + continue; + + kfd_debugfs_remove_entry(entry); + } + } + list_for_each_entry_safe(entry, next, &procs, list) { - if (entry->pid != p->lead_thread->pid) + if (entry->process != p) continue; - debugfs_remove_recursive(entry->proc_dentry); - list_del(&entry->list); - kfree(entry); + kfd_debugfs_remove_entry(entry); } + mutex_unlock(&kfd_processes_mutex); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index a55f119ecf4c..88191a4c1657 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1651,14 +1651,14 @@ int kfd_debugfs_hang_hws(struct kfd_node *dev); int pm_debugfs_hang_hws(struct packet_manager *pm); int dqm_debugfs_hang_hws(struct device_queue_manager *dqm); -void kfd_debugfs_add_process(struct kfd_process *p); +int kfd_debugfs_add_process(struct kfd_process *p); void kfd_debugfs_remove_process(struct kfd_process *p); #else static inline void kfd_debugfs_init(void) {} static inline void kfd_debugfs_fini(void) {} -static inline void kfd_debugfs_add_process(struct kfd_process *p) {} +static inline int kfd_debugfs_add_process(struct kfd_process *p) { return 0; } static inline void kfd_debugfs_remove_process(struct kfd_process *p) {} #endif diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index da4257c9aae0..eb508fe3ded7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1013,7 +1013,10 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) if (ret) pr_warn("Failed to create sysfs entry for the kfd_process"); - kfd_debugfs_add_process(process); + ret = kfd_debugfs_add_process(process); + if (ret) + pr_warn("Failed to create debugfs entry for the kfd_process, ret = %d\n", + ret); init_waitqueue_head(&process->wait_irq_drain); } From 5c6c247992d4d9200e073b83f4ec6c703c096845 Mon Sep 17 00:00:00 2001 From: David Francis Date: Tue, 12 May 2026 14:49:41 -0400 Subject: [PATCH 51/51] drm/amdkfd: Check bounds on CRIU restore event id The valid amdkfd event ids go from 0 to KFD_SIGNAL_EVENT_LIMIT - 1. During CRIU restore, ensure that the provided event ids are in that range. v2: No need for lower bound check since idr_alloc rejects negative inputs v3: Also change error message to reflect new error condition Reviewed-by: David Yat Sin Signed-off-by: David Francis Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 08532e9ff4a6..f5fd78f0df7d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -161,7 +161,7 @@ static int create_signal_event(struct file *devkfd, struct kfd_process *p, ret = allocate_event_notification_slot(p, ev, restore_id); if (ret) { - pr_warn("Signal event wasn't created because out of kernel memory\n"); + pr_warn("Failed to create signal event notification slot\n"); return ret; }