diff options
Diffstat (limited to 'drivers/gpu/drm')
45 files changed, 440 insertions, 288 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 2e3a0543760d..e3281d4e3e41 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -765,7 +765,7 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force)  	return ret;  } -static void amdgpu_connector_destroy(struct drm_connector *connector) +static void amdgpu_connector_unregister(struct drm_connector *connector)  {  	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); @@ -773,6 +773,12 @@ static void amdgpu_connector_destroy(struct drm_connector *connector)  		drm_dp_aux_unregister(&amdgpu_connector->ddc_bus->aux);  		amdgpu_connector->ddc_bus->has_aux = false;  	} +} + +static void amdgpu_connector_destroy(struct drm_connector *connector) +{ +	struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); +  	amdgpu_connector_free_edid(connector);  	kfree(amdgpu_connector->con_priv);  	drm_connector_unregister(connector); @@ -826,6 +832,7 @@ static const struct drm_connector_funcs amdgpu_connector_lvds_funcs = {  	.dpms = drm_helper_connector_dpms,  	.detect = amdgpu_connector_lvds_detect,  	.fill_modes = drm_helper_probe_single_connector_modes, +	.early_unregister = amdgpu_connector_unregister,  	.destroy = amdgpu_connector_destroy,  	.set_property = amdgpu_connector_set_lcd_property,  }; @@ -936,6 +943,7 @@ static const struct drm_connector_funcs amdgpu_connector_vga_funcs = {  	.dpms = drm_helper_connector_dpms,  	.detect = amdgpu_connector_vga_detect,  	.fill_modes = drm_helper_probe_single_connector_modes, +	.early_unregister = amdgpu_connector_unregister,  	.destroy = amdgpu_connector_destroy,  	.set_property = amdgpu_connector_set_property,  }; @@ -1203,6 +1211,7 @@ static const struct drm_connector_funcs amdgpu_connector_dvi_funcs = {  	.detect = amdgpu_connector_dvi_detect,  	.fill_modes = drm_helper_probe_single_connector_modes,  	.set_property = amdgpu_connector_set_property, +	.early_unregister = amdgpu_connector_unregister,  	.destroy = amdgpu_connector_destroy,  	.force = amdgpu_connector_dvi_force,  }; @@ -1493,6 +1502,7 @@ static const struct drm_connector_funcs amdgpu_connector_dp_funcs = {  	.detect = amdgpu_connector_dp_detect,  	.fill_modes = drm_helper_probe_single_connector_modes,  	.set_property = amdgpu_connector_set_property, +	.early_unregister = amdgpu_connector_unregister,  	.destroy = amdgpu_connector_destroy,  	.force = amdgpu_connector_dvi_force,  }; @@ -1502,6 +1512,7 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = {  	.detect = amdgpu_connector_dp_detect,  	.fill_modes = drm_helper_probe_single_connector_modes,  	.set_property = amdgpu_connector_set_lcd_property, +	.early_unregister = amdgpu_connector_unregister,  	.destroy = amdgpu_connector_destroy,  	.force = amdgpu_connector_dvi_force,  }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index e203e5561107..a5e2fcbef0f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -43,6 +43,9 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx)  		ctx->rings[i].sequence = 1;  		ctx->rings[i].fences = &ctx->fences[amdgpu_sched_jobs * i];  	} + +	ctx->reset_counter = atomic_read(&adev->gpu_reset_counter); +  	/* create context entity for each ring */  	for (i = 0; i < adev->num_rings; i++) {  		struct amdgpu_ring *ring = adev->rings[i]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7dbe85d67d26..b4f4a9239069 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1408,16 +1408,6 @@ static int amdgpu_late_init(struct amdgpu_device *adev)  	for (i = 0; i < adev->num_ip_blocks; i++) {  		if (!adev->ip_block_status[i].valid)  			continue; -		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_UVD || -			adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_VCE) -			continue; -		/* enable clockgating to save power */ -		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, -								    AMD_CG_STATE_GATE); -		if (r) { -			DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); -			return r; -		}  		if (adev->ip_blocks[i].funcs->late_init) {  			r = adev->ip_blocks[i].funcs->late_init((void *)adev);  			if (r) { @@ -1426,6 +1416,18 @@ static int amdgpu_late_init(struct amdgpu_device *adev)  			}  			adev->ip_block_status[i].late_initialized = true;  		} +		/* skip CG for VCE/UVD, it's handled specially */ +		if (adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_UVD && +		    adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_VCE) { +			/* enable clockgating to save power */ +			r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, +									    AMD_CG_STATE_GATE); +			if (r) { +				DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n", +					  adev->ip_blocks[i].funcs->name, r); +				return r; +			} +		}  	}  	return 0; @@ -1435,6 +1437,30 @@ static int amdgpu_fini(struct amdgpu_device *adev)  {  	int i, r; +	/* need to disable SMC first */ +	for (i = 0; i < adev->num_ip_blocks; i++) { +		if (!adev->ip_block_status[i].hw) +			continue; +		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) { +			/* ungate blocks before hw fini so that we can shutdown the blocks safely */ +			r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, +									    AMD_CG_STATE_UNGATE); +			if (r) { +				DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", +					  adev->ip_blocks[i].funcs->name, r); +				return r; +			} +			r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); +			/* XXX handle errors */ +			if (r) { +				DRM_DEBUG("hw_fini of IP block <%s> failed %d\n", +					  adev->ip_blocks[i].funcs->name, r); +			} +			adev->ip_block_status[i].hw = false; +			break; +		} +	} +  	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {  		if (!adev->ip_block_status[i].hw)  			continue; @@ -2073,7 +2099,8 @@ static bool amdgpu_check_soft_reset(struct amdgpu_device *adev)  		if (!adev->ip_block_status[i].valid)  			continue;  		if (adev->ip_blocks[i].funcs->check_soft_reset) -			adev->ip_blocks[i].funcs->check_soft_reset(adev); +			adev->ip_block_status[i].hang = +				adev->ip_blocks[i].funcs->check_soft_reset(adev);  		if (adev->ip_block_status[i].hang) {  			DRM_INFO("IP block:%d is hang!\n", i);  			asic_hang = true; @@ -2102,12 +2129,20 @@ static int amdgpu_pre_soft_reset(struct amdgpu_device *adev)  static bool amdgpu_need_full_reset(struct amdgpu_device *adev)  { -	if (adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang || -	    adev->ip_block_status[AMD_IP_BLOCK_TYPE_SMC].hang || -	    adev->ip_block_status[AMD_IP_BLOCK_TYPE_ACP].hang || -	    adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang) { -		DRM_INFO("Some block need full reset!\n"); -		return true; +	int i; + +	for (i = 0; i < adev->num_ip_blocks; i++) { +		if (!adev->ip_block_status[i].valid) +			continue; +		if ((adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) || +		    (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) || +		    (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_ACP) || +		    (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_DCE)) { +			if (adev->ip_block_status[i].hang) { +				DRM_INFO("Some block need full reset!\n"); +				return true; +			} +		}  	}  	return false;  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index fe36caf1b7d7..14f57d9915e3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -113,24 +113,26 @@ void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,  	printk("\n");  } +  u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)  {  	struct drm_device *dev = adev->ddev;  	struct drm_crtc *crtc;  	struct amdgpu_crtc *amdgpu_crtc; -	u32 line_time_us, vblank_lines; +	u32 vblank_in_pixels;  	u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */  	if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {  		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {  			amdgpu_crtc = to_amdgpu_crtc(crtc);  			if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { -				line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) / -					amdgpu_crtc->hw_mode.clock; -				vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end - +				vblank_in_pixels = +					amdgpu_crtc->hw_mode.crtc_htotal * +					(amdgpu_crtc->hw_mode.crtc_vblank_end -  					amdgpu_crtc->hw_mode.crtc_vdisplay + -					(amdgpu_crtc->v_border * 2); -				vblank_time_us = vblank_lines * line_time_us; +					(amdgpu_crtc->v_border * 2)); + +				vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;  				break;  			}  		} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index e1fa8731d1e2..3cb5e903cd62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -345,8 +345,8 @@ static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev,  	ent = debugfs_create_file(name,  				  S_IFREG | S_IRUGO, root,  				  ring, &amdgpu_debugfs_ring_fops); -	if (IS_ERR(ent)) -		return PTR_ERR(ent); +	if (!ent) +		return -ENOMEM;  	i_size_write(ent->d_inode, ring->ring_size + 12);  	ring->ent = ent; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 887483b8b818..dcaf691f56b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -555,10 +555,13 @@ struct amdgpu_ttm_tt {  int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages)  {  	struct amdgpu_ttm_tt *gtt = (void *)ttm; -	int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); +	unsigned int flags = 0;  	unsigned pinned = 0;  	int r; +	if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY)) +		flags |= FOLL_WRITE; +  	if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) {  		/* check that we only use anonymous memory  		   to prevent problems with writeback */ @@ -581,7 +584,7 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages)  		list_add(&guptask.list, >t->guptasks);  		spin_unlock(>t->guptasklock); -		r = get_user_pages(userptr, num_pages, write, 0, p, NULL); +		r = get_user_pages(userptr, num_pages, flags, p, NULL);  		spin_lock(>t->guptasklock);  		list_del(&guptask.list); diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index f80a0834e889..3c082e143730 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c @@ -1514,14 +1514,16 @@ static int cz_dpm_set_powergating_state(void *handle,  	return 0;  } -/* borrowed from KV, need future unify */  static int cz_dpm_get_temperature(struct amdgpu_device *adev)  {  	int actual_temp = 0; -	uint32_t temp = RREG32_SMC(0xC0300E0C); +	uint32_t val = RREG32_SMC(ixTHM_TCON_CUR_TMP); +	uint32_t temp = REG_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP); -	if (temp) +	if (REG_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL))  		actual_temp = 1000 * ((temp / 8) - 49); +	else +		actual_temp = 1000 * (temp / 8);  	return actual_temp;  } diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 613ebb7ed50f..4108c686aa7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -3188,16 +3188,11 @@ static int dce_v10_0_wait_for_idle(void *handle)  	return 0;  } -static int dce_v10_0_check_soft_reset(void *handle) +static bool dce_v10_0_check_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (dce_v10_0_is_display_hung(adev)) -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = true; -	else -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = false; - -	return 0; +	return dce_v10_0_is_display_hung(adev);  }  static int dce_v10_0_soft_reset(void *handle) @@ -3205,9 +3200,6 @@ static int dce_v10_0_soft_reset(void *handle)  	u32 srbm_soft_reset = 0, tmp;  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang) -		return 0; -  	if (dce_v10_0_is_display_hung(adev))  		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 6c6ff57b1c95..ee6a48a09214 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4087,14 +4087,21 @@ static int gfx_v8_0_rlc_load_microcode(struct amdgpu_device *adev)  static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev)  {  	int r; +	u32 tmp;  	gfx_v8_0_rlc_stop(adev);  	/* disable CG */ -	WREG32(mmRLC_CGCG_CGLS_CTRL, 0); +	tmp = RREG32(mmRLC_CGCG_CGLS_CTRL); +	tmp &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | +		 RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK); +	WREG32(mmRLC_CGCG_CGLS_CTRL, tmp);  	if (adev->asic_type == CHIP_POLARIS11 || -	    adev->asic_type == CHIP_POLARIS10) -		WREG32(mmRLC_CGCG_CGLS_CTRL_3D, 0); +	    adev->asic_type == CHIP_POLARIS10) { +		tmp = RREG32(mmRLC_CGCG_CGLS_CTRL_3D); +		tmp &= ~0x3; +		WREG32(mmRLC_CGCG_CGLS_CTRL_3D, tmp); +	}  	/* disable PG */  	WREG32(mmRLC_PG_CNTL, 0); @@ -5137,7 +5144,7 @@ static int gfx_v8_0_wait_for_idle(void *handle)  	return -ETIMEDOUT;  } -static int gfx_v8_0_check_soft_reset(void *handle) +static bool gfx_v8_0_check_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 grbm_soft_reset = 0, srbm_soft_reset = 0; @@ -5189,16 +5196,14 @@ static int gfx_v8_0_check_soft_reset(void *handle)  						SRBM_SOFT_RESET, SOFT_RESET_SEM, 1);  	if (grbm_soft_reset || srbm_soft_reset) { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang = true;  		adev->gfx.grbm_soft_reset = grbm_soft_reset;  		adev->gfx.srbm_soft_reset = srbm_soft_reset; +		return true;  	} else { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang = false;  		adev->gfx.grbm_soft_reset = 0;  		adev->gfx.srbm_soft_reset = 0; +		return false;  	} - -	return 0;  }  static void gfx_v8_0_inactive_hqd(struct amdgpu_device *adev, @@ -5226,7 +5231,8 @@ static int gfx_v8_0_pre_soft_reset(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 grbm_soft_reset = 0, srbm_soft_reset = 0; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang) +	if ((!adev->gfx.grbm_soft_reset) && +	    (!adev->gfx.srbm_soft_reset))  		return 0;  	grbm_soft_reset = adev->gfx.grbm_soft_reset; @@ -5264,7 +5270,8 @@ static int gfx_v8_0_soft_reset(void *handle)  	u32 grbm_soft_reset = 0, srbm_soft_reset = 0;  	u32 tmp; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang) +	if ((!adev->gfx.grbm_soft_reset) && +	    (!adev->gfx.srbm_soft_reset))  		return 0;  	grbm_soft_reset = adev->gfx.grbm_soft_reset; @@ -5334,7 +5341,8 @@ static int gfx_v8_0_post_soft_reset(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 grbm_soft_reset = 0, srbm_soft_reset = 0; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang) +	if ((!adev->gfx.grbm_soft_reset) && +	    (!adev->gfx.srbm_soft_reset))  		return 0;  	grbm_soft_reset = adev->gfx.grbm_soft_reset; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 1b319f5bc696..c22ef140a542 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1099,7 +1099,7 @@ static int gmc_v8_0_wait_for_idle(void *handle)  } -static int gmc_v8_0_check_soft_reset(void *handle) +static bool gmc_v8_0_check_soft_reset(void *handle)  {  	u32 srbm_soft_reset = 0;  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1116,20 +1116,19 @@ static int gmc_v8_0_check_soft_reset(void *handle)  							SRBM_SOFT_RESET, SOFT_RESET_MC, 1);  	}  	if (srbm_soft_reset) { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = true;  		adev->mc.srbm_soft_reset = srbm_soft_reset; +		return true;  	} else { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = false;  		adev->mc.srbm_soft_reset = 0; +		return false;  	} -	return 0;  }  static int gmc_v8_0_pre_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) +	if (!adev->mc.srbm_soft_reset)  		return 0;  	gmc_v8_0_mc_stop(adev, &adev->mc.save); @@ -1145,7 +1144,7 @@ static int gmc_v8_0_soft_reset(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) +	if (!adev->mc.srbm_soft_reset)  		return 0;  	srbm_soft_reset = adev->mc.srbm_soft_reset; @@ -1175,7 +1174,7 @@ static int gmc_v8_0_post_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) +	if (!adev->mc.srbm_soft_reset)  		return 0;  	gmc_v8_0_mc_resume(adev, &adev->mc.save); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index f325fd86430b..a9d10941fb53 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1268,7 +1268,7 @@ static int sdma_v3_0_wait_for_idle(void *handle)  	return -ETIMEDOUT;  } -static int sdma_v3_0_check_soft_reset(void *handle) +static bool sdma_v3_0_check_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset = 0; @@ -1281,14 +1281,12 @@ static int sdma_v3_0_check_soft_reset(void *handle)  	}  	if (srbm_soft_reset) { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang = true;  		adev->sdma.srbm_soft_reset = srbm_soft_reset; +		return true;  	} else { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang = false;  		adev->sdma.srbm_soft_reset = 0; +		return false;  	} - -	return 0;  }  static int sdma_v3_0_pre_soft_reset(void *handle) @@ -1296,7 +1294,7 @@ static int sdma_v3_0_pre_soft_reset(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset = 0; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang) +	if (!adev->sdma.srbm_soft_reset)  		return 0;  	srbm_soft_reset = adev->sdma.srbm_soft_reset; @@ -1315,7 +1313,7 @@ static int sdma_v3_0_post_soft_reset(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset = 0; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang) +	if (!adev->sdma.srbm_soft_reset)  		return 0;  	srbm_soft_reset = adev->sdma.srbm_soft_reset; @@ -1335,7 +1333,7 @@ static int sdma_v3_0_soft_reset(void *handle)  	u32 srbm_soft_reset = 0;  	u32 tmp; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang) +	if (!adev->sdma.srbm_soft_reset)  		return 0;  	srbm_soft_reset = adev->sdma.srbm_soft_reset; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 8bd08925b370..3de7bca5854b 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -3499,6 +3499,12 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,  		max_sclk = 75000;  		max_mclk = 80000;  	} +	/* Limit clocks for some HD8600 parts */ +	if (adev->pdev->device == 0x6660 && +	    adev->pdev->revision == 0x83) { +		max_sclk = 75000; +		max_mclk = 80000; +	}  	if (rps->vce_active) {  		rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index d127d59f953a..b4ea229bb449 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -373,7 +373,7 @@ static int tonga_ih_wait_for_idle(void *handle)  	return -ETIMEDOUT;  } -static int tonga_ih_check_soft_reset(void *handle) +static bool tonga_ih_check_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset = 0; @@ -384,21 +384,19 @@ static int tonga_ih_check_soft_reset(void *handle)  						SOFT_RESET_IH, 1);  	if (srbm_soft_reset) { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang = true;  		adev->irq.srbm_soft_reset = srbm_soft_reset; +		return true;  	} else { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang = false;  		adev->irq.srbm_soft_reset = 0; +		return false;  	} - -	return 0;  }  static int tonga_ih_pre_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang) +	if (!adev->irq.srbm_soft_reset)  		return 0;  	return tonga_ih_hw_fini(adev); @@ -408,7 +406,7 @@ static int tonga_ih_post_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang) +	if (!adev->irq.srbm_soft_reset)  		return 0;  	return tonga_ih_hw_init(adev); @@ -419,7 +417,7 @@ static int tonga_ih_soft_reset(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang) +	if (!adev->irq.srbm_soft_reset)  		return 0;  	srbm_soft_reset = adev->irq.srbm_soft_reset; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index e0fd9f21ed95..ab3df6d75656 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -770,7 +770,7 @@ static int uvd_v6_0_wait_for_idle(void *handle)  }  #define AMDGPU_UVD_STATUS_BUSY_MASK    0xfd -static int uvd_v6_0_check_soft_reset(void *handle) +static bool uvd_v6_0_check_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset = 0; @@ -782,19 +782,19 @@ static int uvd_v6_0_check_soft_reset(void *handle)  		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_UVD, 1);  	if (srbm_soft_reset) { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang = true;  		adev->uvd.srbm_soft_reset = srbm_soft_reset; +		return true;  	} else { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang = false;  		adev->uvd.srbm_soft_reset = 0; +		return false;  	} -	return 0;  } +  static int uvd_v6_0_pre_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang) +	if (!adev->uvd.srbm_soft_reset)  		return 0;  	uvd_v6_0_stop(adev); @@ -806,7 +806,7 @@ static int uvd_v6_0_soft_reset(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang) +	if (!adev->uvd.srbm_soft_reset)  		return 0;  	srbm_soft_reset = adev->uvd.srbm_soft_reset; @@ -836,7 +836,7 @@ static int uvd_v6_0_post_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang) +	if (!adev->uvd.srbm_soft_reset)  		return 0;  	mdelay(5); diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 3f6db4ec0102..8533269ec160 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -561,7 +561,7 @@ static int vce_v3_0_wait_for_idle(void *handle)  #define  AMDGPU_VCE_STATUS_BUSY_MASK (VCE_STATUS_VCPU_REPORT_AUTO_BUSY_MASK | \  				      VCE_STATUS_VCPU_REPORT_RB0_BUSY_MASK) -static int vce_v3_0_check_soft_reset(void *handle) +static bool vce_v3_0_check_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset = 0; @@ -591,16 +591,15 @@ static int vce_v3_0_check_soft_reset(void *handle)  		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);  	}  	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0); +	mutex_unlock(&adev->grbm_idx_mutex);  	if (srbm_soft_reset) { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = true;  		adev->vce.srbm_soft_reset = srbm_soft_reset; +		return true;  	} else { -		adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = false;  		adev->vce.srbm_soft_reset = 0; +		return false;  	} -	mutex_unlock(&adev->grbm_idx_mutex); -	return 0;  }  static int vce_v3_0_soft_reset(void *handle) @@ -608,7 +607,7 @@ static int vce_v3_0_soft_reset(void *handle)  	struct amdgpu_device *adev = (struct amdgpu_device *)handle;  	u32 srbm_soft_reset; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang) +	if (!adev->vce.srbm_soft_reset)  		return 0;  	srbm_soft_reset = adev->vce.srbm_soft_reset; @@ -638,7 +637,7 @@ static int vce_v3_0_pre_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang) +	if (!adev->vce.srbm_soft_reset)  		return 0;  	mdelay(5); @@ -651,7 +650,7 @@ static int vce_v3_0_post_soft_reset(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang) +	if (!adev->vce.srbm_soft_reset)  		return 0;  	mdelay(5); diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index c934b78c9e2f..bec8125bceb0 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -165,7 +165,7 @@ struct amd_ip_funcs {  	/* poll for idle */  	int (*wait_for_idle)(void *handle);  	/* check soft reset the IP block */ -	int (*check_soft_reset)(void *handle); +	bool (*check_soft_reset)(void *handle);  	/* pre soft reset the IP block */  	int (*pre_soft_reset)(void *handle);  	/* soft reset the IP block */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c index 92b117843875..8cee4e0f9fde 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c @@ -49,6 +49,7 @@ static const pem_event_action * const uninitialize_event[] = {  	uninitialize_display_phy_access_tasks,  	disable_gfx_voltage_island_power_gating_tasks,  	disable_gfx_clock_gating_tasks, +	uninitialize_thermal_controller_tasks,  	set_boot_state_tasks,  	adjust_power_state_tasks,  	disable_dynamic_state_management_tasks, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 7e4fcbbbe086..960424913496 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1785,6 +1785,21 @@ static int cz_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_c  	return 0;  } +static int cz_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ +	int actual_temp = 0; +	uint32_t val = cgs_read_ind_register(hwmgr->device, +					     CGS_IND_REG__SMC, ixTHM_TCON_CUR_TMP); +	uint32_t temp = PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP); + +	if (PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL)) +		actual_temp = ((temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; +	else +		actual_temp = (temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + +	return actual_temp; +} +  static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)  {  	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); @@ -1881,6 +1896,9 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value)  	case AMDGPU_PP_SENSOR_VCE_POWER:  		*value = cz_hwmgr->vce_power_gated ? 0 : 1;  		return 0; +	case AMDGPU_PP_SENSOR_GPU_TEMP: +		*value = cz_thermal_get_temperature(hwmgr); +		return 0;  	default:  		return -EINVAL;  	} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 508245d49d33..609996c84ad5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -1030,20 +1030,19 @@ static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)  	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);  	/* disable SCLK dpm */ -	if (!data->sclk_dpm_key_disabled) -		PP_ASSERT_WITH_CODE( -				(smum_send_msg_to_smc(hwmgr->smumgr, -						PPSMC_MSG_DPM_Disable) == 0), -				"Failed to disable SCLK DPM!", -				return -EINVAL); +	if (!data->sclk_dpm_key_disabled) { +		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), +				"Trying to disable SCLK DPM when DPM is disabled", +				return 0); +		smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Disable); +	}  	/* disable MCLK dpm */  	if (!data->mclk_dpm_key_disabled) { -		PP_ASSERT_WITH_CODE( -				(smum_send_msg_to_smc(hwmgr->smumgr, -						PPSMC_MSG_MCLKDPM_Disable) == 0), -				"Failed to disable MCLK DPM!", -				return -EINVAL); +		PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), +				"Trying to disable MCLK DPM when DPM is disabled", +				return 0); +		smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_MCLKDPM_Disable);  	}  	return 0; @@ -1069,10 +1068,13 @@ static int smu7_stop_dpm(struct pp_hwmgr *hwmgr)  				return -EINVAL);  	} -	if (smu7_disable_sclk_mclk_dpm(hwmgr)) { -		printk(KERN_ERR "Failed to disable Sclk DPM and Mclk DPM!"); -		return -EINVAL; -	} +	smu7_disable_sclk_mclk_dpm(hwmgr); + +	PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), +			"Trying to disable voltage DPM when DPM is disabled", +			return 0); + +	smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Disable);  	return 0;  } @@ -1226,7 +1228,7 @@ int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)  	PP_ASSERT_WITH_CODE((0 == tmp_result),  			"Failed to enable VR hot GPIO interrupt!", result = tmp_result); -	smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_HasDisplay); +	smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_NoDisplay);  	tmp_result = smu7_enable_sclk_control(hwmgr);  	PP_ASSERT_WITH_CODE((0 == tmp_result), @@ -1306,6 +1308,12 @@ int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)  	PP_ASSERT_WITH_CODE((tmp_result == 0),  			"Failed to disable thermal auto throttle!", result = tmp_result); +	if (1 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) { +		PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DisableAvfs)), +					"Failed to disable AVFS!", +					return -EINVAL); +	} +  	tmp_result = smu7_stop_dpm(hwmgr);  	PP_ASSERT_WITH_CODE((tmp_result == 0),  			"Failed to stop DPM!", result = tmp_result); @@ -1452,8 +1460,10 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr)  	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL; -	if (table_info != NULL) -		sclk_table = table_info->vdd_dep_on_sclk; +	if (table_info == NULL) +		return -EINVAL; + +	sclk_table = table_info->vdd_dep_on_sclk;  	for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) {  		vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; @@ -3802,13 +3812,15 @@ static inline bool smu7_are_power_levels_equal(const struct smu7_performance_lev  int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal)  { -	const struct smu7_power_state *psa = cast_const_phw_smu7_power_state(pstate1); -	const struct smu7_power_state *psb = cast_const_phw_smu7_power_state(pstate2); +	const struct smu7_power_state *psa; +	const struct smu7_power_state *psb;  	int i;  	if (pstate1 == NULL || pstate2 == NULL || equal == NULL)  		return -EINVAL; +	psa = cast_const_phw_smu7_power_state(pstate1); +	psb = cast_const_phw_smu7_power_state(pstate2);  	/* If the two states don't even have the same number of performance levels they cannot be the same state. */  	if (psa->performance_level_count != psb->performance_level_count) {  		*equal = false; @@ -4324,6 +4336,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {  	.set_mclk_od = smu7_set_mclk_od,  	.get_clock_by_type = smu7_get_clock_by_type,  	.read_sensor = smu7_read_sensor, +	.dynamic_state_management_disable = smu7_disable_dpm_tasks,  };  uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c index eda802bc63c8..8c889caba420 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c @@ -2458,7 +2458,7 @@ static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr,  			PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE),  				"Invalid VramInfo table.", return -EINVAL); -			if (!data->is_memory_gddr5) { +			if (!data->is_memory_gddr5 && j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE) {  				table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD;  				table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD;  				for (k = 0; k < table->num_entries; k++) { diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 2f58e9e2a59c..a51f8cbcfe26 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -332,17 +332,19 @@ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms)  {  	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); -	if (dcrtc->dpms != dpms) { -		dcrtc->dpms = dpms; -		if (!IS_ERR(dcrtc->clk) && !dpms_blanked(dpms)) -			WARN_ON(clk_prepare_enable(dcrtc->clk)); -		armada_drm_crtc_update(dcrtc); -		if (!IS_ERR(dcrtc->clk) && dpms_blanked(dpms)) -			clk_disable_unprepare(dcrtc->clk); +	if (dpms_blanked(dcrtc->dpms) != dpms_blanked(dpms)) {  		if (dpms_blanked(dpms))  			armada_drm_vblank_off(dcrtc); -		else +		else if (!IS_ERR(dcrtc->clk)) +			WARN_ON(clk_prepare_enable(dcrtc->clk)); +		dcrtc->dpms = dpms; +		armada_drm_crtc_update(dcrtc); +		if (!dpms_blanked(dpms))  			drm_crtc_vblank_on(&dcrtc->crtc); +		else if (!IS_ERR(dcrtc->clk)) +			clk_disable_unprepare(dcrtc->clk); +	} else if (dcrtc->dpms != dpms) { +		dcrtc->dpms = dpms;  	}  } diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 1df2d33d0b40..ffb2ab389d1d 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -54,9 +54,6 @@ int drm_name_info(struct seq_file *m, void *data)  	mutex_lock(&dev->master_mutex);  	master = dev->master; -	if (!master) -		goto out_unlock; -  	seq_printf(m, "%s", dev->driver->name);  	if (dev->dev)  		seq_printf(m, " dev=%s", dev_name(dev->dev)); @@ -65,7 +62,6 @@ int drm_name_info(struct seq_file *m, void *data)  	if (dev->unique)  		seq_printf(m, " unique=%s", dev->unique);  	seq_printf(m, "\n"); -out_unlock:  	mutex_unlock(&dev->master_mutex);  	return 0; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index cb86c7e5495c..d9230132dfbc 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -329,20 +329,34 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,  	/*  	 * Append a LINK to the submitted command buffer to return to  	 * the ring buffer.  return_target is the ring target address. -	 * We need three dwords: event, wait, link. +	 * We need at most 7 dwords in the return target: 2 cache flush + +	 * 2 semaphore stall + 1 event + 1 wait + 1 link.  	 */ -	return_dwords = 3; +	return_dwords = 7;  	return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords);  	CMD_LINK(cmdbuf, return_dwords, return_target);  	/* -	 * Append event, wait and link pointing back to the wait -	 * command to the ring buffer. +	 * Append a cache flush, stall, event, wait and link pointing back to +	 * the wait command to the ring buffer.  	 */ +	if (gpu->exec_state == ETNA_PIPE_2D) { +		CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, +				       VIVS_GL_FLUSH_CACHE_PE2D); +	} else { +		CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, +				       VIVS_GL_FLUSH_CACHE_DEPTH | +				       VIVS_GL_FLUSH_CACHE_COLOR); +		CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, +				       VIVS_TS_FLUSH_CACHE_FLUSH); +	} +	CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); +	CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);  	CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |  		       VIVS_GL_EVENT_FROM_PE);  	CMD_WAIT(buffer); -	CMD_LINK(buffer, 2, return_target + 8); +	CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + +			    buffer->user_size - 4);  	if (drm_debug & DRM_UT_DRIVER)  		pr_info("stream link to 0x%08x @ 0x%08x %p\n", diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 5ce3603e6eac..0370b842d9cc 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -748,19 +748,22 @@ static struct page **etnaviv_gem_userptr_do_get_pages(  	int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT;  	struct page **pvec;  	uintptr_t ptr; +	unsigned int flags = 0;  	pvec = drm_malloc_ab(npages, sizeof(struct page *));  	if (!pvec)  		return ERR_PTR(-ENOMEM); +	if (!etnaviv_obj->userptr.ro) +		flags |= FOLL_WRITE; +  	pinned = 0;  	ptr = etnaviv_obj->userptr.ptr;  	down_read(&mm->mmap_sem);  	while (pinned < npages) {  		ret = get_user_pages_remote(task, mm, ptr, npages - pinned, -					    !etnaviv_obj->userptr.ro, 0, -					    pvec + pinned, NULL); +					    flags, pvec + pinned, NULL);  		if (ret < 0)  			break; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index d3796ed8d8c5..169ac96e8f08 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -330,7 +330,8 @@ u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu,  			return (u32)buf->vram_node.start;  		mutex_lock(&mmu->lock); -		ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, buf->size); +		ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, +					      buf->size + SZ_64K);  		if (ret < 0) {  			mutex_unlock(&mmu->lock);  			return 0; diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index aa92decf4233..fbd13fabdf2d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -488,7 +488,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,  		goto err_free;  	} -	ret = get_vaddr_frames(start, npages, true, true, g2d_userptr->vec); +	ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE, +		g2d_userptr->vec);  	if (ret != npages) {  		DRM_ERROR("failed to get user pages from userptr.\n");  		if (ret < 0) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c index 3371635cd4d7..b2d5e188b1b8 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c @@ -51,6 +51,7 @@ static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc)  			   DCU_MODE_DCU_MODE(DCU_MODE_OFF));  	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE,  		     DCU_UPDATE_MODE_READREG); +	clk_disable_unprepare(fsl_dev->pix_clk);  }  static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc) @@ -58,6 +59,7 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)  	struct drm_device *dev = crtc->dev;  	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; +	clk_prepare_enable(fsl_dev->pix_clk);  	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE,  			   DCU_MODE_DCU_MODE_MASK,  			   DCU_MODE_DCU_MODE(DCU_MODE_NORMAL)); @@ -116,8 +118,6 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)  		     DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) |  		     DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) |  		     DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL)); -	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, -		     DCU_UPDATE_MODE_READREG);  	return;  } diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 0884c45aefe8..e04efbed1a54 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -267,12 +267,8 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)  		return ret;  	} -	ret = clk_prepare_enable(fsl_dev->pix_clk); -	if (ret < 0) { -		dev_err(dev, "failed to enable pix clk\n"); -		goto disable_dcu_clk; -	} - +	if (fsl_dev->tcon) +		fsl_tcon_bypass_enable(fsl_dev->tcon);  	fsl_dcu_drm_init_planes(fsl_dev->drm);  	drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state); @@ -284,10 +280,6 @@ static int fsl_dcu_drm_pm_resume(struct device *dev)  	enable_irq(fsl_dev->irq);  	return 0; - -disable_dcu_clk: -	clk_disable_unprepare(fsl_dev->clk); -	return ret;  }  #endif @@ -401,18 +393,12 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)  		goto disable_clk;  	} -	ret = clk_prepare_enable(fsl_dev->pix_clk); -	if (ret < 0) { -		dev_err(dev, "failed to enable pix clk\n"); -		goto unregister_pix_clk; -	} -  	fsl_dev->tcon = fsl_tcon_init(dev);  	drm = drm_dev_alloc(driver, dev);  	if (IS_ERR(drm)) {  		ret = PTR_ERR(drm); -		goto disable_pix_clk; +		goto unregister_pix_clk;  	}  	fsl_dev->dev = dev; @@ -433,8 +419,6 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)  unref:  	drm_dev_unref(drm); -disable_pix_clk: -	clk_disable_unprepare(fsl_dev->pix_clk);  unregister_pix_clk:  	clk_unregister(fsl_dev->pix_clk);  disable_clk: @@ -447,7 +431,6 @@ static int fsl_dcu_drm_remove(struct platform_device *pdev)  	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);  	clk_disable_unprepare(fsl_dev->clk); -	clk_disable_unprepare(fsl_dev->pix_clk);  	clk_unregister(fsl_dev->pix_clk);  	drm_put_dev(fsl_dev->drm); diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index a7e5486bd1e9..9e6f7d8112b3 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -211,11 +211,6 @@ void fsl_dcu_drm_init_planes(struct drm_device *dev)  		for (j = 1; j <= fsl_dev->soc->layer_regs; j++)  			regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0);  	} -	regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, -			   DCU_MODE_DCU_MODE_MASK, -			   DCU_MODE_DCU_MODE(DCU_MODE_OFF)); -	regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, -		     DCU_UPDATE_MODE_READREG);  }  struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev) diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index 26edcc899712..e1dd75b18118 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c @@ -20,38 +20,6 @@  #include "fsl_dcu_drm_drv.h"  #include "fsl_tcon.h" -static int -fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder, -				 struct drm_crtc_state *crtc_state, -				 struct drm_connector_state *conn_state) -{ -	return 0; -} - -static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder) -{ -	struct drm_device *dev = encoder->dev; -	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; - -	if (fsl_dev->tcon) -		fsl_tcon_bypass_disable(fsl_dev->tcon); -} - -static void fsl_dcu_drm_encoder_enable(struct drm_encoder *encoder) -{ -	struct drm_device *dev = encoder->dev; -	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; - -	if (fsl_dev->tcon) -		fsl_tcon_bypass_enable(fsl_dev->tcon); -} - -static const struct drm_encoder_helper_funcs encoder_helper_funcs = { -	.atomic_check = fsl_dcu_drm_encoder_atomic_check, -	.disable = fsl_dcu_drm_encoder_disable, -	.enable = fsl_dcu_drm_encoder_enable, -}; -  static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder)  {  	drm_encoder_cleanup(encoder); @@ -68,13 +36,16 @@ int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,  	int ret;  	encoder->possible_crtcs = 1; + +	/* Use bypass mode for parallel RGB/LVDS encoder */ +	if (fsl_dev->tcon) +		fsl_tcon_bypass_enable(fsl_dev->tcon); +  	ret = drm_encoder_init(fsl_dev->drm, encoder, &encoder_funcs,  			       DRM_MODE_ENCODER_LVDS, NULL);  	if (ret < 0)  		return ret; -	drm_encoder_helper_add(encoder, &encoder_helper_funcs); -  	return 0;  } diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index e537930c64b5..c6f780f5abc9 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -508,6 +508,10 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)  	pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY);  	if (pvec != NULL) {  		struct mm_struct *mm = obj->userptr.mm->mm; +		unsigned int flags = 0; + +		if (!obj->userptr.read_only) +			flags |= FOLL_WRITE;  		ret = -EFAULT;  		if (atomic_inc_not_zero(&mm->mm_users)) { @@ -517,7 +521,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)  					(work->task, mm,  					 obj->userptr.ptr + pinned * PAGE_SIZE,  					 npages - pinned, -					 !obj->userptr.read_only, 0, +					 flags,  					 pvec + pinned, NULL);  				if (ret < 0)  					break; diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 6a4b020dd0b4..5a26eb4545aa 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -156,19 +156,20 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)  	struct drm_device *dev = rdev->ddev;  	struct drm_crtc *crtc;  	struct radeon_crtc *radeon_crtc; -	u32 line_time_us, vblank_lines; +	u32 vblank_in_pixels;  	u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */  	if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {  		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {  			radeon_crtc = to_radeon_crtc(crtc);  			if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { -				line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) / -					radeon_crtc->hw_mode.clock; -				vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end - -					radeon_crtc->hw_mode.crtc_vdisplay + -					(radeon_crtc->v_border * 2); -				vblank_time_us = vblank_lines * line_time_us; +				vblank_in_pixels = +					radeon_crtc->hw_mode.crtc_htotal * +					(radeon_crtc->hw_mode.crtc_vblank_end - +					 radeon_crtc->hw_mode.crtc_vdisplay + +					 (radeon_crtc->v_border * 2)); + +				vblank_time_us = vblank_in_pixels * 1000 / radeon_crtc->hw_mode.clock;  				break;  			}  		} diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 50e96d2c593d..e18839d52e3e 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -927,6 +927,16 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)  	return ret;  } +static void radeon_connector_unregister(struct drm_connector *connector) +{ +	struct radeon_connector *radeon_connector = to_radeon_connector(connector); + +	if (radeon_connector->ddc_bus->has_aux) { +		drm_dp_aux_unregister(&radeon_connector->ddc_bus->aux); +		radeon_connector->ddc_bus->has_aux = false; +	} +} +  static void radeon_connector_destroy(struct drm_connector *connector)  {  	struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -984,6 +994,7 @@ static const struct drm_connector_funcs radeon_lvds_connector_funcs = {  	.dpms = drm_helper_connector_dpms,  	.detect = radeon_lvds_detect,  	.fill_modes = drm_helper_probe_single_connector_modes, +	.early_unregister = radeon_connector_unregister,  	.destroy = radeon_connector_destroy,  	.set_property = radeon_lvds_set_property,  }; @@ -1111,6 +1122,7 @@ static const struct drm_connector_funcs radeon_vga_connector_funcs = {  	.dpms = drm_helper_connector_dpms,  	.detect = radeon_vga_detect,  	.fill_modes = drm_helper_probe_single_connector_modes, +	.early_unregister = radeon_connector_unregister,  	.destroy = radeon_connector_destroy,  	.set_property = radeon_connector_set_property,  }; @@ -1188,6 +1200,7 @@ static const struct drm_connector_funcs radeon_tv_connector_funcs = {  	.dpms = drm_helper_connector_dpms,  	.detect = radeon_tv_detect,  	.fill_modes = drm_helper_probe_single_connector_modes, +	.early_unregister = radeon_connector_unregister,  	.destroy = radeon_connector_destroy,  	.set_property = radeon_connector_set_property,  }; @@ -1519,6 +1532,7 @@ static const struct drm_connector_funcs radeon_dvi_connector_funcs = {  	.detect = radeon_dvi_detect,  	.fill_modes = drm_helper_probe_single_connector_modes,  	.set_property = radeon_connector_set_property, +	.early_unregister = radeon_connector_unregister,  	.destroy = radeon_connector_destroy,  	.force = radeon_dvi_force,  }; @@ -1832,6 +1846,7 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = {  	.detect = radeon_dp_detect,  	.fill_modes = drm_helper_probe_single_connector_modes,  	.set_property = radeon_connector_set_property, +	.early_unregister = radeon_connector_unregister,  	.destroy = radeon_connector_destroy,  	.force = radeon_dvi_force,  }; @@ -1841,6 +1856,7 @@ static const struct drm_connector_funcs radeon_edp_connector_funcs = {  	.detect = radeon_dp_detect,  	.fill_modes = drm_helper_probe_single_connector_modes,  	.set_property = radeon_lvds_set_property, +	.early_unregister = radeon_connector_unregister,  	.destroy = radeon_connector_destroy,  	.force = radeon_dvi_force,  }; @@ -1850,6 +1866,7 @@ static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = {  	.detect = radeon_dp_detect,  	.fill_modes = drm_helper_probe_single_connector_modes,  	.set_property = radeon_lvds_set_property, +	.early_unregister = radeon_connector_unregister,  	.destroy = radeon_connector_destroy,  	.force = radeon_dvi_force,  }; diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index b8ab30a7dd6d..cdb8cb568c15 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1675,20 +1675,20 @@ int radeon_modeset_init(struct radeon_device *rdev)  void radeon_modeset_fini(struct radeon_device *rdev)  { -	radeon_fbdev_fini(rdev); -	kfree(rdev->mode_info.bios_hardcoded_edid); - -	/* free i2c buses */ -	radeon_i2c_fini(rdev); -  	if (rdev->mode_info.mode_config_initialized) { -		radeon_afmt_fini(rdev);  		drm_kms_helper_poll_fini(rdev->ddev);  		radeon_hpd_fini(rdev);  		drm_crtc_force_disable_all(rdev->ddev); +		radeon_fbdev_fini(rdev); +		radeon_afmt_fini(rdev);  		drm_mode_config_cleanup(rdev->ddev);  		rdev->mode_info.mode_config_initialized = false;  	} + +	kfree(rdev->mode_info.bios_hardcoded_edid); + +	/* free i2c buses */ +	radeon_i2c_fini(rdev);  }  static bool is_hdtv_mode(const struct drm_display_mode *mode) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 91c8f4339566..00ea0002b539 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -96,9 +96,10 @@   *   2.45.0 - Allow setting shader registers using DMA/COPY packet3 on SI   *   2.46.0 - Add PFP_SYNC_ME support on evergreen   *   2.47.0 - Add UVD_NO_OP register support + *   2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI   */  #define KMS_DRIVER_MAJOR	2 -#define KMS_DRIVER_MINOR	47 +#define KMS_DRIVER_MINOR	48  #define KMS_DRIVER_PATCHLEVEL	0  int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);  int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 021aa005623f..29f7817af821 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -982,9 +982,8 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)  {  	if (!i2c)  		return; +	WARN_ON(i2c->has_aux);  	i2c_del_adapter(&i2c->adapter); -	if (i2c->has_aux) -		drm_dp_aux_unregister(&i2c->aux);  	kfree(i2c);  } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 455268214b89..3de5e6e21662 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -566,7 +566,8 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm)  		uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE;  		struct page **pages = ttm->pages + pinned; -		r = get_user_pages(userptr, num_pages, write, 0, pages, NULL); +		r = get_user_pages(userptr, num_pages, write ? FOLL_WRITE : 0, +				   pages, NULL);  		if (r < 0)  			goto release_pages; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 7ee9aafbdf74..e402be8821c4 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -4431,6 +4431,7 @@ static bool si_vm_reg_valid(u32 reg)  	case SPI_CONFIG_CNTL:  	case SPI_CONFIG_CNTL_1:  	case TA_CNTL_AUX: +	case TA_CS_BC_BASE_ADDR:  		return true;  	default:  		DRM_ERROR("Invalid register 0x%x in CS\n", reg); diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index eb220eecba78..65a911ddd509 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -1145,6 +1145,7 @@  #define	SPI_LB_CU_MASK					0x9354  #define	TA_CNTL_AUX					0x9508 +#define	TA_CS_BC_BASE_ADDR				0x950C  #define CC_RB_BACKEND_DISABLE				0x98F4  #define		BACKEND_DISABLE(x)     			((x) << 16) diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c index 7e2a12c4fed2..1a3ad769f8c8 100644 --- a/drivers/gpu/drm/via/via_dmablit.c +++ b/drivers/gpu/drm/via/via_dmablit.c @@ -241,8 +241,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)  	down_read(¤t->mm->mmap_sem);  	ret = get_user_pages((unsigned long)xfer->mem_addr,  			     vsg->num_pages, -			     (vsg->direction == DMA_FROM_DEVICE), -			     0, vsg->pages, NULL); +			     (vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0, +			     vsg->pages, NULL);  	up_read(¤t->mm->mmap_sem);  	if (ret != vsg->num_pages) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index e8ae3dc476d1..18061a4bc2f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -241,15 +241,15 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,  			      void *ptr);  MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); -module_param_named(enable_fbdev, enable_fbdev, int, 0600); +module_param_named(enable_fbdev, enable_fbdev, int, S_IRUSR | S_IWUSR);  MODULE_PARM_DESC(force_dma_api, "Force using the DMA API for TTM pages"); -module_param_named(force_dma_api, vmw_force_iommu, int, 0600); +module_param_named(force_dma_api, vmw_force_iommu, int, S_IRUSR | S_IWUSR);  MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages"); -module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600); +module_param_named(restrict_iommu, vmw_restrict_iommu, int, S_IRUSR | S_IWUSR);  MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages"); -module_param_named(force_coherent, vmw_force_coherent, int, 0600); +module_param_named(force_coherent, vmw_force_coherent, int, S_IRUSR | S_IWUSR);  MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU"); -module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600); +module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, S_IRUSR | S_IWUSR);  MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");  module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 070d750af16d..1e59a486bba8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -43,7 +43,7 @@  #define VMWGFX_DRIVER_DATE "20160210"  #define VMWGFX_DRIVER_MAJOR 2 -#define VMWGFX_DRIVER_MINOR 10 +#define VMWGFX_DRIVER_MINOR 11  #define VMWGFX_DRIVER_PATCHLEVEL 0  #define VMWGFX_FILE_PAGE_OFFSET 0x00100000  #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index dc5beff2b4aa..c7b53d987f06 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -35,17 +35,37 @@  #define VMW_RES_HT_ORDER 12  /** + * enum vmw_resource_relocation_type - Relocation type for resources + * + * @vmw_res_rel_normal: Traditional relocation. The resource id in the + * command stream is replaced with the actual id after validation. + * @vmw_res_rel_nop: NOP relocation. The command is unconditionally replaced + * with a NOP. + * @vmw_res_rel_cond_nop: Conditional NOP relocation. If the resource id + * after validation is -1, the command is replaced with a NOP. Otherwise no + * action. + */ +enum vmw_resource_relocation_type { +	vmw_res_rel_normal, +	vmw_res_rel_nop, +	vmw_res_rel_cond_nop, +	vmw_res_rel_max +}; + +/**   * struct vmw_resource_relocation - Relocation info for resources   *   * @head: List head for the software context's relocation list.   * @res: Non-ref-counted pointer to the resource. - * @offset: Offset of 4 byte entries into the command buffer where the + * @offset: Offset of single byte entries into the command buffer where the   * id that needs fixup is located. + * @rel_type: Type of relocation.   */  struct vmw_resource_relocation {  	struct list_head head;  	const struct vmw_resource *res; -	unsigned long offset; +	u32 offset:29; +	enum vmw_resource_relocation_type rel_type:3;  };  /** @@ -109,7 +129,18 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,  				   struct vmw_dma_buffer *vbo,  				   bool validate_as_mob,  				   uint32_t *p_val_node); - +/** + * vmw_ptr_diff - Compute the offset from a to b in bytes + * + * @a: A starting pointer. + * @b: A pointer offset in the same address space. + * + * Returns: The offset in bytes between the two pointers. + */ +static size_t vmw_ptr_diff(void *a, void *b) +{ +	return (unsigned long) b - (unsigned long) a; +}  /**   * vmw_resources_unreserve - unreserve resources previously reserved for @@ -409,11 +440,14 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,   * @list: Pointer to head of relocation list.   * @res: The resource.   * @offset: Offset into the command buffer currently being parsed where the - * id that needs fixup is located. Granularity is 4 bytes. + * id that needs fixup is located. Granularity is one byte. + * @rel_type: Relocation type.   */  static int vmw_resource_relocation_add(struct list_head *list,  				       const struct vmw_resource *res, -				       unsigned long offset) +				       unsigned long offset, +				       enum vmw_resource_relocation_type +				       rel_type)  {  	struct vmw_resource_relocation *rel; @@ -425,6 +459,7 @@ static int vmw_resource_relocation_add(struct list_head *list,  	rel->res = res;  	rel->offset = offset; +	rel->rel_type = rel_type;  	list_add_tail(&rel->head, list);  	return 0; @@ -459,11 +494,24 @@ static void vmw_resource_relocations_apply(uint32_t *cb,  {  	struct vmw_resource_relocation *rel; +	/* Validate the struct vmw_resource_relocation member size */ +	BUILD_BUG_ON(SVGA_CB_MAX_SIZE >= (1 << 29)); +	BUILD_BUG_ON(vmw_res_rel_max >= (1 << 3)); +  	list_for_each_entry(rel, list, head) { -		if (likely(rel->res != NULL)) -			cb[rel->offset] = rel->res->id; -		else -			cb[rel->offset] = SVGA_3D_CMD_NOP; +		u32 *addr = (u32 *)((unsigned long) cb + rel->offset); +		switch (rel->rel_type) { +		case vmw_res_rel_normal: +			*addr = rel->res->id; +			break; +		case vmw_res_rel_nop: +			*addr = SVGA_3D_CMD_NOP; +			break; +		default: +			if (rel->res->id == -1) +				*addr = SVGA_3D_CMD_NOP; +			break; +		}  	}  } @@ -655,7 +703,9 @@ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,  	*p_val = NULL;  	ret = vmw_resource_relocation_add(&sw_context->res_relocations,  					  res, -					  id_loc - sw_context->buf_start); +					  vmw_ptr_diff(sw_context->buf_start, +						       id_loc), +					  vmw_res_rel_normal);  	if (unlikely(ret != 0))  		return ret; @@ -721,7 +771,8 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,  		return vmw_resource_relocation_add  			(&sw_context->res_relocations, res, -			 id_loc - sw_context->buf_start); +			 vmw_ptr_diff(sw_context->buf_start, id_loc), +			 vmw_res_rel_normal);  	}  	ret = vmw_user_resource_lookup_handle(dev_priv, @@ -2143,10 +2194,10 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv,  		return ret;  	return vmw_resource_relocation_add(&sw_context->res_relocations, -					   NULL, &cmd->header.id - -					   sw_context->buf_start); - -	return 0; +					   NULL, +					   vmw_ptr_diff(sw_context->buf_start, +							&cmd->header.id), +					   vmw_res_rel_nop);  }  /** @@ -2188,10 +2239,10 @@ static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv,  		return ret;  	return vmw_resource_relocation_add(&sw_context->res_relocations, -					   NULL, &cmd->header.id - -					   sw_context->buf_start); - -	return 0; +					   NULL, +					   vmw_ptr_diff(sw_context->buf_start, +							&cmd->header.id), +					   vmw_res_rel_nop);  }  /** @@ -2848,8 +2899,7 @@ static int vmw_cmd_dx_cid_check(struct vmw_private *dev_priv,   * @header: Pointer to the command header in the command stream.   *   * Check that the view exists, and if it was not created using this - * command batch, make sure it's validated (present in the device) so that - * the remove command will not confuse the device. + * command batch, conditionally make this command a NOP.   */  static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv,  				  struct vmw_sw_context *sw_context, @@ -2877,10 +2927,16 @@ static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv,  		return ret;  	/* -	 * Add view to the validate list iff it was not created using this -	 * command batch. +	 * If the view wasn't created during this command batch, it might +	 * have been removed due to a context swapout, so add a +	 * relocation to conditionally make this command a NOP to avoid +	 * device errors.  	 */ -	return vmw_view_res_val_add(sw_context, view); +	return vmw_resource_relocation_add(&sw_context->res_relocations, +					   view, +					   vmw_ptr_diff(sw_context->buf_start, +							&cmd->header.id), +					   vmw_res_rel_cond_nop);  }  /** @@ -3029,6 +3085,35 @@ static int vmw_cmd_dx_genmips(struct vmw_private *dev_priv,  				   cmd->body.shaderResourceViewId);  } +/** + * vmw_cmd_dx_transfer_from_buffer - + * Validate an SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER command + * + * @dev_priv: Pointer to a device private struct. + * @sw_context: The software context being used for this batch. + * @header: Pointer to the command header in the command stream. + */ +static int vmw_cmd_dx_transfer_from_buffer(struct vmw_private *dev_priv, +					   struct vmw_sw_context *sw_context, +					   SVGA3dCmdHeader *header) +{ +	struct { +		SVGA3dCmdHeader header; +		SVGA3dCmdDXTransferFromBuffer body; +	} *cmd = container_of(header, typeof(*cmd), header); +	int ret; + +	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, +				user_surface_converter, +				&cmd->body.srcSid, NULL); +	if (ret != 0) +		return ret; + +	return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, +				 user_surface_converter, +				 &cmd->body.destSid, NULL); +} +  static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,  				struct vmw_sw_context *sw_context,  				void *buf, uint32_t *size) @@ -3379,6 +3464,9 @@ static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {  		    &vmw_cmd_buffer_copy_check, true, false, true),  	VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY_REGION,  		    &vmw_cmd_pred_copy_check, true, false, true), +	VMW_CMD_DEF(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER, +		    &vmw_cmd_dx_transfer_from_buffer, +		    true, false, true),  };  static int vmw_cmd_check(struct vmw_private *dev_priv, @@ -3848,14 +3936,14 @@ static void *vmw_execbuf_cmdbuf(struct vmw_private *dev_priv,  	int ret;  	*header = NULL; -	if (!dev_priv->cman || kernel_commands) -		return kernel_commands; -  	if (command_size > SVGA_CB_MAX_SIZE) {  		DRM_ERROR("Command buffer is too large.\n");  		return ERR_PTR(-EINVAL);  	} +	if (!dev_priv->cman || kernel_commands) +		return kernel_commands; +  	/* If possible, add a little space for fencing. */  	cmdbuf_size = command_size + 512;  	cmdbuf_size = min_t(size_t, cmdbuf_size, SVGA_CB_MAX_SIZE); @@ -4232,9 +4320,6 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,  	ttm_bo_unref(&query_val.bo);  	ttm_bo_unref(&pinned_val.bo);  	vmw_dmabuf_unreference(&dev_priv->pinned_bo); -	DRM_INFO("Dummy query bo pin count: %d\n", -		 dev_priv->dummy_query_bo->pin_count); -  out_unlock:  	return; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 6a328d507a28..52ca1c9d070e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -574,10 +574,8 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo,  		bool nonblock = !!(flags & drm_vmw_synccpu_dontblock);  		long lret; -		if (nonblock) -			return reservation_object_test_signaled_rcu(bo->resv, true) ? 0 : -EBUSY; - -		lret = reservation_object_wait_timeout_rcu(bo->resv, true, true, MAX_SCHEDULE_TIMEOUT); +		lret = reservation_object_wait_timeout_rcu(bo->resv, true, true, +					nonblock ? 0 : MAX_SCHEDULE_TIMEOUT);  		if (!lret)  			return -EBUSY;  		else if (lret < 0) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index c2a721a8cef9..b445ce9b9757 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -324,7 +324,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)  	if (res->id != -1) {  		cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size()); -		if (unlikely(cmd == NULL)) { +		if (unlikely(!cmd)) {  			DRM_ERROR("Failed reserving FIFO space for surface "  				  "destruction.\n");  			return; @@ -397,7 +397,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res)  	submit_size = vmw_surface_define_size(srf);  	cmd = vmw_fifo_reserve(dev_priv, submit_size); -	if (unlikely(cmd == NULL)) { +	if (unlikely(!cmd)) {  		DRM_ERROR("Failed reserving FIFO space for surface "  			  "creation.\n");  		ret = -ENOMEM; @@ -446,11 +446,10 @@ static int vmw_legacy_srf_dma(struct vmw_resource *res,  	uint8_t *cmd;  	struct vmw_private *dev_priv = res->dev_priv; -	BUG_ON(val_buf->bo == NULL); - +	BUG_ON(!val_buf->bo);  	submit_size = vmw_surface_dma_size(srf);  	cmd = vmw_fifo_reserve(dev_priv, submit_size); -	if (unlikely(cmd == NULL)) { +	if (unlikely(!cmd)) {  		DRM_ERROR("Failed reserving FIFO space for surface "  			  "DMA.\n");  		return -ENOMEM; @@ -538,7 +537,7 @@ static int vmw_legacy_srf_destroy(struct vmw_resource *res)  	submit_size = vmw_surface_destroy_size();  	cmd = vmw_fifo_reserve(dev_priv, submit_size); -	if (unlikely(cmd == NULL)) { +	if (unlikely(!cmd)) {  		DRM_ERROR("Failed reserving FIFO space for surface "  			  "eviction.\n");  		return -ENOMEM; @@ -578,7 +577,7 @@ static int vmw_surface_init(struct vmw_private *dev_priv,  	int ret;  	struct vmw_resource *res = &srf->res; -	BUG_ON(res_free == NULL); +	BUG_ON(!res_free);  	if (!dev_priv->has_mob)  		vmw_fifo_resource_inc(dev_priv);  	ret = vmw_resource_init(dev_priv, res, true, res_free, @@ -700,7 +699,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,  	struct drm_vmw_surface_create_req *req = &arg->req;  	struct drm_vmw_surface_arg *rep = &arg->rep;  	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; -	struct drm_vmw_size __user *user_sizes;  	int ret;  	int i, j;  	uint32_t cur_bo_offset; @@ -748,7 +746,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,  	}  	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); -	if (unlikely(user_srf == NULL)) { +	if (unlikely(!user_srf)) {  		ret = -ENOMEM;  		goto out_no_user_srf;  	} @@ -763,29 +761,21 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,  	memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));  	srf->num_sizes = num_sizes;  	user_srf->size = size; - -	srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL); -	if (unlikely(srf->sizes == NULL)) { -		ret = -ENOMEM; +	srf->sizes = memdup_user((struct drm_vmw_size __user *)(unsigned long) +				 req->size_addr, +				 sizeof(*srf->sizes) * srf->num_sizes); +	if (IS_ERR(srf->sizes)) { +		ret = PTR_ERR(srf->sizes);  		goto out_no_sizes;  	} -	srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets), -			       GFP_KERNEL); -	if (unlikely(srf->offsets == NULL)) { +	srf->offsets = kmalloc_array(srf->num_sizes, +				     sizeof(*srf->offsets), +				     GFP_KERNEL); +	if (unlikely(!srf->offsets)) {  		ret = -ENOMEM;  		goto out_no_offsets;  	} -	user_sizes = (struct drm_vmw_size __user *)(unsigned long) -	    req->size_addr; - -	ret = copy_from_user(srf->sizes, user_sizes, -			     srf->num_sizes * sizeof(*srf->sizes)); -	if (unlikely(ret != 0)) { -		ret = -EFAULT; -		goto out_no_copy; -	} -  	srf->base_size = *srf->sizes;  	srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;  	srf->multisample_count = 0; @@ -923,7 +913,7 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,  	ret = -EINVAL;  	base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle); -	if (unlikely(base == NULL)) { +	if (unlikely(!base)) {  		DRM_ERROR("Could not find surface to reference.\n");  		goto out_no_lookup;  	} @@ -1069,7 +1059,7 @@ static int vmw_gb_surface_create(struct vmw_resource *res)  	cmd = vmw_fifo_reserve(dev_priv, submit_len);  	cmd2 = (typeof(cmd2))cmd; -	if (unlikely(cmd == NULL)) { +	if (unlikely(!cmd)) {  		DRM_ERROR("Failed reserving FIFO space for surface "  			  "creation.\n");  		ret = -ENOMEM; @@ -1135,7 +1125,7 @@ static int vmw_gb_surface_bind(struct vmw_resource *res,  	submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0);  	cmd1 = vmw_fifo_reserve(dev_priv, submit_size); -	if (unlikely(cmd1 == NULL)) { +	if (unlikely(!cmd1)) {  		DRM_ERROR("Failed reserving FIFO space for surface "  			  "binding.\n");  		return -ENOMEM; @@ -1185,7 +1175,7 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res,  	submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2));  	cmd = vmw_fifo_reserve(dev_priv, submit_size); -	if (unlikely(cmd == NULL)) { +	if (unlikely(!cmd)) {  		DRM_ERROR("Failed reserving FIFO space for surface "  			  "unbinding.\n");  		return -ENOMEM; @@ -1244,7 +1234,7 @@ static int vmw_gb_surface_destroy(struct vmw_resource *res)  	vmw_binding_res_list_scrub(&res->binding_head);  	cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); -	if (unlikely(cmd == NULL)) { +	if (unlikely(!cmd)) {  		DRM_ERROR("Failed reserving FIFO space for surface "  			  "destruction.\n");  		mutex_unlock(&dev_priv->binding_mutex); @@ -1410,7 +1400,7 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data,  	user_srf = container_of(base, struct vmw_user_surface, prime.base);  	srf = &user_srf->srf; -	if (srf->res.backup == NULL) { +	if (!srf->res.backup) {  		DRM_ERROR("Shared GB surface is missing a backup buffer.\n");  		goto out_bad_resource;  	} @@ -1524,7 +1514,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,  	}  	user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); -	if (unlikely(user_srf == NULL)) { +	if (unlikely(!user_srf)) {  		ret = -ENOMEM;  		goto out_no_user_srf;  	}  | 

