diff options
Diffstat (limited to 'drivers/gpu/drm/amd')
26 files changed, 179 insertions, 105 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ef6e78224fdf..c3641331d4de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1614,11 +1614,9 @@ static inline void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_cap  #if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)  bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev);  bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); -void amdgpu_choose_low_power_state(struct amdgpu_device *adev);  #else  static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }  static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; } -static inline void amdgpu_choose_low_power_state(struct amdgpu_device *adev) { }  #endif  void amdgpu_register_gpu_instance(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index b7f8f2ff143d..707e131f89d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -1533,22 +1533,4 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev)  #endif /* CONFIG_AMD_PMC */  } -/** - * amdgpu_choose_low_power_state - * - * @adev: amdgpu_device_pointer - * - * Choose the target low power state for the GPU - */ -void amdgpu_choose_low_power_state(struct amdgpu_device *adev) -{ -	if (adev->in_runpm) -		return; - -	if (amdgpu_acpi_is_s0ix_active(adev)) -		adev->in_s0ix = true; -	else if (amdgpu_acpi_is_s3_active(adev)) -		adev->in_s3 = true; -} -  #endif /* CONFIG_SUSPEND */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7f354cd532dc..f8b3e04d71ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4907,28 +4907,20 @@ static int amdgpu_device_evict_resources(struct amdgpu_device *adev)   * @data: data   *   * This function is called when the system is about to suspend or hibernate. - * It is used to evict resources from the device before the system goes to - * sleep while there is still access to swap. + * It is used to set the appropriate flags so that eviction can be optimized + * in the pm prepare callback.   */  static int amdgpu_device_pm_notifier(struct notifier_block *nb, unsigned long mode,  				     void *data)  {  	struct amdgpu_device *adev = container_of(nb, struct amdgpu_device, pm_nb); -	int r;  	switch (mode) {  	case PM_HIBERNATION_PREPARE:  		adev->in_s4 = true; -		fallthrough; -	case PM_SUSPEND_PREPARE: -		r = amdgpu_device_evict_resources(adev); -		/* -		 * This is considered non-fatal at this time because -		 * amdgpu_device_prepare() will also fatally evict resources. -		 * See https://gitlab.freedesktop.org/drm/amd/-/issues/3781 -		 */ -		if (r) -			drm_warn(adev_to_drm(adev), "Failed to evict resources, freeze active processes if problems occur: %d\n", r); +		break; +	case PM_POST_HIBERNATION: +		adev->in_s4 = false;  		break;  	} @@ -4949,15 +4941,13 @@ int amdgpu_device_prepare(struct drm_device *dev)  	struct amdgpu_device *adev = drm_to_adev(dev);  	int i, r; -	amdgpu_choose_low_power_state(adev); -  	if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)  		return 0;  	/* Evict the majority of BOs before starting suspend sequence */  	r = amdgpu_device_evict_resources(adev);  	if (r) -		goto unprepare; +		return r;  	flush_delayed_work(&adev->gfx.gfx_off_delay_work); @@ -4968,15 +4958,10 @@ int amdgpu_device_prepare(struct drm_device *dev)  			continue;  		r = adev->ip_blocks[i].version->funcs->prepare_suspend(&adev->ip_blocks[i]);  		if (r) -			goto unprepare; +			return r;  	}  	return 0; - -unprepare: -	adev->in_s0ix = adev->in_s3 = adev->in_s4 = false; - -	return r;  }  /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index e6913fcf2c7b..44e120f9f764 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -199,6 +199,11 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,  		break;  	case TTM_PL_VRAM: +		/* XGMI-accessible memory should never be DMA-mapped */ +		if (WARN_ON(amdgpu_dmabuf_is_xgmi_accessible( +				dma_buf_attach_adev(attach), bo))) +			return ERR_PTR(-EINVAL); +  		r = amdgpu_vram_mgr_alloc_sgt(adev, bo->tbo.resource, 0,  					      bo->tbo.base.size, attach->dev,  					      dir, &sgt); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 24ee4710f807..72c807f5822e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2615,13 +2615,8 @@ static int amdgpu_pmops_freeze(struct device *dev)  static int amdgpu_pmops_thaw(struct device *dev)  {  	struct drm_device *drm_dev = dev_get_drvdata(dev); -	struct amdgpu_device *adev = drm_to_adev(drm_dev); -	int r; - -	r = amdgpu_device_resume(drm_dev, true); -	adev->in_s4 = false; -	return r; +	return amdgpu_device_resume(drm_dev, true);  }  static int amdgpu_pmops_poweroff(struct device *dev) @@ -2634,9 +2629,6 @@ static int amdgpu_pmops_poweroff(struct device *dev)  static int amdgpu_pmops_restore(struct device *dev)  {  	struct drm_device *drm_dev = dev_get_drvdata(dev); -	struct amdgpu_device *adev = drm_to_adev(drm_dev); - -	adev->in_s4 = false;  	return amdgpu_device_resume(drm_dev, true);  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index cdcdae7f71ce..83adf81defc7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -66,7 +66,6 @@  #define VCN_ENC_CMD_REG_WAIT		0x0000000c  #define VCN_AON_SOC_ADDRESS_2_0 	0x1f800 -#define VCN1_AON_SOC_ADDRESS_3_0 	0x48000  #define VCN_VID_IP_ADDRESS_2_0		0x0  #define VCN_AON_IP_ADDRESS_2_0		0x30000 diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c index f1dc13b3ab38..cbbeadeb53f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c @@ -41,7 +41,12 @@ static void hdp_v4_0_flush_hdp(struct amdgpu_device *adev,  {  	if (!ring || !ring->funcs->emit_wreg) {  		WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); -		RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); +		/* We just need to read back a register to post the write. +		 * Reading back the remapped register causes problems on +		 * some platforms so just read back the memory size register. +		 */ +		if (adev->nbio.funcs->get_memsize) +			adev->nbio.funcs->get_memsize(adev);  	} else {  		amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);  	} diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c index 43195c079748..086a647308df 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c @@ -32,7 +32,12 @@ static void hdp_v5_0_flush_hdp(struct amdgpu_device *adev,  {  	if (!ring || !ring->funcs->emit_wreg) {  		WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); -		RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); +		/* We just need to read back a register to post the write. +		 * Reading back the remapped register causes problems on +		 * some platforms so just read back the memory size register. +		 */ +		if (adev->nbio.funcs->get_memsize) +			adev->nbio.funcs->get_memsize(adev);  	} else {  		amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);  	} diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c b/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c index fcb8dd2876bc..40940b4ab400 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c @@ -33,7 +33,17 @@ static void hdp_v5_2_flush_hdp(struct amdgpu_device *adev,  	if (!ring || !ring->funcs->emit_wreg) {  		WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2,  			0); -		RREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); +		if (amdgpu_sriov_vf(adev)) { +			/* this is fine because SR_IOV doesn't remap the register */ +			RREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); +		} else { +			/* We just need to read back a register to post the write. +			 * Reading back the remapped register causes problems on +			 * some platforms so just read back the memory size register. +			 */ +			if (adev->nbio.funcs->get_memsize) +				adev->nbio.funcs->get_memsize(adev); +		}  	} else {  		amdgpu_ring_emit_wreg(ring,  			(adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c index a88d25a06c29..6ccd31c8bc69 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c @@ -35,7 +35,12 @@ static void hdp_v6_0_flush_hdp(struct amdgpu_device *adev,  {  	if (!ring || !ring->funcs->emit_wreg) {  		WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); -		RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); +		/* We just need to read back a register to post the write. +		 * Reading back the remapped register causes problems on +		 * some platforms so just read back the memory size register. +		 */ +		if (adev->nbio.funcs->get_memsize) +			adev->nbio.funcs->get_memsize(adev);  	} else {  		amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);  	} diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c index 49f7eb4fbd11..2c9239a22f39 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c @@ -32,7 +32,12 @@ static void hdp_v7_0_flush_hdp(struct amdgpu_device *adev,  {  	if (!ring || !ring->funcs->emit_wreg) {  		WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0); -		RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2); +		/* We just need to read back a register to post the write. +		 * Reading back the remapped register causes problems on +		 * some platforms so just read back the memory size register. +		 */ +		if (adev->nbio.funcs->get_memsize) +			adev->nbio.funcs->get_memsize(adev);  	} else {  		amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);  	} diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c index 2ece3ae75ec1..bed5ef4d8788 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c @@ -360,7 +360,7 @@ static void nbio_v7_11_get_clockgating_state(struct amdgpu_device *adev,  		*flags |= AMD_CG_SUPPORT_BIF_LS;  } -#define MMIO_REG_HOLE_OFFSET (0x80000 - PAGE_SIZE) +#define MMIO_REG_HOLE_OFFSET 0x44000  static void nbio_v7_11_set_reg_remap(struct amdgpu_device *adev)  { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index 8e7a36f26e9c..b8d835c9e17e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -39,6 +39,7 @@  #define VCN_VID_SOC_ADDRESS_2_0					0x1fa00  #define VCN1_VID_SOC_ADDRESS_3_0				0x48200 +#define VCN1_AON_SOC_ADDRESS_3_0				0x48000  #define mmUVD_CONTEXT_ID_INTERNAL_OFFSET			0x1fd  #define mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET			0x503 diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index d716510b8dd6..3eec1b8feaee 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -39,6 +39,7 @@  #define VCN_VID_SOC_ADDRESS_2_0					0x1fa00  #define VCN1_VID_SOC_ADDRESS_3_0				0x48200 +#define VCN1_AON_SOC_ADDRESS_3_0				0x48000  #define mmUVD_CONTEXT_ID_INTERNAL_OFFSET			0x27  #define mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET			0x0f diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 22ae1939476f..0b19f0ab4480 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -40,6 +40,7 @@  #define VCN_VID_SOC_ADDRESS_2_0					0x1fa00  #define VCN1_VID_SOC_ADDRESS_3_0				0x48200 +#define VCN1_AON_SOC_ADDRESS_3_0				0x48000  #define mmUVD_CONTEXT_ID_INTERNAL_OFFSET			0x27  #define mmUVD_GPCOM_VCPU_CMD_INTERNAL_OFFSET			0x0f diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index c6f6392c1c20..1f777c125b00 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -46,6 +46,7 @@  #define VCN_VID_SOC_ADDRESS_2_0							0x1fb00  #define VCN1_VID_SOC_ADDRESS_3_0						0x48300 +#define VCN1_AON_SOC_ADDRESS_3_0						0x48000  #define VCN_HARVEST_MMSCH								0 @@ -614,7 +615,8 @@ static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,  	/* VCN global tiling registers */  	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET( -		VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect); +			VCN, inst_idx, regUVD_GFX10_ADDR_CONFIG), +			adev->gfx.config.gb_addr_config, 0, indirect);  }  /** diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 3e176b4b7c69..012f6ea928ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -45,6 +45,7 @@  #define VCN_VID_SOC_ADDRESS_2_0		0x1fb00  #define VCN1_VID_SOC_ADDRESS_3_0	0x48300 +#define VCN1_AON_SOC_ADDRESS_3_0	0x48000  static const struct amdgpu_hwip_reg_entry vcn_reg_list_4_0_3[] = {  	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_POWER_STATUS), diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index ba603b2246e2..a1171e6152ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -46,6 +46,7 @@  #define VCN_VID_SOC_ADDRESS_2_0						0x1fb00  #define VCN1_VID_SOC_ADDRESS_3_0					(0x48300 + 0x38000) +#define VCN1_AON_SOC_ADDRESS_3_0					(0x48000 + 0x38000)  #define VCN_HARVEST_MMSCH							0 diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index d99d05f42f1d..b90da3d3e140 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -533,7 +533,8 @@ static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_vcn_inst *vinst,  	/* VCN global tiling registers */  	WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( -		VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect); +		VCN, inst_idx, regUVD_GFX10_ADDR_CONFIG), +		adev->gfx.config.gb_addr_config, 0, indirect);  	return;  } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c index 581d8629b9d9..e0e84ef7f568 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c @@ -503,6 +503,52 @@ static void vcn_v5_0_1_enable_clock_gating(struct amdgpu_vcn_inst *vinst)  }  /** + * vcn_v5_0_1_pause_dpg_mode - VCN pause with dpg mode + * + * @vinst: VCN instance + * @new_state: pause state + * + * Pause dpg mode for VCN block + */ +static int vcn_v5_0_1_pause_dpg_mode(struct amdgpu_vcn_inst *vinst, +				     struct dpg_pause_state *new_state) +{ +	struct amdgpu_device *adev = vinst->adev; +	uint32_t reg_data = 0; +	int vcn_inst; + +	vcn_inst = GET_INST(VCN, vinst->inst); + +	/* pause/unpause if state is changed */ +	if (vinst->pause_state.fw_based != new_state->fw_based) { +		DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d %s\n", +			vinst->pause_state.fw_based, new_state->fw_based, +			new_state->fw_based ? "VCN_DPG_STATE__PAUSE" : "VCN_DPG_STATE__UNPAUSE"); +		reg_data = RREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE) & +			(~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); + +		if (new_state->fw_based == VCN_DPG_STATE__PAUSE) { +			/* pause DPG */ +			reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; +			WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data); + +			/* wait for ACK */ +			SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_DPG_PAUSE, +					UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, +					UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK); +		} else { +			/* unpause DPG, no need to wait */ +			reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK; +			WREG32_SOC15(VCN, vcn_inst, regUVD_DPG_PAUSE, reg_data); +		} +		vinst->pause_state.fw_based = new_state->fw_based; +	} + +	return 0; +} + + +/**   * vcn_v5_0_1_start_dpg_mode - VCN start with dpg mode   *   * @vinst: VCN instance @@ -518,6 +564,7 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,  	volatile struct amdgpu_vcn5_fw_shared *fw_shared =  		adev->vcn.inst[inst_idx].fw_shared.cpu_addr;  	struct amdgpu_ring *ring; +	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__PAUSE};  	int vcn_inst;  	uint32_t tmp; @@ -582,6 +629,9 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,  	if (indirect)  		amdgpu_vcn_psp_update_sram(adev, inst_idx, AMDGPU_UCODE_ID_VCN0_RAM); +	/* Pause dpg */ +	vcn_v5_0_1_pause_dpg_mode(vinst, &state); +  	ring = &adev->vcn.inst[inst_idx].ring_enc[0];  	WREG32_SOC15(VCN, vcn_inst, regUVD_RB_BASE_LO, lower_32_bits(ring->gpu_addr)); @@ -775,9 +825,13 @@ static void vcn_v5_0_1_stop_dpg_mode(struct amdgpu_vcn_inst *vinst)  	int inst_idx = vinst->inst;  	uint32_t tmp;  	int vcn_inst; +	struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};  	vcn_inst = GET_INST(VCN, inst_idx); +	/* Unpause dpg */ +	vcn_v5_0_1_pause_dpg_mode(vinst, &state); +  	/* Wait for power status to be 1 */  	SOC15_WAIT_ON_RREG(VCN, vcn_inst, regUVD_POWER_STATUS, 1,  		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 536f73131c2d..64df8ca448b3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -673,15 +673,21 @@ static void dm_crtc_high_irq(void *interrupt_params)  	spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);  	if (acrtc->dm_irq_params.stream && -	    acrtc->dm_irq_params.vrr_params.supported && -	    acrtc->dm_irq_params.freesync_config.state == -		    VRR_STATE_ACTIVE_VARIABLE) { +		acrtc->dm_irq_params.vrr_params.supported) { +		bool replay_en = acrtc->dm_irq_params.stream->link->replay_settings.replay_feature_enabled; +		bool psr_en = acrtc->dm_irq_params.stream->link->psr_settings.psr_feature_enabled; +		bool fs_active_var_en = acrtc->dm_irq_params.freesync_config.state == VRR_STATE_ACTIVE_VARIABLE; +  		mod_freesync_handle_v_update(adev->dm.freesync_module,  					     acrtc->dm_irq_params.stream,  					     &acrtc->dm_irq_params.vrr_params); -		dc_stream_adjust_vmin_vmax(adev->dm.dc, acrtc->dm_irq_params.stream, -					   &acrtc->dm_irq_params.vrr_params.adjust); +		/* update vmin_vmax only if freesync is enabled, or only if PSR and REPLAY are disabled */ +		if (fs_active_var_en || (!fs_active_var_en && !replay_en && !psr_en)) { +			dc_stream_adjust_vmin_vmax(adev->dm.dc, +					acrtc->dm_irq_params.stream, +					&acrtc->dm_irq_params.vrr_params.adjust); +		}  	}  	/* @@ -12743,7 +12749,7 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(  		 * Transient states before tunneling is enabled could  		 * lead to this error. We can ignore this for now.  		 */ -		if (p_notify->result != AUX_RET_ERROR_PROTOCOL_ERROR) { +		if (p_notify->result == AUX_RET_ERROR_PROTOCOL_ERROR) {  			DRM_WARN("DPIA AUX failed on 0x%x(%d), error %d\n",  					payload->address, payload->length,  					p_notify->result); @@ -12752,22 +12758,14 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(  		goto out;  	} +	payload->reply[0] = adev->dm.dmub_notify->aux_reply.command & 0xF; +	if (adev->dm.dmub_notify->aux_reply.command & 0xF0) +		/* The reply is stored in the top nibble of the command. */ +		payload->reply[0] = (adev->dm.dmub_notify->aux_reply.command >> 4) & 0xF; -	payload->reply[0] = adev->dm.dmub_notify->aux_reply.command; -	if (!payload->write && p_notify->aux_reply.length && -			(payload->reply[0] == AUX_TRANSACTION_REPLY_AUX_ACK)) { - -		if (payload->length != p_notify->aux_reply.length) { -			DRM_WARN("invalid read length %d from DPIA AUX 0x%x(%d)!\n", -				p_notify->aux_reply.length, -					payload->address, payload->length); -			*operation_result = AUX_RET_ERROR_INVALID_REPLY; -			goto out; -		} - +	if (!payload->write && p_notify->aux_reply.length)  		memcpy(payload->data, p_notify->aux_reply.data,  				p_notify->aux_reply.length); -	}  	/* success */  	ret = p_notify->aux_reply.length; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 5198a079b463..8f22ad966543 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -173,6 +173,9 @@ void hdcp_update_display(struct hdcp_workqueue *hdcp_work,  	unsigned int conn_index = aconnector->base.index;  	guard(mutex)(&hdcp_w->mutex); +	drm_connector_get(&aconnector->base); +	if (hdcp_w->aconnector[conn_index]) +		drm_connector_put(&hdcp_w->aconnector[conn_index]->base);  	hdcp_w->aconnector[conn_index] = aconnector;  	memset(&link_adjust, 0, sizeof(link_adjust)); @@ -220,7 +223,6 @@ static void hdcp_remove_display(struct hdcp_workqueue *hdcp_work,  	unsigned int conn_index = aconnector->base.index;  	guard(mutex)(&hdcp_w->mutex); -	hdcp_w->aconnector[conn_index] = aconnector;  	/* the removal of display will invoke auth reset -> hdcp destroy and  	 * we'd expect the Content Protection (CP) property changed back to @@ -236,7 +238,10 @@ static void hdcp_remove_display(struct hdcp_workqueue *hdcp_work,  	}  	mod_hdcp_remove_display(&hdcp_w->hdcp, aconnector->base.index, &hdcp_w->output); - +	if (hdcp_w->aconnector[conn_index]) { +		drm_connector_put(&hdcp_w->aconnector[conn_index]->base); +		hdcp_w->aconnector[conn_index] = NULL; +	}  	process_output(hdcp_w);  } @@ -254,6 +259,10 @@ void hdcp_reset_display(struct hdcp_workqueue *hdcp_work, unsigned int link_inde  	for (conn_index = 0; conn_index < AMDGPU_DM_MAX_DISPLAY_INDEX; conn_index++) {  		hdcp_w->encryption_status[conn_index] =  			MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF; +		if (hdcp_w->aconnector[conn_index]) { +			drm_connector_put(&hdcp_w->aconnector[conn_index]->base); +			hdcp_w->aconnector[conn_index] = NULL; +		}  	}  	process_output(hdcp_w); @@ -488,6 +497,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)  	struct hdcp_workqueue *hdcp_work = handle;  	struct amdgpu_dm_connector *aconnector = config->dm_stream_ctx;  	int link_index = aconnector->dc_link->link_index; +	unsigned int conn_index = aconnector->base.index;  	struct mod_hdcp_display *display = &hdcp_work[link_index].display;  	struct mod_hdcp_link *link = &hdcp_work[link_index].link;  	struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index]; @@ -544,7 +554,10 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)  	guard(mutex)(&hdcp_w->mutex);  	mod_hdcp_add_display(&hdcp_w->hdcp, link, display, &hdcp_w->output); - +	drm_connector_get(&aconnector->base); +	if (hdcp_w->aconnector[conn_index]) +		drm_connector_put(&hdcp_w->aconnector[conn_index]->base); +	hdcp_w->aconnector[conn_index] = aconnector;  	process_output(hdcp_w);  } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 7ceedf626d23..074b79fd5822 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -51,6 +51,9 @@  #define PEAK_FACTOR_X1000 1006 +/* + * This function handles both native AUX and I2C-Over-AUX transactions. + */  static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,  				  struct drm_dp_aux_msg *msg)  { @@ -87,15 +90,25 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,  	if (adev->dm.aux_hpd_discon_quirk) {  		if (msg->address == DP_SIDEBAND_MSG_DOWN_REQ_BASE &&  			operation_result == AUX_RET_ERROR_HPD_DISCON) { -			result = 0; +			result = msg->size;  			operation_result = AUX_RET_SUCCESS;  		}  	} -	if (payload.write && result >= 0) -		result = msg->size; +	/* +	 * result equals to 0 includes the cases of AUX_DEFER/I2C_DEFER +	 */ +	if (payload.write && result >= 0) { +		if (result) { +			/*one byte indicating partially written bytes. Force 0 to retry*/ +			drm_info(adev_to_drm(adev), "amdgpu: AUX partially written\n"); +			result = 0; +		} else if (!payload.reply[0]) +			/*I2C_ACK|AUX_ACK*/ +			result = msg->size; +	} -	if (result < 0) +	if (result < 0) {  		switch (operation_result) {  		case AUX_RET_SUCCESS:  			break; @@ -114,6 +127,13 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,  			break;  		} +		drm_info(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result); +	} + +	if (payload.reply[0]) +		drm_info(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.", +			payload.reply[0]); +  	return result;  } diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c index 5d16f36ec95c..ed6584535e89 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_wrapper.c @@ -234,7 +234,9 @@ static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_s  	if (!result)  		return false; +	DC_FP_START();  	result = dml2_build_mode_programming(mode_programming); +	DC_FP_END();  	if (!result)  		return false; @@ -277,7 +279,9 @@ static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *co  	mode_support->dml2_instance = dml_init->dml2_instance;  	dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);  	dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming; +	DC_FP_START();  	is_supported = dml2_check_mode_supported(mode_support); +	DC_FP_END();  	if (!is_supported)  		return false; @@ -288,16 +292,12 @@ bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml  {  	bool out = false; -	DC_FP_START(); -  	/* Use dml_validate_only for fast_validate path */  	if (fast_validate)  		out = dml21_check_mode_support(in_dc, context, dml_ctx);  	else  		out = dml21_mode_check_and_programming(in_dc, context, dml_ctx); -	DC_FP_END(); -  	return out;  } diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index 2061d43b92e1..ab6baf269801 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -973,7 +973,9 @@ static void populate_dml_surface_cfg_from_plane_state(enum dml_project_id dml2_p  	}  } -static void get_scaler_data_for_plane(const struct dc_plane_state *in, struct dc_state *context, struct scaler_data *out) +static struct scaler_data *get_scaler_data_for_plane( +		const struct dc_plane_state *in, +		struct dc_state *context)  {  	int i;  	struct pipe_ctx *temp_pipe = &context->res_ctx.temp_pipe; @@ -994,7 +996,7 @@ static void get_scaler_data_for_plane(const struct dc_plane_state *in, struct dc  	}  	ASSERT(i < MAX_PIPES); -	memcpy(out, &temp_pipe->plane_res.scl_data, sizeof(*out)); +	return &temp_pipe->plane_res.scl_data;  }  static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned int location, @@ -1057,11 +1059,7 @@ static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out  						    const struct dc_plane_state *in, struct dc_state *context,  						    const struct soc_bounding_box_st *soc)  { -	struct scaler_data *scaler_data = kzalloc(sizeof(*scaler_data), GFP_KERNEL); -	if (!scaler_data) -		return; - -	get_scaler_data_for_plane(in, context, scaler_data); +	struct scaler_data *scaler_data = get_scaler_data_for_plane(in, context);  	out->CursorBPP[location] = dml_cur_32bit;  	out->CursorWidth[location] = 256; @@ -1126,8 +1124,6 @@ static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out  	out->DynamicMetadataTransmittedBytes[location] = 0;  	out->NumberOfCursors[location] = 1; - -	kfree(scaler_data);  }  static unsigned int map_stream_to_dml_display_cfg(const struct dml2_context *dml2, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index 2a59cc61ed8c..944650cb13de 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -2114,8 +2114,6 @@ static bool dcn32_resource_construct(  #define REG_STRUCT dccg_regs  	dccg_regs_init(); -	DC_FP_START(); -  	ctx->dc_bios->regs = &bios_regs;  	pool->base.res_cap = &res_cap_dcn32; @@ -2501,14 +2499,10 @@ static bool dcn32_resource_construct(  	if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0))  		dc->config.sdpif_request_limit_words_per_umc = 16; -	DC_FP_END(); -  	return true;  create_fail: -	DC_FP_END(); -  	dcn32_resource_destruct(pool);  	return false; | 
