From c4d9c64c11427ba88448c8c54b89bcfb13da7a29 Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Tue, 22 Sep 2026 16:41:57 -0400 Subject: [PATCH] drm/amdgpu: re-check connection state before sending NPA-REVOKE The export cleanup worker checks amdgpu_ualink_check_conn_ready() once when building npa_release_bitmap, but not again in the send loop. Cleanup workers run concurrently on the unbounded NPA WQ (one per exported handle), so when a peer's egress dies many workers have already seeded npa_release_bitmap from a connection that was still ESTABLISHED and all issue an LSDMA copy to the dead peer, flooding the log with repeated NPA-REVOKE send failures. Re-check the connection immediately before each send, as the tlb shootdown, force_retry_rpcs and unmap_all_npa_addr loops already do, so once the first worker marks a peer NOT_READY the rest skip it. With the re-check in place, seed npa_release_bitmap with a single bitmap_copy() of importers_bitmap instead of a separate build loop; peers that fail the re-check or the send are dropped from the bitmap in the send loop. Signed-off-by: Mukul Joshi Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c | 35 +++++++++++++--------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c index 39b7cc8bc1c5..f6ad64be4349 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c @@ -2936,19 +2936,12 @@ static void amdgpu_ualink_exp_cleanup_worker(struct work_struct *work) amdgpu_bo_unref(&bo); exp_xa_node->bo = NULL; - /* Build the full npa_release_bitmap before sending any NPA-REVOKE. */ - for_each_set_bit(remote_acc_id, exp_xa_node->importers_bitmap, - AMDGPU_UALINK_ACCEL_MAX) { - imp_entry = &exp_xa_node->importer_entries[remote_acc_id]; - if (!amdgpu_ualink_check_conn_ready(adev, remote_acc_id, - imp_entry->generation_count)) { - clear_bit(remote_acc_id, - exp_xa_node->importers_bitmap); - continue; - } - - set_bit(remote_acc_id, exp_xa_node->npa_release_bitmap); - } + /* Seed npa_release_bitmap with all importers before any NPA-REVOKE, so + * the release IRQ only sees it empty once every responder has replied. + * Dead peers are dropped from it in the send loop below. + */ + bitmap_copy(exp_xa_node->npa_release_bitmap, + exp_xa_node->importers_bitmap, AMDGPU_UALINK_ACCEL_MAX); /* Send NPA-REVOKE to all importers which have imported this memory. * On send failure clear the bit (no response will arrive) and mark the @@ -2956,6 +2949,21 @@ static void amdgpu_ualink_exp_cleanup_worker(struct work_struct *work) */ for_each_set_bit(remote_acc_id, exp_xa_node->importers_bitmap, AMDGPU_UALINK_ACCEL_MAX) { + imp_entry = &exp_xa_node->importer_entries[remote_acc_id]; + + /* Re-check the connection right before the send: concurrent + * cleanup workers all seed the bitmap while the peer is still + * ESTABLISHED, so once its egress dies and the first worker + * marks it NOT_READY, this skips the rest instead of flooding + * the log with failed LSDMA sends to the same dead peer. + */ + if (!amdgpu_ualink_check_conn_ready(adev, remote_acc_id, + imp_entry->generation_count)) { + clear_bit(remote_acc_id, + exp_xa_node->npa_release_bitmap); + continue; + } + dev_dbg(adev->dev, "EXP-CLEANUP: Sending NPA-REVOKE to remote:%u\n", remote_acc_id); @@ -2966,7 +2974,6 @@ static void amdgpu_ualink_exp_cleanup_worker(struct work_struct *work) remote_acc_id); clear_bit(remote_acc_id, exp_xa_node->npa_release_bitmap); - imp_entry = &exp_xa_node->importer_entries[remote_acc_id]; amdgpu_ualink_handle_connection_reset(adev, remote_acc_id, AMDGPU_UALINK_CONN_NOT_READY, imp_entry->generation_count);