diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
20 files changed, 234 insertions, 47 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 992f00b65be4..e055d5be1c3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1820,6 +1820,8 @@ struct amdgpu_asic_funcs {  	/* MM block clocks */  	int (*set_uvd_clocks)(struct amdgpu_device *adev, u32 vclk, u32 dclk);  	int (*set_vce_clocks)(struct amdgpu_device *adev, u32 evclk, u32 ecclk); +	/* query virtual capabilities */ +	u32 (*get_virtual_caps)(struct amdgpu_device *adev);  };  /* @@ -1914,8 +1916,12 @@ void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device);  /* GPU virtualization */ +#define AMDGPU_VIRT_CAPS_SRIOV_EN       (1 << 0) +#define AMDGPU_VIRT_CAPS_IS_VF          (1 << 1)  struct amdgpu_virtualization {  	bool supports_sr_iov; +	bool is_virtual; +	u32 caps;  };  /* @@ -2204,6 +2210,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)  #define amdgpu_asic_get_xclk(adev) (adev)->asic_funcs->get_xclk((adev))  #define amdgpu_asic_set_uvd_clocks(adev, v, d) (adev)->asic_funcs->set_uvd_clocks((adev), (v), (d))  #define amdgpu_asic_set_vce_clocks(adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec)) +#define amdgpu_asic_get_virtual_caps(adev) ((adev)->asic_funcs->get_virtual_caps((adev)))  #define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev))  #define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev))  #define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 199f76baf22c..cf6f49fc1c75 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) @@ -898,7 +909,7 @@ static int amdgpu_cgs_acpi_eval_object(struct cgs_device *cgs_device,  	struct cgs_acpi_method_argument *argument = NULL;  	uint32_t i, count;  	acpi_status status; -	int result; +	int result = 0;  	uint32_t func_no = 0xFFFFFFFF;  	handle = ACPI_HANDLE(&adev->pdev->dev); @@ -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..6e920086af46 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;  } @@ -1378,6 +1385,15 @@ static int amdgpu_resume(struct amdgpu_device *adev)  	return 0;  } +static bool amdgpu_device_is_virtual(void) +{ +#ifdef CONFIG_X86 +	return boot_cpu_has(X86_FEATURE_HYPERVISOR); +#else +	return false; +#endif +} +  /**   * amdgpu_device_init - initialize the driver   * @@ -1512,9 +1528,14 @@ int amdgpu_device_init(struct amdgpu_device *adev,  	adev->virtualization.supports_sr_iov =  		amdgpu_atombios_has_gpu_virtualization_table(adev); +	/* Check if we are executing in a virtualized environment */ +	adev->virtualization.is_virtual = amdgpu_device_is_virtual(); +	adev->virtualization.caps = amdgpu_asic_get_virtual_caps(adev); +  	/* Post card if necessary */  	if (!amdgpu_card_posted(adev) || -	    adev->virtualization.supports_sr_iov) { +	    (adev->virtualization.is_virtual && +	     !(adev->virtualization.caps & AMDGPU_VIRT_CAPS_SRIOV_EN))) {  		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_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 40a23704a981..d851ea15059f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -447,7 +447,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file  			dev_info.max_memory_clock = adev->pm.default_mclk * 10;  		}  		dev_info.enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask; -		dev_info.num_rb_pipes = adev->gfx.config.num_rbs; +		dev_info.num_rb_pipes = adev->gfx.config.max_backends_per_se * +			adev->gfx.config.max_shader_engines;  		dev_info.num_hw_gfx_contexts = adev->gfx.config.max_hw_contexts;  		dev_info._pad = 0;  		dev_info.ids_flags = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 589b36e8c5cf..0e13d80d2a95 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -270,30 +270,28 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev,  	struct drm_device *ddev = dev_get_drvdata(dev);  	struct amdgpu_device *adev = ddev->dev_private;  	enum amd_pm_state_type state = 0; -	long idx; +	unsigned long idx;  	int ret;  	if (strlen(buf) == 1)  		adev->pp_force_state_enabled = false; -	else { -		ret = kstrtol(buf, 0, &idx); +	else if (adev->pp_enabled) { +		struct pp_states_info data; -		if (ret) { +		ret = kstrtoul(buf, 0, &idx); +		if (ret || idx >= ARRAY_SIZE(data.states)) {  			count = -EINVAL;  			goto fail;  		} -		if (adev->pp_enabled) { -			struct pp_states_info data; -			amdgpu_dpm_get_pp_num_states(adev, &data); -			state = data.states[idx]; -			/* only set user selected power states */ -			if (state != POWER_STATE_TYPE_INTERNAL_BOOT && -				state != POWER_STATE_TYPE_DEFAULT) { -				amdgpu_dpm_dispatch_task(adev, -						AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL); -				adev->pp_force_state_enabled = true; -			} +		amdgpu_dpm_get_pp_num_states(adev, &data); +		state = data.states[idx]; +		/* only set user selected power states */ +		if (state != POWER_STATE_TYPE_INTERNAL_BOOT && +		    state != POWER_STATE_TYPE_DEFAULT) { +			amdgpu_dpm_dispatch_task(adev, +					AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL); +			adev->pp_force_state_enabled = true;  		}  	}  fail: 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/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.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 07bc795a4ca9..910431808542 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -962,6 +962,12 @@ static bool cik_read_bios_from_rom(struct amdgpu_device *adev,  	return true;  } +static u32 cik_get_virtual_caps(struct amdgpu_device *adev) +{ +	/* CIK does not support SR-IOV */ +	return 0; +} +  static const struct amdgpu_allowed_register_entry cik_allowed_read_registers[] = {  	{mmGRBM_STATUS, false},  	{mmGB_ADDR_CONFIG, false}, @@ -2007,6 +2013,7 @@ static const struct amdgpu_asic_funcs cik_asic_funcs =  	.get_xclk = &cik_get_xclk,  	.set_uvd_clocks = &cik_set_uvd_clocks,  	.set_vce_clocks = &cik_set_vce_clocks, +	.get_virtual_caps = &cik_get_virtual_caps,  	/* these should be moved to their own ip modules */  	.get_gpu_clock_counter = &gfx_v7_0_get_gpu_clock_counter,  	.wait_for_mc_idle = &gmc_v7_0_mc_wait_for_idle, 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..fc8ff4d3ccf8 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;  } @@ -4816,7 +4833,7 @@ static int gfx_v7_0_eop_irq(struct amdgpu_device *adev,  	case 2:  		for (i = 0; i < adev->gfx.num_compute_rings; i++) {  			ring = &adev->gfx.compute_ring[i]; -			if ((ring->me == me_id) & (ring->pipe == pipe_id)) +			if ((ring->me == me_id) && (ring->pipe == pipe_id))  				amdgpu_fence_process(ring);  		}  		break; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index f19bab68fd83..1a5cbaff1e34 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -297,7 +297,8 @@ static const u32 polaris11_golden_common_all[] =  static const u32 golden_settings_polaris10_a11[] =  {  	mmATC_MISC_CG, 0x000c0fc0, 0x000c0200, -	mmCB_HW_CONTROL, 0xfffdf3cf, 0x00006208, +	mmCB_HW_CONTROL, 0xfffdf3cf, 0x00007208, +	mmCB_HW_CONTROL_2, 0, 0x0f000000,  	mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,  	mmDB_DEBUG2, 0xf00fffff, 0x00000400,  	mmPA_SC_ENHANCE, 0xffffffff, 0x20000001, @@ -836,6 +837,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 +2004,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 +3995,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/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 2c88d0b66cf3..a65c96029476 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -421,6 +421,20 @@ static bool vi_read_bios_from_rom(struct amdgpu_device *adev,  	return true;  } +static u32 vi_get_virtual_caps(struct amdgpu_device *adev) +{ +	u32 caps = 0; +	u32 reg = RREG32(mmBIF_IOV_FUNC_IDENTIFIER); + +	if (REG_GET_FIELD(reg, BIF_IOV_FUNC_IDENTIFIER, IOV_ENABLE)) +		caps |= AMDGPU_VIRT_CAPS_SRIOV_EN; + +	if (REG_GET_FIELD(reg, BIF_IOV_FUNC_IDENTIFIER, FUNC_IDENTIFIER)) +		caps |= AMDGPU_VIRT_CAPS_IS_VF; + +	return caps; +} +  static const struct amdgpu_allowed_register_entry tonga_allowed_read_registers[] = {  	{mmGB_MACROTILE_MODE7, true},  }; @@ -1118,6 +1132,7 @@ static const struct amdgpu_asic_funcs vi_asic_funcs =  	.get_xclk = &vi_get_xclk,  	.set_uvd_clocks = &vi_set_uvd_clocks,  	.set_vce_clocks = &vi_set_vce_clocks, +	.get_virtual_caps = &vi_get_virtual_caps,  	/* these should be moved to their own ip modules */  	.get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter,  	.wait_for_mc_idle = &gmc_v8_0_mc_wait_for_idle, | 
