diff options
| author | Andrey Grodzovsky <andrey.grodzovsky@amd.com> | 2021-05-19 23:20:57 -0400 | 
|---|---|---|
| committer | Andrey Grodzovsky <andrey.grodzovsky@amd.com> | 2021-05-19 23:48:50 -0400 | 
| commit | e9669fb7826270bd73554208b49b6353ab3d856f (patch) | |
| tree | a987b86023e0d5b73ebdc7f1320c69d40d5c99c3 /drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |
| parent | 72c8c97b1522ce7ed1789a42fc9828784ebb5e23 (diff) | |
drm/amdgpu: Add early fini callback
Use it to call disply code dependent on device->drv_data
before it's set to NULL on device unplug
v5:
Move HW finilization into this callback to prevent MMIO accesses
post cpi remove.
v7:
Split kfd suspend from device exit to expdite HW related
stuff to amdgpu_pci_remove
v8:
Squash previous KFD commit into this commit to avoid compile break.
Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210520032057.497334-1-andrey.grodzovsky@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_device.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 59 | 
1 files changed, 40 insertions, 19 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8bee95ad32d9..bc75e35dd8d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2558,34 +2558,26 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)  	return 0;  } -/** - * amdgpu_device_ip_fini - run fini for hardware IPs - * - * @adev: amdgpu_device pointer - * - * Main teardown pass for hardware IPs.  The list of all the hardware - * IPs that make up the asic is walked and the hw_fini and sw_fini callbacks - * are run.  hw_fini tears down the hardware associated with each IP - * and sw_fini tears down any software state associated with each IP. - * Returns 0 on success, negative error code on failure. - */ -static int amdgpu_device_ip_fini(struct amdgpu_device *adev) +static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev)  {  	int i, r; -	if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done) -		amdgpu_virt_release_ras_err_handler_data(adev); +	for (i = 0; i < adev->num_ip_blocks; i++) { +		if (!adev->ip_blocks[i].version->funcs->early_fini) +			continue; -	amdgpu_ras_pre_fini(adev); +		r = adev->ip_blocks[i].version->funcs->early_fini((void *)adev); +		if (r) { +			DRM_DEBUG("early_fini of IP block <%s> failed %d\n", +				  adev->ip_blocks[i].version->funcs->name, r); +		} +	} -	if (adev->gmc.xgmi.num_physical_nodes > 1) -		amdgpu_xgmi_remove_device(adev); +	amdgpu_amdkfd_suspend(adev, false);  	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);  	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE); -	amdgpu_amdkfd_device_fini(adev); -  	/* need to disable SMC first */  	for (i = 0; i < adev->num_ip_blocks; i++) {  		if (!adev->ip_blocks[i].status.hw) @@ -2616,6 +2608,33 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)  		adev->ip_blocks[i].status.hw = false;  	} +	return 0; +} + +/** + * amdgpu_device_ip_fini - run fini for hardware IPs + * + * @adev: amdgpu_device pointer + * + * Main teardown pass for hardware IPs.  The list of all the hardware + * IPs that make up the asic is walked and the hw_fini and sw_fini callbacks + * are run.  hw_fini tears down the hardware associated with each IP + * and sw_fini tears down any software state associated with each IP. + * Returns 0 on success, negative error code on failure. + */ +static int amdgpu_device_ip_fini(struct amdgpu_device *adev) +{ +	int i, r; + +	if (amdgpu_sriov_vf(adev) && adev->virt.ras_init_done) +		amdgpu_virt_release_ras_err_handler_data(adev); + +	amdgpu_ras_pre_fini(adev); + +	if (adev->gmc.xgmi.num_physical_nodes > 1) +		amdgpu_xgmi_remove_device(adev); + +	amdgpu_amdkfd_device_fini_sw(adev);  	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {  		if (!adev->ip_blocks[i].status.sw) @@ -3681,6 +3700,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)  	amdgpu_fbdev_fini(adev);  	amdgpu_irq_fini_hw(adev); + +	amdgpu_device_ip_fini_early(adev);  }  void amdgpu_device_fini_sw(struct amdgpu_device *adev) | 
