Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 971fe9a9 authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/amdgpu: switch the GDS only on demand v2



Switching the GDS space to often seems to be problematic.

This patch together with the following can avoid VM faults on context switch.

v2: extend commit message a bit

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1)
Reviewed-by: Chunming Zhou <david1.zhou@amd.com> (v1)
parent cffadc83
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -922,6 +922,13 @@ struct amdgpu_vm_manager_id {
	struct list_head	list;
	struct list_head	list;
	struct fence		*active;
	struct fence		*active;
	atomic_long_t		owner;
	atomic_long_t		owner;

	uint32_t		gds_base;
	uint32_t		gds_size;
	uint32_t		gws_base;
	uint32_t		gws_size;
	uint32_t		oa_base;
	uint32_t		oa_size;
};
};


struct amdgpu_vm_manager {
struct amdgpu_vm_manager {
@@ -961,6 +968,7 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring,
		     uint32_t gds_base, uint32_t gds_size,
		     uint32_t gds_base, uint32_t gds_size,
		     uint32_t gws_base, uint32_t gws_size,
		     uint32_t gws_base, uint32_t gws_size,
		     uint32_t oa_base, uint32_t oa_size);
		     uint32_t oa_base, uint32_t oa_size);
void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr);
uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr);
int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
				    struct amdgpu_vm *vm);
				    struct amdgpu_vm *vm);
+4 −0
Original line number Original line Diff line number Diff line
@@ -165,6 +165,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,


		if (ib->ctx != ctx || ib->vm != vm) {
		if (ib->ctx != ctx || ib->vm != vm) {
			ring->current_ctx = old_ctx;
			ring->current_ctx = old_ctx;
			if (ib->vm_id)
				amdgpu_vm_reset_id(adev, ib->vm_id);
			amdgpu_ring_undo(ring);
			amdgpu_ring_undo(ring);
			return -EINVAL;
			return -EINVAL;
		}
		}
@@ -181,6 +183,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
	if (r) {
	if (r) {
		dev_err(adev->dev, "failed to emit fence (%d)\n", r);
		dev_err(adev->dev, "failed to emit fence (%d)\n", r);
		ring->current_ctx = old_ctx;
		ring->current_ctx = old_ctx;
		if (ib->vm_id)
			amdgpu_vm_reset_id(adev, ib->vm_id);
		amdgpu_ring_undo(ring);
		amdgpu_ring_undo(ring);
		return r;
		return r;
	}
	}
+41 −2
Original line number Original line Diff line number Diff line
@@ -252,17 +252,54 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring,
		     uint32_t gws_base, uint32_t gws_size,
		     uint32_t gws_base, uint32_t gws_size,
		     uint32_t oa_base, uint32_t oa_size)
		     uint32_t oa_base, uint32_t oa_size)
{
{
	struct amdgpu_device *adev = ring->adev;
	struct amdgpu_vm_manager_id *mgr_id = &adev->vm_manager.ids[vm_id];

	if (pd_addr != AMDGPU_VM_NO_FLUSH) {
	if (pd_addr != AMDGPU_VM_NO_FLUSH) {
		trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id);
		trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id);
		amdgpu_ring_emit_vm_flush(ring, vm_id, pd_addr);
		amdgpu_ring_emit_vm_flush(ring, vm_id, pd_addr);
	}
	}


	if (ring->funcs->emit_gds_switch)
	if (ring->funcs->emit_gds_switch && (
	    mgr_id->gds_base != gds_base ||
	    mgr_id->gds_size != gds_size ||
	    mgr_id->gws_base != gws_base ||
	    mgr_id->gws_size != gws_size ||
	    mgr_id->oa_base != oa_base ||
	    mgr_id->oa_size != oa_size)) {

		mgr_id->gds_base = gds_base;
		mgr_id->gds_size = gds_size;
		mgr_id->gws_base = gws_base;
		mgr_id->gws_size = gws_size;
		mgr_id->oa_base = oa_base;
		mgr_id->oa_size = oa_size;
		amdgpu_ring_emit_gds_switch(ring, vm_id,
		amdgpu_ring_emit_gds_switch(ring, vm_id,
					    gds_base, gds_size,
					    gds_base, gds_size,
					    gws_base, gws_size,
					    gws_base, gws_size,
					    oa_base, oa_size);
					    oa_base, oa_size);
	}
	}
}

/**
 * amdgpu_vm_reset_id - reset VMID to zero
 *
 * @adev: amdgpu device structure
 * @vm_id: vmid number to use
 *
 * Reset saved GDW, GWS and OA to force switch on next flush.
 */
void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id)
{
	struct amdgpu_vm_manager_id *mgr_id = &adev->vm_manager.ids[vm_id];

	mgr_id->gds_base = 0;
	mgr_id->gds_size = 0;
	mgr_id->gws_base = 0;
	mgr_id->gws_size = 0;
	mgr_id->oa_base = 0;
	mgr_id->oa_size = 0;
}


/**
/**
 * amdgpu_vm_bo_find - find the bo_va for a specific vm & bo
 * amdgpu_vm_bo_find - find the bo_va for a specific vm & bo
@@ -1425,9 +1462,11 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
	INIT_LIST_HEAD(&adev->vm_manager.ids_lru);
	INIT_LIST_HEAD(&adev->vm_manager.ids_lru);


	/* skip over VMID 0, since it is the system VM */
	/* skip over VMID 0, since it is the system VM */
	for (i = 1; i < adev->vm_manager.num_ids; ++i)
	for (i = 1; i < adev->vm_manager.num_ids; ++i) {
		amdgpu_vm_reset_id(adev, i);
		list_add_tail(&adev->vm_manager.ids[i].list,
		list_add_tail(&adev->vm_manager.ids[i].list,
			      &adev->vm_manager.ids_lru);
			      &adev->vm_manager.ids_lru);
	}


	atomic_set(&adev->vm_manager.vm_pte_next_ring, 0);
	atomic_set(&adev->vm_manager.vm_pte_next_ring, 0);
}
}