Skip to content

Commit b09cdeb

Browse files
Jie1zhangalexdeucher
authored andcommitted
drm/amdgpu: Optimize VM invalidation engine allocation and synchronize GPU TLB flush
- Modify the VM invalidation engine allocation logic to handle SDMA page rings. SDMA page rings now share the VM invalidation engine with SDMA gfx rings instead of allocating a separate engine. This change ensures efficient resource management and avoids the issue of insufficient VM invalidation engines. - Add synchronization for GPU TLB flush operations in gmc_v9_0.c. Use spin_lock and spin_unlock to ensure thread safety and prevent race conditions during TLB flush operations. This improves the stability and reliability of the driver, especially in multi-threaded environments. v2: replace the sdma ring check with a function `amdgpu_sdma_is_page_queue` to check if a ring is an SDMA page queue.(Lijo) v3: Add GC version check, only enabled on GC9.4.3/9.4.4/9.5.0 v4: Fix code style and add more detailed description (Christian) v5: Remove dependency on vm_inv_eng loop order, explicitly lookup shared inv_eng(Christian/Lijo) v6: Added search shared ring function amdgpu_sdma_get_shared_ring (Lijo) Suggested-by: Lijo Lazar <[email protected]> Signed-off-by: Jesse Zhang <[email protected]> Reviewed-by: Lijo Lazar <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent ea6dd40 commit b09cdeb

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev)
573573
unsigned vm_inv_engs[AMDGPU_MAX_VMHUBS] = {0};
574574
unsigned i;
575575
unsigned vmhub, inv_eng;
576+
struct amdgpu_ring *shared_ring;
576577

577578
/* init the vm inv eng for all vmhubs */
578579
for_each_set_bit(i, adev->vmhubs_mask, AMDGPU_MAX_VMHUBS) {
@@ -595,6 +596,10 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev)
595596
ring == &adev->cper.ring_buf)
596597
continue;
597598

599+
/* Skip if the ring is a shared ring */
600+
if (amdgpu_sdma_is_shared_inv_eng(adev, ring))
601+
continue;
602+
598603
inv_eng = ffs(vm_inv_engs[vmhub]);
599604
if (!inv_eng) {
600605
dev_err(adev->dev, "no VM inv eng for ring %s\n",
@@ -607,6 +612,21 @@ int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev)
607612

608613
dev_info(adev->dev, "ring %s uses VM inv eng %u on hub %u\n",
609614
ring->name, ring->vm_inv_eng, ring->vm_hub);
615+
/* SDMA has a special packet which allows it to use the same
616+
* invalidation engine for all the rings in one instance.
617+
* Therefore, we do not allocate a separate VM invalidation engine
618+
* for SDMA page rings. Instead, they share the VM invalidation
619+
* engine with the SDMA gfx ring. This change ensures efficient
620+
* resource management and avoids the issue of insufficient VM
621+
* invalidation engines.
622+
*/
623+
shared_ring = amdgpu_sdma_get_shared_ring(adev, ring);
624+
if (shared_ring) {
625+
shared_ring->vm_inv_eng = ring->vm_inv_eng;
626+
dev_info(adev->dev, "ring %s shares VM invalidation engine %u with ring %s on hub %u\n",
627+
ring->name, ring->vm_inv_eng, shared_ring->name, ring->vm_hub);
628+
continue;
629+
}
610630
}
611631

612632
return 0;

drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,39 @@ void amdgpu_sdma_sysfs_reset_mask_fini(struct amdgpu_device *adev)
504504
}
505505
}
506506

507+
struct amdgpu_ring *amdgpu_sdma_get_shared_ring(struct amdgpu_device *adev, struct amdgpu_ring *ring)
508+
{
509+
if (adev->sdma.has_page_queue &&
510+
(ring->me < adev->sdma.num_instances) &&
511+
(ring == &adev->sdma.instance[ring->me].ring))
512+
return &adev->sdma.instance[ring->me].page;
513+
else
514+
return NULL;
515+
}
516+
517+
/**
518+
* amdgpu_sdma_is_shared_inv_eng - Check if a ring is an SDMA ring that shares a VM invalidation engine
519+
* @adev: Pointer to the AMDGPU device structure
520+
* @ring: Pointer to the ring structure to check
521+
*
522+
* This function checks if the given ring is an SDMA ring that shares a VM invalidation engine.
523+
* It returns true if the ring is such an SDMA ring, false otherwise.
524+
*/
525+
bool amdgpu_sdma_is_shared_inv_eng(struct amdgpu_device *adev, struct amdgpu_ring *ring)
526+
{
527+
int i = ring->me;
528+
529+
if (!adev->sdma.has_page_queue || i >= adev->sdma.num_instances)
530+
return false;
531+
532+
if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3) ||
533+
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 4) ||
534+
amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0))
535+
return (ring == &adev->sdma.instance[i].page);
536+
else
537+
return false;
538+
}
539+
507540
/**
508541
* amdgpu_sdma_register_on_reset_callbacks - Register SDMA reset callbacks
509542
* @funcs: Pointer to the callback structure containing pre_reset and post_reset functions
@@ -544,7 +577,7 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id)
544577
{
545578
struct sdma_on_reset_funcs *funcs;
546579
int ret = 0;
547-
struct amdgpu_sdma_instance *sdma_instance = &adev->sdma.instance[instance_id];;
580+
struct amdgpu_sdma_instance *sdma_instance = &adev->sdma.instance[instance_id];
548581
struct amdgpu_ring *gfx_ring = &sdma_instance->ring;
549582
struct amdgpu_ring *page_ring = &sdma_instance->page;
550583
bool gfx_sched_stopped = false, page_sched_stopped = false;

drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,7 @@ int amdgpu_sdma_ras_sw_init(struct amdgpu_device *adev);
196196
void amdgpu_debugfs_sdma_sched_mask_init(struct amdgpu_device *adev);
197197
int amdgpu_sdma_sysfs_reset_mask_init(struct amdgpu_device *adev);
198198
void amdgpu_sdma_sysfs_reset_mask_fini(struct amdgpu_device *adev);
199+
bool amdgpu_sdma_is_shared_inv_eng(struct amdgpu_device *adev, struct amdgpu_ring *ring);
200+
struct amdgpu_ring *amdgpu_sdma_get_shared_ring(struct amdgpu_device *adev,
201+
struct amdgpu_ring *ring);
199202
#endif

0 commit comments

Comments
 (0)