diff options
Diffstat (limited to 'drivers/gpu')
131 files changed, 1417 insertions, 582 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 164141bc8b4a..39018f784f9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1272,6 +1272,7 @@ void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);  int amdgpu_device_pci_reset(struct amdgpu_device *adev);  bool amdgpu_device_need_post(struct amdgpu_device *adev);  bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev); +bool amdgpu_device_aspm_support_quirk(void);  void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes,  				  u64 num_vis_bytes); @@ -1391,10 +1392,12 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta  int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);  void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); +bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);  void amdgpu_acpi_detect(void);  #else  static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }  static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } +static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }  static inline void amdgpu_acpi_detect(void) { }  static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }  static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, @@ -1405,11 +1408,9 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,  #if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)  bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev); -bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);  bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);  #else  static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } -static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }  static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; }  #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index d4196fcb85a0..aeeec211861c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -971,6 +971,34 @@ static bool amdgpu_atcs_pci_probe_handle(struct pci_dev *pdev)  	return true;  } + +/** + * amdgpu_acpi_should_gpu_reset + * + * @adev: amdgpu_device_pointer + * + * returns true if should reset GPU, false if not + */ +bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) +{ +	if ((adev->flags & AMD_IS_APU) && +	    adev->gfx.imu.funcs) /* Not need to do mode2 reset for IMU enabled APUs */ +		return false; + +	if ((adev->flags & AMD_IS_APU) && +	    amdgpu_acpi_is_s3_active(adev)) +		return false; + +	if (amdgpu_sriov_vf(adev)) +		return false; + +#if IS_ENABLED(CONFIG_SUSPEND) +	return pm_suspend_target_state != PM_SUSPEND_TO_IDLE; +#else +	return true; +#endif +} +  /*   * amdgpu_acpi_detect - detect ACPI ATIF/ATCS methods   * @@ -1043,24 +1071,6 @@ bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev)  }  /** - * amdgpu_acpi_should_gpu_reset - * - * @adev: amdgpu_device_pointer - * - * returns true if should reset GPU, false if not - */ -bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) -{ -	if (adev->flags & AMD_IS_APU) -		return false; - -	if (amdgpu_sriov_vf(adev)) -		return false; - -	return pm_suspend_target_state != PM_SUSPEND_TO_IDLE; -} - -/**   * amdgpu_acpi_is_s0ix_active   *   * @adev: amdgpu_device_pointer diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c4a4e2fe6681..3d98fc2ad36b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -80,6 +80,10 @@  #include <drm/drm_drv.h> +#if IS_ENABLED(CONFIG_X86) +#include <asm/intel-family.h> +#endif +  MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");  MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");  MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin"); @@ -1356,6 +1360,17 @@ bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)  	return pcie_aspm_enabled(adev->pdev);  } +bool amdgpu_device_aspm_support_quirk(void) +{ +#if IS_ENABLED(CONFIG_X86) +	struct cpuinfo_x86 *c = &cpu_data(0); + +	return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE); +#else +	return true; +#endif +} +  /* if we get transitioned to only one device, take VGA back */  /**   * amdgpu_device_vga_set_decode - enable/disable vga decode @@ -4145,8 +4160,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)  	if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3))  		DRM_WARN("smart shift update failed\n"); -	drm_kms_helper_poll_disable(dev); -  	if (fbcon)  		drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true); @@ -4243,8 +4256,6 @@ exit:  	if (fbcon)  		drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false); -	drm_kms_helper_poll_enable(dev); -  	amdgpu_ras_resume(adev);  	if (adev->mode_info.num_crtc) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index b719852daa07..1a3cb53d2e0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -543,6 +543,7 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,  	struct harvest_table *harvest_info;  	u16 offset;  	int i; +	uint32_t umc_harvest_config = 0;  	bhdr = (struct binary_header *)adev->mman.discovery_bin;  	offset = le16_to_cpu(bhdr->table_list[HARVEST_INFO].offset); @@ -570,12 +571,17 @@ static void amdgpu_discovery_read_from_harvest_table(struct amdgpu_device *adev,  			adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;  			break;  		case UMC_HWID: +			umc_harvest_config |= +				1 << (le16_to_cpu(harvest_info->list[i].number_instance));  			(*umc_harvest_count)++;  			break;  		default:  			break;  		}  	} + +	adev->umc.active_mask = ((1 << adev->umc.node_inst_num) - 1) & +				~umc_harvest_config;  }  /* ================================================== */ @@ -1156,8 +1162,10 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)  						AMDGPU_MAX_SDMA_INSTANCES);  			} -			if (le16_to_cpu(ip->hw_id) == UMC_HWID) +			if (le16_to_cpu(ip->hw_id) == UMC_HWID) {  				adev->gmc.num_umc++; +				adev->umc.node_inst_num++; +			}  			for (k = 0; k < num_base_address; k++) {  				/* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 503f89a766c3..d60fe7eb5579 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -1618,6 +1618,8 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)  	struct drm_connector_list_iter iter;  	int r; +	drm_kms_helper_poll_disable(dev); +  	/* turn off display hw */  	drm_modeset_lock_all(dev);  	drm_connector_list_iter_begin(dev, &iter); @@ -1694,6 +1696,8 @@ int amdgpu_display_resume_helper(struct amdgpu_device *adev)  	drm_modeset_unlock_all(dev); +	drm_kms_helper_poll_enable(dev); +  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index f5ffca24def4..ba5def374368 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2467,7 +2467,10 @@ static int amdgpu_pmops_freeze(struct device *dev)  	adev->in_s4 = false;  	if (r)  		return r; -	return amdgpu_asic_reset(adev); + +	if (amdgpu_acpi_should_gpu_reset(adev)) +		return amdgpu_asic_reset(adev); +	return 0;  }  static int amdgpu_pmops_thaw(struct device *dev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index faff4a3f96e6..f52d0ba91a77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -678,6 +678,15 @@ void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring)  		ptr = &ring->fence_drv.fences[i];  		old = rcu_dereference_protected(*ptr, 1);  		if (old && old->ops == &amdgpu_job_fence_ops) { +			struct amdgpu_job *job; + +			/* For non-scheduler bad job, i.e. failed ib test, we need to signal +			 * it right here or we won't be able to track them in fence_drv +			 * and they will remain unsignaled during sa_bo free. +			 */ +			job = container_of(old, struct amdgpu_job, hw_fence); +			if (!job->base.s_fence && !dma_fence_is_signaled(old)) +				dma_fence_signal(old);  			RCU_INIT_POINTER(*ptr, NULL);  			dma_fence_put(old);  		} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index e3e1ed4314dd..6c7d672412b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1315,7 +1315,7 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)  	if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM ||  	    !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) || -	    adev->in_suspend || adev->shutdown) +	    adev->in_suspend || drm_dev_is_unplugged(adev_to_drm(adev)))  		return;  	if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 28fe6d941054..3f5d13035aff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -602,27 +602,14 @@ psp_cmd_submit_buf(struct psp_context *psp,  		   struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr)  {  	int ret; -	int index, idx; +	int index;  	int timeout = 20000;  	bool ras_intr = false;  	bool skip_unsupport = false; -	bool dev_entered;  	if (psp->adev->no_hw_access)  		return 0; -	dev_entered = drm_dev_enter(adev_to_drm(psp->adev), &idx); -	/* -	 * We allow sending PSP messages LOAD_ASD and UNLOAD_TA without acquiring -	 * a lock in drm_dev_enter during driver unload because we must call -	 * drm_dev_unplug as the beginning  of unload driver sequence . It is very -	 * crucial that userspace can't access device instances anymore. -	 */ -	if (!dev_entered) -		WARN_ON(psp->cmd_buf_mem->cmd_id != GFX_CMD_ID_LOAD_ASD && -			psp->cmd_buf_mem->cmd_id != GFX_CMD_ID_UNLOAD_TA && -			psp->cmd_buf_mem->cmd_id != GFX_CMD_ID_INVOKE_CMD); -  	memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE);  	memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); @@ -686,8 +673,6 @@ psp_cmd_submit_buf(struct psp_context *psp,  	}  exit: -	if (dev_entered) -		drm_dev_exit(idx);  	return ret;  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index f2bf979af588..36e19336f3b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -42,7 +42,7 @@  #define LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst)) LOOP_UMC_CH_INST((ch_inst))  #define LOOP_UMC_NODE_INST(node_inst) \ -		for ((node_inst) = 0; (node_inst) < adev->umc.node_inst_num; (node_inst)++) +		for_each_set_bit((node_inst), &(adev->umc.active_mask), adev->umc.node_inst_num)  #define LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst, ch_inst) \  		LOOP_UMC_NODE_INST((node_inst)) LOOP_UMC_INST_AND_CH((umc_inst), (ch_inst)) @@ -69,7 +69,7 @@ struct amdgpu_umc {  	/* number of umc instance with memory map register access */  	uint32_t umc_inst_num; -	/*number of umc node instance with memory map register access*/ +	/* Total number of umc node instance including harvest one */  	uint32_t node_inst_num;  	/* UMC regiser per channel offset */ @@ -82,6 +82,9 @@ struct amdgpu_umc {  	const struct amdgpu_umc_funcs *funcs;  	struct amdgpu_umc_ras *ras; + +	/* active mask for umc node instance */ +	unsigned long active_mask;  };  int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 25217b05c0ea..e7974de8b035 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -26,6 +26,7 @@  #include <linux/firmware.h>  #include <linux/module.h> +#include <linux/dmi.h>  #include <linux/pci.h>  #include <linux/debugfs.h>  #include <drm/drm_drv.h> @@ -114,6 +115,24 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)  	    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))  		adev->vcn.indirect_sram = true; +	/* +	 * Some Steam Deck's BIOS versions are incompatible with the +	 * indirect SRAM mode, leading to amdgpu being unable to get +	 * properly probed (and even potentially crashing the kernel). +	 * Hence, check for these versions here - notice this is +	 * restricted to Vangogh (Deck's APU). +	 */ +	if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 0, 2)) { +		const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION); + +		if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) || +		     !strncmp("F7A0114", bios_ver, 7))) { +			adev->vcn.indirect_sram = false; +			dev_info(adev->dev, +				"Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver); +		} +	} +  	hdr = (const struct common_firmware_header *)adev->vcn.fw->data;  	adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index b9e9480448af..4f7bab52282a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -124,6 +124,8 @@ enum AMDGIM_FEATURE_FLAG {  	AMDGIM_FEATURE_PP_ONE_VF = (1 << 4),  	/* Indirect Reg Access enabled */  	AMDGIM_FEATURE_INDIRECT_REG_ACCESS = (1 << 5), +	/* AV1 Support MODE*/ +	AMDGIM_FEATURE_AV1_SUPPORT = (1 << 6),  };  enum AMDGIM_REG_ACCESS_FLAG { @@ -322,6 +324,8 @@ static inline bool is_virtual_machine(void)  	((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug)  #define amdgpu_sriov_is_normal(adev) \  	((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug)) +#define amdgpu_sriov_is_av1_support(adev) \ +	((adev)->virt.gim_feature & AMDGIM_FEATURE_AV1_SUPPORT)  bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);  void amdgpu_virt_init_setting(struct amdgpu_device *adev);  void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h index 6c97148ca0ed..24d42d24e6a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -93,7 +93,8 @@ union amd_sriov_msg_feature_flags {  		uint32_t mm_bw_management  : 1;  		uint32_t pp_one_vf_mode	   : 1;  		uint32_t reg_indirect_acc  : 1; -		uint32_t reserved	   : 26; +		uint32_t av1_support       : 1; +		uint32_t reserved	   : 25;  	} flags;  	uint32_t all;  }; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 3bf697a80cf2..ecf8ceb53311 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1287,6 +1287,11 @@ static int gfx_v11_0_sw_init(void *handle)  		break;  	} +	/* Enable CG flag in one VF mode for enabling RLC safe mode enter/exit */ +	if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3) && +		amdgpu_sriov_is_pp_one_vf(adev)) +		adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG; +  	/* EOP Event */  	r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,  			      GFX_11_0_0__SRCID__CP_EOP_INTERRUPT, @@ -4655,6 +4660,14 @@ static bool gfx_v11_0_check_soft_reset(void *handle)  	return false;  } +static int gfx_v11_0_post_soft_reset(void *handle) +{ +	/** +	 * GFX soft reset will impact MES, need resume MES when do GFX soft reset +	 */ +	return amdgpu_mes_resume((struct amdgpu_device *)handle); +} +  static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev)  {  	uint64_t clock; @@ -6166,6 +6179,7 @@ static const struct amd_ip_funcs gfx_v11_0_ip_funcs = {  	.wait_for_idle = gfx_v11_0_wait_for_idle,  	.soft_reset = gfx_v11_0_soft_reset,  	.check_soft_reset = gfx_v11_0_check_soft_reset, +	.post_soft_reset = gfx_v11_0_post_soft_reset,  	.set_clockgating_state = gfx_v11_0_set_clockgating_state,  	.set_powergating_state = gfx_v11_0_set_powergating_state,  	.get_clockgating_state = gfx_v11_0_get_clockgating_state, diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index 85e0afc3d4f7..af7b3ba1ca00 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -567,7 +567,6 @@ static void gmc_v11_0_set_umc_funcs(struct amdgpu_device *adev)  	case IP_VERSION(8, 10, 0):  		adev->umc.channel_inst_num = UMC_V8_10_CHANNEL_INSTANCE_NUM;  		adev->umc.umc_inst_num = UMC_V8_10_UMC_INSTANCE_NUM; -		adev->umc.node_inst_num = adev->gmc.num_umc;  		adev->umc.max_ras_err_cnt_per_query = UMC_V8_10_TOTAL_CHANNEL_NUM(adev);  		adev->umc.channel_offs = UMC_V8_10_PER_CHANNEL_OFFSET;  		adev->umc.retire_unit = UMC_V8_10_NA_COL_2BITS_POWER_OF_2_NUM; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c index 4b0d563c6522..4ef1fa4603c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c @@ -382,11 +382,6 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev)  		if (def != data)  			WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_MST_CTRL_3), data);  		break; -	case IP_VERSION(7, 5, 1): -		data = RREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2); -		data &= ~RCC_DEV2_EPF0_STRAP2__STRAP_NO_SOFT_RESET_DEV2_F0_MASK; -		WREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2, data); -		fallthrough;  	default:  		def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CONFIG_CNTL));  		data = REG_SET_FIELD(data, PCIE_CONFIG_CNTL, @@ -399,6 +394,15 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev)  		break;  	} +	switch (adev->ip_versions[NBIO_HWIP][0]) { +	case IP_VERSION(7, 3, 0): +	case IP_VERSION(7, 5, 1): +		data = RREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2); +		data &= ~RCC_DEV2_EPF0_STRAP2__STRAP_NO_SOFT_RESET_DEV2_F0_MASK; +		WREG32_SOC15(NBIO, 0, regRCC_DEV2_EPF0_STRAP2, data); +		break; +	} +  	if (amdgpu_sriov_vf(adev))  		adev->rmmio_remap.reg_offset = SOC15_REG_OFFSET(NBIO, 0,  			regBIF_BX_PF0_HDP_MEM_COHERENCY_FLUSH_CNTL) << 2; diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index d972025f0d20..ebe0e2d7dbd1 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -444,9 +444,10 @@ static int nv_read_register(struct amdgpu_device *adev, u32 se_num,  	*value = 0;  	for (i = 0; i < ARRAY_SIZE(nv_allowed_read_registers); i++) {  		en = &nv_allowed_read_registers[i]; -		if (adev->reg_offset[en->hwip][en->inst] && -		    reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] -				   + en->reg_offset)) +		if (!adev->reg_offset[en->hwip][en->inst]) +			continue; +		else if (reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] +					+ en->reg_offset))  			continue;  		*value = nv_get_register_value(adev, @@ -577,7 +578,7 @@ static void nv_pcie_gen3_enable(struct amdgpu_device *adev)  static void nv_program_aspm(struct amdgpu_device *adev)  { -	if (!amdgpu_device_should_use_aspm(adev)) +	if (!amdgpu_device_should_use_aspm(adev) || !amdgpu_device_aspm_support_quirk())  		return;  	if (!(adev->flags & AMD_IS_APU) && @@ -1054,8 +1055,8 @@ static int nv_common_late_init(void *handle)  			amdgpu_virt_update_sriov_video_codec(adev,  							     sriov_sc_video_codecs_encode_array,  							     ARRAY_SIZE(sriov_sc_video_codecs_encode_array), -							     sriov_sc_video_codecs_decode_array_vcn1, -							     ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn1)); +							     sriov_sc_video_codecs_decode_array_vcn0, +							     ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn0));  		}  	} diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 7cd17dda32ce..2eddd7f6cd41 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -439,8 +439,9 @@ static int soc15_read_register(struct amdgpu_device *adev, u32 se_num,  	*value = 0;  	for (i = 0; i < ARRAY_SIZE(soc15_allowed_read_registers); i++) {  		en = &soc15_allowed_read_registers[i]; -		if (adev->reg_offset[en->hwip][en->inst] && -			reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] +		if (!adev->reg_offset[en->hwip][en->inst]) +			continue; +		else if (reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg]  					+ en->reg_offset))  			continue; diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 620f7409825d..c82b3a7ea5f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -102,6 +102,59 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_decode_vcn1 =  	.codec_array = vcn_4_0_0_video_codecs_decode_array_vcn1,  }; +/* SRIOV SOC21, not const since data is controlled by host */ +static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn0[] = { +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, +}; + +static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn1[] = { +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)}, +}; + +static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn0 = { +	.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0), +	.codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn0, +}; + +static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn1 = { +	.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1), +	.codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn1, +}; + +static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn0[] = { +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, +}; + +static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn1[] = { +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, +	{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, +}; + +static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn0 = { +	.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0), +	.codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn0, +}; + +static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn1 = { +	.codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1), +	.codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn1, +}; +  static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,  				 const struct amdgpu_video_codecs **codecs)  { @@ -111,16 +164,32 @@ static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,  	switch (adev->ip_versions[UVD_HWIP][0]) {  	case IP_VERSION(4, 0, 0):  	case IP_VERSION(4, 0, 2): -		if (adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) { -			if (encode) -				*codecs = &vcn_4_0_0_video_codecs_encode_vcn1; -			else -				*codecs = &vcn_4_0_0_video_codecs_decode_vcn1; +	case IP_VERSION(4, 0, 4): +		if (amdgpu_sriov_vf(adev)) { +			if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) || +			!amdgpu_sriov_is_av1_support(adev)) { +				if (encode) +					*codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn1; +				else +					*codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn1; +			} else { +				if (encode) +					*codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn0; +				else +					*codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn0; +			}  		} else { -			if (encode) -				*codecs = &vcn_4_0_0_video_codecs_encode_vcn0; -			else -				*codecs = &vcn_4_0_0_video_codecs_decode_vcn0; +			if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0)) { +				if (encode) +					*codecs = &vcn_4_0_0_video_codecs_encode_vcn1; +				else +					*codecs = &vcn_4_0_0_video_codecs_decode_vcn1; +			} else { +				if (encode) +					*codecs = &vcn_4_0_0_video_codecs_encode_vcn0; +				else +					*codecs = &vcn_4_0_0_video_codecs_decode_vcn0; +			}  		}  		return 0;  	default: @@ -291,9 +360,10 @@ static int soc21_read_register(struct amdgpu_device *adev, u32 se_num,  	*value = 0;  	for (i = 0; i < ARRAY_SIZE(soc21_allowed_read_registers); i++) {  		en = &soc21_allowed_read_registers[i]; -		if (adev->reg_offset[en->hwip][en->inst] && -		    reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] -				   + en->reg_offset)) +		if (!adev->reg_offset[en->hwip][en->inst]) +			continue; +		else if (reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] +					+ en->reg_offset))  			continue;  		*value = soc21_get_register_value(adev, @@ -728,8 +798,23 @@ static int soc21_common_late_init(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (amdgpu_sriov_vf(adev)) +	if (amdgpu_sriov_vf(adev)) {  		xgpu_nv_mailbox_get_irq(adev); +		if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) || +		!amdgpu_sriov_is_av1_support(adev)) { +			amdgpu_virt_update_sriov_video_codec(adev, +							     sriov_vcn_4_0_0_video_codecs_encode_array_vcn1, +							     ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1), +							     sriov_vcn_4_0_0_video_codecs_decode_array_vcn1, +							     ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1)); +		} else { +			amdgpu_virt_update_sriov_video_codec(adev, +							     sriov_vcn_4_0_0_video_codecs_encode_array_vcn0, +							     ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0), +							     sriov_vcn_4_0_0_video_codecs_decode_array_vcn0, +							     ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0)); +		} +	}  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h index 25eaf4af5fcf..c6dfd433fec7 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h @@ -31,9 +31,9 @@  /* number of umc instance with memory map register access */  #define UMC_V8_10_UMC_INSTANCE_NUM		2 -/* Total channel instances for all umc nodes */ +/* Total channel instances for all available umc nodes */  #define UMC_V8_10_TOTAL_CHANNEL_NUM(adev) \ -	(UMC_V8_10_CHANNEL_INSTANCE_NUM * UMC_V8_10_UMC_INSTANCE_NUM * (adev)->umc.node_inst_num) +	(UMC_V8_10_CHANNEL_INSTANCE_NUM * UMC_V8_10_UMC_INSTANCE_NUM * (adev)->gmc.num_umc)  /* UMC regiser per channel offset */  #define UMC_V8_10_PER_CHANNEL_OFFSET	0x400 diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 12ef782eb478..ceab8783575c 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -81,10 +81,6 @@  #include "mxgpu_vi.h"  #include "amdgpu_dm.h" -#if IS_ENABLED(CONFIG_X86) -#include <asm/intel-family.h> -#endif -  #define ixPCIE_LC_L1_PM_SUBSTATE	0x100100C6  #define PCIE_LC_L1_PM_SUBSTATE__LC_L1_SUBSTATES_OVERRIDE_EN_MASK	0x00000001L  #define PCIE_LC_L1_PM_SUBSTATE__LC_PCI_PM_L1_2_OVERRIDE_MASK	0x00000002L @@ -1138,24 +1134,13 @@ static void vi_enable_aspm(struct amdgpu_device *adev)  		WREG32_PCIE(ixPCIE_LC_CNTL, data);  } -static bool aspm_support_quirk_check(void) -{ -#if IS_ENABLED(CONFIG_X86) -	struct cpuinfo_x86 *c = &cpu_data(0); - -	return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE); -#else -	return true; -#endif -} -  static void vi_program_aspm(struct amdgpu_device *adev)  {  	u32 data, data1, orig;  	bool bL1SS = false;  	bool bClkReqSupport = true; -	if (!amdgpu_device_should_use_aspm(adev) || !aspm_support_quirk_check()) +	if (!amdgpu_device_should_use_aspm(adev) || !amdgpu_device_aspm_support_quirk())  		return;  	if (adev->flags & AMD_IS_APU || diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index a0e30f21e12e..de310ed367ca 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1312,14 +1312,14 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,  		args->n_success = i+1;  	} -	mutex_unlock(&p->mutex); -  	err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, (struct kgd_mem *) mem, true);  	if (err) {  		pr_debug("Sync memory failed, wait interrupted by user signal\n");  		goto sync_memory_failed;  	} +	mutex_unlock(&p->mutex); +  	/* Flush TLBs after waiting for the page table updates to complete */  	for (i = 0; i < args->n_devices; i++) {  		peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); @@ -1335,9 +1335,9 @@ get_process_device_data_failed:  bind_process_to_device_failed:  get_mem_obj_from_handle_failed:  map_memory_to_gpu_failed: +sync_memory_failed:  	mutex_unlock(&p->mutex);  copy_from_user_failed: -sync_memory_failed:  	kfree(devices_arr);  	return err; @@ -1351,6 +1351,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,  	void *mem;  	long err = 0;  	uint32_t *devices_arr = NULL, i; +	bool flush_tlb;  	if (!args->n_devices) {  		pr_debug("Device IDs array empty\n"); @@ -1403,16 +1404,19 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,  		}  		args->n_success = i+1;  	} -	mutex_unlock(&p->mutex); -	if (kfd_flush_tlb_after_unmap(pdd->dev)) { +	flush_tlb = kfd_flush_tlb_after_unmap(pdd->dev); +	if (flush_tlb) {  		err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev,  				(struct kgd_mem *) mem, true);  		if (err) {  			pr_debug("Sync memory failed, wait interrupted by user signal\n");  			goto sync_memory_failed;  		} +	} +	mutex_unlock(&p->mutex); +	if (flush_tlb) {  		/* Flush TLBs after waiting for the page table updates to complete */  		for (i = 0; i < args->n_devices; i++) {  			peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); @@ -1428,9 +1432,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,  bind_process_to_device_failed:  get_mem_obj_from_handle_failed:  unmap_memory_from_gpu_failed: +sync_memory_failed:  	mutex_unlock(&p->mutex);  copy_from_user_failed: -sync_memory_failed:  	kfree(devices_arr);  	return err;  } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 3de7f616a001..ec70a1658dc3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -59,6 +59,7 @@ static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,  				unsigned int chunk_size);  static void kfd_gtt_sa_fini(struct kfd_dev *kfd); +static int kfd_resume_iommu(struct kfd_dev *kfd);  static int kfd_resume(struct kfd_dev *kfd);  static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd) @@ -624,7 +625,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,  	svm_migrate_init(kfd->adev); -	if (kgd2kfd_resume_iommu(kfd)) +	if (kfd_resume_iommu(kfd))  		goto device_iommu_error;  	if (kfd_resume(kfd)) @@ -773,6 +774,14 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)  int kgd2kfd_resume_iommu(struct kfd_dev *kfd)  { +	if (!kfd->init_complete) +		return 0; + +	return kfd_resume_iommu(kfd); +} + +static int kfd_resume_iommu(struct kfd_dev *kfd) +{  	int err = 0;  	err = kfd_iommu_resume(kfd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c index cbef2e147da5..38c9e1ca6691 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c @@ -280,7 +280,7 @@ phys_addr_t kfd_get_process_doorbells(struct kfd_process_device *pdd)  	if (!pdd->doorbell_index) {  		int r = kfd_alloc_process_doorbells(pdd->dev,  						    &pdd->doorbell_index); -		if (r) +		if (r < 0)  			return 0;  	} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index de8ce72344fc..54933903bcb8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -289,7 +289,7 @@ static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate)  static int  svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,  			 struct migrate_vma *migrate, struct dma_fence **mfence, -			 dma_addr_t *scratch) +			 dma_addr_t *scratch, uint64_t ttm_res_offset)  {  	uint64_t npages = migrate->npages;  	struct device *dev = adev->dev; @@ -299,19 +299,13 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,  	uint64_t i, j;  	int r; -	pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, -		 prange->last); +	pr_debug("svms 0x%p [0x%lx 0x%lx 0x%llx]\n", prange->svms, prange->start, +		 prange->last, ttm_res_offset);  	src = scratch;  	dst = (uint64_t *)(scratch + npages); -	r = svm_range_vram_node_new(adev, prange, true); -	if (r) { -		dev_dbg(adev->dev, "fail %d to alloc vram\n", r); -		goto out; -	} - -	amdgpu_res_first(prange->ttm_res, prange->offset << PAGE_SHIFT, +	amdgpu_res_first(prange->ttm_res, ttm_res_offset,  			 npages << PAGE_SHIFT, &cursor);  	for (i = j = 0; i < npages; i++) {  		struct page *spage; @@ -391,14 +385,14 @@ out_free_vram_pages:  		migrate->dst[i + 3] = 0;  	}  #endif -out: +  	return r;  }  static long  svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,  			struct vm_area_struct *vma, uint64_t start, -			uint64_t end, uint32_t trigger) +			uint64_t end, uint32_t trigger, uint64_t ttm_res_offset)  {  	struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms);  	uint64_t npages = (end - start) >> PAGE_SHIFT; @@ -451,7 +445,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,  	else  		pr_debug("0x%lx pages migrated\n", cpages); -	r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch); +	r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch, ttm_res_offset);  	migrate_vma_pages(&migrate);  	pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n", @@ -499,6 +493,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,  	unsigned long addr, start, end;  	struct vm_area_struct *vma;  	struct amdgpu_device *adev; +	uint64_t ttm_res_offset;  	unsigned long cpages = 0;  	long r = 0; @@ -520,6 +515,13 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,  	start = prange->start << PAGE_SHIFT;  	end = (prange->last + 1) << PAGE_SHIFT; +	r = svm_range_vram_node_new(adev, prange, true); +	if (r) { +		dev_dbg(adev->dev, "fail %ld to alloc vram\n", r); +		return r; +	} +	ttm_res_offset = prange->offset << PAGE_SHIFT; +  	for (addr = start; addr < end;) {  		unsigned long next; @@ -528,18 +530,21 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,  			break;  		next = min(vma->vm_end, end); -		r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger); +		r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger, ttm_res_offset);  		if (r < 0) {  			pr_debug("failed %ld to migrate\n", r);  			break;  		} else {  			cpages += r;  		} +		ttm_res_offset += next - addr;  		addr = next;  	}  	if (cpages)  		prange->actual_loc = best_loc; +	else +		svm_range_vram_node_free(prange);  	return r < 0 ? r : 0;  } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c index 09b966dc3768..aee2212e52f6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c @@ -77,6 +77,7 @@ err_ioctl:  static void kfd_exit(void)  { +	kfd_cleanup_processes();  	kfd_debugfs_fini();  	kfd_process_destroy_wq();  	kfd_procfs_shutdown(); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index bfa30d12406b..7e4d992e48b3 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -928,6 +928,7 @@ bool kfd_dev_is_large_bar(struct kfd_dev *dev);  int kfd_process_create_wq(void);  void kfd_process_destroy_wq(void); +void kfd_cleanup_processes(void);  struct kfd_process *kfd_create_process(struct file *filep);  struct kfd_process *kfd_get_process(const struct task_struct *task);  struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 7acd55a814b2..4208e0f01064 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1167,6 +1167,17 @@ static void kfd_process_free_notifier(struct mmu_notifier *mn)  	kfd_unref_process(container_of(mn, struct kfd_process, mmu_notifier));  } +static void kfd_process_notifier_release_internal(struct kfd_process *p) +{ +	cancel_delayed_work_sync(&p->eviction_work); +	cancel_delayed_work_sync(&p->restore_work); + +	/* Indicate to other users that MM is no longer valid */ +	p->mm = NULL; + +	mmu_notifier_put(&p->mmu_notifier); +} +  static void kfd_process_notifier_release(struct mmu_notifier *mn,  					struct mm_struct *mm)  { @@ -1181,17 +1192,22 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,  		return;  	mutex_lock(&kfd_processes_mutex); +	/* +	 * Do early return if table is empty. +	 * +	 * This could potentially happen if this function is called concurrently +	 * by mmu_notifier and by kfd_cleanup_pocesses. +	 * +	 */ +	if (hash_empty(kfd_processes_table)) { +		mutex_unlock(&kfd_processes_mutex); +		return; +	}  	hash_del_rcu(&p->kfd_processes);  	mutex_unlock(&kfd_processes_mutex);  	synchronize_srcu(&kfd_processes_srcu); -	cancel_delayed_work_sync(&p->eviction_work); -	cancel_delayed_work_sync(&p->restore_work); - -	/* Indicate to other users that MM is no longer valid */ -	p->mm = NULL; - -	mmu_notifier_put(&p->mmu_notifier); +	kfd_process_notifier_release_internal(p);  }  static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = { @@ -1200,6 +1216,43 @@ static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = {  	.free_notifier = kfd_process_free_notifier,  }; +/* + * This code handles the case when driver is being unloaded before all + * mm_struct are released.  We need to safely free the kfd_process and + * avoid race conditions with mmu_notifier that might try to free them. + * + */ +void kfd_cleanup_processes(void) +{ +	struct kfd_process *p; +	struct hlist_node *p_temp; +	unsigned int temp; +	HLIST_HEAD(cleanup_list); + +	/* +	 * Move all remaining kfd_process from the process table to a +	 * temp list for processing.   Once done, callback from mmu_notifier +	 * release will not see the kfd_process in the table and do early return, +	 * avoiding double free issues. +	 */ +	mutex_lock(&kfd_processes_mutex); +	hash_for_each_safe(kfd_processes_table, temp, p_temp, p, kfd_processes) { +		hash_del_rcu(&p->kfd_processes); +		synchronize_srcu(&kfd_processes_srcu); +		hlist_add_head(&p->kfd_processes, &cleanup_list); +	} +	mutex_unlock(&kfd_processes_mutex); + +	hlist_for_each_entry_safe(p, p_temp, &cleanup_list, kfd_processes) +		kfd_process_notifier_release_internal(p); + +	/* +	 * Ensures that all outstanding free_notifier get called, triggering +	 * the release of the kfd_process struct. +	 */ +	mmu_notifier_synchronize(); +} +  static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)  {  	unsigned long  offset; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 5137476ec18e..4236539d9f93 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -218,8 +218,8 @@ static int init_user_queue(struct process_queue_manager *pqm,  	return 0;  cleanup: -	if (dev->shared_resources.enable_mes) -		uninit_queue(*q); +	uninit_queue(*q); +	*q = NULL;  	return retval;  } 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 009ef917dad4..a01fd41643fc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5105,9 +5105,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,  		for (; flip_addrs->dirty_rect_count < num_clips; clips++)  			fill_dc_dirty_rect(new_plane_state->plane, -					   &dirty_rects[i], clips->x1, -					   clips->y1, clips->x2 - clips->x1, -					   clips->y2 - clips->y1, +					   &dirty_rects[flip_addrs->dirty_rect_count], +					   clips->x1, clips->y1, +					   clips->x2 - clips->x1, clips->y2 - clips->y1,  					   &flip_addrs->dirty_rect_count,  					   false);  		return; @@ -7244,7 +7244,6 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,  	if (!aconnector->mst_root)  		drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16); -	/* This defaults to the max in the range, but we want 8bpc for non-edp. */  	aconnector->base.state->max_bpc = 16;  	aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc; 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 8e572f07ec47..4abfd2c9679f 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 @@ -561,7 +561,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)  	link->dp.mst_enabled = config->mst_enabled;  	link->dp.usb4_enabled = config->usb4_enabled;  	display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION; -	link->adjust.auth_delay = 0; +	link->adjust.auth_delay = 2;  	link->adjust.hdcp1.disable = 0;  	conn_state = aconnector->base.state; 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 1583157da355..efd025d8961e 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 @@ -177,6 +177,40 @@ void dm_helpers_dp_update_branch_info(  	const struct dc_link *link)  {} +static void dm_helpers_construct_old_payload( +			struct dc_link *link, +			int pbn_per_slot, +			struct drm_dp_mst_atomic_payload *new_payload, +			struct drm_dp_mst_atomic_payload *old_payload) +{ +	struct link_mst_stream_allocation_table current_link_table = +									link->mst_stream_alloc_table; +	struct link_mst_stream_allocation *dc_alloc; +	int i; + +	*old_payload = *new_payload; + +	/* Set correct time_slots/PBN of old payload. +	 * other fields (delete & dsc_enabled) in +	 * struct drm_dp_mst_atomic_payload are don't care fields +	 * while calling drm_dp_remove_payload() +	 */ +	for (i = 0; i < current_link_table.stream_count; i++) { +		dc_alloc = +			¤t_link_table.stream_allocations[i]; + +		if (dc_alloc->vcp_id == new_payload->vcpi) { +			old_payload->time_slots = dc_alloc->slot_count; +			old_payload->pbn = dc_alloc->slot_count * pbn_per_slot; +			break; +		} +	} + +	/* make sure there is an old payload*/ +	ASSERT(i != current_link_table.stream_count); + +} +  /*   * Writes payload allocation table in immediate downstream device.   */ @@ -188,7 +222,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(  {  	struct amdgpu_dm_connector *aconnector;  	struct drm_dp_mst_topology_state *mst_state; -	struct drm_dp_mst_atomic_payload *payload; +	struct drm_dp_mst_atomic_payload *target_payload, *new_payload, old_payload;  	struct drm_dp_mst_topology_mgr *mst_mgr;  	aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; @@ -204,17 +238,26 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(  	mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);  	/* It's OK for this to fail */ -	payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); -	if (enable) -		drm_dp_add_payload_part1(mst_mgr, mst_state, payload); -	else -		drm_dp_remove_payload(mst_mgr, mst_state, payload, payload); +	new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port); + +	if (enable) { +		target_payload = new_payload; + +		drm_dp_add_payload_part1(mst_mgr, mst_state, new_payload); +	} else { +		/* construct old payload by VCPI*/ +		dm_helpers_construct_old_payload(stream->link, mst_state->pbn_div, +						new_payload, &old_payload); +		target_payload = &old_payload; + +		drm_dp_remove_payload(mst_mgr, mst_state, &old_payload, new_payload); +	}  	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or  	 * AUX message. The sequence is slot 1-63 allocated sequence for each  	 * stream. AMD ASIC stream slot allocation should follow the same  	 * sequence. copy DRM MST allocation to dc */ -	fill_dc_mst_payload_table_from_drm(stream->link, enable, payload, proposed_table); +	fill_dc_mst_payload_table_from_drm(stream->link, enable, target_payload, proposed_table);  	return true;  } 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 e25e1b2bf194..8dc442f90eaf 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 @@ -212,6 +212,21 @@ bool needs_dsc_aux_workaround(struct dc_link *link)  	return false;  } +bool is_synaptics_cascaded_panamera(struct dc_link *link, struct drm_dp_mst_port *port) +{ +	u8 branch_vendor_data[4] = { 0 }; // Vendor data 0x50C ~ 0x50F + +	if (drm_dp_dpcd_read(port->mgr->aux, DP_BRANCH_VENDOR_SPECIFIC_START, &branch_vendor_data, 4) == 4) { +		if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && +				IS_SYNAPTICS_CASCADED_PANAMERA(link->dpcd_caps.branch_dev_name, branch_vendor_data)) { +			DRM_INFO("Synaptics Cascaded MST hub\n"); +			return true; +		} +	} + +	return false; +} +  static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector)  {  	struct dc_sink *dc_sink = aconnector->dc_sink; @@ -235,6 +250,10 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto  	    needs_dsc_aux_workaround(aconnector->dc_link))  		aconnector->dsc_aux = &aconnector->mst_root->dm_dp_aux.aux; +	/* synaptics cascaded MST hub case */ +	if (!aconnector->dsc_aux && is_synaptics_cascaded_panamera(aconnector->dc_link, port)) +		aconnector->dsc_aux = port->mgr->aux; +  	if (!aconnector->dsc_aux)  		return false; @@ -662,12 +681,25 @@ struct dsc_mst_fairness_params {  	struct amdgpu_dm_connector *aconnector;  }; -static int kbps_to_peak_pbn(int kbps) +static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link) +{ +	u8 link_coding_cap; +	uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B; + +	link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link); +	if (link_coding_cap == DP_128b_132b_ENCODING) +		fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B; + +	return fec_overhead_multiplier_x1000; +} + +static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000)  {  	u64 peak_kbps = kbps;  	peak_kbps *= 1006; -	peak_kbps = div_u64(peak_kbps, 1000); +	peak_kbps *= fec_overhead_multiplier_x1000; +	peak_kbps = div_u64(peak_kbps, 1000 * 1000);  	return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000));  } @@ -761,11 +793,12 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,  	int link_timeslots_used;  	int fair_pbn_alloc;  	int ret = 0; +	uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);  	for (i = 0; i < count; i++) {  		if (vars[i + k].dsc_enabled) {  			initial_slack[i] = -			kbps_to_peak_pbn(params[i].bw_range.max_kbps) - vars[i + k].pbn; +			kbps_to_peak_pbn(params[i].bw_range.max_kbps, fec_overhead_multiplier_x1000) - vars[i + k].pbn;  			bpp_increased[i] = false;  			remaining_to_increase += 1;  		} else { @@ -861,6 +894,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,  	int next_index;  	int remaining_to_try = 0;  	int ret; +	uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);  	for (i = 0; i < count; i++) {  		if (vars[i + k].dsc_enabled @@ -890,7 +924,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,  		if (next_index == -1)  			break; -		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps); +		vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000);  		ret = drm_dp_atomic_find_time_slots(state,  						    params[next_index].port->mgr,  						    params[next_index].port, @@ -903,7 +937,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,  			vars[next_index].dsc_enabled = false;  			vars[next_index].bpp_x16 = 0;  		} else { -			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps); +			vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps, fec_overhead_multiplier_x1000);  			ret = drm_dp_atomic_find_time_slots(state,  							    params[next_index].port->mgr,  							    params[next_index].port, @@ -932,6 +966,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,  	int count = 0;  	int i, k, ret;  	bool debugfs_overwrite = false; +	uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);  	memset(params, 0, sizeof(params)); @@ -993,7 +1028,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,  	/* Try no compression */  	for (i = 0; i < count; i++) {  		vars[i + k].aconnector = params[i].aconnector; -		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); +		vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);  		vars[i + k].dsc_enabled = false;  		vars[i + k].bpp_x16 = 0;  		ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, @@ -1012,7 +1047,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,  	/* Try max compression */  	for (i = 0; i < count; i++) {  		if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) { -			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps); +			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000);  			vars[i + k].dsc_enabled = true;  			vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;  			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, @@ -1020,7 +1055,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,  			if (ret < 0)  				return ret;  		} else { -			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); +			vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);  			vars[i + k].dsc_enabled = false;  			vars[i + k].bpp_x16 = 0;  			ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 97fd70df531b..1e4ede1e57ab 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -34,6 +34,21 @@  #define SYNAPTICS_RC_OFFSET        0x4BC  #define SYNAPTICS_RC_DATA          0x4C0 +#define DP_BRANCH_VENDOR_SPECIFIC_START 0x50C + +/** + * Panamera MST Hub detection + * Offset DPCD 050Eh == 0x5A indicates cascaded MST hub case + * Check from beginning of branch device vendor specific field (050Ch) + */ +#define IS_SYNAPTICS_PANAMERA(branchDevName) (((int)branchDevName[4] & 0xF0) == 0x50 ? 1 : 0) +#define BRANCH_HW_REVISION_PANAMERA_A2 0x10 +#define SYNAPTICS_CASCADED_HUB_ID  0x5A +#define IS_SYNAPTICS_CASCADED_PANAMERA(devName, data) ((IS_SYNAPTICS_PANAMERA(devName) && ((int)data[2] == SYNAPTICS_CASCADED_HUB_ID)) ? 1 : 0) + +#define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B	1031 +#define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B	1000 +  struct amdgpu_display_manager;  struct amdgpu_dm_connector; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index 24715ca2fa94..01383aac6b41 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -529,6 +529,19 @@ static struct clk_bw_params vg_bw_params = {  }; +static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks) +{ +	uint32_t max = 0; +	int i; + +	for (i = 0; i < num_clocks; ++i) { +		if (clocks[i] > max) +			max = clocks[i]; +	} + +	return max; +} +  static unsigned int find_dcfclk_for_voltage(const struct vg_dpm_clocks *clock_table,  		unsigned int voltage)  { @@ -572,12 +585,16 @@ static void vg_clk_mgr_helper_populate_bw_params(  	bw_params->clk_table.num_entries = j + 1; -	for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) { +	for (i = 0; i < bw_params->clk_table.num_entries - 1; i++, j--) {  		bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[j].fclk;  		bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].memclk;  		bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].voltage;  		bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->DfPstateTable[j].voltage);  	} +	bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[j].fclk; +	bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[j].memclk; +	bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[j].voltage; +	bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, VG_NUM_DCFCLK_DPM_LEVELS);  	bw_params->vram_type = bios_info->memory_type;  	bw_params->num_channels = bios_info->ma_channel_number; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 3b4d4d68359b..df787fcf8e86 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -998,8 +998,5 @@ void dcn30_prepare_bandwidth(struct dc *dc,  			dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);  	dcn20_prepare_bandwidth(dc, context); - -	dc_dmub_srv_p_state_delegate(dc, -		context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching, context);  } diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c index e4472c6be6c3..3fb4bcc34353 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c @@ -271,8 +271,7 @@ static void dccg32_set_dpstreamclk(  	dccg32_set_dtbclk_p_src(dccg, src, otg_inst);  	/* enabled to select one of the DTBCLKs for pipe */ -	switch (otg_inst) -	{ +	switch (dp_hpo_inst) {  	case 0:  		REG_UPDATE_2(DPSTREAMCLK_CNTL,  			     DPSTREAMCLK0_EN, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index 16f892125b6f..9d14045cccd6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -1104,7 +1104,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign  			*k2_div = PIXEL_RATE_DIV_BY_2;  		else  			*k2_div = PIXEL_RATE_DIV_BY_4; -	} else if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) { +	} else if (dc_is_dp_signal(stream->signal)) {  		if (two_pix_per_container) {  			*k1_div = PIXEL_RATE_DIV_BY_1;  			*k2_div = PIXEL_RATE_DIV_BY_2; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 74e50c09bb62..4b7abb4af623 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -1915,6 +1915,7 @@ int dcn32_populate_dml_pipes_from_context(  	bool subvp_in_use = false;  	uint8_t is_pipe_split_expected[MAX_PIPES] = {0};  	struct dc_crtc_timing *timing; +	bool vsr_odm_support = false;  	dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); @@ -1932,12 +1933,15 @@ int dcn32_populate_dml_pipes_from_context(  		timing = &pipe->stream->timing;  		pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; +		vsr_odm_support = (res_ctx->pipe_ctx[i].stream->src.width >= 5120 && +				res_ctx->pipe_ctx[i].stream->src.width > res_ctx->pipe_ctx[i].stream->dst.width);  		if (context->stream_count == 1 &&  				context->stream_status[0].plane_count == 1 &&  				!dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&  				is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) &&  				pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ && -				dc->debug.enable_single_display_2to1_odm_policy) { +				dc->debug.enable_single_display_2to1_odm_policy && +				!vsr_odm_support) { //excluding 2to1 ODM combine on >= 5k vsr  			pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;  		}  		pipe_cnt++; @@ -2182,6 +2186,7 @@ static bool dcn32_resource_construct(  	dc->caps.edp_dsc_support = true;  	dc->caps.extended_aux_timeout_support = true;  	dc->caps.dmcub_support = true; +	dc->caps.seamless_odm = true;  	/* Color pipeline capabilities */  	dc->caps.color.dpp.dcn_arch = 1; diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index 38216c789d77..f70025ef7b69 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -855,6 +855,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,  	struct dc_sink *prev_sink = NULL;  	struct dpcd_caps prev_dpcd_caps;  	enum dc_connection_type new_connection_type = dc_connection_none; +	enum dc_connection_type pre_connection_type = link->type;  	const uint32_t post_oui_delay = 30; // 30ms  	DC_LOGGER_INIT(link->ctx->logger); @@ -957,6 +958,8 @@ static bool detect_link_and_local_sink(struct dc_link *link,  			}  			if (!detect_dp(link, &sink_caps, reason)) { +				link->type = pre_connection_type; +  				if (prev_sink)  					dc_sink_release(prev_sink);  				return false; @@ -1244,11 +1247,16 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason)  	bool is_delegated_to_mst_top_mgr = false;  	enum dc_connection_type pre_link_type = link->type; +	DC_LOGGER_INIT(link->ctx->logger); +  	is_local_sink_detect_success = detect_link_and_local_sink(link, reason);  	if (is_local_sink_detect_success && link->local_sink)  		verify_link_capability(link, link->local_sink, reason); +	DC_LOG_DC("%s: link_index=%d is_local_sink_detect_success=%d pre_link_type=%d link_type=%d\n", __func__, +				link->link_index, is_local_sink_detect_success, pre_link_type, link->type); +  	if (is_local_sink_detect_success && link->local_sink &&  			dc_is_dp_signal(link->local_sink->sink_signal) &&  			link->dpcd_caps.is_mst_capable) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h index f77401709d83..2162ecd1057d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h @@ -27,7 +27,7 @@  // *** IMPORTANT ***  // SMU TEAM: Always increment the interface version if  // any structure is changed in this file -#define PMFW_DRIVER_IF_VERSION 7 +#define PMFW_DRIVER_IF_VERSION 8  typedef struct {    int32_t value; @@ -198,7 +198,7 @@ typedef struct {    uint16_t SkinTemp;    uint16_t DeviceState;    uint16_t CurTemp;                     //[centi-Celsius] -  uint16_t spare2; +  uint16_t FilterAlphaValue;    uint16_t AverageGfxclkFrequency;    uint16_t AverageFclkFrequency; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index 1c0ae2cb757b..85a090b9e3d9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -29,7 +29,7 @@  #define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04  #define SMU13_DRIVER_IF_VERSION_ALDE 0x08  #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0 0x37 -#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x07 +#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x08  #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04  #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32  #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x37 @@ -61,6 +61,12 @@  #define CTF_OFFSET_HOTSPOT		5  #define CTF_OFFSET_MEM			5 +static const int pmfw_decoded_link_speed[5] = {1, 2, 3, 4, 5}; +static const int pmfw_decoded_link_width[7] = {0, 1, 2, 4, 8, 12, 16}; + +#define DECODE_GEN_SPEED(gen_speed_idx)		(pmfw_decoded_link_speed[gen_speed_idx]) +#define DECODE_LANE_WIDTH(lane_width_idx)	(pmfw_decoded_link_width[lane_width_idx]) +  struct smu_13_0_max_sustainable_clocks {  	uint32_t display_clock;  	uint32_t phy_clock; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 697e98a0a20a..75f18681e984 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2143,16 +2143,9 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu)  		(OverDriveTable_t *)smu->smu_table.boot_overdrive_table;  	OverDriveTable_t *user_od_table =  		(OverDriveTable_t *)smu->smu_table.user_overdrive_table; +	OverDriveTable_t user_od_table_bak;  	int ret = 0; -	/* -	 * For S3/S4/Runpm resume, no need to setup those overdrive tables again as -	 *   - either they already have the default OD settings got during cold bootup -	 *   - or they have some user customized OD settings which cannot be overwritten -	 */ -	if (smu->adev->in_suspend) -		return 0; -  	ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE,  				   0, (void *)boot_od_table, false);  	if (ret) { @@ -2163,7 +2156,23 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu)  	sienna_cichlid_dump_od_table(smu, boot_od_table);  	memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t)); -	memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t)); + +	/* +	 * For S3/S4/Runpm resume, we need to setup those overdrive tables again, +	 * but we have to preserve user defined values in "user_od_table". +	 */ +	if (!smu->adev->in_suspend) { +		memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t)); +		smu->user_dpm_profile.user_od = false; +	} else if (smu->user_dpm_profile.user_od) { +		memcpy(&user_od_table_bak, user_od_table, sizeof(OverDriveTable_t)); +		memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t)); +		user_od_table->GfxclkFmin = user_od_table_bak.GfxclkFmin; +		user_od_table->GfxclkFmax = user_od_table_bak.GfxclkFmax; +		user_od_table->UclkFmin = user_od_table_bak.UclkFmin; +		user_od_table->UclkFmax = user_od_table_bak.UclkFmax; +		user_od_table->VddGfxOffset = user_od_table_bak.VddGfxOffset; +	}  	return 0;  } @@ -2373,6 +2382,20 @@ static int sienna_cichlid_od_edit_dpm_table(struct smu_context *smu,  	return ret;  } +static int sienna_cichlid_restore_user_od_settings(struct smu_context *smu) +{ +	struct smu_table_context *table_context = &smu->smu_table; +	OverDriveTable_t *od_table = table_context->overdrive_table; +	OverDriveTable_t *user_od_table = table_context->user_overdrive_table; +	int res; + +	res = smu_v11_0_restore_user_od_settings(smu); +	if (res == 0) +		memcpy(od_table, user_od_table, sizeof(OverDriveTable_t)); + +	return res; +} +  static int sienna_cichlid_run_btc(struct smu_context *smu)  {  	int res; @@ -4400,7 +4423,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {  	.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,  	.set_default_od_settings = sienna_cichlid_set_default_od_settings,  	.od_edit_dpm_table = sienna_cichlid_od_edit_dpm_table, -	.restore_user_od_settings = smu_v11_0_restore_user_od_settings, +	.restore_user_od_settings = sienna_cichlid_restore_user_od_settings,  	.run_btc = sienna_cichlid_run_btc,  	.set_power_source = smu_v11_0_set_power_source,  	.get_pp_feature_mask = smu_cmn_get_pp_feature_mask, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 923a9fb3c887..a5c97d61e92a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -46,6 +46,7 @@  #include "asic_reg/mp/mp_13_0_0_sh_mask.h"  #include "smu_cmn.h"  #include "amdgpu_ras.h" +#include "umc_v8_10.h"  /*   * DO NOT use these for err/warn/info/debug messages. @@ -90,6 +91,12 @@  #define DEBUGSMC_MSG_Mode1Reset	2 +/* + * SMU_v13_0_10 supports ECCTABLE since version 80.34.0, + * use this to check ECCTABLE feature whether support + */ +#define SUPPORT_ECCTABLE_SMU_13_0_10_VERSION 0x00502200 +  static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] = {  	MSG_MAP(TestMessage,			PPSMC_MSG_TestMessage,                 1),  	MSG_MAP(GetSmuVersion,			PPSMC_MSG_GetSmuVersion,               1), @@ -229,6 +236,7 @@ static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {  	TAB_MAP(ACTIVITY_MONITOR_COEFF),  	[SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},  	TAB_MAP(I2C_COMMANDS), +	TAB_MAP(ECCINFO),  };  static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { @@ -462,6 +470,8 @@ static int smu_v13_0_0_tables_init(struct smu_context *smu)  		       AMDGPU_GEM_DOMAIN_VRAM);  	SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE,  			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); +	SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t), +			PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);  	smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);  	if (!smu_table->metrics_table) @@ -477,8 +487,14 @@ static int smu_v13_0_0_tables_init(struct smu_context *smu)  	if (!smu_table->watermarks_table)  		goto err2_out; +	smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL); +	if (!smu_table->ecc_table) +		goto err3_out; +  	return 0; +err3_out: +	kfree(smu_table->watermarks_table);  err2_out:  	kfree(smu_table->gpu_metrics_table);  err1_out: @@ -1128,8 +1144,8 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,  					(pcie_table->pcie_lane[i] == 5) ? "x12" :  					(pcie_table->pcie_lane[i] == 6) ? "x16" : "",  					pcie_table->clk_freq[i], -					((gen_speed - 1) == pcie_table->pcie_gen[i]) && -					(lane_width == link_width[pcie_table->pcie_lane[i]]) ? +					(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) && +					(lane_width == DECODE_LANE_WIDTH(link_width[pcie_table->pcie_lane[i]])) ?  					"*" : "");  		break; @@ -2036,6 +2052,64 @@ static int smu_v13_0_0_send_bad_mem_channel_flag(struct smu_context *smu,  	return ret;  } +static int smu_v13_0_0_check_ecc_table_support(struct smu_context *smu) +{ +	struct amdgpu_device *adev = smu->adev; +	uint32_t if_version = 0xff, smu_version = 0xff; +	int ret = 0; + +	ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); +	if (ret) +		return -EOPNOTSUPP; + +	if ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 10)) && +		(smu_version >= SUPPORT_ECCTABLE_SMU_13_0_10_VERSION)) +		return ret; +	else +		return -EOPNOTSUPP; +} + +static ssize_t smu_v13_0_0_get_ecc_info(struct smu_context *smu, +									void *table) +{ +	struct smu_table_context *smu_table = &smu->smu_table; +	struct amdgpu_device *adev = smu->adev; +	EccInfoTable_t *ecc_table = NULL; +	struct ecc_info_per_ch *ecc_info_per_channel = NULL; +	int i, ret = 0; +	struct umc_ecc_info *eccinfo = (struct umc_ecc_info *)table; + +	ret = smu_v13_0_0_check_ecc_table_support(smu); +	if (ret) +		return ret; + +	ret = smu_cmn_update_table(smu, +					SMU_TABLE_ECCINFO, +					0, +					smu_table->ecc_table, +					false); +	if (ret) { +		dev_info(adev->dev, "Failed to export SMU ecc table!\n"); +		return ret; +	} + +	ecc_table = (EccInfoTable_t *)smu_table->ecc_table; + +	for (i = 0; i < UMC_V8_10_TOTAL_CHANNEL_NUM(adev); i++) { +		ecc_info_per_channel = &(eccinfo->ecc[i]); +		ecc_info_per_channel->ce_count_lo_chip = +				ecc_table->EccInfo[i].ce_count_lo_chip; +		ecc_info_per_channel->ce_count_hi_chip = +				ecc_table->EccInfo[i].ce_count_hi_chip; +		ecc_info_per_channel->mca_umc_status = +				ecc_table->EccInfo[i].mca_umc_status; +		ecc_info_per_channel->mca_umc_addr = +				ecc_table->EccInfo[i].mca_umc_addr; +	} + +	return ret; +} +  static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {  	.get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask,  	.set_default_dpm_table = smu_v13_0_0_set_default_dpm_table, @@ -2111,6 +2185,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {  	.send_hbm_bad_pages_num = smu_v13_0_0_smu_send_bad_mem_page_num,  	.send_hbm_bad_channel_flag = smu_v13_0_0_send_bad_mem_channel_flag,  	.gpo_control = smu_v13_0_gpo_control, +	.get_ecc_info = smu_v13_0_0_get_ecc_info,  };  void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 9e1967d8049e..4399416dd9b8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -575,6 +575,14 @@ static int smu_v13_0_7_set_default_dpm_table(struct smu_context *smu)  						     dpm_table);  		if (ret)  			return ret; + +		if (skutable->DriverReportedClocks.GameClockAc && +			(dpm_table->dpm_levels[dpm_table->count - 1].value > +			skutable->DriverReportedClocks.GameClockAc)) { +			dpm_table->dpm_levels[dpm_table->count - 1].value = +				skutable->DriverReportedClocks.GameClockAc; +			dpm_table->max = skutable->DriverReportedClocks.GameClockAc; +		}  	} else {  		dpm_table->count = 1;  		dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; @@ -828,6 +836,57 @@ static int smu_v13_0_7_get_smu_metrics_data(struct smu_context *smu,  	return ret;  } +static int smu_v13_0_7_get_dpm_ultimate_freq(struct smu_context *smu, +					     enum smu_clk_type clk_type, +					     uint32_t *min, +					     uint32_t *max) +{ +	struct smu_13_0_dpm_context *dpm_context = +		smu->smu_dpm.dpm_context; +	struct smu_13_0_dpm_table *dpm_table; + +	switch (clk_type) { +	case SMU_MCLK: +	case SMU_UCLK: +		/* uclk dpm table */ +		dpm_table = &dpm_context->dpm_tables.uclk_table; +		break; +	case SMU_GFXCLK: +	case SMU_SCLK: +		/* gfxclk dpm table */ +		dpm_table = &dpm_context->dpm_tables.gfx_table; +		break; +	case SMU_SOCCLK: +		/* socclk dpm table */ +		dpm_table = &dpm_context->dpm_tables.soc_table; +		break; +	case SMU_FCLK: +		/* fclk dpm table */ +		dpm_table = &dpm_context->dpm_tables.fclk_table; +		break; +	case SMU_VCLK: +	case SMU_VCLK1: +		/* vclk dpm table */ +		dpm_table = &dpm_context->dpm_tables.vclk_table; +		break; +	case SMU_DCLK: +	case SMU_DCLK1: +		/* dclk dpm table */ +		dpm_table = &dpm_context->dpm_tables.dclk_table; +		break; +	default: +		dev_err(smu->adev->dev, "Unsupported clock type!\n"); +		return -EINVAL; +	} + +	if (min) +		*min = dpm_table->min; +	if (max) +		*max = dpm_table->max; + +	return 0; +} +  static int smu_v13_0_7_read_sensor(struct smu_context *smu,  				   enum amd_pp_sensors sensor,  				   void *data, @@ -1074,8 +1133,8 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,  					(pcie_table->pcie_lane[i] == 5) ? "x12" :  					(pcie_table->pcie_lane[i] == 6) ? "x16" : "",  					pcie_table->clk_freq[i], -					(gen_speed == pcie_table->pcie_gen[i]) && -					(lane_width == pcie_table->pcie_lane[i]) ? +					(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) && +					(lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?  					"*" : "");  		break; @@ -1329,9 +1388,17 @@ static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)  				&dpm_context->dpm_tables.fclk_table;  	struct smu_umd_pstate_table *pstate_table =  				&smu->pstate_table; +	struct smu_table_context *table_context = &smu->smu_table; +	PPTable_t *pptable = table_context->driver_pptable; +	DriverReportedClocks_t driver_clocks = +		pptable->SkuTable.DriverReportedClocks;  	pstate_table->gfxclk_pstate.min = gfx_table->min; -	pstate_table->gfxclk_pstate.peak = gfx_table->max; +	if (driver_clocks.GameClockAc && +		(driver_clocks.GameClockAc < gfx_table->max)) +		pstate_table->gfxclk_pstate.peak = driver_clocks.GameClockAc; +	else +		pstate_table->gfxclk_pstate.peak = gfx_table->max;  	pstate_table->uclk_pstate.min = mem_table->min;  	pstate_table->uclk_pstate.peak = mem_table->max; @@ -1348,12 +1415,12 @@ static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)  	pstate_table->fclk_pstate.min = fclk_table->min;  	pstate_table->fclk_pstate.peak = fclk_table->max; -	/* -	 * For now, just use the mininum clock frequency. -	 * TODO: update them when the real pstate settings available -	 */ -	pstate_table->gfxclk_pstate.standard = gfx_table->min; -	pstate_table->uclk_pstate.standard = mem_table->min; +	if (driver_clocks.BaseClockAc && +		driver_clocks.BaseClockAc < gfx_table->max) +		pstate_table->gfxclk_pstate.standard = driver_clocks.BaseClockAc; +	else +		pstate_table->gfxclk_pstate.standard = gfx_table->max; +	pstate_table->uclk_pstate.standard = mem_table->max;  	pstate_table->socclk_pstate.standard = soc_table->min;  	pstate_table->vclk_pstate.standard = vclk_table->min;  	pstate_table->dclk_pstate.standard = dclk_table->min; @@ -1676,7 +1743,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {  	.dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable,  	.init_pptable_microcode = smu_v13_0_init_pptable_microcode,  	.populate_umd_state_clk = smu_v13_0_7_populate_umd_state_clk, -	.get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq, +	.get_dpm_ultimate_freq = smu_v13_0_7_get_dpm_ultimate_freq,  	.get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,  	.read_sensor = smu_v13_0_7_read_sensor,  	.feature_is_enabled = smu_cmn_feature_is_enabled, diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 0643887800b4..142668cd6d7c 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -99,7 +99,6 @@ static int armada_drm_bind(struct device *dev)  	if (ret) {  		dev_err(dev, "[" DRM_NAME ":%s] can't kick out simple-fb: %d\n",  			__func__, ret); -		kfree(priv);  		return ret;  	} diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index 2019a8167d69..b40baced1331 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -676,8 +676,8 @@ static int lt8912_parse_dt(struct lt8912 *lt)  	lt->hdmi_port = of_drm_find_bridge(port_node);  	if (!lt->hdmi_port) { -		dev_err(lt->dev, "%s: Failed to get hdmi port\n", __func__); -		ret = -ENODEV; +		ret = -EPROBE_DEFER; +		dev_err_probe(lt->dev, ret, "%s: Failed to get hdmi port\n", __func__);  		goto err_free_host_node;  	} diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c b/drivers/gpu/drm/display/drm_hdmi_helper.c index 0264abe55278..faf5e9efa7d3 100644 --- a/drivers/gpu/drm/display/drm_hdmi_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c @@ -44,10 +44,8 @@ int drm_hdmi_infoframe_set_hdr_metadata(struct hdmi_drm_infoframe *frame,  	/* Sink EOTF is Bit map while infoframe is absolute values */  	if (!is_eotf_supported(hdr_metadata->hdmi_metadata_type1.eotf, -	    connector->hdr_sink_metadata.hdmi_type1.eotf)) { -		DRM_DEBUG_KMS("EOTF Not Supported\n"); -		return -EINVAL; -	} +	    connector->hdr_sink_metadata.hdmi_type1.eotf)) +		DRM_DEBUG_KMS("Unknown EOTF %d\n", hdr_metadata->hdmi_metadata_type1.eotf);  	err = hdmi_drm_infoframe_init(frame);  	if (err < 0) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 5457c02ca1ab..fed41800fea7 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1070,6 +1070,7 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,  	drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name);  	drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");  	drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware); +	drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);  	if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)  		if (state->writeback_job && state->writeback_job->fb) diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index 3d1f50f481cf..7098f125b54a 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -146,8 +146,8 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size)  		unsigned int order;  		u64 root_size; -		root_size = rounddown_pow_of_two(size); -		order = ilog2(root_size) - ilog2(chunk_size); +		order = ilog2(size) - ilog2(chunk_size); +		root_size = chunk_size << order;  		root = drm_block_alloc(mm, NULL, order, offset);  		if (!root) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3d0a4da661bc..261a62e15934 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2796,7 +2796,7 @@ u32 drm_edid_get_panel_id(struct i2c_adapter *adapter)  	 * the EDID then we'll just return 0.  	 */ -	base_block = kmalloc(EDID_LENGTH, GFP_KERNEL); +	base_block = kzalloc(EDID_LENGTH, GFP_KERNEL);  	if (!base_block)  		return 0; diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 7a3cb08dc942..a5d392f7e11f 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -1388,10 +1388,13 @@ EXPORT_SYMBOL(drm_gem_lru_move_tail);   *   * @lru: The LRU to scan   * @nr_to_scan: The number of pages to try to reclaim + * @remaining: The number of pages left to reclaim, should be initialized by caller   * @shrink: Callback to try to shrink/reclaim the object.   */  unsigned long -drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan, +drm_gem_lru_scan(struct drm_gem_lru *lru, +		 unsigned int nr_to_scan, +		 unsigned long *remaining,  		 bool (*shrink)(struct drm_gem_object *obj))  {  	struct drm_gem_lru still_in_lru; @@ -1430,8 +1433,10 @@ drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,  		 * hit shrinker in response to trying to get backing pages  		 * for this obj (ie. while it's lock is already held)  		 */ -		if (!dma_resv_trylock(obj->resv)) +		if (!dma_resv_trylock(obj->resv)) { +			*remaining += obj->size >> PAGE_SHIFT;  			goto tail; +		}  		if (shrink(obj)) {  			freed += obj->size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 75185a960fc4..2b2163c8138e 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -619,11 +619,14 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct  	int ret;  	if (obj->import_attach) { -		/* Drop the reference drm_gem_mmap_obj() acquired.*/ -		drm_gem_object_put(obj);  		vma->vm_private_data = NULL; +		ret = dma_buf_mmap(obj->dma_buf, vma, 0); + +		/* Drop the reference drm_gem_mmap_obj() acquired.*/ +		if (!ret) +			drm_gem_object_put(obj); -		return dma_buf_mmap(obj->dma_buf, vma, 0); +		return ret;  	}  	ret = drm_gem_shmem_get_pages(shmem); diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 5522d610c5cf..b1a38e6ce2f8 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -328,10 +328,17 @@ static const struct dmi_system_id orientation_data[] = {  		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"),  		},  		.driver_data = (void *)&lcd1200x1920_rightside_up, -	}, {	/* Lenovo Yoga Book X90F / X91F / X91L */ +	}, {	/* Lenovo Yoga Book X90F / X90L */  		.matches = { -		  /* Non exact match to match all versions */ -		  DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"), +		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), +		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), +		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"), +		}, +		.driver_data = (void *)&lcd1200x1920_rightside_up, +	}, {	/* Lenovo Yoga Book X91F / X91L */ +		.matches = { +		  /* Non exact match to match F + L versions */ +		  DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),  		},  		.driver_data = (void *)&lcd1200x1920_rightside_up,  	}, {	/* Lenovo Yoga Tablet 2 830F / 830L */ diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 44ca803237a5..31a7f59ccb49 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -22,7 +22,6 @@  #include "etnaviv_gem.h"  #include "etnaviv_mmu.h"  #include "etnaviv_perfmon.h" -#include "common.xml.h"  /*   * DRM operations: @@ -476,47 +475,7 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {  	ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW),  }; -static void etnaviv_fop_show_fdinfo(struct seq_file *m, struct file *f) -{ -	struct drm_file *file = f->private_data; -	struct drm_device *dev = file->minor->dev; -	struct etnaviv_drm_private *priv = dev->dev_private; -	struct etnaviv_file_private *ctx = file->driver_priv; - -	/* -	 * For a description of the text output format used here, see -	 * Documentation/gpu/drm-usage-stats.rst. -	 */ -	seq_printf(m, "drm-driver:\t%s\n", dev->driver->name); -	seq_printf(m, "drm-client-id:\t%u\n", ctx->id); - -	for (int i = 0; i < ETNA_MAX_PIPES; i++) { -		struct etnaviv_gpu *gpu = priv->gpu[i]; -		char engine[10] = "UNK"; -		int cur = 0; - -		if (!gpu) -			continue; - -		if (gpu->identity.features & chipFeatures_PIPE_2D) -			cur = snprintf(engine, sizeof(engine), "2D"); -		if (gpu->identity.features & chipFeatures_PIPE_3D) -			cur = snprintf(engine + cur, sizeof(engine) - cur, -				       "%s3D", cur ? "/" : ""); -		if (gpu->identity.nn_core_count > 0) -			cur = snprintf(engine + cur, sizeof(engine) - cur, -				       "%sNN", cur ? "/" : ""); - -		seq_printf(m, "drm-engine-%s:\t%llu ns\n", engine, -			   ctx->sched_entity[i].elapsed_ns); -	} -} - -static const struct file_operations fops = { -	.owner = THIS_MODULE, -	DRM_GEM_FOPS, -	.show_fdinfo = etnaviv_fop_show_fdinfo, -}; +DEFINE_DRM_GEM_FOPS(fops);  static const struct drm_driver etnaviv_drm_driver = {  	.driver_features    = DRIVER_GEM | DRIVER_RENDER, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index 7031db145a77..3524b5811682 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -91,7 +91,15 @@ static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)  static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,  		struct vm_area_struct *vma)  { -	return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0); +	int ret; + +	ret = dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0); +	if (!ret) { +		/* Drop the reference acquired by drm_gem_mmap_obj(). */ +		drm_gem_object_put(&etnaviv_obj->base); +	} + +	return ret;  }  static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = { diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 468a792e6a40..fc0eaf40dc94 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -300,9 +300,21 @@ static void configure_dual_link_mode(struct intel_encoder *encoder,  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); +	i915_reg_t dss_ctl1_reg, dss_ctl2_reg;  	u32 dss_ctl1; -	dss_ctl1 = intel_de_read(dev_priv, DSS_CTL1); +	/* FIXME: Move all DSS handling to intel_vdsc.c */ +	if (DISPLAY_VER(dev_priv) >= 12) { +		struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + +		dss_ctl1_reg = ICL_PIPE_DSS_CTL1(crtc->pipe); +		dss_ctl2_reg = ICL_PIPE_DSS_CTL2(crtc->pipe); +	} else { +		dss_ctl1_reg = DSS_CTL1; +		dss_ctl2_reg = DSS_CTL2; +	} + +	dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg);  	dss_ctl1 |= SPLITTER_ENABLE;  	dss_ctl1 &= ~OVERLAP_PIXELS_MASK;  	dss_ctl1 |= OVERLAP_PIXELS(intel_dsi->pixel_overlap); @@ -323,16 +335,16 @@ static void configure_dual_link_mode(struct intel_encoder *encoder,  		dss_ctl1 &= ~LEFT_DL_BUF_TARGET_DEPTH_MASK;  		dss_ctl1 |= LEFT_DL_BUF_TARGET_DEPTH(dl_buffer_depth); -		dss_ctl2 = intel_de_read(dev_priv, DSS_CTL2); +		dss_ctl2 = intel_de_read(dev_priv, dss_ctl2_reg);  		dss_ctl2 &= ~RIGHT_DL_BUF_TARGET_DEPTH_MASK;  		dss_ctl2 |= RIGHT_DL_BUF_TARGET_DEPTH(dl_buffer_depth); -		intel_de_write(dev_priv, DSS_CTL2, dss_ctl2); +		intel_de_write(dev_priv, dss_ctl2_reg, dss_ctl2);  	} else {  		/* Interleave */  		dss_ctl1 |= DUAL_LINK_MODE_INTERLEAVE;  	} -	intel_de_write(dev_priv, DSS_CTL1, dss_ctl1); +	intel_de_write(dev_priv, dss_ctl1_reg, dss_ctl1);  }  /* aka DSI 8X clock */ diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 8d97c299e657..bd598a7f5047 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -47,6 +47,11 @@ struct intel_color_funcs {  	 */  	void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);  	/* +	 * Perform any extra tasks needed after all the +	 * double buffered registers have been latched. +	 */ +	void (*color_post_update)(const struct intel_crtc_state *crtc_state); +	/*  	 * Load LUTs (and other single buffered color management  	 * registers). Will (hopefully) be called during the vblank  	 * following the latching of any double buffered registers @@ -614,9 +619,33 @@ static void ilk_lut_12p4_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)  static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)  { +	/* +	 * Despite Wa_1406463849, ICL no longer suffers from the SKL +	 * DC5/PSR CSC black screen issue (see skl_color_commit_noarm()). +	 * Possibly due to the extra sticky CSC arming +	 * (see icl_color_post_update()). +	 * +	 * On TGL+ all CSC arming issues have been properly fixed. +	 */  	icl_load_csc_matrix(crtc_state);  } +static void skl_color_commit_noarm(const struct intel_crtc_state *crtc_state) +{ +	/* +	 * Possibly related to display WA #1184, SKL CSC loses the latched +	 * CSC coeff/offset register values if the CSC registers are disarmed +	 * between DC5 exit and PSR exit. This will cause the plane(s) to +	 * output all black (until CSC_MODE is rearmed and properly latched). +	 * Once PSR exit (and proper register latching) has occurred the +	 * danger is over. Thus when PSR is enabled the CSC coeff/offset +	 * register programming will be peformed from skl_color_commit_arm() +	 * which is called after PSR exit. +	 */ +	if (!crtc_state->has_psr) +		ilk_load_csc_matrix(crtc_state); +} +  static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state)  {  	ilk_load_csc_matrix(crtc_state); @@ -659,6 +688,9 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)  	enum pipe pipe = crtc->pipe;  	u32 val = 0; +	if (crtc_state->has_psr) +		ilk_load_csc_matrix(crtc_state); +  	/*  	 * We don't (yet) allow userspace to control the pipe background color,  	 * so force it to black, but apply pipe gamma and CSC appropriately @@ -677,6 +709,47 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)  			  crtc_state->csc_mode);  } +static void icl_color_commit_arm(const struct intel_crtc_state *crtc_state) +{ +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +	struct drm_i915_private *i915 = to_i915(crtc->base.dev); +	enum pipe pipe = crtc->pipe; + +	/* +	 * We don't (yet) allow userspace to control the pipe background color, +	 * so force it to black. +	 */ +	intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), 0); + +	intel_de_write(i915, GAMMA_MODE(crtc->pipe), +		       crtc_state->gamma_mode); + +	intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe), +			  crtc_state->csc_mode); +} + +static void icl_color_post_update(const struct intel_crtc_state *crtc_state) +{ +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); +	struct drm_i915_private *i915 = to_i915(crtc->base.dev); + +	/* +	 * Despite Wa_1406463849, ICL CSC is no longer disarmed by +	 * coeff/offset register *writes*. Instead, once CSC_MODE +	 * is armed it stays armed, even after it has been latched. +	 * Afterwards the coeff/offset registers become effectively +	 * self-arming. That self-arming must be disabled before the +	 * next icl_color_commit_noarm() tries to write the next set +	 * of coeff/offset registers. Fortunately register *reads* +	 * do still disarm the CSC. Naturally this must not be done +	 * until the previously written CSC registers have actually +	 * been latched. +	 * +	 * TGL+ no longer need this workaround. +	 */ +	intel_de_read_fw(i915, PIPE_CSC_PREOFF_HI(crtc->pipe)); +} +  static struct drm_property_blob *  create_linear_lut(struct drm_i915_private *i915, int lut_size)  { @@ -1373,6 +1446,14 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)  	i915->display.funcs.color->color_commit_arm(crtc_state);  } +void intel_color_post_update(const struct intel_crtc_state *crtc_state) +{ +	struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + +	if (i915->display.funcs.color->color_post_update) +		i915->display.funcs.color->color_post_update(crtc_state); +} +  void intel_color_prepare_commit(struct intel_crtc_state *crtc_state)  {  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -3064,10 +3145,20 @@ static const struct intel_color_funcs i9xx_color_funcs = {  	.lut_equal = i9xx_lut_equal,  }; +static const struct intel_color_funcs tgl_color_funcs = { +	.color_check = icl_color_check, +	.color_commit_noarm = icl_color_commit_noarm, +	.color_commit_arm = icl_color_commit_arm, +	.load_luts = icl_load_luts, +	.read_luts = icl_read_luts, +	.lut_equal = icl_lut_equal, +}; +  static const struct intel_color_funcs icl_color_funcs = {  	.color_check = icl_color_check,  	.color_commit_noarm = icl_color_commit_noarm, -	.color_commit_arm = skl_color_commit_arm, +	.color_commit_arm = icl_color_commit_arm, +	.color_post_update = icl_color_post_update,  	.load_luts = icl_load_luts,  	.read_luts = icl_read_luts,  	.lut_equal = icl_lut_equal, @@ -3075,7 +3166,7 @@ static const struct intel_color_funcs icl_color_funcs = {  static const struct intel_color_funcs glk_color_funcs = {  	.color_check = glk_color_check, -	.color_commit_noarm = ilk_color_commit_noarm, +	.color_commit_noarm = skl_color_commit_noarm,  	.color_commit_arm = skl_color_commit_arm,  	.load_luts = glk_load_luts,  	.read_luts = glk_read_luts, @@ -3084,7 +3175,7 @@ static const struct intel_color_funcs glk_color_funcs = {  static const struct intel_color_funcs skl_color_funcs = {  	.color_check = ivb_color_check, -	.color_commit_noarm = ilk_color_commit_noarm, +	.color_commit_noarm = skl_color_commit_noarm,  	.color_commit_arm = skl_color_commit_arm,  	.load_luts = bdw_load_luts,  	.read_luts = bdw_read_luts, @@ -3180,7 +3271,9 @@ void intel_color_init_hooks(struct drm_i915_private *i915)  		else  			i915->display.funcs.color = &i9xx_color_funcs;  	} else { -		if (DISPLAY_VER(i915) >= 11) +		if (DISPLAY_VER(i915) >= 12) +			i915->display.funcs.color = &tgl_color_funcs; +		else if (DISPLAY_VER(i915) == 11)  			i915->display.funcs.color = &icl_color_funcs;  		else if (DISPLAY_VER(i915) == 10)  			i915->display.funcs.color = &glk_color_funcs; diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index d620b5b1e2a6..8002492be709 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -21,6 +21,7 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state);  void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);  void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);  void intel_color_commit_arm(const struct intel_crtc_state *crtc_state); +void intel_color_post_update(const struct intel_crtc_state *crtc_state);  void intel_color_load_luts(const struct intel_crtc_state *crtc_state);  void intel_color_get_config(struct intel_crtc_state *crtc_state);  bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 82be0fbe9934..d5b5d40ed817 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -683,6 +683,14 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)  	 */  	intel_vrr_send_push(new_crtc_state); +	/* +	 * Seamless M/N update may need to update frame timings. +	 * +	 * FIXME Should be synchronized with the start of vblank somehow... +	 */ +	if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state)) +		intel_crtc_update_active_timings(new_crtc_state); +  	local_irq_enable();  	if (intel_vgpu_active(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index d3994e2a7d63..63b4b73f47c6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1209,6 +1209,9 @@ static void intel_post_plane_update(struct intel_atomic_state *state,  	if (needs_cursorclk_wa(old_crtc_state) &&  	    !needs_cursorclk_wa(new_crtc_state))  		icl_wa_cursorclkgating(dev_priv, pipe, false); + +	if (intel_crtc_needs_color_update(new_crtc_state)) +		intel_color_post_update(new_crtc_state);  }  static void intel_crtc_enable_flip_done(struct intel_atomic_state *state, @@ -5145,6 +5148,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,  	 * only fields that are know to not cause problems are preserved. */  	saved_state->uapi = crtc_state->uapi; +	saved_state->inherited = crtc_state->inherited;  	saved_state->scaler_state = crtc_state->scaler_state;  	saved_state->shared_dpll = crtc_state->shared_dpll;  	saved_state->dpll_hw_state = crtc_state->dpll_hw_state; @@ -7090,6 +7094,8 @@ static void intel_update_crtc(struct intel_atomic_state *state,  	intel_fbc_update(state, crtc); +	drm_WARN_ON(&i915->drm, !intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF)); +  	if (!modeset &&  	    intel_crtc_needs_color_update(new_crtc_state))  		intel_color_commit_noarm(new_crtc_state); @@ -7457,8 +7463,28 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  	drm_atomic_helper_wait_for_dependencies(&state->base);  	drm_dp_mst_atomic_wait_for_dependencies(&state->base); -	if (state->modeset) -		wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET); +	/* +	 * During full modesets we write a lot of registers, wait +	 * for PLLs, etc. Doing that while DC states are enabled +	 * is not a good idea. +	 * +	 * During fastsets and other updates we also need to +	 * disable DC states due to the following scenario: +	 * 1. DC5 exit and PSR exit happen +	 * 2. Some or all _noarm() registers are written +	 * 3. Due to some long delay PSR is re-entered +	 * 4. DC5 entry -> DMC saves the already written new +	 *    _noarm() registers and the old not yet written +	 *    _arm() registers +	 * 5. DC5 exit -> DMC restores a mixture of old and +	 *    new register values and arms the update +	 * 6. PSR exit -> hardware latches a mixture of old and +	 *    new register values -> corrupted frame, or worse +	 * 7. New _arm() registers are finally written +	 * 8. Hardware finally latches a complete set of new +	 *    register values, and subsequent frames will be OK again +	 */ +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DC_OFF);  	intel_atomic_prepare_plane_clear_colors(state); @@ -7607,8 +7633,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)  		 * the culprit.  		 */  		intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore); -		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);  	} +	intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF, wakeref);  	intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);  	/* diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 54c517ca9632..582234f0c49a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1631,6 +1631,8 @@ struct intel_psr {  	bool psr2_sel_fetch_cff_enabled;  	bool req_psr2_sdp_prior_scanline;  	u8 sink_sync_latency; +	u8 io_wake_lines; +	u8 fast_wake_lines;  	ktime_t last_entry_attempt;  	ktime_t last_exit;  	bool sink_not_reliable; diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 257aa2b7cf20..3485d5e6dd3c 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -384,15 +384,12 @@ static void disable_all_event_handlers(struct drm_i915_private *i915)  	}  } -static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable) +static void adlp_pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)  {  	enum pipe pipe; -	if (DISPLAY_VER(i915) < 13) -		return; -  	/* -	 * Wa_16015201720:adl-p,dg2, mtl +	 * Wa_16015201720:adl-p,dg2  	 * The WA requires clock gating to be disabled all the time  	 * for pipe A and B.  	 * For pipe C and D clock gating needs to be disabled only @@ -408,6 +405,25 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)  				     PIPEDMC_GATING_DIS, 0);  } +static void mtl_pipedmc_clock_gating_wa(struct drm_i915_private *i915) +{ +	/* +	 * Wa_16015201720 +	 * The WA requires clock gating to be disabled all the time +	 * for pipe A and B. +	 */ +	intel_de_rmw(i915, GEN9_CLKGATE_DIS_0, 0, +		     MTL_PIPEDMC_GATING_DIS_A | MTL_PIPEDMC_GATING_DIS_B); +} + +static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable) +{ +	if (DISPLAY_VER(i915) >= 14 && enable) +		mtl_pipedmc_clock_gating_wa(i915); +	else if (DISPLAY_VER(i915) == 13) +		adlp_pipedmc_clock_gating_wa(i915, enable); +} +  void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe)  {  	if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe))) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 054a009e800d..7c9b328bc2d7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -232,7 +232,7 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,  			return slots;  	} -	intel_link_compute_m_n(crtc_state->pipe_bpp, +	intel_link_compute_m_n(crtc_state->dsc.compressed_bpp,  			       crtc_state->lane_count,  			       adjusted_mode->crtc_clock,  			       crtc_state->port_clock, @@ -265,6 +265,19 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder,  	return 0;  } +static bool intel_dp_mst_has_audio(const struct drm_connector_state *conn_state) +{ +	const struct intel_digital_connector_state *intel_conn_state = +		to_intel_digital_connector_state(conn_state); +	struct intel_connector *connector = +		to_intel_connector(conn_state->connector); + +	if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) +		return connector->port->has_audio; +	else +		return intel_conn_state->force_audio == HDMI_AUDIO_ON; +} +  static int intel_dp_mst_compute_config(struct intel_encoder *encoder,  				       struct intel_crtc_state *pipe_config,  				       struct drm_connector_state *conn_state) @@ -272,10 +285,6 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);  	struct intel_dp *intel_dp = &intel_mst->primary->dp; -	struct intel_connector *connector = -		to_intel_connector(conn_state->connector); -	struct intel_digital_connector_state *intel_conn_state = -		to_intel_digital_connector_state(conn_state);  	const struct drm_display_mode *adjusted_mode =  		&pipe_config->hw.adjusted_mode;  	struct link_config_limits limits; @@ -287,11 +296,9 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;  	pipe_config->has_pch_encoder = false; -	if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) -		pipe_config->has_audio = connector->port->has_audio; -	else -		pipe_config->has_audio = -			intel_conn_state->force_audio == HDMI_AUDIO_ON; +	pipe_config->has_audio = +		intel_dp_mst_has_audio(conn_state) && +		intel_audio_compute_config(encoder, pipe_config, conn_state);  	/*  	 * for MST we always configure max link bw - the spec doesn't diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index ad1a37b515fb..2a9f40a2b3ed 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -301,6 +301,7 @@ intel_dpt_create(struct intel_framebuffer *fb)  	vm->pte_encode = gen8_ggtt_pte_encode;  	dpt->obj = dpt_obj; +	dpt->obj->is_dpt = true;  	return &dpt->vm;  } @@ -309,5 +310,6 @@ void intel_dpt_destroy(struct i915_address_space *vm)  {  	struct i915_dpt *dpt = i915_vm_to_dpt(vm); +	dpt->obj->is_dpt = false;  	i915_vm_put(&dpt->vm);  } diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index f76b06293eb9..38825b30db16 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -210,6 +210,7 @@ static int intelfb_create(struct drm_fb_helper *helper,  	bool prealloc = false;  	void __iomem *vaddr;  	struct drm_i915_gem_object *obj; +	struct i915_gem_ww_ctx ww;  	int ret;  	mutex_lock(&ifbdev->hpd_lock); @@ -283,13 +284,24 @@ static int intelfb_create(struct drm_fb_helper *helper,  		info->fix.smem_len = vma->size;  	} -	vaddr = i915_vma_pin_iomap(vma); -	if (IS_ERR(vaddr)) { -		drm_err(&dev_priv->drm, -			"Failed to remap framebuffer into virtual memory (%pe)\n", vaddr); -		ret = PTR_ERR(vaddr); -		goto out_unpin; +	for_i915_gem_ww(&ww, ret, false) { +		ret = i915_gem_object_lock(vma->obj, &ww); + +		if (ret) +			continue; + +		vaddr = i915_vma_pin_iomap(vma); +		if (IS_ERR(vaddr)) { +			drm_err(&dev_priv->drm, +				"Failed to remap framebuffer into virtual memory (%pe)\n", vaddr); +			ret = PTR_ERR(vaddr); +			continue; +		}  	} + +	if (ret) +		goto out_unpin; +  	info->screen_base = vaddr;  	info->screen_size = vma->size; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 7a72e15e6836..9f1a0bebae24 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -542,6 +542,14 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)  	val |= EDP_PSR2_FRAME_BEFORE_SU(max_t(u8, intel_dp->psr.sink_sync_latency + 1, 2));  	val |= intel_psr2_get_tp_time(intel_dp); +	if (DISPLAY_VER(dev_priv) >= 12) { +		if (intel_dp->psr.io_wake_lines < 9 && +		    intel_dp->psr.fast_wake_lines < 9) +			val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; +		else +			val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_3; +	} +  	/* Wa_22012278275:adl-p */  	if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_E0)) {  		static const u8 map[] = { @@ -558,31 +566,21 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)  		 * Still using the default IO_BUFFER_WAKE and FAST_WAKE, see  		 * comments bellow for more information  		 */ -		u32 tmp, lines = 7; - -		val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; +		u32 tmp; -		tmp = map[lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES]; +		tmp = map[intel_dp->psr.io_wake_lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];  		tmp = tmp << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT;  		val |= tmp; -		tmp = map[lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES]; +		tmp = map[intel_dp->psr.fast_wake_lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];  		tmp = tmp << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT;  		val |= tmp;  	} else if (DISPLAY_VER(dev_priv) >= 12) { -		/* -		 * TODO: 7 lines of IO_BUFFER_WAKE and FAST_WAKE are default -		 * values from BSpec. In order to setting an optimal power -		 * consumption, lower than 4k resolution mode needs to decrease -		 * IO_BUFFER_WAKE and FAST_WAKE. And higher than 4K resolution -		 * mode needs to increase IO_BUFFER_WAKE and FAST_WAKE. -		 */ -		val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; -		val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(7); -		val |= TGL_EDP_PSR2_FAST_WAKE(7); +		val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines); +		val |= TGL_EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines);  	} else if (DISPLAY_VER(dev_priv) >= 9) { -		val |= EDP_PSR2_IO_BUFFER_WAKE(7); -		val |= EDP_PSR2_FAST_WAKE(7); +		val |= EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines); +		val |= EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines);  	}  	if (intel_dp->psr.req_psr2_sdp_prior_scanline) @@ -842,6 +840,46 @@ static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_d  	return true;  } +static bool _compute_psr2_wake_times(struct intel_dp *intel_dp, +				     struct intel_crtc_state *crtc_state) +{ +	struct drm_i915_private *i915 = dp_to_i915(intel_dp); +	int io_wake_lines, io_wake_time, fast_wake_lines, fast_wake_time; +	u8 max_wake_lines; + +	if (DISPLAY_VER(i915) >= 12) { +		io_wake_time = 42; +		/* +		 * According to Bspec it's 42us, but based on testing +		 * it is not enough -> use 45 us. +		 */ +		fast_wake_time = 45; +		max_wake_lines = 12; +	} else { +		io_wake_time = 50; +		fast_wake_time = 32; +		max_wake_lines = 8; +	} + +	io_wake_lines = intel_usecs_to_scanlines( +		&crtc_state->uapi.adjusted_mode, io_wake_time); +	fast_wake_lines = intel_usecs_to_scanlines( +		&crtc_state->uapi.adjusted_mode, fast_wake_time); + +	if (io_wake_lines > max_wake_lines || +	    fast_wake_lines > max_wake_lines) +		return false; + +	if (i915->params.psr_safest_params) +		io_wake_lines = fast_wake_lines = max_wake_lines; + +	/* According to Bspec lower limit should be set as 7 lines. */ +	intel_dp->psr.io_wake_lines = max(io_wake_lines, 7); +	intel_dp->psr.fast_wake_lines = max(fast_wake_lines, 7); + +	return true; +} +  static bool intel_psr2_config_valid(struct intel_dp *intel_dp,  				    struct intel_crtc_state *crtc_state)  { @@ -936,6 +974,12 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,  		return false;  	} +	if (!_compute_psr2_wake_times(intel_dp, crtc_state)) { +		drm_dbg_kms(&dev_priv->drm, +			    "PSR2 not enabled, Unable to use long enough wake times\n"); +		return false; +	} +  	if (HAS_PSR2_SEL_FETCH(dev_priv)) {  		if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) &&  		    !HAS_PSR_HW_TRACKING(dev_priv)) { diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index c65c771f5c46..1cfb94b5cedb 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -1419,6 +1419,36 @@ static const struct intel_mpllb_state dg2_hdmi_262750 = {  		REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),  }; +static const struct intel_mpllb_state dg2_hdmi_267300 = { +	.clock = 267300, +	.ref_control = +		REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), +	.mpllb_cp = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), +	.mpllb_div = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), +	.mpllb_div2 = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 74) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), +	.mpllb_fracn1 = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), +	.mpllb_fracn2 = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 30146) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 36699), +	.mpllb_sscen = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; +  static const struct intel_mpllb_state dg2_hdmi_268500 = {  	.clock = 268500,  	.ref_control = @@ -1509,6 +1539,36 @@ static const struct intel_mpllb_state dg2_hdmi_241500 = {  		REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),  }; +static const struct intel_mpllb_state dg2_hdmi_319890 = { +	.clock = 319890, +	.ref_control = +		REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), +	.mpllb_cp = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), +	.mpllb_div = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), +	.mpllb_div2 = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 94) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), +	.mpllb_fracn1 = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), +	.mpllb_fracn2 = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 64094) | +		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13631), +	.mpllb_sscen = +		REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), +}; +  static const struct intel_mpllb_state dg2_hdmi_497750 = {  	.clock = 497750,  	.ref_control = @@ -1696,8 +1756,10 @@ static const struct intel_mpllb_state * const dg2_hdmi_tables[] = {  	&dg2_hdmi_209800,  	&dg2_hdmi_241500,  	&dg2_hdmi_262750, +	&dg2_hdmi_267300,  	&dg2_hdmi_268500,  	&dg2_hdmi_296703, +	&dg2_hdmi_319890,  	&dg2_hdmi_497750,  	&dg2_hdmi_592000,  	&dg2_hdmi_593407, diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index f45328712bff..be510b9c0d07 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -418,9 +418,9 @@ static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port)  	val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));  	if (val == 0xffffffff) {  		drm_dbg_kms(&i915->drm, -			    "Port %s: PHY in TCCOLD, assume safe mode\n", +			    "Port %s: PHY in TCCOLD, assume not owned\n",  			    dig_port->tc_port_name); -		return true; +		return false;  	}  	return val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c index 8949fb0a944f..3198b64ad7db 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c @@ -127,7 +127,8 @@ i915_gem_object_create_lmem_from_data(struct drm_i915_private *i915,  	memcpy(map, data, size); -	i915_gem_object_unpin_map(obj); +	i915_gem_object_flush_map(obj); +	__i915_gem_object_release_map(obj);  	return obj;  } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index f9a8acbba715..885ccde9dc3c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -303,7 +303,7 @@ i915_gem_object_never_mmap(const struct drm_i915_gem_object *obj)  static inline bool  i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj)  { -	return READ_ONCE(obj->frontbuffer); +	return READ_ONCE(obj->frontbuffer) || obj->is_dpt;  }  static inline unsigned int diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 19c9bdd8f905..5dcbbef31d44 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -491,6 +491,9 @@ struct drm_i915_gem_object {  	 */  	unsigned int cache_dirty:1; +	/* @is_dpt: Object houses a display page table (DPT) */ +	unsigned int is_dpt:1; +  	/**  	 * @read_domains: Read memory domains.  	 * diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 7420276827a5..4758f21c91e1 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -1067,11 +1067,12 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)  			.interruptible = true,  			.no_wait_gpu = true, /* should be idle already */  		}; +		int err;  		GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED)); -		ret = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx); -		if (ret) { +		err = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx); +		if (err) {  			dma_resv_unlock(bo->base.resv);  			return VM_FAULT_SIGBUS;  		} diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 1bbe6708d0a7..750326434677 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2018,6 +2018,8 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)  	 * inspecting the queue to see if we need to resumbit.  	 */  	if (*prev != *execlists->active) { /* elide lite-restores */ +		struct intel_context *prev_ce = NULL, *active_ce = NULL; +  		/*  		 * Note the inherent discrepancy between the HW runtime,  		 * recorded as part of the context switch, and the CPU @@ -2029,9 +2031,15 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)  		 * and correct overselves later when updating from HW.  		 */  		if (*prev) -			lrc_runtime_stop((*prev)->context); +			prev_ce = (*prev)->context;  		if (*execlists->active) -			lrc_runtime_start((*execlists->active)->context); +			active_ce = (*execlists->active)->context; +		if (prev_ce != active_ce) { +			if (prev_ce) +				lrc_runtime_stop(prev_ce); +			if (active_ce) +				lrc_runtime_start(active_ce); +		}  		new_timeslice(execlists);  	} diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index f0dbfc434e07..40d357cf8b04 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -737,12 +737,12 @@ int intel_gt_init(struct intel_gt *gt)  	if (err)  		goto err_gt; -	intel_uc_init_late(>->uc); -  	err = i915_inject_probe_error(gt->i915, -EIO);  	if (err)  		goto err_gt; +	intel_uc_init_late(>->uc); +  	intel_migrate_init(>->migrate, gt);  	goto out_fw; diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index cef3d6f5c34e..56b993f6e7dc 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -21,31 +21,10 @@  #include "intel_rc6.h"  #include "intel_rps.h"  #include "intel_wakeref.h" -#include "intel_pcode.h"  #include "pxp/intel_pxp_pm.h"  #define I915_GT_SUSPEND_IDLE_TIMEOUT (HZ / 2) -static void mtl_media_busy(struct intel_gt *gt) -{ -	/* Wa_14017073508: mtl */ -	if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) && -	    gt->type == GT_MEDIA) -		snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE, -				  PCODE_MBOX_GT_STATE_MEDIA_BUSY, -				  PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0); -} - -static void mtl_media_idle(struct intel_gt *gt) -{ -	/* Wa_14017073508: mtl */ -	if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) && -	    gt->type == GT_MEDIA) -		snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE, -				  PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY, -				  PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0); -} -  static void user_forcewake(struct intel_gt *gt, bool suspend)  {  	int count = atomic_read(>->user_wakeref); @@ -93,9 +72,6 @@ static int __gt_unpark(struct intel_wakeref *wf)  	GT_TRACE(gt, "\n"); -	/* Wa_14017073508: mtl */ -	mtl_media_busy(gt); -  	/*  	 * It seems that the DMC likes to transition between the DC states a lot  	 * when there are no connected displays (no active power domains) during @@ -145,9 +121,6 @@ static int __gt_park(struct intel_wakeref *wf)  	GEM_BUG_ON(!wakeref);  	intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref); -	/* Wa_14017073508: mtl */ -	mtl_media_idle(gt); -  	return 0;  } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 83df4cd5e06c..80dbbef86b1d 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -580,7 +580,7 @@ static bool perf_limit_reasons_eval(void *data)  }  DEFINE_SIMPLE_ATTRIBUTE(perf_limit_reasons_fops, perf_limit_reasons_get, -			perf_limit_reasons_clear, "%llu\n"); +			perf_limit_reasons_clear, "0x%llx\n");  void intel_gt_pm_debugfs_register(struct intel_gt *gt, struct dentry *root)  { diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 5c91622dfca4..f4150f61f39c 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -486,6 +486,7 @@ static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6)  static bool rc6_supported(struct intel_rc6 *rc6)  {  	struct drm_i915_private *i915 = rc6_to_i915(rc6); +	struct intel_gt *gt = rc6_to_gt(rc6);  	if (!HAS_RC6(i915))  		return false; @@ -502,6 +503,13 @@ static bool rc6_supported(struct intel_rc6 *rc6)  		return false;  	} +	if (IS_MTL_MEDIA_STEP(gt->i915, STEP_A0, STEP_B0) && +	    gt->type == GT_MEDIA) { +		drm_notice(&i915->drm, +			   "Media RC6 disabled on A step\n"); +		return false; +	} +  	return true;  } diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index f5d7b5126433..2c92fa9d1942 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -2075,16 +2075,6 @@ void intel_rps_sanitize(struct intel_rps *rps)  		rps_disable_interrupts(rps);  } -u32 intel_rps_read_rpstat_fw(struct intel_rps *rps) -{ -	struct drm_i915_private *i915 = rps_to_i915(rps); -	i915_reg_t rpstat; - -	rpstat = (GRAPHICS_VER(i915) >= 12) ? GEN12_RPSTAT1 : GEN6_RPSTAT1; - -	return intel_uncore_read_fw(rps_to_gt(rps)->uncore, rpstat); -} -  u32 intel_rps_read_rpstat(struct intel_rps *rps)  {  	struct drm_i915_private *i915 = rps_to_i915(rps); @@ -2095,7 +2085,7 @@ u32 intel_rps_read_rpstat(struct intel_rps *rps)  	return intel_uncore_read(rps_to_gt(rps)->uncore, rpstat);  } -u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat) +static u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat)  {  	struct drm_i915_private *i915 = rps_to_i915(rps);  	u32 cagf; @@ -2118,10 +2108,11 @@ u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat)  	return cagf;  } -static u32 read_cagf(struct intel_rps *rps) +static u32 __read_cagf(struct intel_rps *rps, bool take_fw)  {  	struct drm_i915_private *i915 = rps_to_i915(rps);  	struct intel_uncore *uncore = rps_to_uncore(rps); +	i915_reg_t r = INVALID_MMIO_REG;  	u32 freq;  	/* @@ -2129,22 +2120,30 @@ static u32 read_cagf(struct intel_rps *rps)  	 * registers will return 0 freq when GT is in RC6  	 */  	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) { -		freq = intel_uncore_read(uncore, MTL_MIRROR_TARGET_WP1); +		r = MTL_MIRROR_TARGET_WP1;  	} else if (GRAPHICS_VER(i915) >= 12) { -		freq = intel_uncore_read(uncore, GEN12_RPSTAT1); +		r = GEN12_RPSTAT1;  	} else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {  		vlv_punit_get(i915);  		freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);  		vlv_punit_put(i915);  	} else if (GRAPHICS_VER(i915) >= 6) { -		freq = intel_uncore_read(uncore, GEN6_RPSTAT1); +		r = GEN6_RPSTAT1;  	} else { -		freq = intel_uncore_read(uncore, MEMSTAT_ILK); +		r = MEMSTAT_ILK;  	} +	if (i915_mmio_reg_valid(r)) +		freq = take_fw ? intel_uncore_read(uncore, r) : intel_uncore_read_fw(uncore, r); +  	return intel_rps_get_cagf(rps, freq);  } +static u32 read_cagf(struct intel_rps *rps) +{ +	return __read_cagf(rps, true); +} +  u32 intel_rps_read_actual_frequency(struct intel_rps *rps)  {  	struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm; @@ -2157,7 +2156,12 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps)  	return freq;  } -u32 intel_rps_read_punit_req(struct intel_rps *rps) +u32 intel_rps_read_actual_frequency_fw(struct intel_rps *rps) +{ +	return intel_gpu_freq(rps, __read_cagf(rps, false)); +} + +static u32 intel_rps_read_punit_req(struct intel_rps *rps)  {  	struct intel_uncore *uncore = rps_to_uncore(rps);  	struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm; diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index c622962c6bef..a3fa987aa91f 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -37,8 +37,8 @@ void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive);  int intel_gpu_freq(struct intel_rps *rps, int val);  int intel_freq_opcode(struct intel_rps *rps, int val); -u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1);  u32 intel_rps_read_actual_frequency(struct intel_rps *rps); +u32 intel_rps_read_actual_frequency_fw(struct intel_rps *rps);  u32 intel_rps_get_requested_frequency(struct intel_rps *rps);  u32 intel_rps_get_min_frequency(struct intel_rps *rps);  u32 intel_rps_get_min_raw_freq(struct intel_rps *rps); @@ -49,10 +49,8 @@ int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val);  u32 intel_rps_get_rp0_frequency(struct intel_rps *rps);  u32 intel_rps_get_rp1_frequency(struct intel_rps *rps);  u32 intel_rps_get_rpn_frequency(struct intel_rps *rps); -u32 intel_rps_read_punit_req(struct intel_rps *rps);  u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps);  u32 intel_rps_read_rpstat(struct intel_rps *rps); -u32 intel_rps_read_rpstat_fw(struct intel_rps *rps);  void gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps);  void intel_rps_raise_unslice(struct intel_rps *rps);  void intel_rps_lower_unslice(struct intel_rps *rps); diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h index aa87d3832d60..d7e8c374f153 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.h +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h @@ -27,7 +27,7 @@ struct drm_printer;   * is only relevant to pre-Xe_HP platforms (Xe_HP and beyond use the   * I915_MAX_SS_FUSE_BITS value below).   */ -#define GEN_MAX_SS_PER_HSW_SLICE	6 +#define GEN_MAX_SS_PER_HSW_SLICE	8  /*   * Maximum number of 32-bit registers used by hardware to express the diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index fc3b994626a4..710999d7189e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -1571,6 +1571,27 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf,  #endif //CONFIG_DRM_I915_CAPTURE_ERROR +static void guc_capture_find_ecode(struct intel_engine_coredump *ee) +{ +	struct gcap_reg_list_info *reginfo; +	struct guc_mmio_reg *regs; +	i915_reg_t reg_ipehr = RING_IPEHR(0); +	i915_reg_t reg_instdone = RING_INSTDONE(0); +	int i; + +	if (!ee->guc_capture_node) +		return; + +	reginfo = ee->guc_capture_node->reginfo + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE; +	regs = reginfo->regs; +	for (i = 0; i < reginfo->num_regs; i++) { +		if (regs[i].offset == reg_ipehr.reg) +			ee->ipehr = regs[i].value; +		else if (regs[i].offset == reg_instdone.reg) +			ee->instdone.instdone = regs[i].value; +	} +} +  void intel_guc_capture_free_node(struct intel_engine_coredump *ee)  {  	if (!ee || !ee->guc_capture_node) @@ -1612,6 +1633,7 @@ void intel_guc_capture_get_matching_node(struct intel_gt *gt,  			list_del(&n->link);  			ee->guc_capture_node = n;  			ee->guc_capture = guc->capture; +			guc_capture_find_ecode(ee);  			return;  		}  	} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c index b5855091cf6a..8f8dd05835c5 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c @@ -11,20 +11,9 @@  static bool __guc_rc_supported(struct intel_guc *guc)  { -	struct intel_gt *gt = guc_to_gt(guc); - -	/* -	 * Wa_14017073508: mtl -	 * Do not enable gucrc to avoid additional interrupts which -	 * may disrupt pcode wa. -	 */ -	if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) && -	    gt->type == GT_MEDIA) -		return false; -  	/* GuC RC is unavailable for pre-Gen12 */  	return guc->submission_supported && -		GRAPHICS_VER(gt->i915) >= 12; +		GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;  }  static bool __guc_rc_selected(struct intel_guc *guc) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c index 410905da8e97..0c103ca160d1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c @@ -235,6 +235,13 @@ static void delayed_huc_load_fini(struct intel_huc *huc)  	i915_sw_fence_fini(&huc->delayed_load.fence);  } +int intel_huc_sanitize(struct intel_huc *huc) +{ +	delayed_huc_load_complete(huc); +	intel_uc_fw_sanitize(&huc->fw); +	return 0; +} +  static bool vcs_supported(struct intel_gt *gt)  {  	intel_engine_mask_t mask = gt->info.engine_mask; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.h b/drivers/gpu/drm/i915/gt/uc/intel_huc.h index 52db03620c60..db555b3c1f56 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.h @@ -41,6 +41,7 @@ struct intel_huc {  	} delayed_load;  }; +int intel_huc_sanitize(struct intel_huc *huc);  void intel_huc_init_early(struct intel_huc *huc);  int intel_huc_init(struct intel_huc *huc);  void intel_huc_fini(struct intel_huc *huc); @@ -54,12 +55,6 @@ bool intel_huc_is_authenticated(struct intel_huc *huc);  void intel_huc_register_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);  void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus); -static inline int intel_huc_sanitize(struct intel_huc *huc) -{ -	intel_uc_fw_sanitize(&huc->fw); -	return 0; -} -  static inline bool intel_huc_is_supported(struct intel_huc *huc)  {  	return intel_uc_fw_is_supported(&huc->fw); diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 7412abf166a8..8ef93889061a 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -92,8 +92,7 @@ static void debug_active_init(struct i915_active *ref)  static void debug_active_activate(struct i915_active *ref)  {  	lockdep_assert_held(&ref->tree_lock); -	if (!atomic_read(&ref->count)) /* before the first inc */ -		debug_object_activate(ref, &active_debug_desc); +	debug_object_activate(ref, &active_debug_desc);  }  static void debug_active_deactivate(struct i915_active *ref) @@ -422,12 +421,12 @@ replace_barrier(struct i915_active *ref, struct i915_active_fence *active)  	 * we can use it to substitute for the pending idle-barrer  	 * request that we want to emit on the kernel_context.  	 */ -	__active_del_barrier(ref, node_from_active(active)); -	return true; +	return __active_del_barrier(ref, node_from_active(active));  }  int i915_active_add_request(struct i915_active *ref, struct i915_request *rq)  { +	u64 idx = i915_request_timeline(rq)->fence_context;  	struct dma_fence *fence = &rq->fence;  	struct i915_active_fence *active;  	int err; @@ -437,16 +436,19 @@ int i915_active_add_request(struct i915_active *ref, struct i915_request *rq)  	if (err)  		return err; -	active = active_instance(ref, i915_request_timeline(rq)->fence_context); -	if (!active) { -		err = -ENOMEM; -		goto out; -	} +	do { +		active = active_instance(ref, idx); +		if (!active) { +			err = -ENOMEM; +			goto out; +		} + +		if (replace_barrier(ref, active)) { +			RCU_INIT_POINTER(active->fence, NULL); +			atomic_dec(&ref->count); +		} +	} while (unlikely(is_barrier(active))); -	if (replace_barrier(ref, active)) { -		RCU_INIT_POINTER(active->fence, NULL); -		atomic_dec(&ref->count); -	}  	if (!__i915_active_fence_set(active, fence))  		__i915_active_acquire(ref); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 824a34ec0b83..004074936300 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1592,9 +1592,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)  	/*  	 * Wa_16011777198:dg2: Unset the override of GUCRC mode to enable rc6.  	 */ -	if (intel_uc_uses_guc_rc(>->uc) && -	    (IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_C0) || -	     IS_DG2_GRAPHICS_STEP(gt->i915, G11, STEP_A0, STEP_B0))) +	if (stream->override_gucrc)  		drm_WARN_ON(>->i915->drm,  			    intel_guc_slpc_unset_gucrc_mode(>->uc.guc.slpc)); @@ -3305,8 +3303,10 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,  		if (ret) {  			drm_dbg(&stream->perf->i915->drm,  				"Unable to override gucrc mode\n"); -			goto err_config; +			goto err_gucrc;  		} + +		stream->override_gucrc = true;  	}  	ret = alloc_oa_buffer(stream); @@ -3345,11 +3345,15 @@ err_enable:  	free_oa_buffer(stream);  err_oa_buf_alloc: -	free_oa_configs(stream); +	if (stream->override_gucrc) +		intel_guc_slpc_unset_gucrc_mode(>->uc.guc.slpc); +err_gucrc:  	intel_uncore_forcewake_put(stream->uncore, FORCEWAKE_ALL);  	intel_engine_pm_put(stream->engine); +	free_oa_configs(stream); +  err_config:  	free_noa_wait(stream); @@ -4634,13 +4638,13 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,  		err = oa_config->id;  		goto sysfs_err;  	} - -	mutex_unlock(&perf->metrics_lock); +	id = oa_config->id;  	drm_dbg(&perf->i915->drm,  		"Added config %s id=%i\n", oa_config->uuid, oa_config->id); +	mutex_unlock(&perf->metrics_lock); -	return oa_config->id; +	return id;  sysfs_err:  	mutex_unlock(&perf->metrics_lock); diff --git a/drivers/gpu/drm/i915/i915_perf_types.h b/drivers/gpu/drm/i915/i915_perf_types.h index ca150b7af3f2..4d5d8c365d9e 100644 --- a/drivers/gpu/drm/i915/i915_perf_types.h +++ b/drivers/gpu/drm/i915/i915_perf_types.h @@ -316,6 +316,12 @@ struct i915_perf_stream {  	 * buffer should be checked for available data.  	 */  	u64 poll_oa_period; + +	/** +	 * @override_gucrc: GuC RC has been overridden for the perf stream, +	 * and we need to restore the default configuration on release. +	 */ +	bool override_gucrc;  };  /** diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 52531ab28c5f..6d422b056f8a 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -393,14 +393,12 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)  		 * case we assume the system is running at the intended  		 * frequency. Fortunately, the read should rarely fail!  		 */ -		val = intel_rps_read_rpstat_fw(rps); -		if (val) -			val = intel_rps_get_cagf(rps, val); -		else -			val = rps->cur_freq; +		val = intel_rps_read_actual_frequency_fw(rps); +		if (!val) +			val = intel_gpu_freq(rps, rps->cur_freq);  		add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT], -				intel_gpu_freq(rps, val), period_ns / 1000); +				val, period_ns / 1000);  	}  	if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3b2642397b82..747b53b567a0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1786,9 +1786,11 @@   * GEN9 clock gating regs   */  #define GEN9_CLKGATE_DIS_0		_MMIO(0x46530) -#define   DARBF_GATING_DIS		(1 << 27) -#define   PWM2_GATING_DIS		(1 << 14) -#define   PWM1_GATING_DIS		(1 << 13) +#define   DARBF_GATING_DIS		REG_BIT(27) +#define   MTL_PIPEDMC_GATING_DIS_A	REG_BIT(15) +#define   MTL_PIPEDMC_GATING_DIS_B	REG_BIT(14) +#define   PWM2_GATING_DIS		REG_BIT(14) +#define   PWM1_GATING_DIS		REG_BIT(13)  #define GEN9_CLKGATE_DIS_3		_MMIO(0x46538)  #define   TGL_VRH_GATING_DIS		REG_BIT(31) @@ -6596,15 +6598,6 @@  /*   XEHP_PCODE_FREQUENCY_CONFIG param2 */  #define     PCODE_MBOX_DOMAIN_NONE		0x0  #define     PCODE_MBOX_DOMAIN_MEDIAFF		0x3 - -/* Wa_14017210380: mtl */ -#define   PCODE_MBOX_GT_STATE			0x50 -/* sub-commands (param1) */ -#define     PCODE_MBOX_GT_STATE_MEDIA_BUSY	0x1 -#define     PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY	0x2 -/* param2 */ -#define     PCODE_MBOX_GT_STATE_DOMAIN_MEDIA	0x1 -  #define GEN6_PCODE_DATA				_MMIO(0x138128)  #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8  #define   GEN6_PCODE_FREQ_RING_RATIO_SHIFT	16 diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 79bfe3938d3c..7caf937c3c90 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -325,23 +325,23 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)  	ret = meson_encoder_hdmi_init(priv);  	if (ret) -		goto exit_afbcd; +		goto unbind_all;  	ret = meson_plane_create(priv);  	if (ret) -		goto exit_afbcd; +		goto unbind_all;  	ret = meson_overlay_create(priv);  	if (ret) -		goto exit_afbcd; +		goto unbind_all;  	ret = meson_crtc_create(priv);  	if (ret) -		goto exit_afbcd; +		goto unbind_all;  	ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm);  	if (ret) -		goto exit_afbcd; +		goto unbind_all;  	drm_mode_config_reset(drm); @@ -359,6 +359,9 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)  uninstall_irq:  	free_irq(priv->vsync_irq, drm); +unbind_all: +	if (has_components) +		component_unbind_all(drm->dev, drm);  exit_afbcd:  	if (priv->afbcd.ops)  		priv->afbcd.ops->exit(priv); diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index 534621a13a34..3d046878ce6c 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -718,7 +718,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,  	dw_plat_data = &meson_dw_hdmi->dw_plat_data;  	ret = devm_regulator_get_enable_optional(dev, "hdmi"); -	if (ret < 0) +	if (ret < 0 && ret != -ENODEV)  		return ret;  	meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev, diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c index 154837688ab0..5df1957c8e41 100644 --- a/drivers/gpu/drm/meson/meson_vpp.c +++ b/drivers/gpu/drm/meson/meson_vpp.c @@ -100,6 +100,8 @@ void meson_vpp_init(struct meson_drm *priv)  			       priv->io_base + _REG(VPP_DOLBY_CTRL));  		writel_relaxed(0x1020080,  				priv->io_base + _REG(VPP_DUMMY_DATA1)); +		writel_relaxed(0x42020, +				priv->io_base + _REG(VPP_DUMMY_DATA));  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))  		writel_relaxed(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL)); diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 871870ddf7ec..949b18a29a55 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -23,7 +23,6 @@ config DRM_MSM  	select SHMEM  	select TMPFS  	select QCOM_SCM -	select DEVFREQ_GOV_SIMPLE_ONDEMAND  	select WANT_DEV_COREDUMP  	select SND_SOC_HDMI_CODEC if SND_SOC  	select SYNC_FILE diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index d09221f97f71..a1e006ec5dce 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -151,8 +151,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)  	OUT_RING(ring, 1);  	/* Enable local preemption for finegrain preemption */ -	OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1); -	OUT_RING(ring, 0x02); +	OUT_PKT7(ring, CP_PREEMPT_ENABLE_LOCAL, 1); +	OUT_RING(ring, 0x1);  	/* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */  	OUT_PKT7(ring, CP_YIELD_ENABLE, 1); @@ -806,7 +806,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)  	gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);  	/* Set the highest bank bit */ -	if (adreno_is_a540(adreno_gpu)) +	if (adreno_is_a540(adreno_gpu) || adreno_is_a530(adreno_gpu))  		regbit = 2;  	else  		regbit = 1; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index 7658e89844b4..f58dd564d122 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -63,7 +63,7 @@ static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu)  		struct msm_ringbuffer *ring = gpu->rb[i];  		spin_lock_irqsave(&ring->preempt_lock, flags); -		empty = (get_wptr(ring) == ring->memptrs->rptr); +		empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring));  		spin_unlock_irqrestore(&ring->preempt_lock, flags);  		if (!empty) @@ -207,6 +207,7 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu)  		a5xx_gpu->preempt[i]->wptr = 0;  		a5xx_gpu->preempt[i]->rptr = 0;  		a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova; +		a5xx_gpu->preempt[i]->rptr_addr = shadowptr(a5xx_gpu, gpu->rb[i]);  	}  	/* Write a 0 to signal that we aren't switching pagetables */ @@ -257,7 +258,6 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu,  	ptr->data = 0;  	ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE; -	ptr->rptr_addr = shadowptr(a5xx_gpu, ring);  	ptr->counter = counters_iova;  	return 0; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index f3c9600221d4..7f5bc73b2040 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -974,7 +974,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)  	int status, ret;  	if (WARN(!gmu->initialized, "The GMU is not set up yet\n")) -		return 0; +		return -EINVAL;  	gmu->hung = false; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index aae60cbd9164..6faea5049f76 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1746,7 +1746,9 @@ static void a6xx_destroy(struct msm_gpu *gpu)  	a6xx_llc_slices_destroy(a6xx_gpu); +	mutex_lock(&a6xx_gpu->gmu.lock);  	a6xx_gmu_remove(a6xx_gpu); +	mutex_unlock(&a6xx_gpu->gmu.lock);  	adreno_gpu_cleanup(adreno_gpu); diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 36f062c7582f..c5c4c93b3689 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -558,7 +558,8 @@ static void adreno_unbind(struct device *dev, struct device *master,  	struct msm_drm_private *priv = dev_get_drvdata(master);  	struct msm_gpu *gpu = dev_to_gpu(dev); -	WARN_ON_ONCE(adreno_system_suspend(dev)); +	if (pm_runtime_enabled(dev)) +		WARN_ON_ONCE(adreno_system_suspend(dev));  	gpu->funcs->destroy(gpu);  	priv->gpu_pdev = NULL; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index cf053e8f081e..497c9e1673ab 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -12,11 +12,15 @@  #include "dpu_hw_catalog.h"  #include "dpu_kms.h" -#define VIG_MASK \ +#define VIG_BASE_MASK \  	(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\ -	BIT(DPU_SSPP_CSC_10BIT) | BIT(DPU_SSPP_CDP) |\ +	BIT(DPU_SSPP_CDP) |\  	BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_EXCL_RECT)) +#define VIG_MASK \ +	(VIG_BASE_MASK | \ +	BIT(DPU_SSPP_CSC_10BIT)) +  #define VIG_MSM8998_MASK \  	(VIG_MASK | BIT(DPU_SSPP_SCALER_QSEED3)) @@ -26,10 +30,7 @@  #define VIG_SC7180_MASK \  	(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED4)) -#define VIG_SM8250_MASK \ -	(VIG_MASK | BIT(DPU_SSPP_QOS_8LVL) | BIT(DPU_SSPP_SCALER_QSEED3LITE)) - -#define VIG_QCM2290_MASK (VIG_MASK | BIT(DPU_SSPP_QOS_8LVL)) +#define VIG_QCM2290_MASK (VIG_BASE_MASK | BIT(DPU_SSPP_QOS_8LVL))  #define DMA_MSM8998_MASK \  	(BIT(DPU_SSPP_SRC) | BIT(DPU_SSPP_QOS) |\ @@ -51,7 +52,7 @@  	(DMA_MSM8998_MASK | BIT(DPU_SSPP_CURSOR))  #define MIXER_MSM8998_MASK \ -	(BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER)) +	(BIT(DPU_MIXER_SOURCESPLIT))  #define MIXER_SDM845_MASK \  	(BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER) | BIT(DPU_MIXER_COMBINED_ALPHA)) @@ -314,10 +315,9 @@ static const struct dpu_caps msm8998_dpu_caps = {  };  static const struct dpu_caps qcm2290_dpu_caps = { -	.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, +	.max_mixer_width = DEFAULT_DPU_LINE_WIDTH,  	.max_mixer_blendstages = 0x4,  	.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, -	.ubwc_version = DPU_HW_UBWC_VER_20,  	.has_dim_layer = true,  	.has_idle_pc = true,  	.max_linewidth = 2160, @@ -353,9 +353,9 @@ static const struct dpu_caps sc7180_dpu_caps = {  };  static const struct dpu_caps sm6115_dpu_caps = { -	.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH, +	.max_mixer_width = DEFAULT_DPU_LINE_WIDTH,  	.max_mixer_blendstages = 0x4, -	.qseed_type = DPU_SSPP_SCALER_QSEED3LITE, +	.qseed_type = DPU_SSPP_SCALER_QSEED4,  	.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */  	.ubwc_version = DPU_HW_UBWC_VER_10,  	.has_dim_layer = true, @@ -399,7 +399,7 @@ static const struct dpu_caps sc8180x_dpu_caps = {  static const struct dpu_caps sc8280xp_dpu_caps = {  	.max_mixer_width = 2560,  	.max_mixer_blendstages = 11, -	.qseed_type = DPU_SSPP_SCALER_QSEED3LITE, +	.qseed_type = DPU_SSPP_SCALER_QSEED4,  	.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */  	.ubwc_version = DPU_HW_UBWC_VER_40,  	.has_src_split = true, @@ -413,7 +413,7 @@ static const struct dpu_caps sc8280xp_dpu_caps = {  static const struct dpu_caps sm8250_dpu_caps = {  	.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,  	.max_mixer_blendstages = 0xb, -	.qseed_type = DPU_SSPP_SCALER_QSEED3LITE, +	.qseed_type = DPU_SSPP_SCALER_QSEED4,  	.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */  	.ubwc_version = DPU_HW_UBWC_VER_40,  	.has_src_split = true, @@ -427,7 +427,7 @@ static const struct dpu_caps sm8250_dpu_caps = {  static const struct dpu_caps sm8350_dpu_caps = {  	.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,  	.max_mixer_blendstages = 0xb, -	.qseed_type = DPU_SSPP_SCALER_QSEED3LITE, +	.qseed_type = DPU_SSPP_SCALER_QSEED4,  	.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */  	.ubwc_version = DPU_HW_UBWC_VER_40,  	.has_src_split = true, @@ -455,7 +455,7 @@ static const struct dpu_caps sm8450_dpu_caps = {  static const struct dpu_caps sm8550_dpu_caps = {  	.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,  	.max_mixer_blendstages = 0xb, -	.qseed_type = DPU_SSPP_SCALER_QSEED3LITE, +	.qseed_type = DPU_SSPP_SCALER_QSEED4,  	.smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */  	.ubwc_version = DPU_HW_UBWC_VER_40,  	.has_src_split = true, @@ -525,9 +525,9 @@ static const struct dpu_mdp_cfg sdm845_mdp[] = {  			.reg_off = 0x2AC, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_DMA1] = {  			.reg_off = 0x2B4, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA2] = {  			.reg_off = 0x2BC, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA3] = {  			.reg_off = 0x2C4, .bit_off = 8},  	},  }; @@ -542,9 +542,9 @@ static const struct dpu_mdp_cfg sc7180_mdp[] = {  		.reg_off = 0x2AC, .bit_off = 0},  	.clk_ctrls[DPU_CLK_CTRL_DMA0] = {  		.reg_off = 0x2AC, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA1] = {  		.reg_off = 0x2B4, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA2] = {  		.reg_off = 0x2C4, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_WB2] = {  		.reg_off = 0x3B8, .bit_off = 24}, @@ -569,9 +569,9 @@ static const struct dpu_mdp_cfg sc8180x_mdp[] = {  			.reg_off = 0x2AC, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_DMA1] = {  			.reg_off = 0x2B4, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA2] = {  			.reg_off = 0x2BC, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA3] = {  			.reg_off = 0x2C4, .bit_off = 8},  	},  }; @@ -609,9 +609,9 @@ static const struct dpu_mdp_cfg sm8250_mdp[] = {  			.reg_off = 0x2AC, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_DMA1] = {  			.reg_off = 0x2B4, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA2] = {  			.reg_off = 0x2BC, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA3] = {  			.reg_off = 0x2C4, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_REG_DMA] = {  			.reg_off = 0x2BC, .bit_off = 20}, @@ -638,9 +638,9 @@ static const struct dpu_mdp_cfg sm8350_mdp[] = {  			.reg_off = 0x2ac, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_DMA1] = {  			.reg_off = 0x2b4, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA2] = {  			.reg_off = 0x2bc, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA3] = {  			.reg_off = 0x2c4, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_REG_DMA] = {  			.reg_off = 0x2bc, .bit_off = 20}, @@ -666,9 +666,9 @@ static const struct dpu_mdp_cfg sm8450_mdp[] = {  			.reg_off = 0x2AC, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_DMA1] = {  			.reg_off = 0x2B4, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA2] = {  			.reg_off = 0x2BC, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA3] = {  			.reg_off = 0x2C4, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_REG_DMA] = {  			.reg_off = 0x2BC, .bit_off = 20}, @@ -685,9 +685,9 @@ static const struct dpu_mdp_cfg sc7280_mdp[] = {  		.reg_off = 0x2AC, .bit_off = 0},  	.clk_ctrls[DPU_CLK_CTRL_DMA0] = {  		.reg_off = 0x2AC, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA1] = {  		.reg_off = 0x2B4, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA2] = {  		.reg_off = 0x2C4, .bit_off = 8},  	},  }; @@ -696,7 +696,7 @@ static const struct dpu_mdp_cfg sc8280xp_mdp[] = {  	{  	.name = "top_0", .id = MDP_TOP,  	.base = 0x0, .len = 0x494, -	.features = 0, +	.features = BIT(DPU_MDP_PERIPH_0_REMOVED),  	.highest_bank_bit = 2,  	.ubwc_swizzle = 6,  	.clk_ctrls[DPU_CLK_CTRL_VIG0] = { .reg_off = 0x2ac, .bit_off = 0}, @@ -705,8 +705,8 @@ static const struct dpu_mdp_cfg sc8280xp_mdp[] = {  	.clk_ctrls[DPU_CLK_CTRL_VIG3] = { .reg_off = 0x2c4, .bit_off = 0},  	.clk_ctrls[DPU_CLK_CTRL_DMA0] = { .reg_off = 0x2ac, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_DMA1] = { .reg_off = 0x2b4, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { .reg_off = 0x2bc, .bit_off = 8}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { .reg_off = 0x2c4, .bit_off = 8}, +	.clk_ctrls[DPU_CLK_CTRL_DMA2] = { .reg_off = 0x2bc, .bit_off = 8}, +	.clk_ctrls[DPU_CLK_CTRL_DMA3] = { .reg_off = 0x2c4, .bit_off = 8},  	.clk_ctrls[DPU_CLK_CTRL_REG_DMA] = { .reg_off = 0x2bc, .bit_off = 20},  	},  }; @@ -734,9 +734,9 @@ static const struct dpu_mdp_cfg sm8550_mdp[] = {  			.reg_off = 0x28330, .bit_off = 0},  	.clk_ctrls[DPU_CLK_CTRL_DMA3] = {  			.reg_off = 0x2a330, .bit_off = 0}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR0] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA4] = {  			.reg_off = 0x2c330, .bit_off = 0}, -	.clk_ctrls[DPU_CLK_CTRL_CURSOR1] = { +	.clk_ctrls[DPU_CLK_CTRL_DMA5] = {  			.reg_off = 0x2e330, .bit_off = 0},  	.clk_ctrls[DPU_CLK_CTRL_REG_DMA] = {  			.reg_off = 0x2bc, .bit_off = 20}, @@ -828,19 +828,19 @@ static const struct dpu_ctl_cfg sdm845_ctl[] = {  static const struct dpu_ctl_cfg sc7180_ctl[] = {  	{  	.name = "ctl_0", .id = CTL_0, -	.base = 0x1000, .len = 0xE4, +	.base = 0x1000, .len = 0x1dc,  	.features = BIT(DPU_CTL_ACTIVE_CFG),  	.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 9),  	},  	{  	.name = "ctl_1", .id = CTL_1, -	.base = 0x1200, .len = 0xE4, +	.base = 0x1200, .len = 0x1dc,  	.features = BIT(DPU_CTL_ACTIVE_CFG),  	.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 10),  	},  	{  	.name = "ctl_2", .id = CTL_2, -	.base = 0x1400, .len = 0xE4, +	.base = 0x1400, .len = 0x1dc,  	.features = BIT(DPU_CTL_ACTIVE_CFG),  	.intr_start = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 11),  	}, @@ -1190,9 +1190,9 @@ static const struct dpu_sspp_cfg msm8998_sspp[] = {  	SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000,  DMA_MSM8998_MASK,  		sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),  	SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000,  DMA_CURSOR_MSM8998_MASK, -		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), +		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),  	SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000,  DMA_CURSOR_MSM8998_MASK, -		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),  };  static const struct dpu_sspp_cfg sdm845_sspp[] = { @@ -1209,9 +1209,9 @@ static const struct dpu_sspp_cfg sdm845_sspp[] = {  	SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000,  DMA_SDM845_MASK,  		sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),  	SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), +		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),  	SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),  };  static const struct dpu_sspp_sub_blks sc7180_vig_sblk_0 = @@ -1226,57 +1226,57 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = {  	SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000,  DMA_SDM845_MASK,  		sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),  	SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), +		sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),  	SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),  };  static const struct dpu_sspp_sub_blks sm6115_vig_sblk_0 = -				_VIG_SBLK("0", 2, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("0", 2, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_cfg sm6115_sspp[] = { -	SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK,  		sm6115_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),  	SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000,  DMA_SDM845_MASK,  		sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),  };  static const struct dpu_sspp_sub_blks sm8250_vig_sblk_0 = -				_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8250_vig_sblk_1 = -				_VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8250_vig_sblk_2 = -				_VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8250_vig_sblk_3 = -				_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_cfg sm8250_sspp[] = { -	SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK,  		sm8250_vig_sblk_0, 0,  SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), -	SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SC7180_MASK,  		sm8250_vig_sblk_1, 4,  SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), -	SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SC7180_MASK,  		sm8250_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), -	SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SC7180_MASK,  		sm8250_vig_sblk_3, 12,  SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),  	SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000,  DMA_SDM845_MASK,  		sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),  	SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000,  DMA_SDM845_MASK,  		sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),  	SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), +		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),  	SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),  };  static const struct dpu_sspp_sub_blks sm8450_vig_sblk_0 = -				_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8450_vig_sblk_1 = -				_VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8450_vig_sblk_2 = -				_VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8450_vig_sblk_3 = -				_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_cfg sm8450_sspp[] = {  	SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, @@ -1292,21 +1292,21 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = {  	SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000,  DMA_SDM845_MASK,  		sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),  	SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), +		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),  	SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),  };  static const struct dpu_sspp_sub_blks sm8550_vig_sblk_0 = -				_VIG_SBLK("0", 7, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("0", 7, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8550_vig_sblk_1 = -				_VIG_SBLK("1", 8, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("1", 8, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8550_vig_sblk_2 = -				_VIG_SBLK("2", 9, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("2", 9, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8550_vig_sblk_3 = -				_VIG_SBLK("3", 10, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("3", 10, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK("12", 5); -static const struct dpu_sspp_sub_blks sd8550_dma_sblk_5 = _DMA_SBLK("13", 6); +static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK("13", 6);  static const struct dpu_sspp_cfg sm8550_sspp[] = {  	SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK, @@ -1326,9 +1326,9 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = {  	SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000,  DMA_SDM845_MASK,  		sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),  	SSPP_BLK("sspp_12", SSPP_DMA4, 0x2c000,  DMA_CURSOR_SDM845_MASK, -		sm8550_dma_sblk_4, 14, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), +		sm8550_dma_sblk_4, 14, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA4),  	SSPP_BLK("sspp_13", SSPP_DMA5, 0x2e000,  DMA_CURSOR_SDM845_MASK, -		sd8550_dma_sblk_5, 15, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +		sm8550_dma_sblk_5, 15, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA5),  };  static const struct dpu_sspp_cfg sc7280_sspp[] = { @@ -1337,37 +1337,37 @@ static const struct dpu_sspp_cfg sc7280_sspp[] = {  	SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000,  DMA_SDM845_MASK,  		sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),  	SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), +		sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),  	SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000,  DMA_CURSOR_SDM845_MASK, -		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +		sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),  };  static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_0 = -				_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_1 = -				_VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_2 = -				_VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_sub_blks sc8280xp_vig_sblk_3 = -				_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3LITE); +				_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED4);  static const struct dpu_sspp_cfg sc8280xp_sspp[] = { -	SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SC7180_MASK,  		 sc8280xp_vig_sblk_0, 0,  SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0), -	SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SC7180_MASK,  		 sc8280xp_vig_sblk_1, 4,  SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1), -	SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SC7180_MASK,  		 sc8280xp_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2), -	SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SM8250_MASK, +	SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SC7180_MASK,  		 sc8280xp_vig_sblk_3, 12,  SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),  	SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,  		 sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),  	SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK,  		 sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),  	SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK, -		 sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0), +		 sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA2),  	SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK, -		 sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1), +		 sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA3),  };  #define _VIG_SBLK_NOSCALE(num, sdma_pri) \ @@ -1517,7 +1517,7 @@ static const struct dpu_lm_cfg sc7280_lm[] = {  /* QCM2290 */  static const struct dpu_lm_sub_blks qcm2290_lm_sblk = { -	.maxwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH, +	.maxwidth = DEFAULT_DPU_LINE_WIDTH,  	.maxblendstages = 4, /* excluding base layer */  	.blendstage_base = { /* offsets relative to mixer base */  		0x20, 0x38, 0x50, 0x68 @@ -1714,7 +1714,7 @@ static const struct dpu_pingpong_cfg sm8350_pp[] = {  };  static const struct dpu_pingpong_cfg sc7280_pp[] = { -	PP_BLK("pingpong_0", PINGPONG_0, 0x59000, 0, sc7280_pp_sblk, -1, -1), +	PP_BLK("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, -1, -1),  	PP_BLK("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1),  	PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),  	PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1), @@ -2841,8 +2841,6 @@ static const struct dpu_mdss_cfg qcm2290_dpu_cfg = {  	.intf = qcm2290_intf,  	.vbif_count = ARRAY_SIZE(sdm845_vbif),  	.vbif = sdm845_vbif, -	.reg_dma_count = 1, -	.dma_cfg = &sdm845_regdma,  	.perf = &qcm2290_perf_data,  	.mdss_irqs = IRQ_SC7180_MASK,  }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h index ddab9caebb18..e6590302b3bf 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h @@ -515,6 +515,8 @@ enum dpu_clk_ctrl_type {  	DPU_CLK_CTRL_DMA1,  	DPU_CLK_CTRL_DMA2,  	DPU_CLK_CTRL_DMA3, +	DPU_CLK_CTRL_DMA4, +	DPU_CLK_CTRL_DMA5,  	DPU_CLK_CTRL_CURSOR0,  	DPU_CLK_CTRL_CURSOR1,  	DPU_CLK_CTRL_INLINE_ROT0_SSPP, diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index b88a2f3724e6..6c53ea560ffa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -446,7 +446,9 @@ static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,  			 * CTL_LAYER has 3-bit field (and extra bits in EXT register),  			 * all EXT registers has 4-bit fields.  			 */ -			if (cfg->idx == 0) { +			if (cfg->idx == -1) { +				continue; +			} else if (cfg->idx == 0) {  				mixercfg[0] |= mix << cfg->shift;  				mixercfg[1] |= ext << cfg->ext_shift;  			} else { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c index 396429e63756..66c1b70d244f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c @@ -577,6 +577,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,  		ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);  	_dpu_rm_clear_mapping(global_state->dsc_to_enc_id,  		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id); +	_dpu_rm_clear_mapping(global_state->dspp_to_enc_id, +		ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);  }  int dpu_rm_reserve( diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c index 051bdbc093cf..f38296ad8743 100644 --- a/drivers/gpu/drm/msm/msm_gem_shrinker.c +++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c @@ -107,6 +107,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)  		bool (*shrink)(struct drm_gem_object *obj);  		bool cond;  		unsigned long freed; +		unsigned long remaining;  	} stages[] = {  		/* Stages of progressively more aggressive/expensive reclaim: */  		{ &priv->lru.dontneed, purge,        true }, @@ -116,14 +117,18 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)  	};  	long nr = sc->nr_to_scan;  	unsigned long freed = 0; +	unsigned long remaining = 0;  	for (unsigned i = 0; (nr > 0) && (i < ARRAY_SIZE(stages)); i++) {  		if (!stages[i].cond)  			continue;  		stages[i].freed = -			drm_gem_lru_scan(stages[i].lru, nr, stages[i].shrink); +			drm_gem_lru_scan(stages[i].lru, nr, +					&stages[i].remaining, +					 stages[i].shrink);  		nr -= stages[i].freed;  		freed += stages[i].freed; +		remaining += stages[i].remaining;  	}  	if (freed) { @@ -132,7 +137,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)  				     stages[3].freed);  	} -	return (freed > 0) ? freed : SHRINK_STOP; +	return (freed > 0 && remaining > 0) ? freed : SHRINK_STOP;  }  #ifdef CONFIG_DEBUG_FS @@ -182,10 +187,12 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr)  		NULL,  	};  	unsigned idx, unmapped = 0; +	unsigned long remaining = 0;  	for (idx = 0; lrus[idx] && unmapped < vmap_shrink_limit; idx++) {  		unmapped += drm_gem_lru_scan(lrus[idx],  					     vmap_shrink_limit - unmapped, +					     &remaining,  					     vmap_shrink);  	} diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index be4bf77103cd..ac8ed731f76d 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -637,8 +637,8 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,  	int ret = 0;  	uint32_t i, j; -	post_deps = kmalloc_array(nr_syncobjs, sizeof(*post_deps), -	                          GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); +	post_deps = kcalloc(nr_syncobjs, sizeof(*post_deps), +			    GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);  	if (!post_deps)  		return ERR_PTR(-ENOMEM); @@ -653,7 +653,6 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,  		}  		post_deps[i].point = syncobj_desc.point; -		post_deps[i].chain = NULL;  		if (syncobj_desc.flags) {  			ret = -EINVAL; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index ed9d374147b8..5bb777ff1313 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -363,6 +363,35 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,  	return 0;  } +static void +nv50_outp_atomic_fix_depth(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state) +{ +	struct nv50_head_atom *asyh = nv50_head_atom(crtc_state); +	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); +	struct drm_display_mode *mode = &asyh->state.adjusted_mode; +	unsigned int max_rate, mode_rate; + +	switch (nv_encoder->dcb->type) { +	case DCB_OUTPUT_DP: +		max_rate = nv_encoder->dp.link_nr * nv_encoder->dp.link_bw; + +		/* we don't support more than 10 anyway */ +		asyh->or.bpc = min_t(u8, asyh->or.bpc, 10); + +		/* reduce the bpc until it works out */ +		while (asyh->or.bpc > 6) { +			mode_rate = DIV_ROUND_UP(mode->clock * asyh->or.bpc * 3, 8); +			if (mode_rate <= max_rate) +				break; + +			asyh->or.bpc -= 2; +		} +		break; +	default: +		break; +	} +} +  static int  nv50_outp_atomic_check(struct drm_encoder *encoder,  		       struct drm_crtc_state *crtc_state, @@ -381,6 +410,9 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,  	if (crtc_state->mode_changed || crtc_state->connectors_changed)  		asyh->or.bpc = connector->display_info.bpc; +	/* We might have to reduce the bpc */ +	nv50_outp_atomic_fix_depth(encoder, crtc_state); +  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index 591c852f326b..76a6ae5d5652 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -35,8 +35,9 @@ struct nv50_wndw {  int nv50_wndw_new_(const struct nv50_wndw_func *, struct drm_device *,  		   enum drm_plane_type, const char *name, int index, -		   const u32 *format, enum nv50_disp_interlock_type, -		   u32 interlock_data, u32 heads, struct nv50_wndw **); +		   const u32 *format, u32 heads, +		   enum nv50_disp_interlock_type, u32 interlock_data, +		   struct nv50_wndw **);  void nv50_wndw_flush_set(struct nv50_wndw *, u32 *interlock,  			 struct nv50_wndw_atom *);  void nv50_wndw_flush_clr(struct nv50_wndw *, u32 *interlock, bool flush, diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h index c5a4f49ee206..01a22a13b452 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h @@ -2,6 +2,7 @@  #ifndef __NVKM_FB_H__  #define __NVKM_FB_H__  #include <core/subdev.h> +#include <core/falcon.h>  #include <core/mm.h>  /* memory type/access flags, do not match hardware values */ @@ -33,7 +34,7 @@ struct nvkm_fb {  	const struct nvkm_fb_func *func;  	struct nvkm_subdev subdev; -	struct nvkm_blob vpr_scrubber; +	struct nvkm_falcon_fw vpr_scrubber;  	struct {  		struct page *flush_page; diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 40409a29f5b6..91b5ecc57538 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -33,6 +33,7 @@  #include <linux/apple-gmux.h>  #include <linux/backlight.h>  #include <linux/idr.h> +#include <drm/drm_probe_helper.h>  #include "nouveau_drv.h"  #include "nouveau_reg.h" @@ -299,8 +300,12 @@ nv50_backlight_init(struct nouveau_backlight *bl,  	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);  	struct nvif_object *device = &drm->client.device.object; +	/* +	 * Note when this runs the connectors have not been probed yet, +	 * so nv_conn->base.status is not set yet. +	 */  	if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)) || -	    nv_conn->base.status != connector_status_connected) +	    drm_helper_probe_detect(&nv_conn->base, NULL, false) != connector_status_connected)  		return -ENODEV;  	if (nv_conn->type == DCB_CONNECTOR_eDP) { diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index e00876f92aee..d49b4875fc3c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -263,8 +263,6 @@ nouveau_dp_irq(struct work_struct *work)  }  /* TODO: - * - Use the minimum possible BPC here, once we add support for the max bpc - *   property.   * - Validate against the DP caps advertised by the GPU (we don't check these   *   yet)   */ @@ -276,7 +274,11 @@ nv50_dp_mode_valid(struct drm_connector *connector,  {  	const unsigned int min_clock = 25000;  	unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock; -	const u8 bpp = connector->display_info.bpc * 3; +	/* Check with the minmum bpc always, so we can advertise better modes. +	 * In particlar not doing this causes modes to be dropped on HDR +	 * displays as we might check with a bpc of 16 even. +	 */ +	const u8 bpp = 6 * 3;  	if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)  		return MODE_NO_INTERLACE; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index bac7dcc4c2c1..0955340cc421 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -143,6 +143,10 @@ nvkm_fb_mem_unlock(struct nvkm_fb *fb)  	if (!fb->func->vpr.scrub_required)  		return 0; +	ret = nvkm_subdev_oneinit(subdev); +	if (ret) +		return ret; +  	if (!fb->func->vpr.scrub_required(fb)) {  		nvkm_debug(subdev, "VPR not locked\n");  		return 0; @@ -150,7 +154,7 @@ nvkm_fb_mem_unlock(struct nvkm_fb *fb)  	nvkm_debug(subdev, "VPR locked, running scrubber binary\n"); -	if (!fb->vpr_scrubber.size) { +	if (!fb->vpr_scrubber.fw.img) {  		nvkm_warn(subdev, "VPR locked, but no scrubber binary!\n");  		return 0;  	} @@ -229,7 +233,7 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev)  	nvkm_ram_del(&fb->ram); -	nvkm_blob_dtor(&fb->vpr_scrubber); +	nvkm_falcon_fw_dtor(&fb->vpr_scrubber);  	if (fb->sysmem.flush_page) {  		dma_unmap_page(subdev->device->dev, fb->sysmem.flush_page_addr, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c index 5098f219e3e6..a7456e786463 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c @@ -37,5 +37,5 @@ ga100_fb = {  int  ga100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)  { -	return gp102_fb_new_(&ga100_fb, device, type, inst, pfb); +	return gf100_fb_new_(&ga100_fb, device, type, inst, pfb);  } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c index 5a21b0ae4595..dd476e079fe1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c @@ -25,25 +25,20 @@  #include <engine/nvdec.h>  static int -ga102_fb_vpr_scrub(struct nvkm_fb *fb) +ga102_fb_oneinit(struct nvkm_fb *fb)  { -	struct nvkm_falcon_fw fw = {}; -	int ret; +	struct nvkm_subdev *subdev = &fb->subdev; -	ret = nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", &fb->subdev, "nvdec/scrubber", -					0, &fb->subdev.device->nvdec[0]->falcon, &fw); -	if (ret) -		return ret; +	nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", subdev, "nvdec/scrubber", +				  0, &subdev->device->nvdec[0]->falcon, &fb->vpr_scrubber); -	ret = nvkm_falcon_fw_boot(&fw, &fb->subdev, true, NULL, NULL, 0, 0); -	nvkm_falcon_fw_dtor(&fw); -	return ret; +	return gf100_fb_oneinit(fb);  }  static const struct nvkm_fb_func  ga102_fb = {  	.dtor = gf100_fb_dtor, -	.oneinit = gf100_fb_oneinit, +	.oneinit = ga102_fb_oneinit,  	.init = gm200_fb_init,  	.init_page = gv100_fb_init_page,  	.init_unkn = gp100_fb_init_unkn, @@ -51,13 +46,13 @@ ga102_fb = {  	.ram_new = ga102_ram_new,  	.default_bigpage = 16,  	.vpr.scrub_required = tu102_fb_vpr_scrub_required, -	.vpr.scrub = ga102_fb_vpr_scrub, +	.vpr.scrub = gp102_fb_vpr_scrub,  };  int  ga102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)  { -	return gp102_fb_new_(&ga102_fb, device, type, inst, pfb); +	return gf100_fb_new_(&ga102_fb, device, type, inst, pfb);  }  MODULE_FIRMWARE("nvidia/ga102/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c index 76678dd60f93..c4c6f67af7cc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c @@ -31,6 +31,7 @@ gf108_fb = {  	.init = gf100_fb_init,  	.init_page = gf100_fb_init_page,  	.intr = gf100_fb_intr, +	.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,  	.ram_new = gf108_ram_new,  	.default_bigpage = 17,  }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c index f73442ccb424..433fa966ba23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c @@ -77,6 +77,7 @@ gk104_fb = {  	.init = gf100_fb_init,  	.init_page = gf100_fb_init_page,  	.intr = gf100_fb_intr, +	.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,  	.ram_new = gk104_ram_new,  	.default_bigpage = 17,  	.clkgate_pack = gk104_fb_clkgate_pack, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c index 45d6cdffafee..4dc283dedf8b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c @@ -59,6 +59,7 @@ gk110_fb = {  	.init = gf100_fb_init,  	.init_page = gf100_fb_init_page,  	.intr = gf100_fb_intr, +	.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,  	.ram_new = gk104_ram_new,  	.default_bigpage = 17,  	.clkgate_pack = gk110_fb_clkgate_pack, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c index de52462a92bf..90bfff616d35 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c @@ -31,6 +31,7 @@ gm107_fb = {  	.init = gf100_fb_init,  	.init_page = gf100_fb_init_page,  	.intr = gf100_fb_intr, +	.sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,  	.ram_new = gm107_ram_new,  	.default_bigpage = 17,  }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index 2658481d575b..14d942e8b857 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -29,18 +29,7 @@  int  gp102_fb_vpr_scrub(struct nvkm_fb *fb)  { -	struct nvkm_subdev *subdev = &fb->subdev; -	struct nvkm_falcon_fw fw = {}; -	int ret; - -	ret = nvkm_falcon_fw_ctor_hs(&gm200_flcn_fw, "mem-unlock", subdev, NULL, -				     "nvdec/scrubber", 0, &subdev->device->nvdec[0]->falcon, &fw); -	if (ret) -		return ret; - -	ret = nvkm_falcon_fw_boot(&fw, subdev, true, NULL, NULL, 0, 0x00000000); -	nvkm_falcon_fw_dtor(&fw); -	return ret; +	return nvkm_falcon_fw_boot(&fb->vpr_scrubber, &fb->subdev, true, NULL, NULL, 0, 0x00000000);  }  bool @@ -51,10 +40,21 @@ gp102_fb_vpr_scrub_required(struct nvkm_fb *fb)  	return (nvkm_rd32(device, 0x100cd0) & 0x00000010) != 0;  } +int +gp102_fb_oneinit(struct nvkm_fb *fb) +{ +	struct nvkm_subdev *subdev = &fb->subdev; + +	nvkm_falcon_fw_ctor_hs(&gm200_flcn_fw, "mem-unlock", subdev, NULL, "nvdec/scrubber", +			       0, &subdev->device->nvdec[0]->falcon, &fb->vpr_scrubber); + +	return gf100_fb_oneinit(fb); +} +  static const struct nvkm_fb_func  gp102_fb = {  	.dtor = gf100_fb_dtor, -	.oneinit = gf100_fb_oneinit, +	.oneinit = gp102_fb_oneinit,  	.init = gm200_fb_init,  	.init_remapper = gp100_fb_init_remapper,  	.init_page = gm200_fb_init_page, @@ -65,22 +65,9 @@ gp102_fb = {  };  int -gp102_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device, -	      enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb) -{ -	int ret = gf100_fb_new_(func, device, type, inst, pfb); -	if (ret) -		return ret; - -	nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0, -				&(*pfb)->vpr_scrubber); -	return 0; -} - -int  gp102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)  { -	return gp102_fb_new_(&gp102_fb, device, type, inst, pfb); +	return gf100_fb_new_(&gp102_fb, device, type, inst, pfb);  }  MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c index 0e3c0a8f5d71..4d8a286a7a34 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c @@ -31,7 +31,7 @@ gv100_fb_init_page(struct nvkm_fb *fb)  static const struct nvkm_fb_func  gv100_fb = {  	.dtor = gf100_fb_dtor, -	.oneinit = gf100_fb_oneinit, +	.oneinit = gp102_fb_oneinit,  	.init = gm200_fb_init,  	.init_page = gv100_fb_init_page,  	.init_unkn = gp100_fb_init_unkn, @@ -45,7 +45,7 @@ gv100_fb = {  int  gv100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)  { -	return gp102_fb_new_(&gv100_fb, device, type, inst, pfb); +	return gf100_fb_new_(&gv100_fb, device, type, inst, pfb);  }  MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index f517751f94ac..726c30c8bf95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -83,8 +83,7 @@ int gm200_fb_init_page(struct nvkm_fb *);  void gp100_fb_init_remapper(struct nvkm_fb *);  void gp100_fb_init_unkn(struct nvkm_fb *); -int gp102_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *, enum nvkm_subdev_type, int, -		  struct nvkm_fb **); +int gp102_fb_oneinit(struct nvkm_fb *);  bool gp102_fb_vpr_scrub_required(struct nvkm_fb *);  int gp102_fb_vpr_scrub(struct nvkm_fb *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c index be82af0364ee..b8803c124c3b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/tu102.c @@ -31,7 +31,7 @@ tu102_fb_vpr_scrub_required(struct nvkm_fb *fb)  static const struct nvkm_fb_func  tu102_fb = {  	.dtor = gf100_fb_dtor, -	.oneinit = gf100_fb_oneinit, +	.oneinit = gp102_fb_oneinit,  	.init = gm200_fb_init,  	.init_page = gv100_fb_init_page,  	.init_unkn = gp100_fb_init_unkn, @@ -45,7 +45,7 @@ tu102_fb = {  int  tu102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)  { -	return gp102_fb_new_(&tu102_fb, device, type, inst, pfb); +	return gf100_fb_new_(&tu102_fb, device, type, inst, pfb);  }  MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin"); diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 4e83a1891f3e..e961fa27702c 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -282,7 +282,7 @@ static void panfrost_mmu_flush_range(struct panfrost_device *pfdev,  	if (pm_runtime_active(pfdev->dev))  		mmu_hw_do_operation(pfdev, mmu, iova, size, AS_COMMAND_FLUSH_PT); -	pm_runtime_put_sync_autosuspend(pfdev->dev); +	pm_runtime_put_autosuspend(pfdev->dev);  }  static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, @@ -504,6 +504,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,  		if (IS_ERR(pages[i])) {  			mutex_unlock(&bo->base.pages_lock);  			ret = PTR_ERR(pages[i]); +			pages[i] = NULL;  			goto err_pages;  		}  	} diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 15d04a0ec623..e0a8890a62e2 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -507,12 +507,19 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)  {  	struct drm_sched_entity *entity = sched_job->entity;  	bool first; +	ktime_t submit_ts;  	trace_drm_sched_job(sched_job, entity);  	atomic_inc(entity->rq->sched->score);  	WRITE_ONCE(entity->last_user, current->group_leader); + +	/* +	 * After the sched_job is pushed into the entity queue, it may be +	 * completed and freed up at any time. We can no longer access it. +	 * Make sure to set the submit_ts first, to avoid a race. +	 */ +	sched_job->submit_ts = submit_ts = ktime_get();  	first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node); -	sched_job->submit_ts = ktime_get();  	/* first job wakes up scheduler */  	if (first) { @@ -529,7 +536,7 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)  		spin_unlock(&entity->rq_lock);  		if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) -			drm_sched_rq_update_fifo(entity, sched_job->submit_ts); +			drm_sched_rq_update_fifo(entity, submit_ts);  		drm_sched_wakeup(entity->rq->sched);  	} diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 4e6ad6e122bc..0e4378420271 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -906,12 +906,6 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched)  	spin_unlock(&sched->job_list_lock); -	if (job) { -		job->entity->elapsed_ns += ktime_to_ns( -			ktime_sub(job->s_fence->finished.timestamp, -				  job->s_fence->scheduled.timestamp)); -	} -  	return job;  } diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index cc94efbbf2d4..d6c741716167 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -95,12 +95,12 @@ static int sun4i_drv_bind(struct device *dev)  	/* drm_vblank_init calls kcalloc, which can fail */  	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);  	if (ret) -		goto cleanup_mode_config; +		goto unbind_all;  	/* Remove early framebuffers (ie. simplefb) */  	ret = drm_aperture_remove_framebuffers(false, &sun4i_drv_driver);  	if (ret) -		goto cleanup_mode_config; +		goto unbind_all;  	sun4i_framebuffer_init(drm); @@ -119,6 +119,8 @@ static int sun4i_drv_bind(struct device *dev)  finish_poll:  	drm_kms_helper_poll_fini(drm); +unbind_all: +	component_unbind_all(dev, NULL);  cleanup_mode_config:  	drm_mode_config_cleanup(drm);  	of_reserved_mem_device_release(dev); diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c index f8ee714df396..09ee6f6af896 100644 --- a/drivers/gpu/drm/tests/drm_buddy_test.c +++ b/drivers/gpu/drm/tests/drm_buddy_test.c @@ -89,7 +89,8 @@ static int check_block(struct kunit *test, struct drm_buddy *mm,  		err = -EINVAL;  	} -	if (!is_power_of_2(block_size)) { +	/* We can't use is_power_of_2() for a u64 on 32-bit systems. */ +	if (block_size & (block_size - 1)) {  		kunit_err(test, "block size not power of two\n");  		err = -EINVAL;  	} diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index cf35b6090503..accfa52e78c5 100644 --- a/drivers/gpu/drm/tiny/cirrus.c +++ b/drivers/gpu/drm/tiny/cirrus.c @@ -455,7 +455,7 @@ static void cirrus_pipe_update(struct drm_simple_display_pipe *pipe,  	if (state->fb && cirrus->cpp != cirrus_cpp(state->fb))  		cirrus_mode_set(cirrus, &crtc->mode, state->fb); -	if (drm_atomic_helper_damage_merged(old_state, state, &rect)) +	if (state->fb && drm_atomic_helper_damage_merged(old_state, state, &rect))  		cirrus_fb_blit_rect(state->fb, &shadow_plane_state->data[0], &rect);  } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 326a3d13a829..c286c6ffe07f 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -295,8 +295,6 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,  	if (unlock_resv)  		dma_resv_unlock(bo->base.resv); -	ttm_bo_put(bo); -  	return 0;  } diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index c7a1862f322a..ae2f19dc9f81 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -158,7 +158,7 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx,  			struct ttm_buffer_object *bo = res->bo;  			uint32_t num_pages; -			if (!bo) +			if (!bo || bo->resource != res)  				continue;  			num_pages = PFN_UP(bo->base.size); diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index a04a9b20896d..1778a2081fd6 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -604,7 +604,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,  	bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);  	if (virtio_gpu_is_shmem(bo) && use_dma_api) -		dma_sync_sgtable_for_device(&vgdev->vdev->dev, +		dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,  					    bo->base.sgt, DMA_TO_DEVICE);  	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); @@ -1026,7 +1026,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,  	bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);  	if (virtio_gpu_is_shmem(bo) && use_dma_api) -		dma_sync_sgtable_for_device(&vgdev->vdev->dev, +		dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,  					    bo->base.sgt, DMA_TO_DEVICE);  	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 4872d183d860..aae2efeef503 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -487,7 +487,6 @@ static int host1x_get_resets(struct host1x *host)  static int host1x_probe(struct platform_device *pdev)  {  	struct host1x *host; -	int syncpt_irq;  	int err;  	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); @@ -517,8 +516,8 @@ static int host1x_probe(struct platform_device *pdev)  	}  	host->syncpt_irq = platform_get_irq(pdev, 0); -	if (syncpt_irq < 0) -		return syncpt_irq; +	if (host->syncpt_irq < 0) +		return host->syncpt_irq;  	mutex_init(&host->devices_lock);  	INIT_LIST_HEAD(&host->devices); |