diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 59 | 
2 files changed, 51 insertions, 10 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 17600b477cf9..e4a731bc9fc1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -677,6 +677,8 @@ struct amdgpu_mc {  	uint32_t                fw_version;  	struct amdgpu_irq_src	vm_fault;  	uint32_t		vram_type; +	uint32_t                srbm_soft_reset; +	struct amdgpu_mode_mc_save save;  };  /* diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 717359d3ba8c..0a23b8394705 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1092,9 +1092,8 @@ static int gmc_v8_0_wait_for_idle(void *handle)  } -static int gmc_v8_0_soft_reset(void *handle) +static int gmc_v8_0_check_soft_reset(void *handle)  { -	struct amdgpu_mode_mc_save save;  	u32 srbm_soft_reset = 0;  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 tmp = RREG32(mmSRBM_STATUS); @@ -1109,13 +1108,42 @@ static int gmc_v8_0_soft_reset(void *handle)  			srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset,  							SRBM_SOFT_RESET, SOFT_RESET_MC, 1);  	} -  	if (srbm_soft_reset) { -		gmc_v8_0_mc_stop(adev, &save); -		if (gmc_v8_0_wait_for_idle((void *)adev)) { -			dev_warn(adev->dev, "Wait for GMC idle timed out !\n"); -		} +		adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = true; +		adev->mc.srbm_soft_reset = srbm_soft_reset; +	} else { +		adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = false; +		adev->mc.srbm_soft_reset = 0; +	} +	return 0; +} + +static int gmc_v8_0_pre_soft_reset(void *handle) +{ +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) +		return 0; + +	gmc_v8_0_mc_stop(adev, &adev->mc.save); +	if (gmc_v8_0_wait_for_idle(adev)) { +		dev_warn(adev->dev, "Wait for GMC idle timed out !\n"); +	} + +	return 0; +} +static int gmc_v8_0_soft_reset(void *handle) +{ +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; +	u32 srbm_soft_reset; + +	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) +		return 0; +	srbm_soft_reset = adev->mc.srbm_soft_reset; + +	if (srbm_soft_reset) { +		u32 tmp;  		tmp = RREG32(mmSRBM_SOFT_RESET);  		tmp |= srbm_soft_reset; @@ -1131,14 +1159,22 @@ static int gmc_v8_0_soft_reset(void *handle)  		/* Wait a little for things to settle down */  		udelay(50); - -		gmc_v8_0_mc_resume(adev, &save); -		udelay(50);  	}  	return 0;  } +static int gmc_v8_0_post_soft_reset(void *handle) +{ +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) +		return 0; + +	gmc_v8_0_mc_resume(adev, &adev->mc.save); +	return 0; +} +  static int gmc_v8_0_vm_fault_interrupt_state(struct amdgpu_device *adev,  					     struct amdgpu_irq_src *src,  					     unsigned type, @@ -1406,7 +1442,10 @@ const struct amd_ip_funcs gmc_v8_0_ip_funcs = {  	.resume = gmc_v8_0_resume,  	.is_idle = gmc_v8_0_is_idle,  	.wait_for_idle = gmc_v8_0_wait_for_idle, +	.check_soft_reset = gmc_v8_0_check_soft_reset, +	.pre_soft_reset = gmc_v8_0_pre_soft_reset,  	.soft_reset = gmc_v8_0_soft_reset, +	.post_soft_reset = gmc_v8_0_post_soft_reset,  	.set_clockgating_state = gmc_v8_0_set_clockgating_state,  	.set_powergating_state = gmc_v8_0_set_powergating_state,  }; |