diff options
Diffstat (limited to 'drivers/gpu/drm/amd')
45 files changed, 684 insertions, 175 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, |