Call amdgpu_amdkfd_pre_reset() before the lock, for gpu_recover and PCI
error handling. Skip the dequeue when the HWS is hung or the PCI link is
down, so recovery does not wait out the preemption timeout.
Signed-off-by: William Palacek <[email protected]>
---
Notes:
v2:
- Drop the SRC_USER gate and the helper; run for every reset source
- Cover amdgpu_pci_error_detected() as well as gpu_recover()
- Skip the dequeue when the HWS is hung or the PCI link is down
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 16 ++++++++++++++--
.../drm/amd/amdkfd/kfd_device_queue_manager.c | 14 ++++++++++++++
2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index e0014611f039..8ae6228dbf31 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5479,6 +5479,16 @@ static void
amdgpu_device_recovery_prepare(struct amdgpu_device *adev,
}
}
+/* Dequeueing needs reset_domain->sem for read, so run before it
is write-locked */
+static void amdgpu_device_kfd_pre_reset(struct amdgpu_reset_context
*reset_context,
+ struct list_head *device_list)
+{
+ struct amdgpu_device *tmp_adev;
+
+ list_for_each_entry(tmp_adev, device_list, reset_list)
+ amdgpu_amdkfd_pre_reset(tmp_adev, reset_context);
+}
+
static void amdgpu_device_recovery_get_reset_lock(struct
amdgpu_device *adev,
struct list_head *device_list)
{
@@ -5534,8 +5544,6 @@ static void
amdgpu_device_halt_activities(struct amdgpu_device *adev,
cancel_delayed_work_sync(&tmp_adev->delayed_init_work);
- amdgpu_amdkfd_pre_reset(tmp_adev, reset_context);
-
/*
* Mark these ASICs to be reset as untracked first
* And add them back after reset completed
@@ -5784,6 +5792,9 @@ int amdgpu_device_gpu_recover(struct
amdgpu_device *adev,
/* Cannot be called after locking reset domain */
amdgpu_ras_pre_reset(adev, &device_list);
+ /* Cannot be called after locking reset domain either */
+ amdgpu_device_kfd_pre_reset(reset_context, &device_list);
+
/* We need to lock reset domain only once both for XGMI and
single device */
amdgpu_device_recovery_get_reset_lock(adev, &device_list);
@@ -6232,6 +6243,7 @@ pci_ers_result_t
amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta
INIT_LIST_HEAD(&device_list);
amdgpu_device_recovery_prepare(adev, &device_list, hive);
+ amdgpu_device_kfd_pre_reset(&reset_context, &device_list);
amdgpu_device_recovery_get_reset_lock(adev, &device_list);
amdgpu_device_halt_activities(adev, NULL, &reset_context,
&device_list,
hive, false);
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 5e57576fba21..988fce11a4fb 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -81,6 +81,16 @@ static void set_queue_as_reset(struct
device_queue_manager *dqm, struct queue *q
struct qcm_process_device *qpd, bool verbose);
static int reset_queues_mes(struct device_queue_manager *dqm,
struct queue *q);
+/*
+ * A dead HWS or an offline PCI link cannot service a dequeue
request. Skip it
+ * rather than wait out queue_preemption_timeout_ms per node.
+ */
+static inline bool kfd_dqm_can_reach_hw(struct device_queue_manager
*dqm)
+{
+ return !dqm->is_hws_hang &&
+ dqm->dev->adev->pci_channel_state == pci_channel_io_normal;