diff options
Diffstat (limited to 'drivers/gpu/drm/amd')
49 files changed, 408 insertions, 231 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2c04ae133848..c3641331d4de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1123,6 +1123,7 @@ struct amdgpu_device {  	bool				in_s3;  	bool				in_s4;  	bool				in_s0ix; +	suspend_state_t			last_suspend_state;  	enum pp_mp1_state               mp1_state;  	struct amdgpu_doorbell_index doorbell_index; @@ -1613,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_csa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c index cfdf558b48b6..02138aa55793 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c @@ -109,7 +109,7 @@ int amdgpu_unmap_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,  	struct drm_exec exec;  	int r; -	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0); +	drm_exec_init(&exec, 0, 0);  	drm_exec_until_all_locked(&exec) {  		r = amdgpu_vm_lock_pd(vm, &exec, 0);  		if (likely(!r)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b34b915203f2..f8b3e04d71ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3510,6 +3510,7 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)  			amdgpu_device_mem_scratch_fini(adev);  			amdgpu_ib_pool_fini(adev);  			amdgpu_seq64_fini(adev); +			amdgpu_doorbell_fini(adev);  		}  		if (adev->ip_blocks[i].version->funcs->sw_fini) {  			r = adev->ip_blocks[i].version->funcs->sw_fini(&adev->ip_blocks[i]); @@ -4858,7 +4859,6 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)  		iounmap(adev->rmmio);  		adev->rmmio = NULL; -		amdgpu_doorbell_fini(adev);  		drm_dev_exit(idx);  	} @@ -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 667080cc9ae1..44e120f9f764 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -43,6 +43,29 @@  #include <linux/dma-fence-array.h>  #include <linux/pci-p2pdma.h> +static const struct dma_buf_attach_ops amdgpu_dma_buf_attach_ops; + +/** + * dma_buf_attach_adev - Helper to get adev of an attachment + * + * @attach: attachment + * + * Returns: + * A struct amdgpu_device * if the attaching device is an amdgpu device or + * partition, NULL otherwise. + */ +static struct amdgpu_device *dma_buf_attach_adev(struct dma_buf_attachment *attach) +{ +	if (attach->importer_ops == &amdgpu_dma_buf_attach_ops) { +		struct drm_gem_object *obj = attach->importer_priv; +		struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + +		return amdgpu_ttm_adev(bo->tbo.bdev); +	} + +	return NULL; +} +  /**   * amdgpu_dma_buf_attach - &dma_buf_ops.attach implementation   * @@ -54,11 +77,13 @@  static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,  				 struct dma_buf_attachment *attach)  { +	struct amdgpu_device *attach_adev = dma_buf_attach_adev(attach);  	struct drm_gem_object *obj = dmabuf->priv;  	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);  	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); -	if (pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0) +	if (!amdgpu_dmabuf_is_xgmi_accessible(attach_adev, bo) && +	    pci_p2pdma_distance(adev->pdev, attach->dev, false) < 0)  		attach->peer2peer = false;  	amdgpu_vm_bo_update_shared(bo); @@ -77,22 +102,32 @@ static int amdgpu_dma_buf_pin(struct dma_buf_attachment *attach)  {  	struct dma_buf *dmabuf = attach->dmabuf;  	struct amdgpu_bo *bo = gem_to_amdgpu_bo(dmabuf->priv); -	u32 domains = bo->preferred_domains; +	u32 domains = bo->allowed_domains;  	dma_resv_assert_held(dmabuf->resv); -	/* -	 * Try pinning into VRAM to allow P2P with RDMA NICs without ODP +	/* Try pinning into VRAM to allow P2P with RDMA NICs without ODP  	 * support if all attachments can do P2P. If any attachment can't do  	 * P2P just pin into GTT instead. +	 * +	 * To avoid with conflicting pinnings between GPUs and RDMA when move +	 * notifiers are disabled, only allow pinning in VRAM when move +	 * notiers are enabled.  	 */ -	list_for_each_entry(attach, &dmabuf->attachments, node) -		if (!attach->peer2peer) -			domains &= ~AMDGPU_GEM_DOMAIN_VRAM; +	if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) { +		domains &= ~AMDGPU_GEM_DOMAIN_VRAM; +	} else { +		list_for_each_entry(attach, &dmabuf->attachments, node) +			if (!attach->peer2peer) +				domains &= ~AMDGPU_GEM_DOMAIN_VRAM; +	}  	if (domains & AMDGPU_GEM_DOMAIN_VRAM)  		bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; +	if (WARN_ON(!domains)) +		return -EINVAL; +  	return amdgpu_bo_pin(bo, domains);  } @@ -164,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); @@ -470,6 +510,9 @@ bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev,  	struct drm_gem_object *obj = &bo->tbo.base;  	struct drm_gem_object *gobj; +	if (!adev) +		return false; +  	if (obj->import_attach) {  		struct dma_buf *dma_buf = obj->import_attach->dmabuf; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 26bf896f1444..72c807f5822e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2548,8 +2548,20 @@ static int amdgpu_pmops_suspend(struct device *dev)  		adev->in_s0ix = true;  	else if (amdgpu_acpi_is_s3_active(adev))  		adev->in_s3 = true; -	if (!adev->in_s0ix && !adev->in_s3) +	if (!adev->in_s0ix && !adev->in_s3) { +		/* don't allow going deep first time followed by s2idle the next time */ +		if (adev->last_suspend_state != PM_SUSPEND_ON && +		    adev->last_suspend_state != pm_suspend_target_state) { +			drm_err_once(drm_dev, "Unsupported suspend state %d\n", +				     pm_suspend_target_state); +			return -EINVAL; +		}  		return 0; +	} + +	/* cache the state last used for suspend */ +	adev->last_suspend_state = pm_suspend_target_state; +  	return amdgpu_device_suspend(drm_dev, true);  } @@ -2603,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) @@ -2622,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_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 72af5e5a894a..cf2df7790077 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -1438,9 +1438,11 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)  	struct amdgpu_device *adev = ring->adev;  	struct drm_gpu_scheduler *sched = &ring->sched;  	struct drm_sched_entity entity; +	static atomic_t counter;  	struct dma_fence *f;  	struct amdgpu_job *job;  	struct amdgpu_ib *ib; +	void *owner;  	int i, r;  	/* Initialize the scheduler entity */ @@ -1451,9 +1453,15 @@ static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring)  		goto err;  	} -	r = amdgpu_job_alloc_with_ib(ring->adev, &entity, NULL, -				     64, 0, -				     &job); +	/* +	 * Use some unique dummy value as the owner to make sure we execute +	 * the cleaner shader on each submission. The value just need to change +	 * for each submission and is otherwise meaningless. +	 */ +	owner = (void *)(unsigned long)atomic_inc_return(&counter); + +	r = amdgpu_job_alloc_with_ib(ring->adev, &entity, owner, +				     64, 0, &job);  	if (r)  		goto err; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 19ce4da285e8..38e7043016e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -725,8 +725,8 @@ static const struct irq_domain_ops amdgpu_hw_irqdomain_ops = {   */  int amdgpu_irq_add_domain(struct amdgpu_device *adev)  { -	adev->irq.domain = irq_domain_add_linear(NULL, AMDGPU_MAX_IRQ_SRC_ID, -						 &amdgpu_hw_irqdomain_ops, adev); +	adev->irq.domain = irq_domain_create_linear(NULL, AMDGPU_MAX_IRQ_SRC_ID, +						    &amdgpu_hw_irqdomain_ops, adev);  	if (!adev->irq.domain) {  		DRM_ERROR("GPU irq add domain failed\n");  		return -ENODEV; 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/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index a63ce747863f..23e6a05359c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6114,7 +6114,7 @@ static int gfx_v10_0_cp_gfx_load_pfp_microcode(struct amdgpu_device *adev)  	}  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	tmp = RREG32_SOC15(GC, 0, mmCP_PFP_IC_BASE_CNTL);  	tmp = REG_SET_FIELD(tmp, CP_PFP_IC_BASE_CNTL, VMID, 0); @@ -6192,7 +6192,7 @@ static int gfx_v10_0_cp_gfx_load_ce_microcode(struct amdgpu_device *adev)  	}  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	tmp = RREG32_SOC15(GC, 0, mmCP_CE_IC_BASE_CNTL);  	tmp = REG_SET_FIELD(tmp, CP_CE_IC_BASE_CNTL, VMID, 0); @@ -6269,7 +6269,7 @@ static int gfx_v10_0_cp_gfx_load_me_microcode(struct amdgpu_device *adev)  	}  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	tmp = RREG32_SOC15(GC, 0, mmCP_ME_IC_BASE_CNTL);  	tmp = REG_SET_FIELD(tmp, CP_ME_IC_BASE_CNTL, VMID, 0); @@ -6644,7 +6644,7 @@ static int gfx_v10_0_cp_compute_load_microcode(struct amdgpu_device *adev)  	}  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	tmp = RREG32_SOC15(GC, 0, mmCP_CPC_IC_BASE_CNTL);  	tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index d57db42f9536..2a5c2a1ae3c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -2428,7 +2428,7 @@ static int gfx_v11_0_config_me_cache(struct amdgpu_device *adev, uint64_t addr)  	}  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	tmp = RREG32_SOC15(GC, 0, regCP_ME_IC_BASE_CNTL);  	tmp = REG_SET_FIELD(tmp, CP_ME_IC_BASE_CNTL, VMID, 0); @@ -2472,7 +2472,7 @@ static int gfx_v11_0_config_pfp_cache(struct amdgpu_device *adev, uint64_t addr)  	}  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	tmp = RREG32_SOC15(GC, 0, regCP_PFP_IC_BASE_CNTL);  	tmp = REG_SET_FIELD(tmp, CP_PFP_IC_BASE_CNTL, VMID, 0); @@ -2517,7 +2517,7 @@ static int gfx_v11_0_config_mec_cache(struct amdgpu_device *adev, uint64_t addr)  	}  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	tmp = RREG32_SOC15(GC, 0, regCP_CPC_IC_BASE_CNTL);  	tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); @@ -3153,7 +3153,7 @@ static int gfx_v11_0_cp_gfx_load_pfp_microcode_rs64(struct amdgpu_device *adev)  	amdgpu_bo_unreserve(adev->gfx.pfp.pfp_fw_data_obj);  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	WREG32_SOC15(GC, 0, regCP_PFP_IC_BASE_LO,  		lower_32_bits(adev->gfx.pfp.pfp_fw_gpu_addr)); @@ -3371,7 +3371,7 @@ static int gfx_v11_0_cp_gfx_load_me_microcode_rs64(struct amdgpu_device *adev)  	amdgpu_bo_unreserve(adev->gfx.me.me_fw_data_obj);  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	WREG32_SOC15(GC, 0, regCP_ME_IC_BASE_LO,  		lower_32_bits(adev->gfx.me.me_fw_gpu_addr)); @@ -4541,7 +4541,7 @@ static int gfx_v11_0_gfxhub_enable(struct amdgpu_device *adev)  	if (r)  		return r; -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ?  		false : true; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c index e7b58e470292..62a257a4a3e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c @@ -2324,7 +2324,7 @@ static int gfx_v12_0_cp_gfx_load_pfp_microcode_rs64(struct amdgpu_device *adev)  	amdgpu_bo_unreserve(adev->gfx.pfp.pfp_fw_data_obj);  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	WREG32_SOC15(GC, 0, regCP_PFP_IC_BASE_LO,  		lower_32_bits(adev->gfx.pfp.pfp_fw_gpu_addr)); @@ -2468,7 +2468,7 @@ static int gfx_v12_0_cp_gfx_load_me_microcode_rs64(struct amdgpu_device *adev)  	amdgpu_bo_unreserve(adev->gfx.me.me_fw_data_obj);  	if (amdgpu_emu_mode == 1) -		adev->hdp.funcs->flush_hdp(adev, NULL); +		amdgpu_device_flush_hdp(adev, NULL);  	WREG32_SOC15(GC, 0, regCP_ME_IC_BASE_LO,  		lower_32_bits(adev->gfx.me.me_fw_gpu_addr)); @@ -3426,7 +3426,7 @@ static int gfx_v12_0_gfxhub_enable(struct amdgpu_device *adev)  	if (r)  		return r; -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ?  		false : true; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 95d894a231fc..809b3a882d0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -268,7 +268,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,  	ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;  	/* flush hdp cache */ -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	/* This is necessary for SRIOV as well as for GFXOFF to function  	 * properly under bare metal @@ -969,7 +969,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev)  	adev->hdp.funcs->init_registers(adev);  	/* Flush HDP after it is initialized */ -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ?  		false : true; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index ad099f136f84..fec9a007533a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -229,7 +229,7 @@ static void gmc_v11_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,  	ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng;  	/* flush hdp cache */ -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	/* This is necessary for SRIOV as well as for GFXOFF to function  	 * properly under bare metal @@ -752,6 +752,18 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)  	adev->gmc.vram_type = vram_type;  	adev->gmc.vram_vendor = vram_vendor; +	/* The mall_size is already calculated as mall_size_per_umc * num_umc. +	 * However, for gfx1151, which features a 2-to-1 UMC mapping, +	 * the result must be multiplied by 2 to determine the actual mall size. +	 */ +	switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { +	case IP_VERSION(11, 5, 1): +		adev->gmc.mall_size *= 2; +		break; +	default: +		break; +	} +  	switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {  	case IP_VERSION(11, 0, 0):  	case IP_VERSION(11, 0, 1): @@ -899,7 +911,7 @@ static int gmc_v11_0_gart_enable(struct amdgpu_device *adev)  		return r;  	/* Flush HDP after it is initialized */ -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ?  		false : true; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c index 05c026d0b0d9..c6f290704d47 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c @@ -297,7 +297,7 @@ static void gmc_v12_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,  		return;  	/* flush hdp cache */ -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	/* This is necessary for SRIOV as well as for GFXOFF to function  	 * properly under bare metal @@ -881,7 +881,7 @@ static int gmc_v12_0_gart_enable(struct amdgpu_device *adev)  		return r;  	/* Flush HDP after it is initialized */ -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	value = (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS) ?  		false : true; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 783e0c3b86b4..5effe8327d29 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -2435,7 +2435,7 @@ static int gmc_v9_0_hw_init(struct amdgpu_ip_block *ip_block)  	adev->hdp.funcs->init_registers(adev);  	/* After HDP is initialized, flush HDP.*/ -	adev->hdp.funcs->flush_hdp(adev, NULL); +	amdgpu_device_flush_hdp(adev, NULL);  	if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)  		value = false; 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/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index bb5dfc410a66..215543575f47 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -533,7 +533,7 @@ static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)  			}  			memcpy_toio(adev->mman.aper_base_kaddr, buf, sz); -			adev->hdp.funcs->flush_hdp(adev, NULL); +			amdgpu_device_flush_hdp(adev, NULL);  			vfree(buf);  			drm_dev_exit(idx);  		} else { diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c index cc621064610f..afdf8ce3b4c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c @@ -610,7 +610,7 @@ static int psp_v13_0_memory_training(struct psp_context *psp, uint32_t ops)  			}  			memcpy_toio(adev->mman.aper_base_kaddr, buf, sz); -			adev->hdp.funcs->flush_hdp(adev, NULL); +			amdgpu_device_flush_hdp(adev, NULL);  			vfree(buf);  			drm_dev_exit(idx);  		} else { diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c index 7c49c3f3c388..256288c6cd78 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c @@ -498,7 +498,7 @@ static int psp_v14_0_memory_training(struct psp_context *psp, uint32_t ops)  			}  			memcpy_toio(adev->mman.aper_base_kaddr, buf, sz); -			adev->hdp.funcs->flush_hdp(adev, NULL); +			amdgpu_device_flush_hdp(adev, NULL);  			vfree(buf);  			drm_dev_exit(idx);  		} else { 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..f11df9c2ec13 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 @@ -1022,6 +1023,10 @@ static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_vcn_inst *vinst,  			ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |  			VCN_RB1_DB_CTRL__EN_MASK); +	/* Keeping one read-back to ensure all register writes are done, otherwise +	 * it may introduce race conditions */ +	RREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL); +  	return 0;  } @@ -1204,6 +1209,10 @@ static int vcn_v4_0_5_start(struct amdgpu_vcn_inst *vinst)  	WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);  	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); +	/* Keeping one read-back to ensure all register writes are done, otherwise +	 * it may introduce race conditions */ +	RREG32_SOC15(VCN, i, regVCN_RB_ENABLE); +  	return 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/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 86d8bc10d90a..9b3510e53112 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -239,6 +239,13 @@ static const struct amdgpu_video_codec_info cz_video_codecs_decode_array[] =  		.max_pixels_per_frame = 4096 * 4096,  		.max_level = 186,  	}, +	{ +		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, +		.max_width = 4096, +		.max_height = 4096, +		.max_pixels_per_frame = 4096 * 4096, +		.max_level = 0, +	},  };  static const struct amdgpu_video_codecs cz_video_codecs_decode = 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 9fed4471405f..a187cdb43e7e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -372,6 +372,8 @@ get_crtc_by_otg_inst(struct amdgpu_device *adev,  static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,  					      struct dm_crtc_state *new_state)  { +	if (new_state->stream->adjust.timing_adjust_pending) +		return true;  	if (new_state->freesync_config.state ==  VRR_STATE_ACTIVE_FIXED)  		return true;  	else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state)) @@ -673,15 +675,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); +		}  	}  	/* @@ -1920,26 +1928,6 @@ static enum dmub_ips_disable_type dm_get_default_ips_mode(  	switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) {  	case IP_VERSION(3, 5, 0):  	case IP_VERSION(3, 6, 0): -		/* -		 * On DCN35 systems with Z8 enabled, it's possible for IPS2 + Z8 to -		 * cause a hard hang. A fix exists for newer PMFW. -		 * -		 * As a workaround, for non-fixed PMFW, force IPS1+RCG as the deepest -		 * IPS state in all cases, except for s0ix and all displays off (DPMS), -		 * where IPS2 is allowed. -		 * -		 * When checking pmfw version, use the major and minor only. -		 */ -		if ((adev->pm.fw_version & 0x00FFFF00) < 0x005D6300) -			ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; -		else if (amdgpu_ip_version(adev, GC_HWIP, 0) > IP_VERSION(11, 5, 0)) -			/* -			 * Other ASICs with DCN35 that have residency issues with -			 * IPS2 in idle. -			 * We want them to use IPS2 only in display off cases. -			 */ -			ret =  DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; -		break;  	case IP_VERSION(3, 5, 1):  		ret =  DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF;  		break; @@ -3355,16 +3343,16 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,  	for (k = 0; k < dc_state->stream_count; k++) {  		bundle->stream_update.stream = dc_state->streams[k]; -		for (m = 0; m < dc_state->stream_status->plane_count; m++) { +		for (m = 0; m < dc_state->stream_status[k].plane_count; m++) {  			bundle->surface_updates[m].surface = -				dc_state->stream_status->plane_states[m]; +				dc_state->stream_status[k].plane_states[m];  			bundle->surface_updates[m].surface->force_full_update =  				true;  		}  		update_planes_and_stream_adapter(dm->dc,  					 UPDATE_TYPE_FULL, -					 dc_state->stream_status->plane_count, +					 dc_state->stream_status[k].plane_count,  					 dc_state->streams[k],  					 &bundle->stream_update,  					 bundle->surface_updates); @@ -3481,11 +3469,6 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)  		return 0;  	} - -	/* leave display off for S4 sequence */ -	if (adev->in_s4) -		return 0; -  	/* Recreate dc_state - DC invalidates it when setting power state to S3. */  	dc_state_release(dm_state->context);  	dm_state->context = dc_state_create(dm->dc, NULL); @@ -6521,12 +6504,12 @@ decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode,  					const struct drm_display_mode *native_mode,  					bool scale_enabled)  { -	if (scale_enabled) { -		copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); -	} else if (native_mode->clock == drm_mode->clock && -			native_mode->htotal == drm_mode->htotal && -			native_mode->vtotal == drm_mode->vtotal) { -		copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode); +	if (scale_enabled || ( +	    native_mode->clock == drm_mode->clock && +	    native_mode->htotal == drm_mode->htotal && +	    native_mode->vtotal == drm_mode->vtotal)) { +		if (native_mode->crtc_clock) +			copy_crtc_timing_for_drm_display_mode(native_mode, drm_mode);  	} else {  		/* no scaling nor amdgpu inserted, no need to patch */  	} @@ -11043,6 +11026,9 @@ static bool should_reset_plane(struct drm_atomic_state *state,  	    state->allow_modeset)  		return true; +	if (amdgpu_in_reset(adev) && state->allow_modeset) +		return true; +  	/* Exit early if we know that we're adding or removing the plane. */  	if (old_plane_state->crtc != new_plane_state->crtc)  		return true; @@ -12760,7 +12746,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); @@ -12769,22 +12755,15 @@ 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; -		} - +	/*write req may receive a byte indicating partially written number as well*/ +	if (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_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 2cd35392e2da..1395a748d726 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -918,7 +918,7 @@ dm_helpers_probe_acpi_edid(void *data, u8 *buf, unsigned int block, size_t len)  {  	struct drm_connector *connector = data;  	struct acpi_device *acpidev = ACPI_COMPANION(connector->dev->dev); -	unsigned char start = block * EDID_LENGTH; +	unsigned short start = block * EDID_LENGTH;  	struct edid *edid;  	int r; 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..5cdbc86ef8f5 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)  { @@ -59,6 +62,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,  	enum aux_return_code_type operation_result;  	struct amdgpu_device *adev;  	struct ddc_service *ddc; +	uint8_t copy[16];  	if (WARN_ON(msg->size > 16))  		return -E2BIG; @@ -74,6 +78,11 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,  			(msg->request & DP_AUX_I2C_WRITE_STATUS_UPDATE) != 0;  	payload.defer_delay = 0; +	if (payload.write) { +		memcpy(copy, msg->buffer, msg->size); +		payload.data = copy; +	} +  	result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,  				      &operation_result); @@ -87,15 +96,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*/ +			drm_dbg_dp(adev_to_drm(adev), "amdgpu: AUX partially written\n"); +			result = payload.data[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 +133,13 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,  			break;  		} +		drm_dbg_dp(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result); +	} + +	if (payload.reply[0]) +		drm_dbg_dp(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/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 28d1353f403d..ba4ce8a63158 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -439,9 +439,12 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,  	 * Don't adjust DRR while there's bandwidth optimizations pending to  	 * avoid conflicting with firmware updates.  	 */ -	if (dc->ctx->dce_version > DCE_VERSION_MAX) -		if (dc->optimized_required || dc->wm_optimized_required) +	if (dc->ctx->dce_version > DCE_VERSION_MAX) { +		if (dc->optimized_required || dc->wm_optimized_required) { +			stream->adjust.timing_adjust_pending = true;  			return false; +		} +	}  	dc_exit_ips_for_hw_access(dc); @@ -3168,7 +3171,8 @@ static void copy_stream_update_to_stream(struct dc *dc,  	if (update->crtc_timing_adjust) {  		if (stream->adjust.v_total_min != update->crtc_timing_adjust->v_total_min || -			stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max) +			stream->adjust.v_total_max != update->crtc_timing_adjust->v_total_max || +			stream->adjust.timing_adjust_pending)  			update->crtc_timing_adjust->timing_adjust_pending = true;  		stream->adjust = *update->crtc_timing_adjust;  		update->crtc_timing_adjust->timing_adjust_pending = false; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c index 0c8ec30ea672..731fbd4bc600 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c @@ -910,7 +910,7 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm  }  //TODO : Could be possibly moved to a common helper layer. -static bool dml21_wrapper_get_plane_id(const struct dc_state *context, const struct dc_plane_state *plane, unsigned int *plane_id) +static bool dml21_wrapper_get_plane_id(const struct dc_state *context, unsigned int stream_id, const struct dc_plane_state *plane, unsigned int *plane_id)  {  	int i, j; @@ -918,10 +918,12 @@ static bool dml21_wrapper_get_plane_id(const struct dc_state *context, const str  		return false;  	for (i = 0; i < context->stream_count; i++) { -		for (j = 0; j < context->stream_status[i].plane_count; j++) { -			if (context->stream_status[i].plane_states[j] == plane) { -				*plane_id = (i << 16) | j; -				return true; +		if (context->streams[i]->stream_id == stream_id) { +			for (j = 0; j < context->stream_status[i].plane_count; j++) { +				if (context->stream_status[i].plane_states[j] == plane) { +					*plane_id = (i << 16) | j; +					return true; +				}  			}  		}  	} @@ -944,14 +946,14 @@ static unsigned int map_stream_to_dml21_display_cfg(const struct dml2_context *d  	return location;  } -static unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, +static unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id,  		const struct dc_plane_state *plane, const struct dc_state *context)  {  	unsigned int plane_id;  	int i = 0;  	int location = -1; -	if (!dml21_wrapper_get_plane_id(context, plane, &plane_id)) { +	if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) {  		ASSERT(false);  		return -1;  	} @@ -1037,7 +1039,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s  			dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location;  		} else {  			for (plane_index = 0; plane_index < context->stream_status[stream_index].plane_count; plane_index++) { -				disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->stream_status[stream_index].plane_states[plane_index], context); +				disp_cfg_plane_location = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], context);  				if (disp_cfg_plane_location < 0)  					disp_cfg_plane_location = dml_dispcfg->num_planes++; @@ -1048,7 +1050,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s  				populate_dml21_plane_config_from_plane_state(dml_ctx, &dml_dispcfg->plane_descriptors[disp_cfg_plane_location], context->stream_status[stream_index].plane_states[plane_index], context, stream_index);  				dml_dispcfg->plane_descriptors[disp_cfg_plane_location].stream_index = disp_cfg_stream_location; -				if (dml21_wrapper_get_plane_id(context, context->stream_status[stream_index].plane_states[plane_index], &dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[disp_cfg_plane_location])) +				if (dml21_wrapper_get_plane_id(context, context->streams[stream_index]->stream_id, context->stream_status[stream_index].plane_states[plane_index], &dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id[disp_cfg_plane_location]))  					dml_ctx->v21.dml_to_dc_pipe_mapping.disp_cfg_to_plane_id_valid[disp_cfg_plane_location] = true;  				/* apply forced pstate policy */ 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 94e99e540691..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 @@ -2,6 +2,7 @@  //  // Copyright 2024 Advanced Micro Devices, Inc. +#include <linux/vmalloc.h>  #include "dml2_internal_types.h"  #include "dml_top.h" @@ -13,11 +14,11 @@  static bool dml21_allocate_memory(struct dml2_context **dml_ctx)  { -	*dml_ctx = kzalloc(sizeof(struct dml2_context), GFP_KERNEL); +	*dml_ctx = vzalloc(sizeof(struct dml2_context));  	if (!(*dml_ctx))  		return false; -	(*dml_ctx)->v21.dml_init.dml2_instance = kzalloc(sizeof(struct dml2_instance), GFP_KERNEL); +	(*dml_ctx)->v21.dml_init.dml2_instance = vzalloc(sizeof(struct dml2_instance));  	if (!((*dml_ctx)->v21.dml_init.dml2_instance))  		return false; @@ -27,7 +28,7 @@ static bool dml21_allocate_memory(struct dml2_context **dml_ctx)  	(*dml_ctx)->v21.mode_support.display_config = &(*dml_ctx)->v21.display_config;  	(*dml_ctx)->v21.mode_programming.display_config = (*dml_ctx)->v21.mode_support.display_config; -	(*dml_ctx)->v21.mode_programming.programming = kzalloc(sizeof(struct dml2_display_cfg_programming), GFP_KERNEL); +	(*dml_ctx)->v21.mode_programming.programming = vzalloc(sizeof(struct dml2_display_cfg_programming));  	if (!((*dml_ctx)->v21.mode_programming.programming))  		return false; @@ -115,8 +116,8 @@ bool dml21_create(const struct dc *in_dc, struct dml2_context **dml_ctx, const s  void dml21_destroy(struct dml2_context *dml2)  { -	kfree(dml2->v21.dml_init.dml2_instance); -	kfree(dml2->v21.mode_programming.programming); +	vfree(dml2->v21.dml_init.dml2_instance); +	vfree(dml2->v21.mode_programming.programming);  }  static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state, @@ -233,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; @@ -276,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; @@ -287,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/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index f549a778f6f1..e89571874185 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -24,6 +24,8 @@   *   */ +#include <linux/vmalloc.h> +  #include "display_mode_core.h"  #include "dml2_internal_types.h"  #include "dml2_utils.h" @@ -747,7 +749,7 @@ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2  static inline struct dml2_context *dml2_allocate_memory(void)  { -	return (struct dml2_context *) kzalloc(sizeof(struct dml2_context), GFP_KERNEL); +	return (struct dml2_context *) vzalloc(sizeof(struct dml2_context));  }  static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2) @@ -821,7 +823,7 @@ void dml2_destroy(struct dml2_context *dml2)  	if (dml2->architecture == dml2_architecture_21)  		dml21_destroy(dml2); -	kfree(dml2); +	vfree(dml2);  }  void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2, diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c index 1236e0f9a256..712aff7e17f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c @@ -120,10 +120,11 @@ void dpp401_set_cursor_attributes(  	enum dc_cursor_color_format color_format = cursor_attributes->color_format;  	int cur_rom_en = 0; -	// DCN4 should always do Cursor degamma for Cursor Color modes  	if (color_format == CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA ||  		color_format == CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA) { -		cur_rom_en = 1; +		if (cursor_attributes->attribute_flags.bits.ENABLE_CURSOR_DEGAMMA) { +			cur_rom_en = 1; +		}  	}  	REG_UPDATE_3(CURSOR0_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 5489f3d431f6..3af6a3402b89 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -1980,9 +1980,9 @@ void dcn401_program_pipe(  				dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size);  	} -	if (pipe_ctx->update_flags.raw || -		(pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) || -		pipe_ctx->stream->update_flags.raw) +	if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw || +	    pipe_ctx->plane_state->update_flags.raw || +	    pipe_ctx->stream->update_flags.raw))  		dc->hwss.update_dchubp_dpp(dc, pipe_ctx, context);  	if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable || diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index 268626e73c54..53c961f86d43 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -148,6 +148,7 @@ void link_blank_dp_stream(struct dc_link *link, bool hw_init)  void link_set_all_streams_dpms_off_for_link(struct dc_link *link)  {  	struct pipe_ctx *pipes[MAX_PIPES]; +	struct dc_stream_state *streams[MAX_PIPES];  	struct dc_state *state = link->dc->current_state;  	uint8_t count;  	int i; @@ -160,10 +161,18 @@ void link_set_all_streams_dpms_off_for_link(struct dc_link *link)  	link_get_master_pipes_with_dpms_on(link, state, &count, pipes); +	/* The subsequent call to dc_commit_updates_for_stream for a full update +	 * will release the current state and swap to a new state. Releasing the +	 * current state results in the stream pointers in the pipe_ctx structs +	 * to be zero'd. Hence, cache all streams prior to dc_commit_updates_for_stream. +	 */ +	for (i = 0; i < count; i++) +		streams[i] = pipes[i]->stream; +  	for (i = 0; i < count; i++) { -		stream_update.stream = pipes[i]->stream; +		stream_update.stream = streams[i];  		dc_commit_updates_for_stream(link->ctx->dc, NULL, 0, -				pipes[i]->stream, &stream_update, +				streams[i], &stream_update,  				state);  	} diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c index 34d2e097ca2e..5a5d48fadbf2 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_8b_10b.c @@ -35,6 +35,17 @@  #define DC_LOGGER \  	link->ctx->logger +static void get_default_8b_10b_lttpr_aux_rd_interval( +		union training_aux_rd_interval *training_rd_interval) +{ +	/* LTTPR are required to program DPCD 0000Eh to 0x4 (16ms) upon AUX +	 * read reply to this register. Since old sinks with DPCD rev 1.1 +	 * and earlier may not support this register, assume the mandatory +	 * value is programmed by the LTTPR to avoid AUX timeout issues. +	 */ +	training_rd_interval->raw = 0x4; +} +  static int32_t get_cr_training_aux_rd_interval(struct dc_link *link,  		const struct dc_link_settings *link_settings,  		enum lttpr_mode lttpr_mode) @@ -43,17 +54,22 @@ static int32_t get_cr_training_aux_rd_interval(struct dc_link *link,  	uint32_t wait_in_micro_secs = 100;  	memset(&training_rd_interval, 0, sizeof(training_rd_interval)); -	if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING && -			link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { -		core_link_read_dpcd( -				link, -				DP_TRAINING_AUX_RD_INTERVAL, -				(uint8_t *)&training_rd_interval, -				sizeof(training_rd_interval)); -		if (lttpr_mode != LTTPR_MODE_NON_TRANSPARENT) -			wait_in_micro_secs = 400; -		if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) -			wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; +	if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) { +		if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) +			core_link_read_dpcd( +					link, +					DP_TRAINING_AUX_RD_INTERVAL, +					(uint8_t *)&training_rd_interval, +					sizeof(training_rd_interval)); +		else if (dp_is_lttpr_present(link)) +			get_default_8b_10b_lttpr_aux_rd_interval(&training_rd_interval); + +		if (training_rd_interval.raw != 0) { +			if (lttpr_mode != LTTPR_MODE_NON_TRANSPARENT) +				wait_in_micro_secs = 400; +			if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) +				wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; +		}  	}  	return wait_in_micro_secs;  } @@ -71,13 +87,15 @@ static uint32_t get_eq_training_aux_rd_interval(  				DP_128B132B_TRAINING_AUX_RD_INTERVAL,  				(uint8_t *)&training_rd_interval,  				sizeof(training_rd_interval)); -	} else if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING && -			link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { -		core_link_read_dpcd( -				link, -				DP_TRAINING_AUX_RD_INTERVAL, -				(uint8_t *)&training_rd_interval, -				sizeof(training_rd_interval)); +	} else if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) { +		if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) +			core_link_read_dpcd( +					link, +					DP_TRAINING_AUX_RD_INTERVAL, +					(uint8_t *)&training_rd_interval, +					sizeof(training_rd_interval)); +		else if (dp_is_lttpr_present(link)) +			get_default_8b_10b_lttpr_aux_rd_interval(&training_rd_interval);  	}  	switch (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) { 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; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 922def51685b..d533c79f7e21 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1606,7 +1606,6 @@ static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev,  	struct drm_device *ddev = dev_get_drvdata(dev);  	struct amdgpu_device *adev = drm_to_adev(ddev);  	long throttling_logging_interval; -	unsigned long flags;  	int ret = 0;  	ret = kstrtol(buf, 0, &throttling_logging_interval); @@ -1617,18 +1616,12 @@ static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev,  		return -EINVAL;  	if (throttling_logging_interval > 0) { -		raw_spin_lock_irqsave(&adev->throttling_logging_rs.lock, flags);  		/*  		 * Reset the ratelimit timer internals.  		 * This can effectively restart the timer.  		 */ -		adev->throttling_logging_rs.interval = -			(throttling_logging_interval - 1) * HZ; -		adev->throttling_logging_rs.begin = 0; -		adev->throttling_logging_rs.printed = 0; -		adev->throttling_logging_rs.missed = 0; -		raw_spin_unlock_irqrestore(&adev->throttling_logging_rs.lock, flags); - +		ratelimit_state_reset_interval(&adev->throttling_logging_rs, +					       (throttling_logging_interval - 1) * HZ);  		atomic_set(&adev->throttling_logging_enabled, 1);  	} else {  		atomic_set(&adev->throttling_logging_enabled, 0); | 
