diff options
Diffstat (limited to 'drivers/gpu/drm')
61 files changed, 522 insertions, 279 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a2adaacf6adb..d3f220be2ef9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1139,6 +1139,9 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)  		}  	} +	if (!amdgpu_vm_ready(vm)) +		return -EINVAL; +  	r = amdgpu_vm_clear_freed(adev, vm, NULL);  	if (r)  		return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c index 02138aa55793..dfb6cfd83760 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c @@ -88,8 +88,8 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm,  	}  	r = amdgpu_vm_bo_map(adev, *bo_va, csa_addr, 0, size, -			     AMDGPU_PTE_READABLE | AMDGPU_PTE_WRITEABLE | -			     AMDGPU_PTE_EXECUTABLE); +			     AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE | +			     AMDGPU_VM_PAGE_EXECUTABLE);  	if (r) {  		DRM_ERROR("failed to do bo_map on static CSA, err=%d\n", r); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index ff98c87b2e0b..5743ebb2f1b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -514,7 +514,7 @@ bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev,  		return false;  	if (drm_gem_is_imported(obj)) { -		struct dma_buf *dma_buf = obj->dma_buf; +		struct dma_buf *dma_buf = obj->import_attach->dmabuf;  		if (dma_buf->ops != &amdgpu_dmabuf_ops)  			/* No XGMI with non AMD GPUs */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 6626a6e64ff5..d1ccbfcf21fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -317,7 +317,8 @@ static int amdgpu_gem_object_open(struct drm_gem_object *obj,  	 */  	if (!vm->is_compute_context || !vm->process_info)  		return 0; -	if (!drm_gem_is_imported(obj) || !dma_buf_is_dynamic(obj->dma_buf)) +	if (!drm_gem_is_imported(obj) || +	    !dma_buf_is_dynamic(obj->import_attach->dmabuf))  		return 0;  	mutex_lock_nested(&vm->process_info->lock, 1);  	if (!WARN_ON(!vm->process_info->eviction_fence)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 0bd51a04be79..23484317a5fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1039,15 +1039,28 @@ int psp_update_fw_reservation(struct psp_context *psp)  {  	int ret;  	uint64_t reserv_addr, reserv_addr_ext; -	uint32_t reserv_size, reserv_size_ext; +	uint32_t reserv_size, reserv_size_ext, mp0_ip_ver;  	struct amdgpu_device *adev = psp->adev; +	mp0_ip_ver = amdgpu_ip_version(adev, MP0_HWIP, 0); +  	if (amdgpu_sriov_vf(psp->adev))  		return 0; -	if ((amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(14, 0, 2)) && -	    (amdgpu_ip_version(adev, MP0_HWIP, 0) != IP_VERSION(14, 0, 3))) +	switch (mp0_ip_ver) { +	case IP_VERSION(14, 0, 2): +		if (adev->psp.sos.fw_version < 0x3b0e0d) +			return 0; +		break; + +	case IP_VERSION(14, 0, 3): +		if (adev->psp.sos.fw_version < 0x3a0e14) +			return 0; +		break; + +	default:  		return 0; +	}  	ret = psp_get_fw_reservation_info(psp, GFX_CMD_ID_FB_FW_RESERV_ADDR, &reserv_addr, &reserv_size);  	if (ret) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 5cacf5717016..c39bb06ebda1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -654,11 +654,10 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,   * Check if all VM PDs/PTs are ready for updates   *   * Returns: - * True if VM is not evicting. + * True if VM is not evicting and all VM entities are not stopped   */  bool amdgpu_vm_ready(struct amdgpu_vm *vm)  { -	bool empty;  	bool ret;  	amdgpu_vm_eviction_lock(vm); @@ -666,10 +665,18 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm)  	amdgpu_vm_eviction_unlock(vm);  	spin_lock(&vm->status_lock); -	empty = list_empty(&vm->evicted); +	ret &= list_empty(&vm->evicted);  	spin_unlock(&vm->status_lock); -	return ret && empty; +	spin_lock(&vm->immediate.lock); +	ret &= !vm->immediate.stopped; +	spin_unlock(&vm->immediate.lock); + +	spin_lock(&vm->delayed.lock); +	ret &= !vm->delayed.stopped; +	spin_unlock(&vm->delayed.lock); + +	return ret;  }  /** @@ -1276,7 +1283,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,  		struct drm_gem_object *obj = &bo->tbo.base;  		if (drm_gem_is_imported(obj) && bo_va->is_xgmi) { -			struct dma_buf *dma_buf = obj->dma_buf; +			struct dma_buf *dma_buf = obj->import_attach->dmabuf;  			struct drm_gem_object *gobj = dma_buf->priv;  			struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 07c936e90d8e..78f9e86ccc09 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -648,9 +648,8 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,  	list_for_each_entry(block, &vres->blocks, link)  		vis_usage += amdgpu_vram_mgr_vis_size(adev, block); -	amdgpu_vram_mgr_do_reserve(man); -  	drm_buddy_free_list(mm, &vres->blocks, vres->flags); +	amdgpu_vram_mgr_do_reserve(man);  	mutex_unlock(&mgr->lock);  	atomic64_sub(vis_usage, &mgr->vis_usage); 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 cd0e2976e268..a0ca3b2c6bd8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7792,6 +7792,9 @@ amdgpu_dm_connector_atomic_check(struct drm_connector *conn,  	struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn);  	int ret; +	if (WARN_ON(unlikely(!old_con_state || !new_con_state))) +		return -EINVAL; +  	trace_amdgpu_dm_connector_atomic_check(new_con_state);  	if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 010172f930ae..45feb404b097 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -299,6 +299,25 @@ static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)  	irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id);  	if (enable) { +		struct dc *dc = adev->dm.dc; +		struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); +		struct psr_settings *psr = &acrtc_state->stream->link->psr_settings; +		struct replay_settings *pr = &acrtc_state->stream->link->replay_settings; +		bool sr_supported = (psr->psr_version != DC_PSR_VERSION_UNSUPPORTED) || +								pr->config.replay_supported; + +		/* +		 * IPS & self-refresh feature can cause vblank counter resets between +		 * vblank disable and enable. +		 * It may cause system stuck due to waiting for the vblank counter. +		 * Call this function to estimate missed vblanks by using timestamps and +		 * update the vblank counter in DRM. +		 */ +		if (dc->caps.ips_support && +			dc->config.disable_ips != DMUB_IPS_DISABLE_ALL && +			sr_supported && vblank->config.disable_immediate) +			drm_crtc_vblank_restore(crtc); +  		/* vblank irq on -> Only need vupdate irq in vrr mode */  		if (amdgpu_dm_crtc_vrr_active(acrtc_state))  			rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true); diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 67f08495b7e6..154fd2c18e88 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -174,11 +174,8 @@ static struct graphics_object_id bios_parser_get_connector_id(  		return object_id;  	} -	if (tbl->ucNumberOfObjects <= i) { -		dm_error("Can't find connector id %d in connector table of size %d.\n", -			 i, tbl->ucNumberOfObjects); +	if (tbl->ucNumberOfObjects <= i)  		return object_id; -	}  	id = le16_to_cpu(tbl->asObjects[i].usObjectID);  	object_id = object_id_from_bios_object_id(id); diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 2bcae0643e61..58e88778da7f 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -993,7 +993,7 @@ static enum bp_result set_pixel_clock_v3(  	allocation.sPCLKInput.usFbDiv =  			cpu_to_le16((uint16_t)bp_params->feedback_divider);  	allocation.sPCLKInput.ucFracFbDiv = -			(uint8_t)bp_params->fractional_feedback_divider; +			(uint8_t)(bp_params->fractional_feedback_divider / 100000);  	allocation.sPCLKInput.ucPostDiv =  			(uint8_t)bp_params->pixel_clock_post_divider; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c index f5ad0a177038..dbd6ef1b60a0 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c @@ -72,9 +72,9 @@ static const struct state_dependent_clocks dce80_max_clks_by_state[] = {  /* ClocksStateLow */  { .display_clk_khz = 352000, .pixel_clk_khz = 330000},  /* ClocksStateNominal */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, +{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 },  /* ClocksStatePerformance */ -{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; +{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 } };  int dentist_get_divider_from_did(int did)  { @@ -391,8 +391,6 @@ static void dce_pplib_apply_display_requirements(  {  	struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; -	pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); -  	dce110_fill_display_configs(context, pp_display_cfg);  	if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) !=  0) @@ -405,11 +403,9 @@ static void dce_update_clocks(struct clk_mgr *clk_mgr_base,  {  	struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base);  	struct dm_pp_power_level_change_request level_change_req; -	int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; - -	/*TODO: W/A for dal3 linux, investigate why this works */ -	if (!clk_mgr_dce->dfs_bypass_active) -		patched_disp_clk = patched_disp_clk * 115 / 100; +	const int max_disp_clk = +		clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; +	int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz);  	level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context);  	/* get max clock state from PPLIB */ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c index f8409453434c..13cf415e38e5 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c @@ -120,9 +120,15 @@ void dce110_fill_display_configs(  	const struct dc_state *context,  	struct dm_pp_display_configuration *pp_display_cfg)  { +	struct dc *dc = context->clk_mgr->ctx->dc;  	int j;  	int num_cfgs = 0; +	pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); +	pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz; +	pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; +	pp_display_cfg->crtc_index = dc->res_pool->res_cap->num_timing_generator; +  	for (j = 0; j < context->stream_count; j++) {  		int k; @@ -164,6 +170,23 @@ void dce110_fill_display_configs(  		cfg->v_refresh /= stream->timing.h_total;  		cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2)  							/ stream->timing.v_total; + +		/* Find first CRTC index and calculate its line time. +		 * This is necessary for DPM on SI GPUs. +		 */ +		if (cfg->pipe_idx < pp_display_cfg->crtc_index) { +			const struct dc_crtc_timing *timing = +				&context->streams[0]->timing; + +			pp_display_cfg->crtc_index = cfg->pipe_idx; +			pp_display_cfg->line_time_in_us = +				timing->h_total * 10000 / timing->pix_clk_100hz; +		} +	} + +	if (!num_cfgs) { +		pp_display_cfg->crtc_index = 0; +		pp_display_cfg->line_time_in_us = 0;  	}  	pp_display_cfg->display_count = num_cfgs; @@ -223,25 +246,8 @@ void dce11_pplib_apply_display_requirements(  	pp_display_cfg->min_engine_clock_deep_sleep_khz  			= context->bw_ctx.bw.dce.sclk_deep_sleep_khz; -	pp_display_cfg->avail_mclk_switch_time_us = -						dce110_get_min_vblank_time_us(context); -	/* TODO: dce11.2*/ -	pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; - -	pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz; -  	dce110_fill_display_configs(context, pp_display_cfg); -	/* TODO: is this still applicable?*/ -	if (pp_display_cfg->display_count == 1) { -		const struct dc_crtc_timing *timing = -			&context->streams[0]->timing; - -		pp_display_cfg->crtc_index = -			pp_display_cfg->disp_configs[0].pipe_idx; -		pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz; -	} -  	if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) !=  0)  		dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);  } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c index 0267644717b2..a39641a0ff09 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c @@ -83,22 +83,13 @@ static const struct state_dependent_clocks dce60_max_clks_by_state[] = {  static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base)  {  	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); -	int dprefclk_wdivider; -	int dp_ref_clk_khz; -	int target_div; +	struct dc_context *ctx = clk_mgr_base->ctx; +	int dp_ref_clk_khz = 0; -	/* DCE6 has no DPREFCLK_CNTL to read DP Reference Clock source */ - -	/* Read the mmDENTIST_DISPCLK_CNTL to get the currently -	 * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ -	REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); - -	/* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ -	target_div = dentist_get_divider_from_did(dprefclk_wdivider); - -	/* Calculate the current DFS clock, in kHz.*/ -	dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR -		* clk_mgr->base.dentist_vco_freq_khz) / target_div; +	if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev)) +		dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency; +	else +		dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz;  	return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz);  } @@ -109,8 +100,6 @@ static void dce60_pplib_apply_display_requirements(  {  	struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; -	pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); -  	dce110_fill_display_configs(context, pp_display_cfg);  	if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) !=  0) @@ -123,11 +112,9 @@ static void dce60_update_clocks(struct clk_mgr *clk_mgr_base,  {  	struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base);  	struct dm_pp_power_level_change_request level_change_req; -	int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; - -	/*TODO: W/A for dal3 linux, investigate why this works */ -	if (!clk_mgr_dce->dfs_bypass_active) -		patched_disp_clk = patched_disp_clk * 115 / 100; +	const int max_disp_clk = +		clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; +	int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz);  	level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context);  	/* get max clock state from PPLIB */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9ab0ee20ca6f..dcc48b5238e5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -217,11 +217,24 @@ static bool create_links(  		connectors_num,  		num_virtual_links); -	// condition loop on link_count to allow skipping invalid indices +	/* When getting the number of connectors, the VBIOS reports the number of valid indices, +	 * but it doesn't say which indices are valid, and not every index has an actual connector. +	 * So, if we don't find a connector on an index, that is not an error. +	 * +	 * - There is no guarantee that the first N indices will be valid +	 * - VBIOS may report a higher amount of valid indices than there are actual connectors +	 * - Some VBIOS have valid configurations for more connectors than there actually are +	 *   on the card. This may be because the manufacturer used the same VBIOS for different +	 *   variants of the same card. +	 */  	for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) { +		struct graphics_object_id connector_id = bios->funcs->get_connector_id(bios, i);  		struct link_init_data link_init_params = {0};  		struct dc_link *link; +		if (connector_id.id == CONNECTOR_ID_UNKNOWN) +			continue; +  		DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count);  		link_init_params.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index 4a9d07c31bc5..0c50fe266c8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -896,13 +896,13 @@ void dce110_link_encoder_construct(  						enc110->base.id, &bp_cap_info);  	/* Override features with DCE-specific values */ -	if (BP_RESULT_OK == result) { +	if (result == BP_RESULT_OK) {  		enc110->base.features.flags.bits.IS_HBR2_CAPABLE =  				bp_cap_info.DP_HBR2_EN;  		enc110->base.features.flags.bits.IS_HBR3_CAPABLE =  				bp_cap_info.DP_HBR3_EN;  		enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; -	} else { +	} else if (result != BP_RESULT_NORECORD) {  		DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",  				__func__,  				result); @@ -1798,13 +1798,13 @@ void dce60_link_encoder_construct(  						enc110->base.id, &bp_cap_info);  	/* Override features with DCE-specific values */ -	if (BP_RESULT_OK == result) { +	if (result == BP_RESULT_OK) {  		enc110->base.features.flags.bits.IS_HBR2_CAPABLE =  				bp_cap_info.DP_HBR2_EN;  		enc110->base.features.flags.bits.IS_HBR3_CAPABLE =  				bp_cap_info.DP_HBR3_EN;  		enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; -	} else { +	} else if (result != BP_RESULT_NORECORD) {  		DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",  				__func__,  				result); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c index e7a318e26d38..fcd3d86ad517 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c @@ -4,7 +4,6 @@  #include "dc.h"  #include "dc_dmub_srv.h" -#include "dc_dp_types.h"  #include "dmub/dmub_srv.h"  #include "core_types.h"  #include "dmub_replay.h" @@ -44,45 +43,21 @@ static void dmub_replay_get_state(struct dmub_replay *dmub, enum replay_state *s  /*   * Enable/Disable Replay.   */ -static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait, uint8_t panel_inst, -			       struct dc_link *link) +static void dmub_replay_enable(struct dmub_replay *dmub, bool enable, bool wait, uint8_t panel_inst)  {  	union dmub_rb_cmd cmd;  	struct dc_context *dc = dmub->ctx;  	uint32_t retry_count;  	enum replay_state state = REPLAY_STATE_0; -	struct pipe_ctx *pipe_ctx = NULL; -	struct resource_context *res_ctx = &link->ctx->dc->current_state->res_ctx; -	uint8_t i;  	memset(&cmd, 0, sizeof(cmd));  	cmd.replay_enable.header.type = DMUB_CMD__REPLAY;  	cmd.replay_enable.data.panel_inst = panel_inst;  	cmd.replay_enable.header.sub_type = DMUB_CMD__REPLAY_ENABLE; -	if (enable) { +	if (enable)  		cmd.replay_enable.data.enable = REPLAY_ENABLE; -		// hpo stream/link encoder assignments are not static, need to update everytime we try to enable replay -		if (link->cur_link_settings.link_rate >= LINK_RATE_UHBR10) { -			for (i = 0; i < MAX_PIPES; i++) { -				if (res_ctx && -					res_ctx->pipe_ctx[i].stream && -					res_ctx->pipe_ctx[i].stream->link && -					res_ctx->pipe_ctx[i].stream->link == link && -					res_ctx->pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { -					pipe_ctx = &res_ctx->pipe_ctx[i]; -					//TODO: refactor for multi edp support -					break; -				} -			} - -			if (!pipe_ctx) -				return; - -			cmd.replay_enable.data.hpo_stream_enc_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; -			cmd.replay_enable.data.hpo_link_enc_inst = pipe_ctx->link_res.hpo_dp_link_enc->inst; -		} -	} else +	else  		cmd.replay_enable.data.enable = REPLAY_DISABLE;  	cmd.replay_enable.header.payload_bytes = sizeof(struct dmub_rb_cmd_replay_enable_data); @@ -174,17 +149,6 @@ static bool dmub_replay_copy_settings(struct dmub_replay *dmub,  	copy_settings_data->digbe_inst				= replay_context->digbe_inst;  	copy_settings_data->digfe_inst				= replay_context->digfe_inst; -	if (link->cur_link_settings.link_rate >= LINK_RATE_UHBR10) { -		if (pipe_ctx->stream_res.hpo_dp_stream_enc) -			copy_settings_data->hpo_stream_enc_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; -		else -			copy_settings_data->hpo_stream_enc_inst = 0; -		if (pipe_ctx->link_res.hpo_dp_link_enc) -			copy_settings_data->hpo_link_enc_inst = pipe_ctx->link_res.hpo_dp_link_enc->inst; -		else -			copy_settings_data->hpo_link_enc_inst = 0; -	} -  	if (pipe_ctx->plane_res.dpp)  		copy_settings_data->dpp_inst			= pipe_ctx->plane_res.dpp->inst;  	else @@ -247,7 +211,6 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,  	pCmd->header.type = DMUB_CMD__REPLAY;  	pCmd->header.sub_type = DMUB_CMD__REPLAY_SET_COASTING_VTOTAL;  	pCmd->header.payload_bytes = sizeof(struct dmub_cmd_replay_set_coasting_vtotal_data); -	pCmd->replay_set_coasting_vtotal_data.panel_inst = panel_inst;  	pCmd->replay_set_coasting_vtotal_data.coasting_vtotal = (coasting_vtotal & 0xFFFF);  	pCmd->replay_set_coasting_vtotal_data.coasting_vtotal_high = (coasting_vtotal & 0xFFFF0000) >> 16; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h index ccbe385e132c..e6346c0ffc0e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.h @@ -19,7 +19,7 @@ struct dmub_replay_funcs {  	void (*replay_get_state)(struct dmub_replay *dmub, enum replay_state *state,  		uint8_t panel_inst);  	void (*replay_enable)(struct dmub_replay *dmub, bool enable, bool wait, -		uint8_t panel_inst, struct dc_link *link); +		uint8_t panel_inst);  	bool (*replay_copy_settings)(struct dmub_replay *dmub, struct dc_link *link,  		struct replay_context *replay_context, uint8_t panel_inst);  	void (*replay_set_power_opt)(struct dmub_replay *dmub, unsigned int power_opt, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index e7927b8f5ba3..98ec9b5a559c 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -944,7 +944,7 @@ bool edp_set_replay_allow_active(struct dc_link *link, const bool *allow_active,  		// TODO: Handle mux change case if force_static is set  		// If force_static is set, just change the replay_allow_active state directly  		if (replay != NULL && link->replay_settings.replay_feature_enabled) -			replay->funcs->replay_enable(replay, *allow_active, wait, panel_inst, link); +			replay->funcs->replay_enable(replay, *allow_active, wait, panel_inst);  		link->replay_settings.replay_allow_active = *allow_active;  	} diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index c587b3441e07..6a69a788abe8 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -4048,14 +4048,6 @@ struct dmub_cmd_replay_copy_settings_data {  	 */  	uint8_t digbe_inst;  	/** -	 * @hpo_stream_enc_inst: HPO stream encoder instance -	 */ -	uint8_t hpo_stream_enc_inst; -	/** -	 * @hpo_link_enc_inst: HPO link encoder instance -	 */ -	uint8_t hpo_link_enc_inst; -	/**  	 * AUX HW instance.  	 */  	uint8_t aux_inst; @@ -4159,18 +4151,6 @@ struct dmub_rb_cmd_replay_enable_data {  	 * This does not support HDMI/DP2 for now.  	 */  	uint8_t phy_rate; -	/** -	 * @hpo_stream_enc_inst: HPO stream encoder instance -	 */ -	uint8_t hpo_stream_enc_inst; -	/** -	 * @hpo_link_enc_inst: HPO link encoder instance -	 */ -	uint8_t hpo_link_enc_inst; -	/** -	 * @pad: Align structure to 4 byte boundary. -	 */ -	uint8_t pad[2];  };  /** diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index e58e7b93810b..6b7db8ec9a53 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -260,6 +260,9 @@ enum mod_hdcp_status mod_hdcp_hdcp1_create_session(struct mod_hdcp *hdcp)  		return MOD_HDCP_STATUS_FAILURE;  	} +	if (!display) +		return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; +  	hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;  	mutex_lock(&psp->hdcp_context.mutex); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c index 3aea32baea3d..f32474af90b3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -1697,9 +1697,11 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,  				       uint32_t *min_power_limit)  {  	struct smu_table_context *table_context = &smu->smu_table; +	struct smu_14_0_2_powerplay_table *powerplay_table = +		table_context->power_play_table;  	PPTable_t *pptable = table_context->driver_pptable;  	CustomSkuTable_t *skutable = &pptable->CustomSkuTable; -	uint32_t power_limit; +	uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;  	uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];  	if (smu_v14_0_get_current_power_limit(smu, &power_limit)) @@ -1712,11 +1714,29 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,  	if (default_power_limit)  		*default_power_limit = power_limit; -	if (max_power_limit) -		*max_power_limit = msg_limit; +	if (powerplay_table) { +		if (smu->od_enabled && +		    smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { +			od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt; +			od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; +		} else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { +			od_percent_upper = 0; +			od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; +		} +	} + +	dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n", +					od_percent_upper, od_percent_lower, power_limit); + +	if (max_power_limit) { +		*max_power_limit = msg_limit * (100 + od_percent_upper); +		*max_power_limit /= 100; +	} -	if (min_power_limit) -		*min_power_limit = 0; +	if (min_power_limit) { +		*min_power_limit = power_limit * (100 + od_percent_lower); +		*min_power_limit /= 100; +	}  	return 0;  } diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index ed35e567d117..efe534977d12 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1474,8 +1474,8 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)  	dp = devm_drm_bridge_alloc(dev, struct analogix_dp_device, bridge,  				   &analogix_dp_bridge_funcs); -	if (!dp) -		return ERR_PTR(-ENOMEM); +	if (IS_ERR(dp)) +		return ERR_CAST(dp);  	dp->dev = &pdev->dev;  	dp->dpms_mode = DRM_MODE_DPMS_OFF; diff --git a/drivers/gpu/drm/bridge/aux-bridge.c b/drivers/gpu/drm/bridge/aux-bridge.c index b63304d3a80f..b3e4cdff61d6 100644 --- a/drivers/gpu/drm/bridge/aux-bridge.c +++ b/drivers/gpu/drm/bridge/aux-bridge.c @@ -18,6 +18,7 @@ static void drm_aux_bridge_release(struct device *dev)  {  	struct auxiliary_device *adev = to_auxiliary_dev(dev); +	of_node_put(dev->of_node);  	ida_free(&drm_aux_bridge_ida, adev->id);  	kfree(adev); @@ -65,6 +66,7 @@ int drm_aux_bridge_register(struct device *parent)  	ret = auxiliary_device_init(adev);  	if (ret) { +		of_node_put(adev->dev.of_node);  		ida_free(&drm_aux_bridge_ida, adev->id);  		kfree(adev);  		return ret; diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index dd45d9b504d8..4bde00083047 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -1227,6 +1227,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_check);  /**   * drm_bridge_detect - check if anything is attached to the bridge output   * @bridge: bridge control structure + * @connector: attached connector   *   * If the bridge supports output detection, as reported by the   * DRM_BRIDGE_OP_DETECT bridge ops flag, call &drm_bridge_funcs.detect for the diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c index bbc7fecb6f4a..74d949995a72 100644 --- a/drivers/gpu/drm/drm_gpuvm.c +++ b/drivers/gpu/drm/drm_gpuvm.c @@ -2432,6 +2432,8 @@ static const struct drm_gpuvm_ops lock_ops = {   *   * The expected usage is:   * + * .. code-block:: c + *   *    vm_bind {   *        struct drm_exec exec;   * diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs index 09a9b452e8b7..50c286c5cee8 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs @@ -381,6 +381,26 @@ struct DecFifo {      len: usize,  } +// On arm32 architecture, dividing an `u64` by a constant will generate a call +// to `__aeabi_uldivmod` which is not present in the kernel. +// So use the multiply by inverse method for this architecture. +fn div10(val: u64) -> u64 { +    if cfg!(target_arch = "arm") { +        let val_h = val >> 32; +        let val_l = val & 0xFFFFFFFF; +        let b_h: u64 = 0x66666666; +        let b_l: u64 = 0x66666667; + +        let tmp1 = val_h * b_l + ((val_l * b_l) >> 32); +        let tmp2 = val_l * b_h + (tmp1 & 0xffffffff); +        let tmp3 = val_h * b_h + (tmp1 >> 32) + (tmp2 >> 32); + +        tmp3 >> 2 +    } else { +        val / 10 +    } +} +  impl DecFifo {      fn push(&mut self, data: u64, len: usize) {          let mut chunk = data; @@ -389,7 +409,7 @@ impl DecFifo {          }          for i in 0..len {              self.decimals[i] = (chunk % 10) as u8; -            chunk /= 10; +            chunk = div10(chunk);          }          self.len += len;      } diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c index 74f7832ea53e..0726cb5b736e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c @@ -325,6 +325,17 @@ static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp)  	return hibmc_dp_link_reduce_rate(dp);  } +static void hibmc_dp_update_caps(struct hibmc_dp_dev *dp) +{ +	dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; +	if (dp->link.cap.link_rate > DP_LINK_BW_8_1 || !dp->link.cap.link_rate) +		dp->link.cap.link_rate = DP_LINK_BW_8_1; + +	dp->link.cap.lanes = dp->dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; +	if (dp->link.cap.lanes > HIBMC_DP_LANE_NUM_MAX) +		dp->link.cap.lanes = HIBMC_DP_LANE_NUM_MAX; +} +  int hibmc_dp_link_training(struct hibmc_dp_dev *dp)  {  	struct hibmc_dp_link *link = &dp->link; @@ -334,8 +345,7 @@ int hibmc_dp_link_training(struct hibmc_dp_dev *dp)  	if (ret)  		drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret); -	dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; -	dp->link.cap.lanes = 0x2; +	hibmc_dp_update_caps(dp);  	ret = hibmc_dp_get_serdes_rate_cfg(dp);  	if (ret < 0) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 768b97f9e74a..289304500ab0 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -32,7 +32,7 @@  DEFINE_DRM_GEM_FOPS(hibmc_fops); -static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "vblank", "hpd" }; +static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "hibmc-vblank", "hibmc-hpd" };  static irqreturn_t hibmc_interrupt(int irq, void *arg)  { @@ -115,6 +115,8 @@ static const struct drm_mode_config_funcs hibmc_mode_funcs = {  static int hibmc_kms_init(struct hibmc_drm_private *priv)  {  	struct drm_device *dev = &priv->dev; +	struct drm_encoder *encoder; +	u32 clone_mask = 0;  	int ret;  	ret = drmm_mode_config_init(dev); @@ -154,6 +156,12 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv)  		return ret;  	} +	drm_for_each_encoder(encoder, dev) +		clone_mask |= drm_encoder_mask(encoder); + +	drm_for_each_encoder(encoder, dev) +		encoder->possible_clones = clone_mask; +  	return 0;  } @@ -277,7 +285,6 @@ static void hibmc_unload(struct drm_device *dev)  static int hibmc_msi_init(struct drm_device *dev)  {  	struct pci_dev *pdev = to_pci_dev(dev->dev); -	char name[32] = {0};  	int valid_irq_num;  	int irq;  	int ret; @@ -292,9 +299,6 @@ static int hibmc_msi_init(struct drm_device *dev)  	valid_irq_num = ret;  	for (int i = 0; i < valid_irq_num; i++) { -		snprintf(name, ARRAY_SIZE(name) - 1, "%s-%s-%s", -			 dev->driver->name, pci_name(pdev), g_irqs_names_map[i]); -  		irq = pci_irq_vector(pdev, i);  		if (i) @@ -302,10 +306,10 @@ static int hibmc_msi_init(struct drm_device *dev)  			ret = devm_request_threaded_irq(&pdev->dev, irq,  							hibmc_dp_interrupt,  							hibmc_dp_hpd_isr, -							IRQF_SHARED, name, dev); +							IRQF_SHARED, g_irqs_names_map[i], dev);  		else  			ret = devm_request_irq(&pdev->dev, irq, hibmc_interrupt, -					       IRQF_SHARED, name, dev); +					       IRQF_SHARED, g_irqs_names_map[i], dev);  		if (ret) {  			drm_err(dev, "install irq failed: %d\n", ret);  			return ret; @@ -323,13 +327,13 @@ static int hibmc_load(struct drm_device *dev)  	ret = hibmc_hw_init(priv);  	if (ret) -		goto err; +		return ret;  	ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0),  				    pci_resource_len(pdev, 0));  	if (ret) {  		drm_err(dev, "Error initializing VRAM MM; %d\n", ret); -		goto err; +		return ret;  	}  	ret = hibmc_kms_init(priv); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index 274feabe7df0..ca8502e2760c 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -69,6 +69,7 @@ int hibmc_de_init(struct hibmc_drm_private *priv);  int hibmc_vdac_init(struct hibmc_drm_private *priv);  int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *connector); +void hibmc_ddc_del(struct hibmc_vdac *vdac);  int hibmc_dp_init(struct hibmc_drm_private *priv); diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c index 99b3b77b5445..44860011855e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c @@ -95,3 +95,8 @@ int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *vdac)  	return i2c_bit_add_bus(&vdac->adapter);  } + +void hibmc_ddc_del(struct hibmc_vdac *vdac) +{ +	i2c_del_adapter(&vdac->adapter); +} diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index e8a527ede854..841e81f47b68 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -53,7 +53,7 @@ static void hibmc_connector_destroy(struct drm_connector *connector)  {  	struct hibmc_vdac *vdac = to_hibmc_vdac(connector); -	i2c_del_adapter(&vdac->adapter); +	hibmc_ddc_del(vdac);  	drm_connector_cleanup(connector);  } @@ -110,7 +110,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)  	ret = drmm_encoder_init(dev, encoder, NULL, DRM_MODE_ENCODER_DAC, NULL);  	if (ret) {  		drm_err(dev, "failed to init encoder: %d\n", ret); -		return ret; +		goto err;  	}  	drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); @@ -121,7 +121,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)  					  &vdac->adapter);  	if (ret) {  		drm_err(dev, "failed to init connector: %d\n", ret); -		return ret; +		goto err;  	}  	drm_connector_helper_add(connector, &hibmc_connector_helper_funcs); @@ -131,4 +131,9 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)  	connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;  	return 0; + +err: +	hibmc_ddc_del(vdac); + +	return ret;  } diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index fb25ec8adae3..68157f177b6a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -1506,10 +1506,14 @@ u32 gen11_gu_misc_irq_ack(struct intel_display *display, const u32 master_ctl)  	if (!(master_ctl & GEN11_GU_MISC_IRQ))  		return 0; +	intel_display_rpm_assert_block(display); +  	iir = intel_de_read(display, GEN11_GU_MISC_IIR);  	if (likely(iir))  		intel_de_write(display, GEN11_GU_MISC_IIR, iir); +	intel_display_rpm_assert_unblock(display); +  	return iir;  } diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 6e26cb4c5724..685ac98bd001 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -552,10 +552,6 @@ static void ilk_fbc_deactivate(struct intel_fbc *fbc)  	if (dpfc_ctl & DPFC_CTL_EN) {  		dpfc_ctl &= ~DPFC_CTL_EN;  		intel_de_write(display, ILK_DPFC_CONTROL(fbc->id), dpfc_ctl); - -		/* wa_18038517565 Enable DPFC clock gating after FBC disable */ -		if (display->platform.dg2 || DISPLAY_VER(display) >= 14) -			fbc_compressor_clkgate_disable_wa(fbc, false);  	}  } @@ -1710,6 +1706,10 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)  	__intel_fbc_cleanup_cfb(fbc); +	/* wa_18038517565 Enable DPFC clock gating after FBC disable */ +	if (display->platform.dg2 || DISPLAY_VER(display) >= 14) +		fbc_compressor_clkgate_disable_wa(fbc, false); +  	fbc->state.plane = NULL;  	fbc->flip_pending = false;  	fbc->busy_bits = 0; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index ae9053919211..41988e193a41 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -3275,7 +3275,9 @@ static void intel_psr_configure_full_frame_update(struct intel_dp *intel_dp)  static void _psr_invalidate_handle(struct intel_dp *intel_dp)  { -	if (intel_dp->psr.psr2_sel_fetch_enabled) { +	struct intel_display *display = to_intel_display(intel_dp); + +	if (DISPLAY_VER(display) < 20 && intel_dp->psr.psr2_sel_fetch_enabled) {  		if (!intel_dp->psr.psr2_sel_fetch_cff_enabled) {  			intel_dp->psr.psr2_sel_fetch_cff_enabled = true;  			intel_psr_configure_full_frame_update(intel_dp); @@ -3361,7 +3363,7 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)  {  	struct intel_display *display = to_intel_display(intel_dp); -	if (intel_dp->psr.psr2_sel_fetch_enabled) { +	if (DISPLAY_VER(display) < 20 && intel_dp->psr.psr2_sel_fetch_enabled) {  		if (intel_dp->psr.psr2_sel_fetch_cff_enabled) {  			/* can we turn CFF off? */  			if (intel_dp->psr.busy_frontbuffer_bits == 0) @@ -3378,11 +3380,13 @@ static void _psr_flush_handle(struct intel_dp *intel_dp)  		 * existing SU configuration  		 */  		intel_psr_configure_full_frame_update(intel_dp); -	} -	intel_psr_force_update(intel_dp); +		intel_psr_force_update(intel_dp); +	} else { +		intel_psr_exit(intel_dp); +	} -	if (!intel_dp->psr.psr2_sel_fetch_enabled && !intel_dp->psr.active && +	if ((!intel_dp->psr.psr2_sel_fetch_enabled || DISPLAY_VER(display) >= 20) &&  	    !intel_dp->psr.busy_frontbuffer_bits)  		queue_work(display->wq.unordered, &intel_dp->psr.work);  } diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 3bc57579fe53..668ef139391b 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -23,6 +23,7 @@  #include "intel_modeset_lock.h"  #include "intel_tc.h" +#define DP_PIN_ASSIGNMENT_NONE	0x0  #define DP_PIN_ASSIGNMENT_C	0x3  #define DP_PIN_ASSIGNMENT_D	0x4  #define DP_PIN_ASSIGNMENT_E	0x5 @@ -66,6 +67,7 @@ struct intel_tc_port {  	enum tc_port_mode init_mode;  	enum phy_fia phy_fia;  	u8 phy_fia_idx; +	u8 max_lane_count;  };  static enum intel_display_power_domain @@ -307,6 +309,8 @@ static int lnl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)  		REG_FIELD_GET(TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK, val);  	switch (pin_assignment) { +	case DP_PIN_ASSIGNMENT_NONE: +		return 0;  	default:  		MISSING_CASE(pin_assignment);  		fallthrough; @@ -365,12 +369,12 @@ static int intel_tc_port_get_max_lane_count(struct intel_digital_port *dig_port)  	}  } -int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) +static int get_max_lane_count(struct intel_tc_port *tc)  { -	struct intel_display *display = to_intel_display(dig_port); -	struct intel_tc_port *tc = to_tc_port(dig_port); +	struct intel_display *display = to_intel_display(tc->dig_port); +	struct intel_digital_port *dig_port = tc->dig_port; -	if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT) +	if (tc->mode != TC_PORT_DP_ALT)  		return 4;  	assert_tc_cold_blocked(tc); @@ -384,6 +388,25 @@ int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port)  	return intel_tc_port_get_max_lane_count(dig_port);  } +static void read_pin_configuration(struct intel_tc_port *tc) +{ +	tc->max_lane_count = get_max_lane_count(tc); +} + +int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) +{ +	struct intel_display *display = to_intel_display(dig_port); +	struct intel_tc_port *tc = to_tc_port(dig_port); + +	if (!intel_encoder_is_tc(&dig_port->base)) +		return 4; + +	if (DISPLAY_VER(display) < 20) +		return get_max_lane_count(tc); + +	return tc->max_lane_count; +} +  void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,  				      int required_lanes)  { @@ -596,9 +619,12 @@ static void icl_tc_phy_get_hw_state(struct intel_tc_port *tc)  	tc_cold_wref = __tc_cold_block(tc, &domain);  	tc->mode = tc_phy_get_current_mode(tc); -	if (tc->mode != TC_PORT_DISCONNECTED) +	if (tc->mode != TC_PORT_DISCONNECTED) {  		tc->lock_wakeref = tc_cold_block(tc); +		read_pin_configuration(tc); +	} +  	__tc_cold_unblock(tc, domain, tc_cold_wref);  } @@ -656,8 +682,11 @@ static bool icl_tc_phy_connect(struct intel_tc_port *tc,  	tc->lock_wakeref = tc_cold_block(tc); -	if (tc->mode == TC_PORT_TBT_ALT) +	if (tc->mode == TC_PORT_TBT_ALT) { +		read_pin_configuration(tc); +  		return true; +	}  	if ((!tc_phy_is_ready(tc) ||  	     !icl_tc_phy_take_ownership(tc, true)) && @@ -668,6 +697,7 @@ static bool icl_tc_phy_connect(struct intel_tc_port *tc,  		goto out_unblock_tc_cold;  	} +	read_pin_configuration(tc);  	if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))  		goto out_release_phy; @@ -858,9 +888,12 @@ static void adlp_tc_phy_get_hw_state(struct intel_tc_port *tc)  	port_wakeref = intel_display_power_get(display, port_power_domain);  	tc->mode = tc_phy_get_current_mode(tc); -	if (tc->mode != TC_PORT_DISCONNECTED) +	if (tc->mode != TC_PORT_DISCONNECTED) {  		tc->lock_wakeref = tc_cold_block(tc); +		read_pin_configuration(tc); +	} +  	intel_display_power_put(display, port_power_domain, port_wakeref);  } @@ -873,6 +906,9 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)  	if (tc->mode == TC_PORT_TBT_ALT) {  		tc->lock_wakeref = tc_cold_block(tc); + +		read_pin_configuration(tc); +  		return true;  	} @@ -894,6 +930,8 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)  	tc->lock_wakeref = tc_cold_block(tc); +	read_pin_configuration(tc); +  	if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))  		goto out_unblock_tc_cold; @@ -1124,9 +1162,18 @@ static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)  	tc_cold_wref = __tc_cold_block(tc, &domain);  	tc->mode = tc_phy_get_current_mode(tc); -	if (tc->mode != TC_PORT_DISCONNECTED) +	if (tc->mode != TC_PORT_DISCONNECTED) {  		tc->lock_wakeref = tc_cold_block(tc); +		read_pin_configuration(tc); +		/* +		 * Set a valid lane count value for a DP-alt sink which got +		 * disconnected. The driver can only disable the output on this PHY. +		 */ +		if (tc->max_lane_count == 0) +			tc->max_lane_count = 4; +	} +  	drm_WARN_ON(display->drm,  		    (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) &&  		    !xelpdp_tc_phy_tcss_power_is_enabled(tc)); @@ -1138,14 +1185,19 @@ static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)  {  	tc->lock_wakeref = tc_cold_block(tc); -	if (tc->mode == TC_PORT_TBT_ALT) +	if (tc->mode == TC_PORT_TBT_ALT) { +		read_pin_configuration(tc); +  		return true; +	}  	if (!xelpdp_tc_phy_enable_tcss_power(tc, true))  		goto out_unblock_tccold;  	xelpdp_tc_phy_take_ownership(tc, true); +	read_pin_configuration(tc); +  	if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))  		goto out_release_phy; @@ -1226,14 +1278,19 @@ static void tc_phy_get_hw_state(struct intel_tc_port *tc)  	tc->phy_ops->get_hw_state(tc);  } -static bool tc_phy_is_ready_and_owned(struct intel_tc_port *tc, -				      bool phy_is_ready, bool phy_is_owned) +/* Is the PHY owned by display i.e. is it in legacy or DP-alt mode? */ +static bool tc_phy_owned_by_display(struct intel_tc_port *tc, +				    bool phy_is_ready, bool phy_is_owned)  {  	struct intel_display *display = to_intel_display(tc->dig_port); -	drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready); +	if (DISPLAY_VER(display) < 20) { +		drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready); -	return phy_is_ready && phy_is_owned; +		return phy_is_ready && phy_is_owned; +	} else { +		return phy_is_owned; +	}  }  static bool tc_phy_is_connected(struct intel_tc_port *tc, @@ -1244,7 +1301,7 @@ static bool tc_phy_is_connected(struct intel_tc_port *tc,  	bool phy_is_owned = tc_phy_is_owned(tc);  	bool is_connected; -	if (tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) +	if (tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned))  		is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY;  	else  		is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT; @@ -1352,7 +1409,7 @@ tc_phy_get_current_mode(struct intel_tc_port *tc)  	phy_is_ready = tc_phy_is_ready(tc);  	phy_is_owned = tc_phy_is_owned(tc); -	if (!tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) { +	if (!tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) {  		mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode);  	} else {  		drm_WARN_ON(display->drm, live_mode == TC_PORT_TBT_ALT); @@ -1441,11 +1498,11 @@ static void intel_tc_port_reset_mode(struct intel_tc_port *tc,  	intel_display_power_flush_work(display);  	if (!intel_tc_cold_requires_aux_pw(dig_port)) {  		enum intel_display_power_domain aux_domain; -		bool aux_powered;  		aux_domain = intel_aux_power_domain(dig_port); -		aux_powered = intel_display_power_is_enabled(display, aux_domain); -		drm_WARN_ON(display->drm, aux_powered); +		if (intel_display_power_is_enabled(display, aux_domain)) +			drm_dbg_kms(display->drm, "Port %s: AUX unexpectedly powered\n", +				    tc->port_name);  	}  	tc_phy_disconnect(tc); diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index b37e400f74e5..5a95f06900b5 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -634,6 +634,8 @@ static void cfl_ctx_workarounds_init(struct intel_engine_cs *engine,  static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,  				     struct i915_wa_list *wal)  { +	struct drm_i915_private *i915 = engine->i915; +  	/* Wa_1406697149 (WaDisableBankHangMode:icl) */  	wa_write(wal, GEN8_L3CNTLREG, GEN8_ERRDETBCTRL); @@ -669,6 +671,15 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,  	/* Wa_1406306137:icl,ehl */  	wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU); + +	if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { +		/* +		 * Disable Repacking for Compression (masked R/W access) +		 * before rendering compressed surfaces for display. +		 */ +		wa_masked_en(wal, CACHE_MODE_0_GEN7, +			     DISABLE_REPACKING_FOR_COMPRESSION); +	}  }  /* @@ -2306,15 +2317,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)  			     GEN8_RC_SEMA_IDLE_MSG_DISABLE);  	} -	if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { -		/* -		 * "Disable Repacking for Compression (masked R/W access) -		 *  before rendering compressed surfaces for display." -		 */ -		wa_masked_en(wal, CACHE_MODE_0_GEN7, -			     DISABLE_REPACKING_FOR_COMPRESSION); -	} -  	if (GRAPHICS_VER(i915) == 11) {  		/* This is not an Wa. Enable for better image quality */  		wa_masked_en(wal, diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e1e542126310..805d0a87aa54 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -253,6 +253,7 @@ nouveau_check_bl_size(struct nouveau_drm *drm, struct nouveau_bo *nvbo,  int  nouveau_framebuffer_new(struct drm_device *dev, +			const struct drm_format_info *info,  			const struct drm_mode_fb_cmd2 *mode_cmd,  			struct drm_gem_object *gem,  			struct drm_framebuffer **pfb) @@ -260,7 +261,6 @@ nouveau_framebuffer_new(struct drm_device *dev,  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_bo *nvbo = nouveau_gem_object(gem);  	struct drm_framebuffer *fb; -	const struct drm_format_info *info;  	unsigned int height, i;  	uint32_t tile_mode;  	uint8_t kind; @@ -295,9 +295,6 @@ nouveau_framebuffer_new(struct drm_device *dev,  		kind = nvbo->kind;  	} -	info = drm_get_format_info(dev, mode_cmd->pixel_format, -				   mode_cmd->modifier[0]); -  	for (i = 0; i < info->num_planes; i++) {  		height = drm_format_info_plane_height(info,  						      mode_cmd->height, @@ -321,7 +318,7 @@ nouveau_framebuffer_new(struct drm_device *dev,  	if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL)))  		return -ENOMEM; -	drm_helper_mode_fill_fb_struct(dev, fb, NULL, mode_cmd); +	drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd);  	fb->obj[0] = gem;  	ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs); @@ -344,7 +341,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev,  	if (!gem)  		return ERR_PTR(-ENOENT); -	ret = nouveau_framebuffer_new(dev, mode_cmd, gem, &fb); +	ret = nouveau_framebuffer_new(dev, info, mode_cmd, gem, &fb);  	if (ret == 0)  		return fb; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index e45f211501f6..470e0910d484 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -8,8 +8,11 @@  #include <drm/drm_framebuffer.h> +struct drm_format_info; +  int  nouveau_framebuffer_new(struct drm_device *dev, +			const struct drm_format_info *info,  			const struct drm_mode_fb_cmd2 *mode_cmd,  			struct drm_gem_object *gem,  			struct drm_framebuffer **pfb); diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c index edbbda78bac9..c4949e815eb3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_exec.c +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c @@ -60,14 +60,14 @@   * virtual address in the GPU's VA space there is no guarantee that the actual   * mappings are created in the GPU's MMU. If the given memory is swapped out   * at the time the bind operation is executed the kernel will stash the mapping - * details into it's internal alloctor and create the actual MMU mappings once + * details into it's internal allocator and create the actual MMU mappings once   * the memory is swapped back in. While this is transparent for userspace, it is   * guaranteed that all the backing memory is swapped back in and all the memory   * mappings, as requested by userspace previously, are actually mapped once the   * DRM_NOUVEAU_EXEC ioctl is called to submit an exec job.   *   * A VM_BIND job can be executed either synchronously or asynchronously. If - * exectued asynchronously, userspace may provide a list of syncobjs this job + * executed asynchronously, userspace may provide a list of syncobjs this job   * will wait for and/or a list of syncobj the kernel will signal once the   * VM_BIND job finished execution. If executed synchronously the ioctl will   * block until the bind job is finished. For synchronous jobs the kernel will @@ -82,7 +82,7 @@   * Since VM_BIND jobs update the GPU's VA space on job submit, EXEC jobs do have   * an up to date view of the VA space. However, the actual mappings might still   * be pending. Hence, EXEC jobs require to have the particular fences - of - * the corresponding VM_BIND jobs they depent on - attached to them. + * the corresponding VM_BIND jobs they depend on - attached to them.   */  static int diff --git a/drivers/gpu/drm/nouveau/nvif/vmm.c b/drivers/gpu/drm/nouveau/nvif/vmm.c index 99296f03371a..07c1ebc2a941 100644 --- a/drivers/gpu/drm/nouveau/nvif/vmm.c +++ b/drivers/gpu/drm/nouveau/nvif/vmm.c @@ -219,7 +219,8 @@ nvif_vmm_ctor(struct nvif_mmu *mmu, const char *name, s32 oclass,  	case RAW: args->type = NVIF_VMM_V0_TYPE_RAW; break;  	default:  		WARN_ON(1); -		return -EINVAL; +		ret = -EINVAL; +		goto done;  	}  	memcpy(args->data, argv, argc); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c index 9d06ff722fea..0dc4782df8c0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c @@ -325,7 +325,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries)  		rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), info.retries);  		if (IS_ERR_OR_NULL(rpc)) { -			kfree(buf); +			kvfree(buf);  			return rpc;  		} @@ -334,7 +334,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries)  		rpc = r535_gsp_msgq_recv_one_elem(gsp, &info);  		if (IS_ERR_OR_NULL(rpc)) { -			kfree(buf); +			kvfree(buf);  			return rpc;  		} diff --git a/drivers/gpu/drm/nova/file.rs b/drivers/gpu/drm/nova/file.rs index 7e59a34b830d..4fe62cf98a23 100644 --- a/drivers/gpu/drm/nova/file.rs +++ b/drivers/gpu/drm/nova/file.rs @@ -39,7 +39,8 @@ impl File {              _ => return Err(EINVAL),          }; -        getparam.set_value(value); +        #[allow(clippy::useless_conversion)] +        getparam.set_value(value.into());          Ok(0)      } diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 30c81e2e5d6b..bb3105556f19 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -351,7 +351,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,  		}  	} -	fb = omap_framebuffer_init(dev, mode_cmd, bos); +	fb = omap_framebuffer_init(dev, info, mode_cmd, bos);  	if (IS_ERR(fb))  		goto error; @@ -365,9 +365,9 @@ error:  }  struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, +		const struct drm_format_info *info,  		const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)  { -	const struct drm_format_info *format = NULL;  	struct omap_framebuffer *omap_fb = NULL;  	struct drm_framebuffer *fb = NULL;  	unsigned int pitch = mode_cmd->pitches[0]; @@ -377,15 +377,12 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,  			dev, mode_cmd, mode_cmd->width, mode_cmd->height,  			(char *)&mode_cmd->pixel_format); -	format = drm_get_format_info(dev, mode_cmd->pixel_format, -				     mode_cmd->modifier[0]); -  	for (i = 0; i < ARRAY_SIZE(formats); i++) {  		if (formats[i] == mode_cmd->pixel_format)  			break;  	} -	if (!format || i == ARRAY_SIZE(formats)) { +	if (i == ARRAY_SIZE(formats)) {  		dev_dbg(dev->dev, "unsupported pixel format: %4.4s\n",  			(char *)&mode_cmd->pixel_format);  		ret = -EINVAL; @@ -399,7 +396,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,  	}  	fb = &omap_fb->base; -	omap_fb->format = format; +	omap_fb->format = info;  	mutex_init(&omap_fb->lock);  	/* @@ -407,23 +404,23 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,  	 * that the two planes of multiplane formats need the same number of  	 * bytes per pixel.  	 */ -	if (format->num_planes == 2 && pitch != mode_cmd->pitches[1]) { +	if (info->num_planes == 2 && pitch != mode_cmd->pitches[1]) {  		dev_dbg(dev->dev, "pitches differ between planes 0 and 1\n");  		ret = -EINVAL;  		goto fail;  	} -	if (pitch % format->cpp[0]) { +	if (pitch % info->cpp[0]) {  		dev_dbg(dev->dev,  			"buffer pitch (%u bytes) is not a multiple of pixel size (%u bytes)\n", -			pitch, format->cpp[0]); +			pitch, info->cpp[0]);  		ret = -EINVAL;  		goto fail;  	} -	for (i = 0; i < format->num_planes; i++) { +	for (i = 0; i < info->num_planes; i++) {  		struct plane *plane = &omap_fb->planes[i]; -		unsigned int vsub = i == 0 ? 1 : format->vsub; +		unsigned int vsub = i == 0 ? 1 : info->vsub;  		unsigned int size;  		size = pitch * mode_cmd->height / vsub; @@ -440,7 +437,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,  		plane->dma_addr  = 0;  	} -	drm_helper_mode_fill_fb_struct(dev, fb, NULL, mode_cmd); +	drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd);  	ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs);  	if (ret) { diff --git a/drivers/gpu/drm/omapdrm/omap_fb.h b/drivers/gpu/drm/omapdrm/omap_fb.h index 0873f953cf1d..e6010302a22b 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.h +++ b/drivers/gpu/drm/omapdrm/omap_fb.h @@ -13,6 +13,7 @@ struct drm_connector;  struct drm_device;  struct drm_file;  struct drm_framebuffer; +struct drm_format_info;  struct drm_gem_object;  struct drm_mode_fb_cmd2;  struct drm_plane_state; @@ -23,6 +24,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,  		struct drm_file *file, const struct drm_format_info *info,  		const struct drm_mode_fb_cmd2 *mode_cmd);  struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, +		const struct drm_format_info *info,  		const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);  int omap_framebuffer_pin(struct drm_framebuffer *fb);  void omap_framebuffer_unpin(struct drm_framebuffer *fb); diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 7b6396890681..948af7ec1130 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -197,7 +197,10 @@ int omap_fbdev_driver_fbdev_probe(struct drm_fb_helper *helper,  		goto fail;  	} -	fb = omap_framebuffer_init(dev, &mode_cmd, &bo); +	fb = omap_framebuffer_init(dev, +				   drm_get_format_info(dev, mode_cmd.pixel_format, +						       mode_cmd.modifier[0]), +				   &mode_cmd, &bo);  	if (IS_ERR(fb)) {  		dev_err(dev->dev, "failed to allocate fb\n");  		/* note: if fb creation failed, we can't rely on fb destroy diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index bb73f2a68a12..85d6289a6eda 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -432,7 +432,7 @@ static void panfrost_gem_debugfs_bo_print(struct panfrost_gem_object *bo,  	if (!refcount)  		return; -	resident_size = bo->base.pages ? bo->base.base.size : 0; +	resident_size = panfrost_gem_rss(&bo->base.base);  	snprintf(creator_info, sizeof(creator_info),  		 "%s/%d", bo->debugfs.creator.process_name, bo->debugfs.creator.tgid); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index b4bf5dfeea2d..4dc77c398617 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1297,12 +1297,13 @@ static const struct drm_framebuffer_funcs radeon_fb_funcs = {  int  radeon_framebuffer_init(struct drm_device *dev,  			struct drm_framebuffer *fb, +			const struct drm_format_info *info,  			const struct drm_mode_fb_cmd2 *mode_cmd,  			struct drm_gem_object *obj)  {  	int ret;  	fb->obj[0] = obj; -	drm_helper_mode_fill_fb_struct(dev, fb, NULL, mode_cmd); +	drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd);  	ret = drm_framebuffer_init(dev, fb, &radeon_fb_funcs);  	if (ret) {  		fb->obj[0] = NULL; @@ -1341,7 +1342,7 @@ radeon_user_framebuffer_create(struct drm_device *dev,  		return ERR_PTR(-ENOMEM);  	} -	ret = radeon_framebuffer_init(dev, fb, mode_cmd, obj); +	ret = radeon_framebuffer_init(dev, fb, info, mode_cmd, obj);  	if (ret) {  		kfree(fb);  		drm_gem_object_put(obj); diff --git a/drivers/gpu/drm/radeon/radeon_fbdev.c b/drivers/gpu/drm/radeon/radeon_fbdev.c index e3a481bbee7b..dc81b0c2dbff 100644 --- a/drivers/gpu/drm/radeon/radeon_fbdev.c +++ b/drivers/gpu/drm/radeon/radeon_fbdev.c @@ -53,10 +53,10 @@ static void radeon_fbdev_destroy_pinned_object(struct drm_gem_object *gobj)  }  static int radeon_fbdev_create_pinned_object(struct drm_fb_helper *fb_helper, +					     const struct drm_format_info *info,  					     struct drm_mode_fb_cmd2 *mode_cmd,  					     struct drm_gem_object **gobj_p)  { -	const struct drm_format_info *info;  	struct radeon_device *rdev = fb_helper->dev->dev_private;  	struct drm_gem_object *gobj = NULL;  	struct radeon_bo *rbo = NULL; @@ -67,8 +67,6 @@ static int radeon_fbdev_create_pinned_object(struct drm_fb_helper *fb_helper,  	int height = mode_cmd->height;  	u32 cpp; -	info = drm_get_format_info(rdev_to_drm(rdev), mode_cmd->pixel_format, -				   mode_cmd->modifier[0]);  	cpp = info->cpp[0];  	/* need to align pitch with crtc limits */ @@ -206,6 +204,7 @@ int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,  				    struct drm_fb_helper_surface_size *sizes)  {  	struct radeon_device *rdev = fb_helper->dev->dev_private; +	const struct drm_format_info *format_info;  	struct drm_mode_fb_cmd2 mode_cmd = { };  	struct fb_info *info;  	struct drm_gem_object *gobj; @@ -224,7 +223,9 @@ int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,  	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,  							  sizes->surface_depth); -	ret = radeon_fbdev_create_pinned_object(fb_helper, &mode_cmd, &gobj); +	format_info = drm_get_format_info(rdev_to_drm(rdev), mode_cmd.pixel_format, +					  mode_cmd.modifier[0]); +	ret = radeon_fbdev_create_pinned_object(fb_helper, format_info, &mode_cmd, &gobj);  	if (ret) {  		DRM_ERROR("failed to create fbcon object %d\n", ret);  		return ret; @@ -236,7 +237,7 @@ int radeon_fbdev_driver_fbdev_probe(struct drm_fb_helper *fb_helper,  		ret = -ENOMEM;  		goto err_radeon_fbdev_destroy_pinned_object;  	} -	ret = radeon_framebuffer_init(rdev_to_drm(rdev), fb, &mode_cmd, gobj); +	ret = radeon_framebuffer_init(rdev_to_drm(rdev), fb, format_info, &mode_cmd, gobj);  	if (ret) {  		DRM_ERROR("failed to initialize framebuffer %d\n", ret);  		goto err_kfree; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 3102f6c2d055..9e34da2cacef 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -40,6 +40,7 @@  struct drm_fb_helper;  struct drm_fb_helper_surface_size; +struct drm_format_info;  struct edid;  struct drm_edid; @@ -890,6 +891,7 @@ extern void  radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on);  int radeon_framebuffer_init(struct drm_device *dev,  			     struct drm_framebuffer *rfb, +			     const struct drm_format_info *info,  			     const struct drm_mode_fb_cmd2 *mode_cmd,  			     struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index ab525668939a..faf50d872be3 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -53,6 +53,7 @@ config ROCKCHIP_CDN_DP  	bool "Rockchip cdn DP"  	depends on EXTCON=y || (EXTCON=m && DRM_ROCKCHIP=m)  	select DRM_DISPLAY_HELPER +	select DRM_BRIDGE_CONNECTOR  	select DRM_DISPLAY_DP_HELPER  	help  	  This selects support for Rockchip SoC specific extensions diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 186f6452a7d3..b50927a824b4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -2579,12 +2579,13 @@ static int vop2_win_init(struct vop2 *vop2)  }  /* - * The window registers are only updated when config done is written. - * Until that they read back the old value. As we read-modify-write - * these registers mark them as non-volatile. This makes sure we read - * the new values from the regmap register cache. + * The window and video port registers are only updated when config + * done is written. Until that they read back the old value. As we + * read-modify-write these registers mark them as non-volatile. This + * makes sure we read the new values from the regmap register cache.   */  static const struct regmap_range vop2_nonvolatile_range[] = { +	regmap_reg_range(RK3568_VP0_CTRL_BASE, RK3588_VP3_CTRL_BASE + 255),  	regmap_reg_range(0x1000, 0x23ff),  }; diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 7299fa8971ce..981dada8f3a8 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -1033,13 +1033,14 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)  		NULL : &result->dst_pitch;  	drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); -	buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32)); +	buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));  	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);  	buf = dst.vaddr; /* restore original value of buf */  	memset(buf, 0, dst_size);  	drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); +	buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));  	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);  } diff --git a/drivers/gpu/drm/xe/regs/xe_bars.h b/drivers/gpu/drm/xe/regs/xe_bars.h index ce05b6ae832f..880140d6ccdc 100644 --- a/drivers/gpu/drm/xe/regs/xe_bars.h +++ b/drivers/gpu/drm/xe/regs/xe_bars.h @@ -7,5 +7,6 @@  #define GTTMMADR_BAR			0 /* MMIO + GTT */  #define LMEM_BAR			2 /* VRAM */ +#define VF_LMEM_BAR			9 /* VF VRAM */  #endif diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index f08fc4377d25..c17ed1ae8649 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -332,6 +332,7 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channe  	int ret = 0;  	u32 reg_val, max;  	struct xe_reg rapl_limit; +	u64 max_supp_power_limit = 0;  	mutex_lock(&hwmon->hwmon_lock); @@ -356,6 +357,20 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, u32 attr, int channe  		goto unlock;  	} +	/* +	 * If the sysfs value exceeds the maximum pcode supported power limit value, clamp it to +	 * the supported maximum (U12.3 format). +	 * This is to avoid truncation during reg_val calculation below and ensure the valid +	 * power limit is sent for pcode which would clamp it to card-supported value. +	 */ +	max_supp_power_limit = ((PWR_LIM_VAL) >> hwmon->scl_shift_power) * SF_POWER; +	if (value > max_supp_power_limit) { +		value = max_supp_power_limit; +		drm_info(&hwmon->xe->drm, +			 "Power limit clamped as selected %s exceeds channel %d limit\n", +			 PWR_ATTR_TO_STR(attr), channel); +	} +  	/* Computation in 64-bits to avoid overflow. Round to nearest. */  	reg_val = DIV_ROUND_CLOSEST_ULL((u64)value << hwmon->scl_shift_power, SF_POWER); @@ -739,9 +754,23 @@ static int xe_hwmon_power_curr_crit_write(struct xe_hwmon *hwmon, int channel,  {  	int ret;  	u32 uval; +	u64 max_crit_power_curr = 0;  	mutex_lock(&hwmon->hwmon_lock); +	/* +	 * If the sysfs value exceeds the pcode mailbox cmd POWER_SETUP_SUBCOMMAND_WRITE_I1 +	 * max supported value, clamp it to the command's max (U10.6 format). +	 * This is to avoid truncation during uval calculation below and ensure the valid power +	 * limit is sent for pcode which would clamp it to card-supported value. +	 */ +	max_crit_power_curr = (POWER_SETUP_I1_DATA_MASK >> POWER_SETUP_I1_SHIFT) * scale_factor; +	if (value > max_crit_power_curr) { +		value = max_crit_power_curr; +		drm_info(&hwmon->xe->drm, +			 "Power limit clamped as selected exceeds channel %d limit\n", +			 channel); +	}  	uval = DIV_ROUND_CLOSEST_ULL(value << POWER_SETUP_I1_SHIFT, scale_factor);  	ret = xe_hwmon_pcode_write_i1(hwmon, uval); diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index ba1cff2e4cda..84f412fd3c5d 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -408,7 +408,7 @@ struct xe_migrate *xe_migrate_init(struct xe_tile *tile)  	/* Special layout, prepared below.. */  	vm = xe_vm_create(xe, XE_VM_FLAG_MIGRATION | -			  XE_VM_FLAG_SET_TILE_ID(tile)); +			  XE_VM_FLAG_SET_TILE_ID(tile), NULL);  	if (IS_ERR(vm))  		return ERR_CAST(vm); @@ -1820,15 +1820,19 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,  	if (!IS_ALIGNED(len, XE_CACHELINE_BYTES) ||  	    !IS_ALIGNED((unsigned long)buf + offset, XE_CACHELINE_BYTES)) {  		int buf_offset = 0; +		void *bounce; +		int err; + +		BUILD_BUG_ON(!is_power_of_2(XE_CACHELINE_BYTES)); +		bounce = kmalloc(XE_CACHELINE_BYTES, GFP_KERNEL); +		if (!bounce) +			return -ENOMEM;  		/*  		 * Less than ideal for large unaligned access but this should be  		 * fairly rare, can fixup if this becomes common.  		 */  		do { -			u8 bounce[XE_CACHELINE_BYTES]; -			void *ptr = (void *)bounce; -			int err;  			int copy_bytes = min_t(int, bytes_left,  					       XE_CACHELINE_BYTES -  					       (offset & XE_CACHELINE_MASK)); @@ -1837,22 +1841,22 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,  			err = xe_migrate_access_memory(m, bo,  						       offset &  						       ~XE_CACHELINE_MASK, -						       (void *)ptr, -						       sizeof(bounce), 0); +						       bounce, +						       XE_CACHELINE_BYTES, 0);  			if (err) -				return err; +				break;  			if (write) { -				memcpy(ptr + ptr_offset, buf + buf_offset, copy_bytes); +				memcpy(bounce + ptr_offset, buf + buf_offset, copy_bytes);  				err = xe_migrate_access_memory(m, bo,  							       offset & ~XE_CACHELINE_MASK, -							       (void *)ptr, -							       sizeof(bounce), write); +							       bounce, +							       XE_CACHELINE_BYTES, write);  				if (err) -					return err; +					break;  			} else { -				memcpy(buf + buf_offset, ptr + ptr_offset, +				memcpy(buf + buf_offset, bounce + ptr_offset,  				       copy_bytes);  			} @@ -1861,7 +1865,8 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,  			offset += copy_bytes;  		} while (bytes_left); -		return 0; +		kfree(bounce); +		return err;  	}  	dma_addr = xe_migrate_dma_map(xe, buf, len + page_offset, write); @@ -1882,8 +1887,11 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,  		else  			current_bytes = min_t(int, bytes_left, cursor.size); -		if (fence) -			dma_fence_put(fence); +		if (current_bytes & ~PAGE_MASK) { +			int pitch = 4; + +			current_bytes = min_t(int, current_bytes, S16_MAX * pitch); +		}  		__fence = xe_migrate_vram(m, current_bytes,  					  (unsigned long)buf & ~PAGE_MASK, @@ -1892,11 +1900,15 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,  					  XE_MIGRATE_COPY_TO_VRAM :  					  XE_MIGRATE_COPY_TO_SRAM);  		if (IS_ERR(__fence)) { -			if (fence) +			if (fence) {  				dma_fence_wait(fence, false); +				dma_fence_put(fence); +			}  			fence = __fence;  			goto out_err;  		} + +		dma_fence_put(fence);  		fence = __fence;  		buf += current_bytes; diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c index 447a7867eecb..af05db07162e 100644 --- a/drivers/gpu/drm/xe/xe_pci_sriov.c +++ b/drivers/gpu/drm/xe/xe_pci_sriov.c @@ -3,6 +3,10 @@   * Copyright © 2023-2024 Intel Corporation   */ +#include <linux/bitops.h> +#include <linux/pci.h> + +#include "regs/xe_bars.h"  #include "xe_assert.h"  #include "xe_device.h"  #include "xe_gt_sriov_pf_config.h" @@ -128,6 +132,18 @@ static void pf_engine_activity_stats(struct xe_device *xe, unsigned int num_vfs,  	}  } +static int resize_vf_vram_bar(struct xe_device *xe, int num_vfs) +{ +	struct pci_dev *pdev = to_pci_dev(xe->drm.dev); +	u32 sizes; + +	sizes = pci_iov_vf_bar_get_sizes(pdev, VF_LMEM_BAR, num_vfs); +	if (!sizes) +		return 0; + +	return pci_iov_vf_bar_set_size(pdev, VF_LMEM_BAR, __fls(sizes)); +} +  static int pf_enable_vfs(struct xe_device *xe, int num_vfs)  {  	struct pci_dev *pdev = to_pci_dev(xe->drm.dev); @@ -158,6 +174,12 @@ static int pf_enable_vfs(struct xe_device *xe, int num_vfs)  	if (err < 0)  		goto failed; +	if (IS_DGFX(xe)) { +		err = resize_vf_vram_bar(xe, num_vfs); +		if (err) +			xe_sriov_info(xe, "Failed to set VF LMEM BAR size: %d\n", err); +	} +  	err = pci_enable_sriov(pdev, num_vfs);  	if (err < 0)  		goto failed; diff --git a/drivers/gpu/drm/xe/xe_pxp_submit.c b/drivers/gpu/drm/xe/xe_pxp_submit.c index d92ec0f515b0..ca95f2a4d4ef 100644 --- a/drivers/gpu/drm/xe/xe_pxp_submit.c +++ b/drivers/gpu/drm/xe/xe_pxp_submit.c @@ -101,7 +101,7 @@ static int allocate_gsc_client_resources(struct xe_gt *gt,  	xe_assert(xe, hwe);  	/* PXP instructions must be issued from PPGTT */ -	vm = xe_vm_create(xe, XE_VM_FLAG_GSC); +	vm = xe_vm_create(xe, XE_VM_FLAG_GSC, NULL);  	if (IS_ERR(vm))  		return PTR_ERR(vm); diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c index 1c3c04d52f55..90244fe59b59 100644 --- a/drivers/gpu/drm/xe/xe_shrinker.c +++ b/drivers/gpu/drm/xe/xe_shrinker.c @@ -54,10 +54,10 @@ xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgea  	write_unlock(&shrinker->lock);  } -static s64 xe_shrinker_walk(struct xe_device *xe, -			    struct ttm_operation_ctx *ctx, -			    const struct xe_bo_shrink_flags flags, -			    unsigned long to_scan, unsigned long *scanned) +static s64 __xe_shrinker_walk(struct xe_device *xe, +			      struct ttm_operation_ctx *ctx, +			      const struct xe_bo_shrink_flags flags, +			      unsigned long to_scan, unsigned long *scanned)  {  	unsigned int mem_type;  	s64 freed = 0, lret; @@ -93,6 +93,48 @@ static s64 xe_shrinker_walk(struct xe_device *xe,  	return freed;  } +/* + * Try shrinking idle objects without writeback first, then if not sufficient, + * try also non-idle objects and finally if that's not sufficient either, + * add writeback. This avoids stalls and explicit writebacks with light or + * moderate memory pressure. + */ +static s64 xe_shrinker_walk(struct xe_device *xe, +			    struct ttm_operation_ctx *ctx, +			    const struct xe_bo_shrink_flags flags, +			    unsigned long to_scan, unsigned long *scanned) +{ +	bool no_wait_gpu = true; +	struct xe_bo_shrink_flags save_flags = flags; +	s64 lret, freed; + +	swap(no_wait_gpu, ctx->no_wait_gpu); +	save_flags.writeback = false; +	lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned); +	swap(no_wait_gpu, ctx->no_wait_gpu); +	if (lret < 0 || *scanned >= to_scan) +		return lret; + +	freed = lret; +	if (!ctx->no_wait_gpu) { +		lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned); +		if (lret < 0) +			return lret; +		freed += lret; +		if (*scanned >= to_scan) +			return freed; +	} + +	if (flags.writeback) { +		lret = __xe_shrinker_walk(xe, ctx, flags, to_scan, scanned); +		if (lret < 0) +			return lret; +		freed += lret; +	} + +	return freed; +} +  static unsigned long  xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc)  { @@ -199,6 +241,7 @@ static unsigned long xe_shrinker_scan(struct shrinker *shrink, struct shrink_con  		runtime_pm = xe_shrinker_runtime_pm_get(shrinker, true, 0, can_backup);  	shrink_flags.purge = false; +  	lret = xe_shrinker_walk(shrinker->xe, &ctx, shrink_flags,  				nr_to_scan, &nr_scanned);  	if (lret >= 0) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 2035604121e6..ec04bef8ae40 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1640,7 +1640,7 @@ static void xe_vm_free_scratch(struct xe_vm *vm)  	}  } -struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) +struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)  {  	struct drm_gem_object *vm_resv_obj;  	struct xe_vm *vm; @@ -1661,9 +1661,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)  	vm->xe = xe;  	vm->size = 1ull << xe->info.va_bits; -  	vm->flags = flags; +	if (xef) +		vm->xef = xe_file_get(xef);  	/**  	 * GSC VMs are kernel-owned, only used for PXP ops and can sometimes be  	 * manipulated under the PXP mutex. However, the PXP mutex can be taken @@ -1794,6 +1795,20 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)  	if (number_tiles > 1)  		vm->composite_fence_ctx = dma_fence_context_alloc(1); +	if (xef && xe->info.has_asid) { +		u32 asid; + +		down_write(&xe->usm.lock); +		err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm, +				      XA_LIMIT(1, XE_MAX_ASID - 1), +				      &xe->usm.next_asid, GFP_KERNEL); +		up_write(&xe->usm.lock); +		if (err < 0) +			goto err_unlock_close; + +		vm->usm.asid = asid; +	} +  	trace_xe_vm_create(vm);  	return vm; @@ -1814,6 +1829,8 @@ err_no_resv:  	for_each_tile(tile, xe, id)  		xe_range_fence_tree_fini(&vm->rftree[id]);  	ttm_lru_bulk_move_fini(&xe->ttm, &vm->lru_bulk_move); +	if (vm->xef) +		xe_file_put(vm->xef);  	kfree(vm);  	if (flags & XE_VM_FLAG_LR_MODE)  		xe_pm_runtime_put(xe); @@ -2059,9 +2076,8 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data,  	struct xe_device *xe = to_xe_device(dev);  	struct xe_file *xef = to_xe_file(file);  	struct drm_xe_vm_create *args = data; -	struct xe_tile *tile;  	struct xe_vm *vm; -	u32 id, asid; +	u32 id;  	int err;  	u32 flags = 0; @@ -2097,29 +2113,10 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data,  	if (args->flags & DRM_XE_VM_CREATE_FLAG_FAULT_MODE)  		flags |= XE_VM_FLAG_FAULT_MODE; -	vm = xe_vm_create(xe, flags); +	vm = xe_vm_create(xe, flags, xef);  	if (IS_ERR(vm))  		return PTR_ERR(vm); -	if (xe->info.has_asid) { -		down_write(&xe->usm.lock); -		err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm, -				      XA_LIMIT(1, XE_MAX_ASID - 1), -				      &xe->usm.next_asid, GFP_KERNEL); -		up_write(&xe->usm.lock); -		if (err < 0) -			goto err_close_and_put; - -		vm->usm.asid = asid; -	} - -	vm->xef = xe_file_get(xef); - -	/* Record BO memory for VM pagetable created against client */ -	for_each_tile(tile, xe, id) -		if (vm->pt_root[id]) -			xe_drm_client_add_bo(vm->xef->client, vm->pt_root[id]->bo); -  #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEM)  	/* Warning: Security issue - never enable by default */  	args->reserved[0] = xe_bo_main_addr(vm->pt_root[0]->bo, XE_PAGE_SIZE); @@ -3421,6 +3418,7 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm,  free_bind_ops:  	if (args->num_binds > 1)  		kvfree(*bind_ops); +	*bind_ops = NULL;  	return err;  } @@ -3527,7 +3525,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)  	struct xe_exec_queue *q = NULL;  	u32 num_syncs, num_ufence = 0;  	struct xe_sync_entry *syncs = NULL; -	struct drm_xe_vm_bind_op *bind_ops; +	struct drm_xe_vm_bind_op *bind_ops = NULL;  	struct xe_vma_ops vops;  	struct dma_fence *fence;  	int err; diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h index 3475a118f666..2f213737c7e5 100644 --- a/drivers/gpu/drm/xe/xe_vm.h +++ b/drivers/gpu/drm/xe/xe_vm.h @@ -26,7 +26,7 @@ struct xe_sync_entry;  struct xe_svm_range;  struct drm_exec; -struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags); +struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef);  struct xe_vm *xe_vm_lookup(struct xe_file *xef, u32 id);  int xe_vma_cmp_vma_cb(const void *key, const struct rb_node *node); | 
