AMD General Except for the eeprom table compatibility is pending for validation, the others look good to me in general.
The series is Reviewed-by: Hawking Zhang <[email protected]> Regards, Hawking -----Original Message----- From: Sun, Ce(Overlord) <[email protected]> Sent: Thursday, June 25, 2026 16:19 To: [email protected] Cc: Zhang, Hawking <[email protected]>; Chai, Thomas <[email protected]>; Zhou1, Tao <[email protected]>; Yang, Stanley <[email protected]>; Sun, Ce(Overlord) <[email protected]> Subject: [PATCH v3 01/44] drm/amdgpu: Retire legacy page retirement RAS code Remove the deprecated legacy RAS code path for page retirement Signed-off-by: Ce Sun <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 304 +----------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 23 -- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 13 +- drivers/gpu/drm/amd/amdgpu/umc_v12_0.c | 17 -- 4 files changed, 2 insertions(+), 355 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 8a49ae4c0132..8095f284d531 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -128,12 +128,6 @@ const char *get_ras_block_str(struct ras_common_if *ras_block) /* typical ECC bad page rate is 1 bad page per 100MB VRAM */ #define RAS_BAD_PAGE_COVER (100 * 1024 * 1024ULL) -#define MAX_UMC_POISON_POLLING_TIME_ASYNC 10 - -#define AMDGPU_RAS_RETIRE_PAGE_INTERVAL 100 //ms - -#define MAX_FLUSH_RETIRE_DWORK_TIMES 100 - #define BYPASS_ALLOCATED_ADDRESS 0x0 #define BYPASS_INITIALIZATION_ADDRESS 0x1 @@ -2489,14 +2483,6 @@ static void amdgpu_ras_interrupt_poison_creation_handler(struct ras_manager *obj event_id = amdgpu_ras_acquire_event_id(adev, type); RAS_EVENT_LOG(adev, event_id, "Poison is created\n"); - if (amdgpu_ip_version(obj->adev, UMC_HWIP, 0) >= IP_VERSION(12, 0, 0)) { - struct amdgpu_ras *con = amdgpu_ras_get_context(obj->adev); - - atomic_inc(&con->page_retirement_req_cnt); - atomic_inc(&con->poison_creation_count); - - wake_up(&con->page_retirement_wq); - } } static void amdgpu_ras_interrupt_umc_handler(struct ras_manager *obj, @@ -3550,38 +3536,6 @@ static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev, } } -int amdgpu_ras_put_poison_req(struct amdgpu_device *adev, - enum amdgpu_ras_block block, uint16_t pasid, - pasid_notify pasid_fn, void *data, uint32_t reset) -{ - int ret = 0; - struct ras_poison_msg poison_msg; - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - - memset(&poison_msg, 0, sizeof(poison_msg)); - poison_msg.block = block; - poison_msg.pasid = pasid; - poison_msg.reset = reset; - poison_msg.pasid_fn = pasid_fn; - poison_msg.data = data; - - ret = kfifo_put(&con->poison_fifo, poison_msg); - if (!ret) { - dev_err(adev->dev, "Poison message fifo is full!\n"); - return -ENOSPC; - } - - return 0; -} - -static int amdgpu_ras_get_poison_req(struct amdgpu_device *adev, - struct ras_poison_msg *poison_msg) -{ - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - - return kfifo_get(&con->poison_fifo, poison_msg); -} - static void amdgpu_ras_ecc_log_init(struct ras_ecc_log_info *ecc_log) { mutex_init(&ecc_log->lock); @@ -3611,232 +3565,6 @@ static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log) ecc_log->consumption_q_count = 0; } -static bool amdgpu_ras_schedule_retirement_dwork(struct amdgpu_ras *con, - uint32_t delayed_ms) -{ - int ret; - - mutex_lock(&con->umc_ecc_log.lock); - ret = radix_tree_tagged(&con->umc_ecc_log.de_page_tree, - UMC_ECC_NEW_DETECTED_TAG); - mutex_unlock(&con->umc_ecc_log.lock); - - if (ret) - schedule_delayed_work(&con->page_retirement_dwork, - msecs_to_jiffies(delayed_ms)); - - return ret ? true : false; -} - -static void amdgpu_ras_do_page_retirement(struct work_struct *work) -{ - struct amdgpu_ras *con = container_of(work, struct amdgpu_ras, - page_retirement_dwork.work); - struct amdgpu_device *adev = con->adev; - struct ras_err_data err_data; - - /* If gpu reset is ongoing, delay retiring the bad pages */ - if (amdgpu_in_reset(adev) || amdgpu_ras_in_recovery(adev)) { - amdgpu_ras_schedule_retirement_dwork(con, - AMDGPU_RAS_RETIRE_PAGE_INTERVAL * 3); - return; - } - - amdgpu_ras_error_data_init(&err_data); - - amdgpu_umc_handle_bad_pages(adev, &err_data); - - amdgpu_ras_error_data_fini(&err_data); - - amdgpu_ras_schedule_retirement_dwork(con, - AMDGPU_RAS_RETIRE_PAGE_INTERVAL); -} - -static int amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev, - uint32_t poison_creation_count) -{ - int ret = 0; - struct ras_ecc_log_info *ecc_log; - struct ras_query_if info; - u32 timeout = MAX_UMC_POISON_POLLING_TIME_ASYNC; - struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - u64 de_queried_count; - u64 consumption_q_count; - enum ras_event_type type = RAS_EVENT_TYPE_POISON_CREATION; - - memset(&info, 0, sizeof(info)); - info.head.block = AMDGPU_RAS_BLOCK__UMC; - - ecc_log = &ras->umc_ecc_log; - ecc_log->de_queried_count = 0; - ecc_log->consumption_q_count = 0; - - do { - ret = amdgpu_ras_query_error_status_with_event(adev, &info, type); - if (ret) - return ret; - - de_queried_count = ecc_log->de_queried_count; - consumption_q_count = ecc_log->consumption_q_count; - - if (de_queried_count && consumption_q_count) - break; - - msleep(100); - } while (--timeout); - - if (de_queried_count) - schedule_delayed_work(&ras->page_retirement_dwork, 0); - - if (amdgpu_ras_is_rma(adev) && atomic_cmpxchg(&ras->rma_in_recovery, 0, 1) == 0) - amdgpu_ras_reset_gpu(adev); - - return 0; -} - -static void amdgpu_ras_clear_poison_fifo(struct amdgpu_device *adev) -{ - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - struct ras_poison_msg msg; - int ret; - - do { - ret = kfifo_get(&con->poison_fifo, &msg); - } while (ret); -} - -static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev, - uint32_t msg_count, uint32_t *gpu_reset) -{ - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - uint32_t reset_flags = 0, reset = 0; - struct ras_poison_msg msg; - int ret, i; - - kgd2kfd_set_sram_ecc_flag(adev->kfd.dev); - - for (i = 0; i < msg_count; i++) { - ret = amdgpu_ras_get_poison_req(adev, &msg); - if (!ret) - continue; - - if (msg.pasid_fn) - msg.pasid_fn(adev, msg.pasid, msg.data); - - reset_flags |= msg.reset; - } - - /* - * Try to ensure poison creation handler is completed first - * to set rma if bad page exceed threshold. - */ - flush_delayed_work(&con->page_retirement_dwork); - - /* for RMA, amdgpu_ras_poison_creation_handler will trigger gpu reset */ - if (reset_flags && !amdgpu_ras_is_rma(adev)) { - if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE1_RESET) - reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET; - else if (reset_flags & AMDGPU_RAS_GPU_RESET_MODE2_RESET) - reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET; - else - reset = reset_flags; - - con->gpu_reset_flags |= reset; - amdgpu_ras_reset_gpu(adev); - - *gpu_reset = reset; - - /* Wait for gpu recovery to complete */ - flush_work(&con->recovery_work); - } - - return 0; -} - -static int amdgpu_ras_page_retirement_thread(void *param) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)param; - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - uint32_t poison_creation_count, msg_count; - uint32_t gpu_reset; - int ret; - - while (!kthread_should_stop()) { - - wait_event_interruptible(con->page_retirement_wq, - kthread_should_stop() || - atomic_read(&con->page_retirement_req_cnt)); - - if (kthread_should_stop()) - break; - - mutex_lock(&con->poison_lock); - gpu_reset = 0; - - do { - poison_creation_count = atomic_read(&con->poison_creation_count); - ret = amdgpu_ras_poison_creation_handler(adev, poison_creation_count); - if (ret == -EIO) - break; - - if (poison_creation_count) { - atomic_sub(poison_creation_count, &con->poison_creation_count); - atomic_sub(poison_creation_count, &con->page_retirement_req_cnt); - } - } while (atomic_read(&con->poison_creation_count) && - !atomic_read(&con->poison_consumption_count)); - - if (ret != -EIO) { - msg_count = kfifo_len(&con->poison_fifo); - if (msg_count) { - ret = amdgpu_ras_poison_consumption_handler(adev, - msg_count, &gpu_reset); - if ((ret != -EIO) && - (gpu_reset != AMDGPU_RAS_GPU_RESET_MODE1_RESET)) - atomic_sub(msg_count, &con->page_retirement_req_cnt); - } - } - - if ((ret == -EIO) || (gpu_reset == AMDGPU_RAS_GPU_RESET_MODE1_RESET)) { - /* gpu mode-1 reset is ongoing or just completed ras mode-1 reset */ - /* Clear poison creation request */ - atomic_set(&con->poison_creation_count, 0); - atomic_set(&con->poison_consumption_count, 0); - - /* Clear poison fifo */ - amdgpu_ras_clear_poison_fifo(adev); - - /* Clear all poison requests */ - atomic_set(&con->page_retirement_req_cnt, 0); - - if (ret == -EIO) { - /* Wait for mode-1 reset to complete */ - down_read(&adev->reset_domain->sem); - up_read(&adev->reset_domain->sem); - } - - /* Wake up work to save bad pages to eeprom */ - schedule_delayed_work(&con->page_retirement_dwork, 0); - } else if (gpu_reset) { - /* gpu just completed mode-2 reset or other reset */ - /* Clear poison consumption messages cached in fifo */ - msg_count = kfifo_len(&con->poison_fifo); - if (msg_count) { - amdgpu_ras_clear_poison_fifo(adev); - atomic_sub(msg_count, &con->page_retirement_req_cnt); - } - - atomic_set(&con->poison_consumption_count, 0); - - /* Wake up work to save bad pages to eeprom */ - schedule_delayed_work(&con->page_retirement_dwork, 0); - } - mutex_unlock(&con->poison_lock); - } - - return 0; -} - int amdgpu_ras_init_badpage_info(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -3917,10 +3645,8 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev, bool init_bp_info) } mutex_init(&con->recovery_lock); - mutex_init(&con->poison_lock); INIT_WORK(&con->recovery_work, amdgpu_ras_do_recovery); atomic_set(&con->in_recovery, 0); - atomic_set(&con->rma_in_recovery, 0); con->eeprom_control.bad_channel_bitmap = 0; max_eeprom_records_count = amdgpu_ras_eeprom_max_record_count(&con->eeprom_control); @@ -3933,20 +3659,8 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev, bool init_bp_info) } mutex_init(&con->page_rsv_lock); - INIT_KFIFO(con->poison_fifo); mutex_init(&con->page_retirement_lock); - init_waitqueue_head(&con->page_retirement_wq); - atomic_set(&con->page_retirement_req_cnt, 0); - atomic_set(&con->poison_creation_count, 0); - atomic_set(&con->poison_consumption_count, 0); - con->page_retirement_thread = - kthread_run(amdgpu_ras_page_retirement_thread, adev, "umc_page_retirement"); - if (IS_ERR(con->page_retirement_thread)) { - con->page_retirement_thread = NULL; - dev_warn(adev->dev, "Failed to create umc_page_retirement thread!!!\n"); - } - - INIT_DELAYED_WORK(&con->page_retirement_dwork, amdgpu_ras_do_page_retirement); + amdgpu_ras_ecc_log_init(&con->umc_ecc_log); #ifdef CONFIG_X86_MCE_AMD if ((adev->asic_type == CHIP_ALDEBARAN) && @@ -3978,31 +3692,15 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_err_handler_data *data = con->eh_data; - int max_flush_timeout = MAX_FLUSH_RETIRE_DWORK_TIMES; - bool ret; /* recovery_init failed to init it, fini is useless */ if (!data) return 0; - /* Save all cached bad pages to eeprom */ - do { - flush_delayed_work(&con->page_retirement_dwork); - ret = amdgpu_ras_schedule_retirement_dwork(con, 0); - } while (ret && max_flush_timeout--); - - if (con->page_retirement_thread) - kthread_stop(con->page_retirement_thread); - - atomic_set(&con->page_retirement_req_cnt, 0); - atomic_set(&con->poison_creation_count, 0); - mutex_destroy(&con->page_rsv_lock); cancel_work_sync(&con->recovery_work); - cancel_delayed_work_sync(&con->page_retirement_dwork); - amdgpu_ras_ecc_log_fini(&con->umc_ecc_log); mutex_lock(&con->recovery_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index a86ab65aa2f0..1629a242d58e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -466,14 +466,6 @@ struct ras_query_context { typedef int (*pasid_notify)(struct amdgpu_device *adev, uint16_t pasid, void *data); -struct ras_poison_msg { - enum amdgpu_ras_block block; - uint16_t pasid; - uint32_t reset; - pasid_notify pasid_fn; - void *data; -}; - struct ras_err_pages { uint32_t count; uint64_t *pfn; @@ -549,7 +541,6 @@ struct amdgpu_ras { /* gpu recovery */ struct work_struct recovery_work; atomic_t in_recovery; - atomic_t rma_in_recovery; struct amdgpu_device *adev; /* error handler data */ struct ras_err_handler_data *eh_data; @@ -587,16 +578,9 @@ struct amdgpu_ras { /* Record special requirements of gpu reset caller */ uint32_t gpu_reset_flags; - struct task_struct *page_retirement_thread; - wait_queue_head_t page_retirement_wq; struct mutex page_retirement_lock; - atomic_t page_retirement_req_cnt; - atomic_t poison_creation_count; - atomic_t poison_consumption_count; struct mutex page_rsv_lock; - DECLARE_KFIFO(poison_fifo, struct ras_poison_msg, 128); struct ras_ecc_log_info umc_ecc_log; - struct delayed_work page_retirement_dwork; /* ras errors detected */ unsigned long ras_err_state; @@ -615,9 +599,6 @@ struct amdgpu_ras { struct list_head critical_region_head; struct mutex critical_region_lock; - /* Protect poison injection */ - struct mutex poison_lock; - /* Disable/Enable uniras switch */ bool uniras_enabled; const struct ras_smu_drv *ras_smu_drv; @@ -1029,10 +1010,6 @@ int amdgpu_ras_reserve_page(struct amdgpu_device *adev, uint64_t pfn); int amdgpu_ras_add_critical_region(struct amdgpu_device *adev, struct amdgpu_bo *bo); bool amdgpu_ras_check_critical_address(struct amdgpu_device *adev, uint64_t addr); -int amdgpu_ras_put_poison_req(struct amdgpu_device *adev, - enum amdgpu_ras_block block, uint16_t pasid, - pasid_notify pasid_fn, void *data, uint32_t reset); - bool amdgpu_ras_in_recovery(struct amdgpu_device *adev); __printf(3, 4) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index a250109edb63..f22d07e9c29c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -276,7 +276,7 @@ int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev, } amdgpu_ras_error_data_fini(&err_data); - } else if (amdgpu_uniras_enabled(adev)) { + } else { struct ras_ih_info ih_info = {0}; ih_info.block = block; @@ -285,17 +285,6 @@ int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev, ih_info.pasid_fn = pasid_fn; ih_info.data = data; amdgpu_ras_mgr_handle_consumer_interrupt(adev, &ih_info); - } else { - struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - int ret; - - ret = amdgpu_ras_put_poison_req(adev, - block, pasid, pasid_fn, data, reset); - if (!ret) { - atomic_inc(&con->page_retirement_req_cnt); - atomic_inc(&con->poison_consumption_count); - wake_up(&con->page_retirement_wq); - } } } else { if (adev->virt.ops && adev->virt.ops->ras_poison_handler) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c index a6df6a778f50..749c1f845ac6 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c @@ -656,23 +656,6 @@ static int umc_v12_0_update_ecc_status(struct amdgpu_device *adev, for (i = 0; i < count; i++) amdgpu_ras_reserve_page(adev, page_pfn[i]); - /* The problem case is as follows: - * 1. GPU A triggers a gpu ras reset, and GPU A drives - * GPU B to also perform a gpu ras reset. - * 2. After gpu B ras reset started, gpu B queried a DE - * data. Since the DE data was queried in the ras reset - * thread instead of the page retirement thread, bad - * page retirement work would not be triggered. Then - * even if all gpu resets are completed, the bad pages - * will be cached in RAM until GPU B's bad page retirement - * work is triggered again and then saved to eeprom. - * Trigger delayed work to save the bad pages to eeprom in time - * after gpu ras reset is completed. - */ - if (amdgpu_ras_in_recovery(adev)) - schedule_delayed_work(&con->page_retirement_dwork, - msecs_to_jiffies(DELAYED_TIME_FOR_GPU_RESET)); - return 0; } -- 2.34.1
