diff options
Diffstat (limited to 'drivers/gpu/drm/amd')
31 files changed, 249 insertions, 92 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 992f00b65be4..01c36b8d6222 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -799,6 +799,7 @@ struct amdgpu_ring {  	unsigned		cond_exe_offs;  	u64				cond_exe_gpu_addr;  	volatile u32	*cond_exe_cpu_addr; +	int                     vmid;  };  /* @@ -936,7 +937,8 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring,  		    unsigned vm_id, uint64_t pd_addr,  		    uint32_t gds_base, uint32_t gds_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, +		    bool vmid_switch);  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);  int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 199f76baf22c..8943099eb135 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -696,6 +696,17 @@ static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)  	return result;  } +static int amdgpu_cgs_rel_firmware(struct cgs_device *cgs_device, enum cgs_ucode_id type) +{ +	CGS_FUNC_ADEV; +	if ((CGS_UCODE_ID_SMU == type) || (CGS_UCODE_ID_SMU_SK == type)) { +		release_firmware(adev->pm.fw); +		return 0; +	} +	/* cannot release other firmware because they are not created by cgs */ +	return -EINVAL; +} +  static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,  					enum cgs_ucode_id type,  					struct cgs_firmware_info *info) @@ -1125,6 +1136,7 @@ static const struct cgs_ops amdgpu_cgs_ops = {  	amdgpu_cgs_pm_query_clock_limits,  	amdgpu_cgs_set_camera_voltages,  	amdgpu_cgs_get_firmware_info, +	amdgpu_cgs_rel_firmware,  	amdgpu_cgs_set_powergating_state,  	amdgpu_cgs_set_clockgating_state,  	amdgpu_cgs_get_active_displays_info, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index bb8b149786d7..964f31404f17 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -827,8 +827,10 @@ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg)   */  static void amdgpu_atombios_fini(struct amdgpu_device *adev)  { -	if (adev->mode_info.atom_context) +	if (adev->mode_info.atom_context) {  		kfree(adev->mode_info.atom_context->scratch); +		kfree(adev->mode_info.atom_context->iio); +	}  	kfree(adev->mode_info.atom_context);  	adev->mode_info.atom_context = NULL;  	kfree(adev->mode_info.atom_card_info); @@ -1325,6 +1327,11 @@ static int amdgpu_fini(struct amdgpu_device *adev)  		adev->ip_block_status[i].valid = false;  	} +	for (i = adev->num_ip_blocks - 1; i >= 0; i--) { +		if (adev->ip_blocks[i].funcs->late_fini) +			adev->ip_blocks[i].funcs->late_fini((void *)adev); +	} +  	return 0;  } @@ -1513,8 +1520,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,  		amdgpu_atombios_has_gpu_virtualization_table(adev);  	/* Post card if necessary */ -	if (!amdgpu_card_posted(adev) || -	    adev->virtualization.supports_sr_iov) { +	if (!amdgpu_card_posted(adev)) {  		if (!adev->bios) {  			dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n");  			return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 34e35423b78e..7a0b1e50f293 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -122,6 +122,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,  	bool skip_preamble, need_ctx_switch;  	unsigned patch_offset = ~0;  	struct amdgpu_vm *vm; +	int vmid = 0, old_vmid = ring->vmid;  	struct fence *hwf;  	uint64_t ctx; @@ -135,9 +136,11 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,  	if (job) {  		vm = job->vm;  		ctx = job->ctx; +		vmid = job->vm_id;  	} else {  		vm = NULL;  		ctx = 0; +		vmid = 0;  	}  	if (!ring->ready) { @@ -163,7 +166,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,  		r = amdgpu_vm_flush(ring, job->vm_id, job->vm_pd_addr,  				    job->gds_base, job->gds_size,  				    job->gws_base, job->gws_size, -				    job->oa_base, job->oa_size); +				    job->oa_base, job->oa_size, +				    (ring->current_ctx == ctx) && (old_vmid != vmid));  		if (r) {  			amdgpu_ring_undo(ring);  			return r; @@ -180,7 +184,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,  	need_ctx_switch = ring->current_ctx != ctx;  	for (i = 0; i < num_ibs; ++i) {  		ib = &ibs[i]; -  		/* drop preamble IBs if we don't have a context switch */  		if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && skip_preamble)  			continue; @@ -188,6 +191,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,  		amdgpu_ring_emit_ib(ring, ib, job ? job->vm_id : 0,  				    need_ctx_switch);  		need_ctx_switch = false; +		ring->vmid = vmid;  	}  	if (ring->funcs->emit_hdp_invalidate) @@ -198,6 +202,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,  		dev_err(adev->dev, "failed to emit fence (%d)\n", r);  		if (job && job->vm_id)  			amdgpu_vm_reset_id(adev, job->vm_id); +		ring->vmid = old_vmid;  		amdgpu_ring_undo(ring);  		return r;  	} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index 6bd961fb43dc..82256558e0f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -183,13 +183,6 @@ static int amdgpu_pp_sw_fini(void *handle)  	if (ret)  		return ret; -#ifdef CONFIG_DRM_AMD_POWERPLAY -	if (adev->pp_enabled) { -		amdgpu_pm_sysfs_fini(adev); -		amd_powerplay_fini(adev->powerplay.pp_handle); -	} -#endif -  	return ret;  } @@ -223,6 +216,22 @@ static int amdgpu_pp_hw_fini(void *handle)  	return ret;  } +static void amdgpu_pp_late_fini(void *handle) +{ +#ifdef CONFIG_DRM_AMD_POWERPLAY +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	if (adev->pp_enabled) { +		amdgpu_pm_sysfs_fini(adev); +		amd_powerplay_fini(adev->powerplay.pp_handle); +	} + +	if (adev->powerplay.ip_funcs->late_fini) +		adev->powerplay.ip_funcs->late_fini( +			  adev->powerplay.pp_handle); +#endif +} +  static int amdgpu_pp_suspend(void *handle)  {  	int ret = 0; @@ -311,6 +320,7 @@ const struct amd_ip_funcs amdgpu_pp_ip_funcs = {  	.sw_fini = amdgpu_pp_sw_fini,  	.hw_init = amdgpu_pp_hw_init,  	.hw_fini = amdgpu_pp_hw_fini, +	.late_fini = amdgpu_pp_late_fini,  	.suspend = amdgpu_pp_suspend,  	.resume = amdgpu_pp_resume,  	.is_idle = amdgpu_pp_is_idle, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 3b02272db678..870f9494252c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -343,6 +343,7 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)  	ring->ring = NULL;  	ring->ring_obj = NULL; +	amdgpu_wb_free(ring->adev, ring->cond_exe_offs);  	amdgpu_wb_free(ring->adev, ring->fence_offs);  	amdgpu_wb_free(ring->adev, ring->rptr_offs);  	amdgpu_wb_free(ring->adev, ring->wptr_offs); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c index 8bf84efafb04..48618ee324eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c @@ -115,6 +115,7 @@ int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,  		return r;  	}  	r = amdgpu_bo_kmap(sa_manager->bo, &sa_manager->cpu_ptr); +	memset(sa_manager->cpu_ptr, 0, sa_manager->size);  	amdgpu_bo_unreserve(sa_manager->bo);  	return r;  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index 01abfc21b4a2..e19520c4b4b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -253,19 +253,20 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)  {  	int r; -	if (adev->uvd.vcpu_bo == NULL) -		return 0; +	kfree(adev->uvd.saved_bo);  	amd_sched_entity_fini(&adev->uvd.ring.sched, &adev->uvd.entity); -	r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false); -	if (!r) { -		amdgpu_bo_kunmap(adev->uvd.vcpu_bo); -		amdgpu_bo_unpin(adev->uvd.vcpu_bo); -		amdgpu_bo_unreserve(adev->uvd.vcpu_bo); -	} +	if (adev->uvd.vcpu_bo) { +		r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false); +		if (!r) { +			amdgpu_bo_kunmap(adev->uvd.vcpu_bo); +			amdgpu_bo_unpin(adev->uvd.vcpu_bo); +			amdgpu_bo_unreserve(adev->uvd.vcpu_bo); +		} -	amdgpu_bo_unref(&adev->uvd.vcpu_bo); +		amdgpu_bo_unref(&adev->uvd.vcpu_bo); +	}  	amdgpu_ring_fini(&adev->uvd.ring); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 9f36ed30ba11..62a4c127620f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -298,7 +298,8 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring,  		    unsigned vm_id, uint64_t pd_addr,  		    uint32_t gds_base, uint32_t gds_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, +		    bool vmid_switch)  {  	struct amdgpu_device *adev = ring->adev;  	struct amdgpu_vm_id *id = &adev->vm_manager.ids[vm_id]; @@ -312,8 +313,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring,  	int r;  	if (ring->funcs->emit_pipeline_sync && ( -	    pd_addr != AMDGPU_VM_NO_FLUSH || gds_switch_needed || -		    ring->type == AMDGPU_RING_TYPE_COMPUTE)) +	    pd_addr != AMDGPU_VM_NO_FLUSH || gds_switch_needed || vmid_switch))  		amdgpu_ring_emit_pipeline_sync(ring);  	if (ring->funcs->emit_vm_flush && diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index ea407db1fbcf..5ec1f1e9c983 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6221,6 +6221,9 @@ static int ci_dpm_sw_fini(void *handle)  	ci_dpm_fini(adev);  	mutex_unlock(&adev->pm.mutex); +	release_firmware(adev->pm.fw); +	adev->pm.fw = NULL; +  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index 518dca43b133..9dc4e24e31e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -66,6 +66,16 @@ MODULE_FIRMWARE("radeon/mullins_sdma1.bin");  u32 amdgpu_cik_gpu_check_soft_reset(struct amdgpu_device *adev); + +static void cik_sdma_free_microcode(struct amdgpu_device *adev) +{ +	int i; +	for (i = 0; i < adev->sdma.num_instances; i++) { +			release_firmware(adev->sdma.instance[i].fw); +			adev->sdma.instance[i].fw = NULL; +	} +} +  /*   * sDMA - System DMA   * Starting with CIK, the GPU has new asynchronous @@ -419,6 +429,8 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)  		/* Initialize the ring buffer's read and write pointers */  		WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);  		WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0); +		WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0); +		WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);  		/* set the wb address whether it's enabled or not */  		WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i], @@ -446,7 +458,12 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)  		WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);  		ring->ready = true; +	} + +	cik_sdma_enable(adev, true); +	for (i = 0; i < adev->sdma.num_instances; i++) { +		ring = &adev->sdma.instance[i].ring;  		r = amdgpu_ring_test_ring(ring);  		if (r) {  			ring->ready = false; @@ -529,8 +546,8 @@ static int cik_sdma_start(struct amdgpu_device *adev)  	if (r)  		return r; -	/* unhalt the MEs */ -	cik_sdma_enable(adev, true); +	/* halt the engine before programing */ +	cik_sdma_enable(adev, false);  	/* start the gfx rings and rlc compute queues */  	r = cik_sdma_gfx_resume(adev); @@ -998,6 +1015,7 @@ static int cik_sdma_sw_fini(void *handle)  	for (i = 0; i < adev->sdma.num_instances; i++)  		amdgpu_ring_fini(&adev->sdma.instance[i].ring); +	cik_sdma_free_microcode(adev);  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c b/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c index 245cabf06575..ed03b75175d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c @@ -72,6 +72,11 @@ static int fiji_dpm_sw_init(void *handle)  static int fiji_dpm_sw_fini(void *handle)  { +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	release_firmware(adev->pm.fw); +	adev->pm.fw = NULL; +  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 7f18a53ab53a..8c6ad1e72f02 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -991,6 +991,22 @@ out:  	return err;  } +static void gfx_v7_0_free_microcode(struct amdgpu_device *adev) +{ +	release_firmware(adev->gfx.pfp_fw); +	adev->gfx.pfp_fw = NULL; +	release_firmware(adev->gfx.me_fw); +	adev->gfx.me_fw = NULL; +	release_firmware(adev->gfx.ce_fw); +	adev->gfx.ce_fw = NULL; +	release_firmware(adev->gfx.mec_fw); +	adev->gfx.mec_fw = NULL; +	release_firmware(adev->gfx.mec2_fw); +	adev->gfx.mec2_fw = NULL; +	release_firmware(adev->gfx.rlc_fw); +	adev->gfx.rlc_fw = NULL; +} +  /**   * gfx_v7_0_tiling_mode_table_init - init the hw tiling table   * @@ -4489,6 +4505,7 @@ static int gfx_v7_0_sw_fini(void *handle)  	gfx_v7_0_cp_compute_fini(adev);  	gfx_v7_0_rlc_fini(adev);  	gfx_v7_0_mec_fini(adev); +	gfx_v7_0_free_microcode(adev);  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index f19bab68fd83..9f6f8669edc3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -836,6 +836,26 @@ err1:  	return r;  } + +static void gfx_v8_0_free_microcode(struct amdgpu_device *adev) { +	release_firmware(adev->gfx.pfp_fw); +	adev->gfx.pfp_fw = NULL; +	release_firmware(adev->gfx.me_fw); +	adev->gfx.me_fw = NULL; +	release_firmware(adev->gfx.ce_fw); +	adev->gfx.ce_fw = NULL; +	release_firmware(adev->gfx.rlc_fw); +	adev->gfx.rlc_fw = NULL; +	release_firmware(adev->gfx.mec_fw); +	adev->gfx.mec_fw = NULL; +	if ((adev->asic_type != CHIP_STONEY) && +	    (adev->asic_type != CHIP_TOPAZ)) +		release_firmware(adev->gfx.mec2_fw); +	adev->gfx.mec2_fw = NULL; + +	kfree(adev->gfx.rlc.register_list_format); +} +  static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)  {  	const char *chip_name; @@ -1983,7 +2003,7 @@ static int gfx_v8_0_sw_fini(void *handle)  	gfx_v8_0_rlc_fini(adev); -	kfree(adev->gfx.rlc.register_list_format); +	gfx_v8_0_free_microcode(adev);  	return 0;  } @@ -3974,11 +3994,15 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)  		amdgpu_ring_write(ring, 0x3a00161a);  		amdgpu_ring_write(ring, 0x0000002e);  		break; -	case CHIP_TOPAZ:  	case CHIP_CARRIZO:  		amdgpu_ring_write(ring, 0x00000002);  		amdgpu_ring_write(ring, 0x00000000);  		break; +	case CHIP_TOPAZ: +		amdgpu_ring_write(ring, adev->gfx.config.num_rbs == 1 ? +				0x00000000 : 0x00000002); +		amdgpu_ring_write(ring, 0x00000000); +		break;  	case CHIP_STONEY:  		amdgpu_ring_write(ring, 0x00000000);  		amdgpu_ring_write(ring, 0x00000000); diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_dpm.c b/drivers/gpu/drm/amd/amdgpu/iceland_dpm.c index 460bc8ad37e6..825ccd63f2dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_dpm.c @@ -72,6 +72,11 @@ static int iceland_dpm_sw_init(void *handle)  static int iceland_dpm_sw_fini(void *handle)  { +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	release_firmware(adev->pm.fw); +	adev->pm.fw = NULL; +  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index f4c3130d3fdb..b556bd0a8797 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -105,6 +105,15 @@ static void sdma_v2_4_init_golden_registers(struct amdgpu_device *adev)  	}  } +static void sdma_v2_4_free_microcode(struct amdgpu_device *adev) +{ +	int i; +	for (i = 0; i < adev->sdma.num_instances; i++) { +		release_firmware(adev->sdma.instance[i].fw); +		adev->sdma.instance[i].fw = NULL; +	} +} +  /**   * sdma_v2_4_init_microcode - load ucode images from disk   * @@ -461,6 +470,8 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)  		/* Initialize the ring buffer's read and write pointers */  		WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);  		WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0); +		WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0); +		WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);  		/* set the wb address whether it's enabled or not */  		WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i], @@ -489,7 +500,11 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)  		WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);  		ring->ready = true; +	} +	sdma_v2_4_enable(adev, true); +	for (i = 0; i < adev->sdma.num_instances; i++) { +		ring = &adev->sdma.instance[i].ring;  		r = amdgpu_ring_test_ring(ring);  		if (r) {  			ring->ready = false; @@ -580,8 +595,8 @@ static int sdma_v2_4_start(struct amdgpu_device *adev)  			return -EINVAL;  	} -	/* unhalt the MEs */ -	sdma_v2_4_enable(adev, true); +	/* halt the engine before programing */ +	sdma_v2_4_enable(adev, false);  	/* start the gfx rings and rlc compute queues */  	r = sdma_v2_4_gfx_resume(adev); @@ -1012,6 +1027,7 @@ static int sdma_v2_4_sw_fini(void *handle)  	for (i = 0; i < adev->sdma.num_instances; i++)  		amdgpu_ring_fini(&adev->sdma.instance[i].ring); +	sdma_v2_4_free_microcode(adev);  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 31d99b0010f7..532ea88da66a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -236,6 +236,15 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)  	}  } +static void sdma_v3_0_free_microcode(struct amdgpu_device *adev) +{ +	int i; +	for (i = 0; i < adev->sdma.num_instances; i++) { +		release_firmware(adev->sdma.instance[i].fw); +		adev->sdma.instance[i].fw = NULL; +	} +} +  /**   * sdma_v3_0_init_microcode - load ucode images from disk   * @@ -672,6 +681,8 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)  		/* Initialize the ring buffer's read and write pointers */  		WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);  		WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0); +		WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0); +		WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);  		/* set the wb address whether it's enabled or not */  		WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i], @@ -711,7 +722,15 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)  		WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);  		ring->ready = true; +	} + +	/* unhalt the MEs */ +	sdma_v3_0_enable(adev, true); +	/* enable sdma ring preemption */ +	sdma_v3_0_ctx_switch_enable(adev, true); +	for (i = 0; i < adev->sdma.num_instances; i++) { +		ring = &adev->sdma.instance[i].ring;  		r = amdgpu_ring_test_ring(ring);  		if (r) {  			ring->ready = false; @@ -804,10 +823,9 @@ static int sdma_v3_0_start(struct amdgpu_device *adev)  		}  	} -	/* unhalt the MEs */ -	sdma_v3_0_enable(adev, true); -	/* enable sdma ring preemption */ -	sdma_v3_0_ctx_switch_enable(adev, true); +	/* disble sdma engine before programing it */ +	sdma_v3_0_ctx_switch_enable(adev, false); +	sdma_v3_0_enable(adev, false);  	/* start the gfx rings and rlc compute queues */  	r = sdma_v3_0_gfx_resume(adev); @@ -1247,6 +1265,7 @@ static int sdma_v3_0_sw_fini(void *handle)  	for (i = 0; i < adev->sdma.num_instances; i++)  		amdgpu_ring_fini(&adev->sdma.instance[i].ring); +	sdma_v3_0_free_microcode(adev);  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c index b7615cefcac4..f06f6f4dc3a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c @@ -71,6 +71,11 @@ static int tonga_dpm_sw_init(void *handle)  static int tonga_dpm_sw_fini(void *handle)  { +	struct amdgpu_device *adev = (struct amdgpu_device *)handle; + +	release_firmware(adev->pm.fw); +	adev->pm.fw = NULL; +  	return 0;  } diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 6080951d539d..afce1edbe250 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -157,6 +157,7 @@ struct amd_ip_funcs {  	int (*hw_init)(void *handle);  	/* tears down the hw state */  	int (*hw_fini)(void *handle); +	void (*late_fini)(void *handle);  	/* handles IP specific hw/sw changes for suspend */  	int (*suspend)(void *handle);  	/* handles IP specific hw/sw changes for resume */ diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index a461e155a160..7464daf89ca1 100644 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -581,6 +581,9 @@ typedef int (*cgs_get_firmware_info)(struct cgs_device *cgs_device,  				     enum cgs_ucode_id type,  				     struct cgs_firmware_info *info); +typedef int (*cgs_rel_firmware)(struct cgs_device *cgs_device, +					 enum cgs_ucode_id type); +  typedef int(*cgs_set_powergating_state)(struct cgs_device *cgs_device,  				  enum amd_ip_block_type block_type,  				  enum amd_powergating_state state); @@ -645,6 +648,7 @@ struct cgs_ops {  	cgs_set_camera_voltages_t set_camera_voltages;  	/* Firmware Info */  	cgs_get_firmware_info get_firmware_info; +	cgs_rel_firmware rel_firmware;  	/* cg pg interface*/  	cgs_set_powergating_state set_powergating_state;  	cgs_set_clockgating_state set_clockgating_state; @@ -738,6 +742,8 @@ struct cgs_device  	CGS_CALL(set_camera_voltages,dev,mask,voltages)  #define cgs_get_firmware_info(dev, type, info)	\  	CGS_CALL(get_firmware_info, dev, type, info) +#define cgs_rel_firmware(dev, type)	\ +	CGS_CALL(rel_firmware, dev, type)  #define cgs_set_powergating_state(dev, block_type, state)	\  	CGS_CALL(set_powergating_state, dev, block_type, state)  #define cgs_set_clockgating_state(dev, block_type, state)	\ diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 8e345bfddb69..e629f8a9fe93 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -73,11 +73,14 @@ static int pp_sw_init(void *handle)  	ret = hwmgr->hwmgr_func->backend_init(hwmgr);  	if (ret) -		goto err; +		goto err1;  	pr_info("amdgpu: powerplay initialized\n");  	return 0; +err1: +	if (hwmgr->pptable_func->pptable_fini) +		hwmgr->pptable_func->pptable_fini(hwmgr);  err:  	pr_err("amdgpu: powerplay initialization failed\n");  	return ret; @@ -100,6 +103,9 @@ static int pp_sw_fini(void *handle)  	if (hwmgr->hwmgr_func->backend_fini != NULL)  		ret = hwmgr->hwmgr_func->backend_fini(hwmgr); +	if (hwmgr->pptable_func->pptable_fini) +		hwmgr->pptable_func->pptable_fini(hwmgr); +  	return ret;  } diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c index 46410e3c7349..fb88e4e5d625 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c @@ -58,9 +58,6 @@ static void pem_fini(struct pp_eventmgr *eventmgr)  	pem_unregister_interrupts(eventmgr);  	pem_handle_event(eventmgr, AMD_PP_EVENT_UNINITIALIZE, &event_data); - -	if (eventmgr != NULL) -		kfree(eventmgr);  }  int eventmgr_init(struct pp_instance *handle) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c index 24a16e49b571..586f73276226 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c @@ -1830,7 +1830,7 @@ static uint16_t fiji_find_closest_vddci(struct pp_hwmgr *hwmgr, uint16_t vddci)  	PP_ASSERT_WITH_CODE(false,  			"VDDCI is larger than max VDDCI in VDDCI Voltage Table!", -			return vddci_table->entries[i].value); +			return vddci_table->entries[i-1].value);  }  static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 1c48917da3cf..20f20e075588 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -93,6 +93,13 @@ int hwmgr_fini(struct pp_hwmgr *hwmgr)  	if (hwmgr == NULL || hwmgr->ps == NULL)  		return -EINVAL; +	/* do hwmgr finish*/ +	kfree(hwmgr->backend); + +	kfree(hwmgr->start_thermal_controller.function_list); + +	kfree(hwmgr->set_temperature_range.function_list); +  	kfree(hwmgr->ps);  	kfree(hwmgr);  	return 0; @@ -462,7 +469,7 @@ uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, u  	PP_ASSERT_WITH_CODE(false,  			"VDDCI is larger than max VDDCI in VDDCI Voltage Table!", -			return vddci_table->entries[i].value); +			return vddci_table->entries[i-1].value);  }  int phm_find_boot_level(void *table, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c index 0b99ab3ba0c5..ae96f14b827c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c @@ -286,7 +286,7 @@ int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr)  		if (polaris10_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,  				(uint8_t *)&data->power_tune_table, -				sizeof(struct SMU74_Discrete_PmFuses), data->sram_end)) +				(sizeof(struct SMU74_Discrete_PmFuses) - 92), data->sram_end))  			PP_ASSERT_WITH_CODE(false,  					"Attempt to download PmFuseTable Failed!",  					return -EINVAL); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c index 16fed487973b..d27e8c40602a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -2847,27 +2847,6 @@ static int tonga_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)  		}  	} -	/* Initialize Vddc DPM table based on allow Vddc values.  And populate corresponding std values. */ -	for (i = 0; i < allowed_vdd_sclk_table->count; i++) { -		data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddc; -		/* tonga_hwmgr->dpm_table.VddcTable.dpm_levels[i].param1 = stdVoltageTable->entries[i].Leakage; */ -		/* param1 is for corresponding std voltage */ -		data->dpm_table.vddc_table.dpm_levels[i].enabled = 1; -	} -	data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count; - -	if (NULL != allowed_vdd_mclk_table) { -		/* Initialize Vddci DPM table based on allow Mclk values */ -		for (i = 0; i < allowed_vdd_mclk_table->count; i++) { -			data->dpm_table.vdd_ci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddci; -			data->dpm_table.vdd_ci_table.dpm_levels[i].enabled = 1; -			data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].mvdd; -			data->dpm_table.mvdd_table.dpm_levels[i].enabled = 1; -		} -		data->dpm_table.vdd_ci_table.count = allowed_vdd_mclk_table->count; -		data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count; -	} -  	/* setup PCIE gen speed levels*/  	tonga_setup_default_pcie_tables(hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c index 10e3630ee39d..296ec7ef6d45 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c @@ -1040,48 +1040,44 @@ int tonga_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)  	struct phm_ppt_v1_information *pp_table_information =  		(struct phm_ppt_v1_information *)(hwmgr->pptable); -	if (NULL != hwmgr->soft_pp_table) { -		kfree(hwmgr->soft_pp_table); +	if (NULL != hwmgr->soft_pp_table)  		hwmgr->soft_pp_table = NULL; -	} -	if (NULL != pp_table_information->vdd_dep_on_sclk) -		pp_table_information->vdd_dep_on_sclk = NULL; +	kfree(pp_table_information->vdd_dep_on_sclk); +	pp_table_information->vdd_dep_on_sclk = NULL; -	if (NULL != pp_table_information->vdd_dep_on_mclk) -		pp_table_information->vdd_dep_on_mclk = NULL; +	kfree(pp_table_information->vdd_dep_on_mclk); +	pp_table_information->vdd_dep_on_mclk = NULL; -	if (NULL != pp_table_information->valid_mclk_values) -		pp_table_information->valid_mclk_values = NULL; +	kfree(pp_table_information->valid_mclk_values); +	pp_table_information->valid_mclk_values = NULL; -	if (NULL != pp_table_information->valid_sclk_values) -		pp_table_information->valid_sclk_values = NULL; +	kfree(pp_table_information->valid_sclk_values); +	pp_table_information->valid_sclk_values = NULL; -	if (NULL != pp_table_information->vddc_lookup_table) -		pp_table_information->vddc_lookup_table = NULL; +	kfree(pp_table_information->vddc_lookup_table); +	pp_table_information->vddc_lookup_table = NULL; -	if (NULL != pp_table_information->vddgfx_lookup_table) -		pp_table_information->vddgfx_lookup_table = NULL; +	kfree(pp_table_information->vddgfx_lookup_table); +	pp_table_information->vddgfx_lookup_table = NULL; -	if (NULL != pp_table_information->mm_dep_table) -		pp_table_information->mm_dep_table = NULL; +	kfree(pp_table_information->mm_dep_table); +	pp_table_information->mm_dep_table = NULL; -	if (NULL != pp_table_information->cac_dtp_table) -		pp_table_information->cac_dtp_table = NULL; +	kfree(pp_table_information->cac_dtp_table); +	pp_table_information->cac_dtp_table = NULL; -	if (NULL != hwmgr->dyn_state.cac_dtp_table) -		hwmgr->dyn_state.cac_dtp_table = NULL; +	kfree(hwmgr->dyn_state.cac_dtp_table); +	hwmgr->dyn_state.cac_dtp_table = NULL; -	if (NULL != pp_table_information->ppm_parameter_table) -		pp_table_information->ppm_parameter_table = NULL; +	kfree(pp_table_information->ppm_parameter_table); +	pp_table_information->ppm_parameter_table = NULL; -	if (NULL != pp_table_information->pcie_table) -		pp_table_information->pcie_table = NULL; +	kfree(pp_table_information->pcie_table); +	pp_table_information->pcie_table = NULL; -	if (NULL != hwmgr->pptable) { -		kfree(hwmgr->pptable); -		hwmgr->pptable = NULL; -	} +	kfree(hwmgr->pptable); +	hwmgr->pptable = NULL;  	return result;  } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c index 673a75c74e18..8e52a2e82db5 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c @@ -1006,10 +1006,16 @@ static int fiji_smu_init(struct pp_smumgr *smumgr)  static int fiji_smu_fini(struct pp_smumgr *smumgr)  { +	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + +	smu_free_memory(smumgr->device, (void *)priv->header_buffer.handle); +  	if (smumgr->backend) {  		kfree(smumgr->backend);  		smumgr->backend = NULL;  	} + +	cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);  	return 0;  } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index de618ead9db8..043b6ac09d5f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -469,6 +469,7 @@ int polaris10_smu_fini(struct pp_smumgr *smumgr)  		kfree(smumgr->backend);  		smumgr->backend = NULL;  	} +	cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);  	return 0;  } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index c483baf6b4fb..0728c1e3d97a 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -81,6 +81,7 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle)  int smum_fini(struct pp_smumgr *smumgr)  { +	kfree(smumgr->device);  	kfree(smumgr);  	return 0;  } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c index 32820b680d88..b22722eabafc 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c @@ -328,10 +328,17 @@ int tonga_write_smc_sram_dword(struct pp_smumgr *smumgr,  static int tonga_smu_fini(struct pp_smumgr *smumgr)  { +	struct tonga_smumgr *priv = (struct tonga_smumgr *)(smumgr->backend); + +	smu_free_memory(smumgr->device, (void *)priv->smu_buffer.handle); +	smu_free_memory(smumgr->device, (void *)priv->header_buffer.handle); +  	if (smumgr->backend != NULL) {  		kfree(smumgr->backend);  		smumgr->backend = NULL;  	} + +	cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);  	return 0;  } | 
