diff options
Diffstat (limited to 'drivers/gpu')
100 files changed, 937 insertions, 634 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 1cf78f4dd339..1e8e1123ddf4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -693,6 +693,10 @@ int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev)  			DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n",  				 adev->clock.default_dispclk / 100);  			adev->clock.default_dispclk = 60000; +		} else if (adev->clock.default_dispclk <= 60000) { +			DRM_INFO("Changing default dispclk from %dMhz to 625Mhz\n", +				 adev->clock.default_dispclk / 100); +			adev->clock.default_dispclk = 62500;  		}  		adev->clock.dp_extclk =  			le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index f2d705e6a75a..ab6b0d0febab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -449,6 +449,7 @@ static const struct pci_device_id pciidlist[] = {  	{0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},  	{0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},  	{0x1002, 0x6995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, +	{0x1002, 0x6997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},  	{0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},  	/* Vega 10 */  	{0x1002, 0x6860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index a4831fe0223b..a2c59a08b2bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -220,9 +220,9 @@ static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man,  }  const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = { -	amdgpu_vram_mgr_init, -	amdgpu_vram_mgr_fini, -	amdgpu_vram_mgr_new, -	amdgpu_vram_mgr_del, -	amdgpu_vram_mgr_debug +	.init		= amdgpu_vram_mgr_init, +	.takedown	= amdgpu_vram_mgr_fini, +	.get_node	= amdgpu_vram_mgr_new, +	.put_node	= amdgpu_vram_mgr_del, +	.debug		= amdgpu_vram_mgr_debug  }; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c index 8c9bc75a9c2d..8a0818b23ea4 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c @@ -165,7 +165,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state)  	struct drm_device *dev = crtc->dev;  	struct amdgpu_device *adev = dev->dev_private;  	int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); -	ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args; +	ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;  	memset(&args, 0, sizeof(args)); @@ -178,7 +178,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state)  void amdgpu_atombios_crtc_powergate_init(struct amdgpu_device *adev)  {  	int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); -	ENABLE_DISP_POWER_GATING_PARAMETERS_V2_1 args; +	ENABLE_DISP_POWER_GATING_PS_ALLOCATION args;  	memset(&args, 0, sizeof(args)); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 0cdeb6a2e4a0..5dffa27afa45 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -1207,8 +1207,11 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,  	u32 tmp, wm_mask, lb_vblank_lead_lines = 0;  	if (amdgpu_crtc->base.enabled && num_heads && mode) { -		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); +		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000, +					    (u32)mode->clock); +		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000, +					  (u32)mode->clock); +		line_time = min(line_time, (u32)65535);  		/* watermark for high clocks */  		if (adev->pm.dpm_enabled) { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 773654a19749..47bbc87f96d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -1176,8 +1176,11 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,  	u32 tmp, wm_mask, lb_vblank_lead_lines = 0;  	if (amdgpu_crtc->base.enabled && num_heads && mode) { -		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); +		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000, +					    (u32)mode->clock); +		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000, +					  (u32)mode->clock); +		line_time = min(line_time, (u32)65535);  		/* watermark for high clocks */  		if (adev->pm.dpm_enabled) { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 1f3552967ba3..d8c9a959493e 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -983,8 +983,11 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,  	fixed20_12 a, b, c;  	if (amdgpu_crtc->base.enabled && num_heads && mode) { -		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); +		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000, +					    (u32)mode->clock); +		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000, +					  (u32)mode->clock); +		line_time = min(line_time, (u32)65535);  		priority_a_cnt = 0;  		priority_b_cnt = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 3c558c170e5e..db30c6ba563a 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -1091,8 +1091,11 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,  	u32 tmp, wm_mask, lb_vblank_lead_lines = 0;  	if (amdgpu_crtc->base.enabled && num_heads && mode) { -		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); +		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000, +					    (u32)mode->clock); +		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000, +					  (u32)mode->clock); +		line_time = min(line_time, (u32)65535);  		/* watermark for high clocks */  		if (adev->pm.dpm_enabled) { diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index fb0819359909..90332f55cfba 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -77,13 +77,26 @@ static int vce_v3_0_set_clockgating_state(void *handle,  static uint64_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)  {  	struct amdgpu_device *adev = ring->adev; +	u32 v; + +	mutex_lock(&adev->grbm_idx_mutex); +	if (adev->vce.harvest_config == 0 || +		adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1) +		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0)); +	else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) +		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));  	if (ring == &adev->vce.ring[0]) -		return RREG32(mmVCE_RB_RPTR); +		v = RREG32(mmVCE_RB_RPTR);  	else if (ring == &adev->vce.ring[1]) -		return RREG32(mmVCE_RB_RPTR2); +		v = RREG32(mmVCE_RB_RPTR2);  	else -		return RREG32(mmVCE_RB_RPTR3); +		v = RREG32(mmVCE_RB_RPTR3); + +	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT); +	mutex_unlock(&adev->grbm_idx_mutex); + +	return v;  }  /** @@ -96,13 +109,26 @@ static uint64_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)  static uint64_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring)  {  	struct amdgpu_device *adev = ring->adev; +	u32 v; + +	mutex_lock(&adev->grbm_idx_mutex); +	if (adev->vce.harvest_config == 0 || +		adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1) +		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0)); +	else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) +		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));  	if (ring == &adev->vce.ring[0]) -		return RREG32(mmVCE_RB_WPTR); +		v = RREG32(mmVCE_RB_WPTR);  	else if (ring == &adev->vce.ring[1]) -		return RREG32(mmVCE_RB_WPTR2); +		v = RREG32(mmVCE_RB_WPTR2);  	else -		return RREG32(mmVCE_RB_WPTR3); +		v = RREG32(mmVCE_RB_WPTR3); + +	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT); +	mutex_unlock(&adev->grbm_idx_mutex); + +	return v;  }  /** @@ -116,12 +142,22 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)  {  	struct amdgpu_device *adev = ring->adev; +	mutex_lock(&adev->grbm_idx_mutex); +	if (adev->vce.harvest_config == 0 || +		adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE1) +		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0)); +	else if (adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) +		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1)); +  	if (ring == &adev->vce.ring[0])  		WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr));  	else if (ring == &adev->vce.ring[1])  		WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr));  	else  		WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr)); + +	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT); +	mutex_unlock(&adev->grbm_idx_mutex);  }  static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override) @@ -231,33 +267,38 @@ static int vce_v3_0_start(struct amdgpu_device *adev)  	struct amdgpu_ring *ring;  	int idx, r; -	ring = &adev->vce.ring[0]; -	WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr)); -	WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); -	WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr); -	WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); -	WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); - -	ring = &adev->vce.ring[1]; -	WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr)); -	WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); -	WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr); -	WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); -	WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); - -	ring = &adev->vce.ring[2]; -	WREG32(mmVCE_RB_RPTR3, lower_32_bits(ring->wptr)); -	WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr)); -	WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr); -	WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr)); -	WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4); -  	mutex_lock(&adev->grbm_idx_mutex);  	for (idx = 0; idx < 2; ++idx) {  		if (adev->vce.harvest_config & (1 << idx))  			continue;  		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx)); + +		/* Program instance 0 reg space for two instances or instance 0 case +		program instance 1 reg space for only instance 1 available case */ +		if (idx != 1 || adev->vce.harvest_config == AMDGPU_VCE_HARVEST_VCE0) { +			ring = &adev->vce.ring[0]; +			WREG32(mmVCE_RB_RPTR, lower_32_bits(ring->wptr)); +			WREG32(mmVCE_RB_WPTR, lower_32_bits(ring->wptr)); +			WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr); +			WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); +			WREG32(mmVCE_RB_SIZE, ring->ring_size / 4); + +			ring = &adev->vce.ring[1]; +			WREG32(mmVCE_RB_RPTR2, lower_32_bits(ring->wptr)); +			WREG32(mmVCE_RB_WPTR2, lower_32_bits(ring->wptr)); +			WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr); +			WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); +			WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); + +			ring = &adev->vce.ring[2]; +			WREG32(mmVCE_RB_RPTR3, lower_32_bits(ring->wptr)); +			WREG32(mmVCE_RB_WPTR3, lower_32_bits(ring->wptr)); +			WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr); +			WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr)); +			WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4); +		} +  		vce_v3_0_mc_resume(adev, idx);  		WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index d5f53d04fa08..83e40fe51b62 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -709,17 +709,17 @@ static int tf_vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr,  static struct phm_master_table_item  vega10_thermal_start_thermal_controller_master_list[] = { -	{NULL, tf_vega10_thermal_initialize}, -	{NULL, tf_vega10_thermal_set_temperature_range}, -	{NULL, tf_vega10_thermal_enable_alert}, +	{ .tableFunction = tf_vega10_thermal_initialize }, +	{ .tableFunction = tf_vega10_thermal_set_temperature_range }, +	{ .tableFunction = tf_vega10_thermal_enable_alert },  /* We should restrict performance levels to low before we halt the SMC.   * On the other hand we are still in boot state when we do this   * so it would be pointless.   * If this assumption changes we have to revisit this table.   */ -	{NULL, tf_vega10_thermal_setup_fan_table}, -	{NULL, tf_vega10_thermal_start_smc_fan_control}, -	{NULL, NULL} +	{ .tableFunction = tf_vega10_thermal_setup_fan_table }, +	{ .tableFunction = tf_vega10_thermal_start_smc_fan_control }, +	{ }  };  static struct phm_master_table_header @@ -731,10 +731,10 @@ vega10_thermal_start_thermal_controller_master = {  static struct phm_master_table_item  vega10_thermal_set_temperature_range_master_list[] = { -	{NULL, tf_vega10_thermal_disable_alert}, -	{NULL, tf_vega10_thermal_set_temperature_range}, -	{NULL, tf_vega10_thermal_enable_alert}, -	{NULL, NULL} +	{ .tableFunction = tf_vega10_thermal_disable_alert }, +	{ .tableFunction = tf_vega10_thermal_set_temperature_range }, +	{ .tableFunction = tf_vega10_thermal_enable_alert }, +	{ }  };  struct phm_master_table_header diff --git a/drivers/gpu/drm/bridge/synopsys/Kconfig b/drivers/gpu/drm/bridge/synopsys/Kconfig index 40d2827a6d19..53e78d092d18 100644 --- a/drivers/gpu/drm/bridge/synopsys/Kconfig +++ b/drivers/gpu/drm/bridge/synopsys/Kconfig @@ -1,6 +1,7 @@  config DRM_DW_HDMI  	tristate  	select DRM_KMS_HELPER +	select REGMAP_MMIO  config DRM_DW_HDMI_AHB_AUDIO  	tristate "Synopsys Designware AHB Audio interface" diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 8be9719284b0..aa885a614e27 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -508,6 +508,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,  		bool has_connectors =  			!!new_crtc_state->connector_mask; +		WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); +  		if (!drm_mode_equal(&old_crtc_state->mode, &new_crtc_state->mode)) {  			DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode changed\n",  					 crtc->base.id, crtc->name); @@ -551,6 +553,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,  	for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) {  		const struct drm_connector_helper_funcs *funcs = connector->helper_private; +		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); +  		/*  		 * This only sets crtc->connectors_changed for routing changes,  		 * drivers must set crtc->connectors_changed themselves when @@ -650,6 +654,8 @@ drm_atomic_helper_check_planes(struct drm_device *dev,  	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {  		const struct drm_plane_helper_funcs *funcs; +		WARN_ON(!drm_modeset_is_locked(&plane->mutex)); +  		funcs = plane->helper_private;  		drm_atomic_helper_plane_changed(state, old_plane_state, new_plane_state, plane); @@ -2663,7 +2669,12 @@ int drm_atomic_helper_resume(struct drm_device *dev,  	drm_modeset_acquire_init(&ctx, 0);  	while (1) { +		err = drm_modeset_lock_all_ctx(dev, &ctx); +		if (err) +			goto out; +  		err = drm_atomic_helper_commit_duplicated_state(state, &ctx); +out:  		if (err != -EDEADLK)  			break; diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 9f847615ac74..48ca2457df8c 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1229,21 +1229,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,  	if (!connector)  		return -ENOENT; -	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); -	encoder = drm_connector_get_encoder(connector); -	if (encoder) -		out_resp->encoder_id = encoder->base.id; -	else -		out_resp->encoder_id = 0; - -	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic, -			(uint32_t __user *)(unsigned long)(out_resp->props_ptr), -			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), -			&out_resp->count_props); -	drm_modeset_unlock(&dev->mode_config.connection_mutex); -	if (ret) -		goto out_unref; -  	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)  		if (connector->encoder_ids[i] != 0)  			encoders_count++; @@ -1256,7 +1241,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,  				if (put_user(connector->encoder_ids[i],  					     encoder_ptr + copied)) {  					ret = -EFAULT; -					goto out_unref; +					goto out;  				}  				copied++;  			} @@ -1300,15 +1285,32 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,  			if (copy_to_user(mode_ptr + copied,  					 &u_mode, sizeof(u_mode))) {  				ret = -EFAULT; +				mutex_unlock(&dev->mode_config.mutex); +  				goto out;  			}  			copied++;  		}  	}  	out_resp->count_modes = mode_count; -out:  	mutex_unlock(&dev->mode_config.mutex); -out_unref: + +	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); +	encoder = drm_connector_get_encoder(connector); +	if (encoder) +		out_resp->encoder_id = encoder->base.id; +	else +		out_resp->encoder_id = 0; + +	/* Only grab properties after probing, to make sure EDID and other +	 * properties reflect the latest status. */ +	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic, +			(uint32_t __user *)(unsigned long)(out_resp->props_ptr), +			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), +			&out_resp->count_props); +	drm_modeset_unlock(&dev->mode_config.connection_mutex); + +out:  	drm_connector_put(connector);  	return ret; diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 3e5f52110ea1..213fb837e1c4 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1208,3 +1208,86 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux)  	return 0;  }  EXPORT_SYMBOL(drm_dp_stop_crc); + +struct dpcd_quirk { +	u8 oui[3]; +	bool is_branch; +	u32 quirks; +}; + +#define OUI(first, second, third) { (first), (second), (third) } + +static const struct dpcd_quirk dpcd_quirk_list[] = { +	/* Analogix 7737 needs reduced M and N at HBR2 link rates */ +	{ OUI(0x00, 0x22, 0xb9), true, BIT(DP_DPCD_QUIRK_LIMITED_M_N) }, +}; + +#undef OUI + +/* + * Get a bit mask of DPCD quirks for the sink/branch device identified by + * ident. The quirk data is shared but it's up to the drivers to act on the + * data. + * + * For now, only the OUI (first three bytes) is used, but this may be extended + * to device identification string and hardware/firmware revisions later. + */ +static u32 +drm_dp_get_quirks(const struct drm_dp_dpcd_ident *ident, bool is_branch) +{ +	const struct dpcd_quirk *quirk; +	u32 quirks = 0; +	int i; + +	for (i = 0; i < ARRAY_SIZE(dpcd_quirk_list); i++) { +		quirk = &dpcd_quirk_list[i]; + +		if (quirk->is_branch != is_branch) +			continue; + +		if (memcmp(quirk->oui, ident->oui, sizeof(ident->oui)) != 0) +			continue; + +		quirks |= quirk->quirks; +	} + +	return quirks; +} + +/** + * drm_dp_read_desc - read sink/branch descriptor from DPCD + * @aux: DisplayPort AUX channel + * @desc: Device decriptor to fill from DPCD + * @is_branch: true for branch devices, false for sink devices + * + * Read DPCD 0x400 (sink) or 0x500 (branch) into @desc. Also debug log the + * identification. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc, +		     bool is_branch) +{ +	struct drm_dp_dpcd_ident *ident = &desc->ident; +	unsigned int offset = is_branch ? DP_BRANCH_OUI : DP_SINK_OUI; +	int ret, dev_id_len; + +	ret = drm_dp_dpcd_read(aux, offset, ident, sizeof(*ident)); +	if (ret < 0) +		return ret; + +	desc->quirks = drm_dp_get_quirks(ident, is_branch); + +	dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id)); + +	DRM_DEBUG_KMS("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n", +		      is_branch ? "branch" : "sink", +		      (int)sizeof(ident->oui), ident->oui, +		      dev_id_len, ident->device_id, +		      ident->hw_rev >> 4, ident->hw_rev & 0xf, +		      ident->sw_major_rev, ident->sw_minor_rev, +		      desc->quirks); + +	return 0; +} +EXPORT_SYMBOL(drm_dp_read_desc); diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index b5c6bb46a425..37b8ad3e30d8 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -358,7 +358,12 @@ EXPORT_SYMBOL(drm_put_dev);  void drm_unplug_dev(struct drm_device *dev)  {  	/* for a USB device */ -	drm_dev_unregister(dev); +	if (drm_core_check_feature(dev, DRIVER_MODESET)) +		drm_modeset_unregister_all(dev); + +	drm_minor_unregister(dev, DRM_MINOR_PRIMARY); +	drm_minor_unregister(dev, DRM_MINOR_RENDER); +	drm_minor_unregister(dev, DRM_MINOR_CONTROL);  	mutex_lock(&drm_global_mutex); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index c4a091e87426..e437fba1209d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -106,9 +106,10 @@ struct etnaviv_gem_submit {  	struct etnaviv_gpu *gpu;  	struct ww_acquire_ctx ticket;  	struct dma_fence *fence; +	u32 flags;  	unsigned int nr_bos;  	struct etnaviv_gem_submit_bo bos[0]; -	u32 flags; +	/* No new members here, the previous one is variable-length! */  };  int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index de80ee1b71df..1013765274da 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -172,7 +172,7 @@ static int submit_fence_sync(const struct etnaviv_gem_submit *submit)  	for (i = 0; i < submit->nr_bos; i++) {  		struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;  		bool write = submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE; -		bool explicit = !(submit->flags & ETNA_SUBMIT_NO_IMPLICIT); +		bool explicit = !!(submit->flags & ETNA_SUBMIT_NO_IMPLICIT);  		ret = etnaviv_gpu_fence_sync_obj(etnaviv_obj, context, write,  						 explicit); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 09d3c4c3c858..50294a7bd29d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -82,14 +82,9 @@ err_file_priv_free:  	return ret;  } -static void exynos_drm_preclose(struct drm_device *dev, -					struct drm_file *file) -{ -	exynos_drm_subdrv_close(dev, file); -} -  static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)  { +	exynos_drm_subdrv_close(dev, file);  	kfree(file->driver_priv);  	file->driver_priv = NULL;  } @@ -145,7 +140,6 @@ static struct drm_driver exynos_drm_driver = {  	.driver_features	= DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME  				  | DRIVER_ATOMIC | DRIVER_RENDER,  	.open			= exynos_drm_open, -	.preclose		= exynos_drm_preclose,  	.lastclose		= exynos_drm_lastclose,  	.postclose		= exynos_drm_postclose,  	.gem_free_object_unlocked = exynos_drm_gem_free_object, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index cb3176930596..39c740572034 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -160,12 +160,9 @@ struct exynos_drm_clk {   *	drm framework doesn't support multiple irq yet.   *	we can refer to the crtc to current hardware interrupt occurred through   *	this pipe value. - * @enabled: if the crtc is enabled or not - * @event: vblank event that is currently queued for flip - * @wait_update: wait all pending planes updates to finish - * @pending_update: number of pending plane updates in this crtc   * @ops: pointer to callbacks for exynos drm specific functionality   * @ctx: A pointer to the crtc's implementation specific context + * @pipe_clk: A pointer to the crtc's pipeline clock.   */  struct exynos_drm_crtc {  	struct drm_crtc			base; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index fc4fda738906..d404de86d5f9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -1633,7 +1633,6 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)  {  	struct device *dev = dsi->dev;  	struct device_node *node = dev->of_node; -	struct device_node *ep;  	int ret;  	ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency", @@ -1641,32 +1640,21 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)  	if (ret < 0)  		return ret; -	ep = of_graph_get_endpoint_by_regs(node, DSI_PORT_OUT, 0); -	if (!ep) { -		dev_err(dev, "no output port with endpoint specified\n"); -		return -EINVAL; -	} - -	ret = exynos_dsi_of_read_u32(ep, "samsung,burst-clock-frequency", +	ret = exynos_dsi_of_read_u32(node, "samsung,burst-clock-frequency",  				     &dsi->burst_clk_rate);  	if (ret < 0) -		goto end; +		return ret; -	ret = exynos_dsi_of_read_u32(ep, "samsung,esc-clock-frequency", +	ret = exynos_dsi_of_read_u32(node, "samsung,esc-clock-frequency",  				     &dsi->esc_clk_rate);  	if (ret < 0) -		goto end; - -	of_node_put(ep); +		return ret;  	dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_OUT, 0);  	if (!dsi->bridge_node)  		return -EINVAL; -end: -	of_node_put(ep); - -	return ret; +	return 0;  }  static int exynos_dsi_bind(struct device *dev, struct device *master, @@ -1817,6 +1805,10 @@ static int exynos_dsi_probe(struct platform_device *pdev)  static int exynos_dsi_remove(struct platform_device *pdev)  { +	struct exynos_dsi *dsi = platform_get_drvdata(pdev); + +	of_node_put(dsi->bridge_node); +  	pm_runtime_disable(&pdev->dev);  	component_del(&pdev->dev, &exynos_dsi_component_ops); diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c index 5abc69c9630f..f77dcfaade6c 100644 --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c @@ -760,7 +760,7 @@ static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)  	 * Get the endpoint node. In our case, dsi has one output port1  	 * to which the external HDMI bridge is connected.  	 */ -	ret = drm_of_find_panel_or_bridge(np, 0, 0, NULL, &dsi->bridge); +	ret = drm_of_find_panel_or_bridge(np, 1, 0, NULL, &dsi->bridge);  	if (ret)  		return ret; diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index dca989eb2d42..24fe04d6307b 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -779,8 +779,26 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)  	vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;  } +static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask) +{ +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; +	struct intel_engine_cs *engine; +	struct intel_vgpu_workload *pos, *n; +	unsigned int tmp; + +	/* free the unsubmited workloads in the queues. */ +	for_each_engine_masked(engine, dev_priv, engine_mask, tmp) { +		list_for_each_entry_safe(pos, n, +			&vgpu->workload_q_head[engine->id], list) { +			list_del_init(&pos->list); +			free_workload(pos); +		} +	} +} +  void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu)  { +	clean_workloads(vgpu, ALL_ENGINES);  	kmem_cache_destroy(vgpu->workloads);  } @@ -811,17 +829,9 @@ void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu,  {  	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;  	struct intel_engine_cs *engine; -	struct intel_vgpu_workload *pos, *n;  	unsigned int tmp; -	for_each_engine_masked(engine, dev_priv, engine_mask, tmp) { -		/* free the unsubmited workload in the queue */ -		list_for_each_entry_safe(pos, n, -			&vgpu->workload_q_head[engine->id], list) { -			list_del_init(&pos->list); -			free_workload(pos); -		} - +	clean_workloads(vgpu, engine_mask); +	for_each_engine_masked(engine, dev_priv, engine_mask, tmp)  		init_vgpu_execlist(vgpu, engine->id); -	}  } diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index c995e540ff96..0ffd69654592 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1366,18 +1366,28 @@ static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset,  		void *p_data, unsigned int bytes)  {  	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; -	i915_reg_t reg = {.reg = offset}; +	u32 v = *(u32 *)p_data; + +	if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv)) +		return intel_vgpu_default_mmio_write(vgpu, +				offset, p_data, bytes);  	switch (offset) {  	case 0x4ddc: -		vgpu_vreg(vgpu, offset) = 0x8000003c; -		/* WaCompressedResourceSamplerPbeMediaNewHashMode:skl */ -		I915_WRITE(reg, vgpu_vreg(vgpu, offset)); +		/* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ +		vgpu_vreg(vgpu, offset) = v & ~(1 << 31);  		break;  	case 0x42080: -		vgpu_vreg(vgpu, offset) = 0x8000; -		/* WaCompressedResourceDisplayNewHashMode:skl */ -		I915_WRITE(reg, vgpu_vreg(vgpu, offset)); +		/* bypass WaCompressedResourceDisplayNewHashMode */ +		vgpu_vreg(vgpu, offset) = v & ~(1 << 15); +		break; +	case 0xe194: +		/* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ +		vgpu_vreg(vgpu, offset) = v & ~(1 << 8); +		break; +	case 0x7014: +		/* bypass WaCompressedResourceSamplerPbeMediaNewHashMode */ +		vgpu_vreg(vgpu, offset) = v & ~(1 << 13);  		break;  	default:  		return -EINVAL; @@ -1634,7 +1644,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)  	MMIO_DFH(GAM_ECOCHK, D_ALL, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS,  		NULL, NULL); -	MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, +		 skl_misc_ctl_write);  	MMIO_DFH(0x9030, D_ALL, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0x20a0, D_ALL, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0x2420, D_ALL, F_CMD_ACCESS, NULL, NULL); @@ -2568,7 +2579,8 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  	MMIO_D(0x6e570, D_BDW_PLUS);  	MMIO_D(0x65f10, D_BDW_PLUS); -	MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, +		 skl_misc_ctl_write);  	MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(HALF_SLICE_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d689e511744e..4bd1467c17b1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -292,6 +292,8 @@ static int per_file_stats(int id, void *ptr, void *data)  	struct file_stats *stats = data;  	struct i915_vma *vma; +	lockdep_assert_held(&obj->base.dev->struct_mutex); +  	stats->count++;  	stats->total += obj->base.size;  	if (!obj->bind_count) @@ -476,6 +478,8 @@ static int i915_gem_object_info(struct seq_file *m, void *data)  		struct drm_i915_gem_request *request;  		struct task_struct *task; +		mutex_lock(&dev->struct_mutex); +  		memset(&stats, 0, sizeof(stats));  		stats.file_priv = file->driver_priv;  		spin_lock(&file->table_lock); @@ -487,7 +491,6 @@ static int i915_gem_object_info(struct seq_file *m, void *data)  		 * still alive (e.g. get_pid(current) => fork() => exit()).  		 * Therefore, we need to protect this ->comm access using RCU.  		 */ -		mutex_lock(&dev->struct_mutex);  		request = list_first_entry_or_null(&file_priv->mm.request_list,  						   struct drm_i915_gem_request,  						   client_link); @@ -497,6 +500,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data)  				PIDTYPE_PID);  		print_file_stats(m, task ? task->comm : "<unknown>", stats);  		rcu_read_unlock(); +  		mutex_unlock(&dev->struct_mutex);  	}  	mutex_unlock(&dev->filelist_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3036d4835b0f..48428672fc6e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1235,6 +1235,15 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)  		goto out_fini;  	pci_set_drvdata(pdev, &dev_priv->drm); +	/* +	 * Disable the system suspend direct complete optimization, which can +	 * leave the device suspended skipping the driver's suspend handlers +	 * if the device was already runtime suspended. This is needed due to +	 * the difference in our runtime and system suspend sequence and +	 * becaue the HDA driver may require us to enable the audio power +	 * domain during system suspend. +	 */ +	pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;  	ret = i915_driver_init_early(dev_priv, ent);  	if (ret < 0) @@ -1272,10 +1281,6 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)  	dev_priv->ipc_enabled = false; -	/* Everything is in place, we can now relax! */ -	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", -		 driver.name, driver.major, driver.minor, driver.patchlevel, -		 driver.date, pci_name(pdev), dev_priv->drm.primary->index);  	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG))  		DRM_INFO("DRM_I915_DEBUG enabled\n");  	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c9b0949f6c1a..2c453a4e97d5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -562,7 +562,8 @@ struct intel_link_m_n {  void intel_link_compute_m_n(int bpp, int nlanes,  			    int pixel_clock, int link_clock, -			    struct intel_link_m_n *m_n); +			    struct intel_link_m_n *m_n, +			    bool reduce_m_n);  /* Interface history:   * @@ -2990,6 +2991,16 @@ static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)  	return false;  } +static inline bool +intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *dev_priv) +{ +#ifdef CONFIG_INTEL_IOMMU +	if (IS_BROXTON(dev_priv) && intel_iommu_gfx_mapped) +		return true; +#endif +	return false; +} +  int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,  				int enable_ppgtt); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b6ac3df18b58..615f0a855222 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2285,8 +2285,8 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)  	struct page *page;  	unsigned long last_pfn = 0;	/* suppress gcc warning */  	unsigned int max_segment; +	gfp_t noreclaim;  	int ret; -	gfp_t gfp;  	/* Assert that the object is not currently in any GPU domain. As it  	 * wasn't in the GTT, there shouldn't be any way it could have been in @@ -2315,22 +2315,31 @@ rebuild_st:  	 * Fail silently without starting the shrinker  	 */  	mapping = obj->base.filp->f_mapping; -	gfp = mapping_gfp_constraint(mapping, ~(__GFP_IO | __GFP_RECLAIM)); -	gfp |= __GFP_NORETRY | __GFP_NOWARN; +	noreclaim = mapping_gfp_constraint(mapping, +					   ~(__GFP_IO | __GFP_RECLAIM)); +	noreclaim |= __GFP_NORETRY | __GFP_NOWARN; +  	sg = st->sgl;  	st->nents = 0;  	for (i = 0; i < page_count; i++) { -		page = shmem_read_mapping_page_gfp(mapping, i, gfp); -		if (unlikely(IS_ERR(page))) { -			i915_gem_shrink(dev_priv, -					page_count, -					I915_SHRINK_BOUND | -					I915_SHRINK_UNBOUND | -					I915_SHRINK_PURGEABLE); +		const unsigned int shrink[] = { +			I915_SHRINK_BOUND | I915_SHRINK_UNBOUND | I915_SHRINK_PURGEABLE, +			0, +		}, *s = shrink; +		gfp_t gfp = noreclaim; + +		do {  			page = shmem_read_mapping_page_gfp(mapping, i, gfp); -		} -		if (unlikely(IS_ERR(page))) { -			gfp_t reclaim; +			if (likely(!IS_ERR(page))) +				break; + +			if (!*s) { +				ret = PTR_ERR(page); +				goto err_sg; +			} + +			i915_gem_shrink(dev_priv, 2 * page_count, *s++); +			cond_resched();  			/* We've tried hard to allocate the memory by reaping  			 * our own buffer, now let the real VM do its job and @@ -2340,15 +2349,26 @@ rebuild_st:  			 * defer the oom here by reporting the ENOMEM back  			 * to userspace.  			 */ -			reclaim = mapping_gfp_mask(mapping); -			reclaim |= __GFP_NORETRY; /* reclaim, but no oom */ - -			page = shmem_read_mapping_page_gfp(mapping, i, reclaim); -			if (IS_ERR(page)) { -				ret = PTR_ERR(page); -				goto err_sg; +			if (!*s) { +				/* reclaim and warn, but no oom */ +				gfp = mapping_gfp_mask(mapping); + +				/* Our bo are always dirty and so we require +				 * kswapd to reclaim our pages (direct reclaim +				 * does not effectively begin pageout of our +				 * buffers on its own). However, direct reclaim +				 * only waits for kswapd when under allocation +				 * congestion. So as a result __GFP_RECLAIM is +				 * unreliable and fails to actually reclaim our +				 * dirty pages -- unless you try over and over +				 * again with !__GFP_NORETRY. However, we still +				 * want to fail this allocation rather than +				 * trigger the out-of-memory killer and for +				 * this we want the future __GFP_MAYFAIL. +				 */  			} -		} +		} while (1); +  		if (!i ||  		    sg->length >= max_segment ||  		    page_to_pfn(page) != last_pfn + 1) { @@ -3298,6 +3318,10 @@ int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags)  {  	int ret; +	/* If the device is asleep, we have no requests outstanding */ +	if (!READ_ONCE(i915->gt.awake)) +		return 0; +  	if (flags & I915_WAIT_LOCKED) {  		struct i915_gem_timeline *tl; @@ -4218,6 +4242,7 @@ i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size)  	mapping = obj->base.filp->f_mapping;  	mapping_set_gfp_mask(mapping, mask); +	GEM_BUG_ON(!(mapping_gfp_mask(mapping) & __GFP_RECLAIM));  	i915_gem_object_init(obj, &i915_gem_object_ops); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index a3e59c8ef27b..9ad13eeed904 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -546,11 +546,12 @@ repeat:  }  static int -i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, +i915_gem_execbuffer_relocate_entry(struct i915_vma *vma,  				   struct eb_vmas *eb,  				   struct drm_i915_gem_relocation_entry *reloc,  				   struct reloc_cache *cache)  { +	struct drm_i915_gem_object *obj = vma->obj;  	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);  	struct drm_gem_object *target_obj;  	struct drm_i915_gem_object *target_i915_obj; @@ -628,6 +629,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  		return -EINVAL;  	} +	/* +	 * If we write into the object, we need to force the synchronisation +	 * barrier, either with an asynchronous clflush or if we executed the +	 * patching using the GPU (though that should be serialised by the +	 * timeline). To be completely sure, and since we are required to +	 * do relocations we are already stalling, disable the user's opt +	 * of our synchronisation. +	 */ +	vma->exec_entry->flags &= ~EXEC_OBJECT_ASYNC; +  	ret = relocate_entry(obj, reloc, cache, target_offset);  	if (ret)  		return ret; @@ -678,7 +689,7 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma,  		do {  			u64 offset = r->presumed_offset; -			ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, r, &cache); +			ret = i915_gem_execbuffer_relocate_entry(vma, eb, r, &cache);  			if (ret)  				goto out; @@ -726,7 +737,7 @@ i915_gem_execbuffer_relocate_vma_slow(struct i915_vma *vma,  	reloc_cache_init(&cache, eb->i915);  	for (i = 0; i < entry->relocation_count; i++) { -		ret = i915_gem_execbuffer_relocate_entry(vma->obj, eb, &relocs[i], &cache); +		ret = i915_gem_execbuffer_relocate_entry(vma, eb, &relocs[i], &cache);  		if (ret)  			break;  	} diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a0563e18d753..f1989b8792dd 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2191,6 +2191,101 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,  		gen8_set_pte(>t_base[i], scratch_pte);  } +static void bxt_vtd_ggtt_wa(struct i915_address_space *vm) +{ +	struct drm_i915_private *dev_priv = vm->i915; + +	/* +	 * Make sure the internal GAM fifo has been cleared of all GTT +	 * writes before exiting stop_machine(). This guarantees that +	 * any aperture accesses waiting to start in another process +	 * cannot back up behind the GTT writes causing a hang. +	 * The register can be any arbitrary GAM register. +	 */ +	POSTING_READ(GFX_FLSH_CNTL_GEN6); +} + +struct insert_page { +	struct i915_address_space *vm; +	dma_addr_t addr; +	u64 offset; +	enum i915_cache_level level; +}; + +static int bxt_vtd_ggtt_insert_page__cb(void *_arg) +{ +	struct insert_page *arg = _arg; + +	gen8_ggtt_insert_page(arg->vm, arg->addr, arg->offset, arg->level, 0); +	bxt_vtd_ggtt_wa(arg->vm); + +	return 0; +} + +static void bxt_vtd_ggtt_insert_page__BKL(struct i915_address_space *vm, +					  dma_addr_t addr, +					  u64 offset, +					  enum i915_cache_level level, +					  u32 unused) +{ +	struct insert_page arg = { vm, addr, offset, level }; + +	stop_machine(bxt_vtd_ggtt_insert_page__cb, &arg, NULL); +} + +struct insert_entries { +	struct i915_address_space *vm; +	struct sg_table *st; +	u64 start; +	enum i915_cache_level level; +}; + +static int bxt_vtd_ggtt_insert_entries__cb(void *_arg) +{ +	struct insert_entries *arg = _arg; + +	gen8_ggtt_insert_entries(arg->vm, arg->st, arg->start, arg->level, 0); +	bxt_vtd_ggtt_wa(arg->vm); + +	return 0; +} + +static void bxt_vtd_ggtt_insert_entries__BKL(struct i915_address_space *vm, +					     struct sg_table *st, +					     u64 start, +					     enum i915_cache_level level, +					     u32 unused) +{ +	struct insert_entries arg = { vm, st, start, level }; + +	stop_machine(bxt_vtd_ggtt_insert_entries__cb, &arg, NULL); +} + +struct clear_range { +	struct i915_address_space *vm; +	u64 start; +	u64 length; +}; + +static int bxt_vtd_ggtt_clear_range__cb(void *_arg) +{ +	struct clear_range *arg = _arg; + +	gen8_ggtt_clear_range(arg->vm, arg->start, arg->length); +	bxt_vtd_ggtt_wa(arg->vm); + +	return 0; +} + +static void bxt_vtd_ggtt_clear_range__BKL(struct i915_address_space *vm, +					  u64 start, +					  u64 length) +{ +	struct clear_range arg = { vm, start, length }; + +	stop_machine(bxt_vtd_ggtt_clear_range__cb, &arg, NULL); +} +  static void gen6_ggtt_clear_range(struct i915_address_space *vm,  				  u64 start, u64 length)  { @@ -2313,7 +2408,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,  		    appgtt->base.allocate_va_range) {  			ret = appgtt->base.allocate_va_range(&appgtt->base,  							     vma->node.start, -							     vma->node.size); +							     vma->size);  			if (ret)  				goto err_pages;  		} @@ -2785,6 +2880,14 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)  	ggtt->base.insert_entries = gen8_ggtt_insert_entries; +	/* Serialize GTT updates with aperture access on BXT if VT-d is on. */ +	if (intel_ggtt_update_needs_vtd_wa(dev_priv)) { +		ggtt->base.insert_entries = bxt_vtd_ggtt_insert_entries__BKL; +		ggtt->base.insert_page    = bxt_vtd_ggtt_insert_page__BKL; +		if (ggtt->base.clear_range != nop_clear_range) +			ggtt->base.clear_range = bxt_vtd_ggtt_clear_range__BKL; +	} +  	ggtt->invalidate = gen6_ggtt_invalidate;  	return ggtt_probe_common(ggtt, size); @@ -2997,7 +3100,8 @@ void i915_ggtt_enable_guc(struct drm_i915_private *i915)  void i915_ggtt_disable_guc(struct drm_i915_private *i915)  { -	i915->ggtt.invalidate = gen6_ggtt_invalidate; +	if (i915->ggtt.invalidate == guc_ggtt_invalidate) +		i915->ggtt.invalidate = gen6_ggtt_invalidate;  }  void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 5ddbc9499775..a74d0ac737cb 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -623,7 +623,7 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,  	 * GPU processing the request, we never over-estimate the  	 * position of the head.  	 */ -	req->head = req->ring->tail; +	req->head = req->ring->emit;  	/* Check that we didn't interrupt ourselves with a new request */  	GEM_BUG_ON(req->timeline->seqno != req->fence.seqno); diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 129ed303a6c4..57d9f7f4ef15 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -59,9 +59,6 @@ static void i915_gem_shrinker_unlock(struct drm_device *dev, bool unlock)  		return;  	mutex_unlock(&dev->struct_mutex); - -	/* expedite the RCU grace period to free some request slabs */ -	synchronize_rcu_expedited();  }  static bool any_vma_pinned(struct drm_i915_gem_object *obj) @@ -274,8 +271,6 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv)  				I915_SHRINK_ACTIVE);  	intel_runtime_pm_put(dev_priv); -	synchronize_rcu(); /* wait for our earlier RCU delayed slab frees */ -  	return freed;  } diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index a0d6d4317a49..fb5231f98c0d 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -278,7 +278,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj,  			obj->mm.quirked = false;  		}  		if (!i915_gem_object_is_tiled(obj)) { -			GEM_BUG_ON(!obj->mm.quirked); +			GEM_BUG_ON(obj->mm.quirked);  			__i915_gem_object_pin_pages(obj);  			obj->mm.quirked = true;  		} diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 1642fff9cf13..ab5140ba108d 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -480,9 +480,7 @@ static void guc_wq_item_append(struct i915_guc_client *client,  	GEM_BUG_ON(freespace < wqi_size);  	/* The GuC firmware wants the tail index in QWords, not bytes */ -	tail = rq->tail; -	assert_ring_tail_valid(rq->ring, rq->tail); -	tail >>= 3; +	tail = intel_ring_set_tail(rq->ring, rq->tail) >> 3;  	GEM_BUG_ON(tail > WQ_RING_TAIL_MAX);  	/* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index fd97fe00cd0d..190f6aa5d15e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2953,7 +2953,6 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)  	u32 pipestat_mask;  	u32 enable_mask;  	enum pipe pipe; -	u32 val;  	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |  			PIPE_CRC_DONE_INTERRUPT_STATUS; @@ -2964,18 +2963,16 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)  	enable_mask = I915_DISPLAY_PORT_INTERRUPT |  		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | -		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; +		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | +		I915_LPE_PIPE_A_INTERRUPT | +		I915_LPE_PIPE_B_INTERRUPT; +  	if (IS_CHERRYVIEW(dev_priv)) -		enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; +		enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT | +			I915_LPE_PIPE_C_INTERRUPT;  	WARN_ON(dev_priv->irq_mask != ~0); -	val = (I915_LPE_PIPE_A_INTERRUPT | -		I915_LPE_PIPE_B_INTERRUPT | -		I915_LPE_PIPE_C_INTERRUPT); - -	enable_mask |= val; -  	dev_priv->irq_mask = ~enable_mask;  	GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index f87b0c4e564d..1a78363c7f4a 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -208,7 +208,7 @@ static const struct intel_device_info intel_ironlake_d_info = {  static const struct intel_device_info intel_ironlake_m_info = {  	GEN5_FEATURES,  	.platform = INTEL_IRONLAKE, -	.is_mobile = 1, +	.is_mobile = 1, .has_fbc = 1,  };  #define GEN6_FEATURES \ @@ -390,7 +390,6 @@ static const struct intel_device_info intel_skylake_gt3_info = {  	.has_hw_contexts = 1, \  	.has_logical_ring_contexts = 1, \  	.has_guc = 1, \ -	.has_decoupled_mmio = 1, \  	.has_aliasing_ppgtt = 1, \  	.has_full_ppgtt = 1, \  	.has_full_48bit_ppgtt = 1, \ diff --git a/drivers/gpu/drm/i915/i915_pvinfo.h b/drivers/gpu/drm/i915/i915_pvinfo.h index c0cb2974caac..2cfe96d3e5d1 100644 --- a/drivers/gpu/drm/i915/i915_pvinfo.h +++ b/drivers/gpu/drm/i915/i915_pvinfo.h @@ -36,10 +36,6 @@  #define VGT_VERSION_MAJOR 1  #define VGT_VERSION_MINOR 0 -#define INTEL_VGT_IF_VERSION_ENCODE(major, minor) ((major) << 16 | (minor)) -#define INTEL_VGT_IF_VERSION \ -	INTEL_VGT_IF_VERSION_ENCODE(VGT_VERSION_MAJOR, VGT_VERSION_MINOR) -  /*   * notifications from guest to vgpu device model   */ @@ -55,8 +51,8 @@ enum vgt_g2v_type {  struct vgt_if {  	u64 magic;		/* VGT_MAGIC */ -	uint16_t version_major; -	uint16_t version_minor; +	u16 version_major; +	u16 version_minor;  	u32 vgt_id;		/* ID of vGT instance */  	u32 rsv1[12];		/* pad to offset 0x40 */  	/* diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5a7c63e64381..65b837e96fe6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8280,7 +8280,7 @@ enum {  /* MIPI DSI registers */ -#define _MIPI_PORT(port, a, c)	((port) ? c : a)	/* ports A and C only */ +#define _MIPI_PORT(port, a, c)	(((port) == PORT_A) ? a : c)	/* ports A and C only */  #define _MMIO_MIPI(port, a, c)	_MMIO(_MIPI_PORT(port, a, c))  #define MIPIO_TXESC_CLK_DIV1			_MMIO(0x160004) diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c index 4ab8a973b61f..2e739018fb4c 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.c +++ b/drivers/gpu/drm/i915/i915_vgpu.c @@ -60,8 +60,8 @@   */  void i915_check_vgpu(struct drm_i915_private *dev_priv)  { -	uint64_t magic; -	uint32_t version; +	u64 magic; +	u16 version_major;  	BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE); @@ -69,10 +69,8 @@ void i915_check_vgpu(struct drm_i915_private *dev_priv)  	if (magic != VGT_MAGIC)  		return; -	version = INTEL_VGT_IF_VERSION_ENCODE( -		__raw_i915_read16(dev_priv, vgtif_reg(version_major)), -		__raw_i915_read16(dev_priv, vgtif_reg(version_minor))); -	if (version != INTEL_VGT_IF_VERSION) { +	version_major = __raw_i915_read16(dev_priv, vgtif_reg(version_major)); +	if (version_major < VGT_VERSION_MAJOR) {  		DRM_INFO("VGT interface version mismatch!\n");  		return;  	} diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 1aba47024656..f066e2d785f5 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -650,6 +650,11 @@ int i915_vma_unbind(struct i915_vma *vma)  				break;  		} +		if (!ret) { +			ret = i915_gem_active_retire(&vma->last_fence, +						     &vma->vm->i915->drm.struct_mutex); +		} +  		__i915_vma_unpin(vma);  		if (ret)  			return ret; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3617927af269..9106ea32b048 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -120,7 +120,8 @@ static void intel_crtc_init_scalers(struct intel_crtc *crtc,  static void skylake_pfit_enable(struct intel_crtc *crtc);  static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);  static void ironlake_pfit_enable(struct intel_crtc *crtc); -static void intel_modeset_setup_hw_state(struct drm_device *dev); +static void intel_modeset_setup_hw_state(struct drm_device *dev, +					 struct drm_modeset_acquire_ctx *ctx);  static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);  struct intel_limit { @@ -3449,7 +3450,7 @@ __intel_display_resume(struct drm_device *dev,  	struct drm_crtc *crtc;  	int i, ret; -	intel_modeset_setup_hw_state(dev); +	intel_modeset_setup_hw_state(dev, ctx);  	i915_redisable_vga(to_i915(dev));  	if (!state) @@ -4598,7 +4599,7 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)  static int  skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, -		  unsigned scaler_user, int *scaler_id, unsigned int rotation, +		  unsigned int scaler_user, int *scaler_id,  		  int src_w, int src_h, int dst_w, int dst_h)  {  	struct intel_crtc_scaler_state *scaler_state = @@ -4607,9 +4608,12 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,  		to_intel_crtc(crtc_state->base.crtc);  	int need_scaling; -	need_scaling = drm_rotation_90_or_270(rotation) ? -		(src_h != dst_w || src_w != dst_h): -		(src_w != dst_w || src_h != dst_h); +	/* +	 * Src coordinates are already rotated by 270 degrees for +	 * the 90/270 degree plane rotation cases (to match the +	 * GTT mapping), hence no need to account for rotation here. +	 */ +	need_scaling = src_w != dst_w || src_h != dst_h;  	/*  	 * if plane is being disabled or scaler is no more required or force detach @@ -4671,7 +4675,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)  	const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;  	return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX, -		&state->scaler_state.scaler_id, DRM_ROTATE_0, +		&state->scaler_state.scaler_id,  		state->pipe_src_w, state->pipe_src_h,  		adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay);  } @@ -4700,7 +4704,6 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,  	ret = skl_update_scaler(crtc_state, force_detach,  				drm_plane_index(&intel_plane->base),  				&plane_state->scaler_id, -				plane_state->base.rotation,  				drm_rect_width(&plane_state->base.src) >> 16,  				drm_rect_height(&plane_state->base.src) >> 16,  				drm_rect_width(&plane_state->base.dst), @@ -5823,7 +5826,8 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,  		intel_update_watermarks(intel_crtc);  } -static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) +static void intel_crtc_disable_noatomic(struct drm_crtc *crtc, +					struct drm_modeset_acquire_ctx *ctx)  {  	struct intel_encoder *encoder;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -5853,7 +5857,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)  		return;  	} -	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; +	state->acquire_ctx = ctx;  	/* Everything's already locked, -EDEADLK can't happen. */  	crtc_state = intel_atomic_get_crtc_state(state, intel_crtc); @@ -6101,7 +6105,7 @@ retry:  	pipe_config->fdi_lanes = lane;  	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock, -			       link_bw, &pipe_config->fdi_m_n); +			       link_bw, &pipe_config->fdi_m_n, false);  	ret = ironlake_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);  	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) { @@ -6277,7 +6281,8 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den)  }  static void compute_m_n(unsigned int m, unsigned int n, -			uint32_t *ret_m, uint32_t *ret_n) +			uint32_t *ret_m, uint32_t *ret_n, +			bool reduce_m_n)  {  	/*  	 * Reduce M/N as much as possible without loss in precision. Several DP @@ -6285,9 +6290,11 @@ static void compute_m_n(unsigned int m, unsigned int n,  	 * values. The passed in values are more likely to have the least  	 * significant bits zero than M after rounding below, so do this first.  	 */ -	while ((m & 1) == 0 && (n & 1) == 0) { -		m >>= 1; -		n >>= 1; +	if (reduce_m_n) { +		while ((m & 1) == 0 && (n & 1) == 0) { +			m >>= 1; +			n >>= 1; +		}  	}  	*ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX); @@ -6298,16 +6305,19 @@ static void compute_m_n(unsigned int m, unsigned int n,  void  intel_link_compute_m_n(int bits_per_pixel, int nlanes,  		       int pixel_clock, int link_clock, -		       struct intel_link_m_n *m_n) +		       struct intel_link_m_n *m_n, +		       bool reduce_m_n)  {  	m_n->tu = 64;  	compute_m_n(bits_per_pixel * pixel_clock,  		    link_clock * nlanes * 8, -		    &m_n->gmch_m, &m_n->gmch_n); +		    &m_n->gmch_m, &m_n->gmch_n, +		    reduce_m_n);  	compute_m_n(pixel_clock, link_clock, -		    &m_n->link_m, &m_n->link_n); +		    &m_n->link_m, &m_n->link_n, +		    reduce_m_n);  }  static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) @@ -12197,6 +12207,15 @@ static void update_scanline_offset(struct intel_crtc *crtc)  	 * type. For DP ports it behaves like most other platforms, but on HDMI  	 * there's an extra 1 line difference. So we need to add two instead of  	 * one to the value. +	 * +	 * On VLV/CHV DSI the scanline counter would appear to increment +	 * approx. 1/3 of a scanline before start of vblank. Unfortunately +	 * that means we can't tell whether we're in vblank or not while +	 * we're on that particular line. We must still set scanline_offset +	 * to 1 so that the vblank timestamps come out correct when we query +	 * the scanline counter from within the vblank interrupt handler. +	 * However if queried just before the start of vblank we'll get an +	 * answer that's slightly in the future.  	 */  	if (IS_GEN2(dev_priv)) {  		const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; @@ -15013,7 +15032,7 @@ int intel_modeset_init(struct drm_device *dev)  	intel_setup_outputs(dev_priv);  	drm_modeset_lock_all(dev); -	intel_modeset_setup_hw_state(dev); +	intel_modeset_setup_hw_state(dev, dev->mode_config.acquire_ctx);  	drm_modeset_unlock_all(dev);  	for_each_intel_crtc(dev, crtc) { @@ -15050,13 +15069,13 @@ int intel_modeset_init(struct drm_device *dev)  	return 0;  } -static void intel_enable_pipe_a(struct drm_device *dev) +static void intel_enable_pipe_a(struct drm_device *dev, +				struct drm_modeset_acquire_ctx *ctx)  {  	struct intel_connector *connector;  	struct drm_connector_list_iter conn_iter;  	struct drm_connector *crt = NULL;  	struct intel_load_detect_pipe load_detect_temp; -	struct drm_modeset_acquire_ctx *ctx = dev->mode_config.acquire_ctx;  	int ret;  	/* We can't just switch on the pipe A, we need to set things up with a @@ -15128,7 +15147,8 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv,  		(HAS_PCH_LPT_H(dev_priv) && pch_transcoder == TRANSCODER_A);  } -static void intel_sanitize_crtc(struct intel_crtc *crtc) +static void intel_sanitize_crtc(struct intel_crtc *crtc, +				struct drm_modeset_acquire_ctx *ctx)  {  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -15174,7 +15194,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)  		plane = crtc->plane;  		crtc->base.primary->state->visible = true;  		crtc->plane = !plane; -		intel_crtc_disable_noatomic(&crtc->base); +		intel_crtc_disable_noatomic(&crtc->base, ctx);  		crtc->plane = plane;  	} @@ -15184,13 +15204,13 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)  		 * resume. Force-enable the pipe to fix this, the update_dpms  		 * call below we restore the pipe to the right state, but leave  		 * the required bits on. */ -		intel_enable_pipe_a(dev); +		intel_enable_pipe_a(dev, ctx);  	}  	/* Adjust the state of the output pipe according to whether we  	 * have active connectors/encoders. */  	if (crtc->active && !intel_crtc_has_encoders(crtc)) -		intel_crtc_disable_noatomic(&crtc->base); +		intel_crtc_disable_noatomic(&crtc->base, ctx);  	if (crtc->active || HAS_GMCH_DISPLAY(dev_priv)) {  		/* @@ -15488,7 +15508,8 @@ get_encoder_power_domains(struct drm_i915_private *dev_priv)   * and sanitizes it to the current state   */  static void -intel_modeset_setup_hw_state(struct drm_device *dev) +intel_modeset_setup_hw_state(struct drm_device *dev, +			     struct drm_modeset_acquire_ctx *ctx)  {  	struct drm_i915_private *dev_priv = to_i915(dev);  	enum pipe pipe; @@ -15508,7 +15529,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev)  	for_each_pipe(dev_priv, pipe) {  		crtc = intel_get_crtc_for_pipe(dev_priv, pipe); -		intel_sanitize_crtc(crtc); +		intel_sanitize_crtc(crtc, ctx);  		intel_dump_pipe_config(crtc, crtc->config,  				       "[setup_hw_state]");  	} diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ee77b519835c..fc691b8b317c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1507,37 +1507,6 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)  	DRM_DEBUG_KMS("common rates: %s\n", str);  } -bool -__intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc) -{ -	u32 base = drm_dp_is_branch(intel_dp->dpcd) ? DP_BRANCH_OUI : -						      DP_SINK_OUI; - -	return drm_dp_dpcd_read(&intel_dp->aux, base, desc, sizeof(*desc)) == -	       sizeof(*desc); -} - -bool intel_dp_read_desc(struct intel_dp *intel_dp) -{ -	struct intel_dp_desc *desc = &intel_dp->desc; -	bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & -		       DP_OUI_SUPPORT; -	int dev_id_len; - -	if (!__intel_dp_read_desc(intel_dp, desc)) -		return false; - -	dev_id_len = strnlen(desc->device_id, sizeof(desc->device_id)); -	DRM_DEBUG_KMS("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n", -		      drm_dp_is_branch(intel_dp->dpcd) ? "branch" : "sink", -		      (int)sizeof(desc->oui), desc->oui, oui_sup ? "" : "(NS)", -		      dev_id_len, desc->device_id, -		      desc->hw_rev >> 4, desc->hw_rev & 0xf, -		      desc->sw_major_rev, desc->sw_minor_rev); - -	return true; -} -  static int rate_to_index(int find, const int *rates)  {  	int i = 0; @@ -1624,6 +1593,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,  	int common_rates[DP_MAX_SUPPORTED_RATES] = {};  	int common_len;  	uint8_t link_bw, rate_select; +	bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc, +					   DP_DPCD_QUIRK_LIMITED_M_N);  	common_len = intel_dp_common_rates(intel_dp, common_rates); @@ -1753,7 +1724,8 @@ found:  	intel_link_compute_m_n(bpp, lane_count,  			       adjusted_mode->crtc_clock,  			       pipe_config->port_clock, -			       &pipe_config->dp_m_n); +			       &pipe_config->dp_m_n, +			       reduce_m_n);  	if (intel_connector->panel.downclock_mode != NULL &&  		dev_priv->drrs.type == SEAMLESS_DRRS_SUPPORT) { @@ -1761,7 +1733,8 @@ found:  			intel_link_compute_m_n(bpp, lane_count,  				intel_connector->panel.downclock_mode->clock,  				pipe_config->port_clock, -				&pipe_config->dp_m2_n2); +				&pipe_config->dp_m2_n2, +				reduce_m_n);  	}  	/* @@ -3622,7 +3595,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)  	if (!intel_dp_read_dpcd(intel_dp))  		return false; -	intel_dp_read_desc(intel_dp); +	drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, +			 drm_dp_is_branch(intel_dp->dpcd));  	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)  		dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] & @@ -4624,7 +4598,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)  	intel_dp_print_rates(intel_dp); -	intel_dp_read_desc(intel_dp); +	drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, +			 drm_dp_is_branch(intel_dp->dpcd));  	intel_dp_configure_mst(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c index 6532e226db29..40ba3134545e 100644 --- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c @@ -119,8 +119,6 @@ static int intel_dp_aux_setup_backlight(struct intel_connector *connector,  	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);  	struct intel_panel *panel = &connector->panel; -	intel_dp_aux_enable_backlight(connector); -  	if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)  		panel->backlight.max = 0xFFFF;  	else diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index c1f62eb07c07..989e25577ac0 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -44,6 +44,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,  	int lane_count, slots;  	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;  	int mst_pbn; +	bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc, +					   DP_DPCD_QUIRK_LIMITED_M_N);  	pipe_config->has_pch_encoder = false;  	bpp = 24; @@ -75,7 +77,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,  	intel_link_compute_m_n(bpp, lane_count,  			       adjusted_mode->crtc_clock,  			       pipe_config->port_clock, -			       &pipe_config->dp_m_n); +			       &pipe_config->dp_m_n, +			       reduce_m_n);  	pipe_config->dp_m_n.tu = slots; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index aaee3949a422..f630c7af5020 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -906,14 +906,6 @@ enum link_m_n_set {  	M2_N2  }; -struct intel_dp_desc { -	u8 oui[3]; -	u8 device_id[6]; -	u8 hw_rev; -	u8 sw_major_rev; -	u8 sw_minor_rev; -} __packed; -  struct intel_dp_compliance_data {  	unsigned long edid;  	uint8_t video_pattern; @@ -957,7 +949,7 @@ struct intel_dp {  	/* Max link BW for the sink as per DPCD registers */  	int max_sink_link_bw;  	/* sink or branch descriptor */ -	struct intel_dp_desc desc; +	struct drm_dp_desc desc;  	struct drm_dp_aux aux;  	enum intel_display_power_domain aux_power_domain;  	uint8_t train_set[4]; @@ -1532,9 +1524,6 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)  }  bool intel_dp_read_dpcd(struct intel_dp *intel_dp); -bool __intel_dp_read_desc(struct intel_dp *intel_dp, -			  struct intel_dp_desc *desc); -bool intel_dp_read_desc(struct intel_dp *intel_dp);  int intel_dp_link_required(int pixel_clock, int bpp);  int intel_dp_max_data_rate(int max_link_clock, int max_lanes);  bool intel_digital_port_connected(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 854e8e0c836b..f94eacff196c 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1075,6 +1075,22 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)  	return 0;  } +static bool ring_is_idle(struct intel_engine_cs *engine) +{ +	struct drm_i915_private *dev_priv = engine->i915; +	bool idle = true; + +	intel_runtime_pm_get(dev_priv); + +	/* No bit for gen2, so assume the CS parser is idle */ +	if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE)) +		idle = false; + +	intel_runtime_pm_put(dev_priv); + +	return idle; +} +  /**   * intel_engine_is_idle() - Report if the engine has finished process all work   * @engine: the intel_engine_cs @@ -1084,8 +1100,6 @@ int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)   */  bool intel_engine_is_idle(struct intel_engine_cs *engine)  { -	struct drm_i915_private *dev_priv = engine->i915; -  	/* Any inflight/incomplete requests? */  	if (!i915_seqno_passed(intel_engine_get_seqno(engine),  			       intel_engine_last_submit(engine))) @@ -1100,7 +1114,7 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine)  		return false;  	/* Ring stopped? */ -	if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE)) +	if (!ring_is_idle(engine))  		return false;  	return true; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index ded2add18b26..d93c58410bff 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -82,20 +82,10 @@ static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc)  static void intel_fbc_get_plane_source_size(struct intel_fbc_state_cache *cache,  					    int *width, int *height)  { -	int w, h; - -	if (drm_rotation_90_or_270(cache->plane.rotation)) { -		w = cache->plane.src_h; -		h = cache->plane.src_w; -	} else { -		w = cache->plane.src_w; -		h = cache->plane.src_h; -	} -  	if (width) -		*width = w; +		*width = cache->plane.src_w;  	if (height) -		*height = h; +		*height = cache->plane.src_h;  }  static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv, @@ -746,6 +736,11 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,  		cache->crtc.hsw_bdw_pixel_rate = crtc_state->pixel_rate;  	cache->plane.rotation = plane_state->base.rotation; +	/* +	 * Src coordinates are already rotated by 270 degrees for +	 * the 90/270 degree plane rotation cases (to match the +	 * GTT mapping), hence no need to account for rotation here. +	 */  	cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16;  	cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16;  	cache->plane.visible = plane_state->base.visible; diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c index 668f00480d97..292fedf30b00 100644 --- a/drivers/gpu/drm/i915/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c @@ -149,44 +149,10 @@ static void lpe_audio_platdev_destroy(struct drm_i915_private *dev_priv)  static void lpe_audio_irq_unmask(struct irq_data *d)  { -	struct drm_i915_private *dev_priv = d->chip_data; -	unsigned long irqflags; -	u32 val = (I915_LPE_PIPE_A_INTERRUPT | -		I915_LPE_PIPE_B_INTERRUPT); - -	if (IS_CHERRYVIEW(dev_priv)) -		val |= I915_LPE_PIPE_C_INTERRUPT; - -	spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - -	dev_priv->irq_mask &= ~val; -	I915_WRITE(VLV_IIR, val); -	I915_WRITE(VLV_IIR, val); -	I915_WRITE(VLV_IMR, dev_priv->irq_mask); -	POSTING_READ(VLV_IMR); - -	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);  }  static void lpe_audio_irq_mask(struct irq_data *d)  { -	struct drm_i915_private *dev_priv = d->chip_data; -	unsigned long irqflags; -	u32 val = (I915_LPE_PIPE_A_INTERRUPT | -		I915_LPE_PIPE_B_INTERRUPT); - -	if (IS_CHERRYVIEW(dev_priv)) -		val |= I915_LPE_PIPE_C_INTERRUPT; - -	spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - -	dev_priv->irq_mask |= val; -	I915_WRITE(VLV_IMR, dev_priv->irq_mask); -	I915_WRITE(VLV_IIR, val); -	I915_WRITE(VLV_IIR, val); -	POSTING_READ(VLV_IIR); - -	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);  }  static struct irq_chip lpe_audio_irqchip = { @@ -330,8 +296,6 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)  	desc = irq_to_desc(dev_priv->lpe_audio.irq); -	lpe_audio_irq_mask(&desc->irq_data); -  	lpe_audio_platdev_destroy(dev_priv);  	irq_free_desc(dev_priv->lpe_audio.irq); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c8f7c631fc1f..62f44d3e7c43 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -326,8 +326,7 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq)  		rq->ctx->ppgtt ?: rq->i915->mm.aliasing_ppgtt;  	u32 *reg_state = ce->lrc_reg_state; -	assert_ring_tail_valid(rq->ring, rq->tail); -	reg_state[CTX_RING_TAIL+1] = rq->tail; +	reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail);  	/* True 32b PPGTT with dynamic page allocation: update PDP  	 * registers and point the unallocated PDPs to scratch page. @@ -1989,7 +1988,7 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,  	ce->ring = ring;  	ce->state = vma; -	ce->initialised = engine->init_context == NULL; +	ce->initialised |= engine->init_context == NULL;  	return 0; @@ -2036,8 +2035,7 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv)  			ce->state->obj->mm.dirty = true;  			i915_gem_object_unpin_map(ce->state->obj); -			ce->ring->head = ce->ring->tail = 0; -			intel_ring_update_space(ce->ring); +			intel_ring_reset(ce->ring, 0);  		}  	}  } diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index 71cbe9c08932..5abef482eacf 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -240,7 +240,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)  		return false;  	} -	intel_dp_read_desc(dp); +	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));  	DRM_DEBUG_KMS("Success: LSPCON init\n");  	return true; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 570bd603f401..078fd1bfa5ea 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3373,20 +3373,26 @@ skl_plane_downscale_amount(const struct intel_crtc_state *cstate,  	/* n.b., src is 16.16 fixed point, dst is whole integer */  	if (plane->id == PLANE_CURSOR) { +		/* +		 * Cursors only support 0/180 degree rotation, +		 * hence no need to account for rotation here. +		 */  		src_w = pstate->base.src_w;  		src_h = pstate->base.src_h;  		dst_w = pstate->base.crtc_w;  		dst_h = pstate->base.crtc_h;  	} else { +		/* +		 * Src coordinates are already rotated by 270 degrees for +		 * the 90/270 degree plane rotation cases (to match the +		 * GTT mapping), hence no need to account for rotation here. +		 */  		src_w = drm_rect_width(&pstate->base.src);  		src_h = drm_rect_height(&pstate->base.src);  		dst_w = drm_rect_width(&pstate->base.dst);  		dst_h = drm_rect_height(&pstate->base.dst);  	} -	if (drm_rotation_90_or_270(pstate->base.rotation)) -		swap(dst_w, dst_h); -  	downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);  	downscale_w = max(src_w / dst_w, (uint32_t)DRM_PLANE_HELPER_NO_SCALING); @@ -3417,12 +3423,14 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,  	if (y && format != DRM_FORMAT_NV12)  		return 0; +	/* +	 * Src coordinates are already rotated by 270 degrees for +	 * the 90/270 degree plane rotation cases (to match the +	 * GTT mapping), hence no need to account for rotation here. +	 */  	width = drm_rect_width(&intel_pstate->base.src) >> 16;  	height = drm_rect_height(&intel_pstate->base.src) >> 16; -	if (drm_rotation_90_or_270(pstate->rotation)) -		swap(width, height); -  	/* for planar format */  	if (format == DRM_FORMAT_NV12) {  		if (y)  /* y-plane data rate */ @@ -3505,12 +3513,14 @@ skl_ddb_min_alloc(const struct drm_plane_state *pstate,  	    fb->modifier != I915_FORMAT_MOD_Yf_TILED)  		return 8; +	/* +	 * Src coordinates are already rotated by 270 degrees for +	 * the 90/270 degree plane rotation cases (to match the +	 * GTT mapping), hence no need to account for rotation here. +	 */  	src_w = drm_rect_width(&intel_pstate->base.src) >> 16;  	src_h = drm_rect_height(&intel_pstate->base.src) >> 16; -	if (drm_rotation_90_or_270(pstate->rotation)) -		swap(src_w, src_h); -  	/* Halve UV plane width and height for NV12 */  	if (fb->format->format == DRM_FORMAT_NV12 && !y) {  		src_w /= 2; @@ -3794,13 +3804,15 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,  		width = intel_pstate->base.crtc_w;  		height = intel_pstate->base.crtc_h;  	} else { +		/* +		 * Src coordinates are already rotated by 270 degrees for +		 * the 90/270 degree plane rotation cases (to match the +		 * GTT mapping), hence no need to account for rotation here. +		 */  		width = drm_rect_width(&intel_pstate->base.src) >> 16;  		height = drm_rect_height(&intel_pstate->base.src) >> 16;  	} -	if (drm_rotation_90_or_270(pstate->rotation)) -		swap(width, height); -  	cpp = fb->format->cpp[0];  	plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); @@ -4335,11 +4347,19 @@ skl_compute_wm(struct drm_atomic_state *state)  	struct drm_crtc_state *cstate;  	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);  	struct skl_wm_values *results = &intel_state->wm_results; +	struct drm_device *dev = state->dev;  	struct skl_pipe_wm *pipe_wm;  	bool changed = false;  	int ret, i;  	/* +	 * When we distrust bios wm we always need to recompute to set the +	 * expected DDB allocations for each CRTC. +	 */ +	if (to_i915(dev)->wm.distrust_bios_wm) +		changed = true; + +	/*  	 * If this transaction isn't actually touching any CRTC's, don't  	 * bother with watermark calculation.  Note that if we pass this  	 * test, we're guaranteed to hold at least one CRTC state mutex, @@ -4349,6 +4369,7 @@ skl_compute_wm(struct drm_atomic_state *state)  	 */  	for_each_new_crtc_in_state(state, crtc, cstate, i)  		changed = true; +  	if (!changed)  		return 0; diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index c3780d0d2baf..559f1ab42bfc 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -435,8 +435,9 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp)  	}  	/* PSR2 is restricted to work with panel resolutions upto 3200x2000 */ -	if (intel_crtc->config->pipe_src_w > 3200 || -				intel_crtc->config->pipe_src_h > 2000) { +	if (dev_priv->psr.psr2_support && +	    (intel_crtc->config->pipe_src_w > 3200 || +	     intel_crtc->config->pipe_src_h > 2000)) {  		dev_priv->psr.psr2_support = false;  		return false;  	} diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 66a2b8b83972..513a0f4b469b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -49,7 +49,7 @@ static int __intel_ring_space(int head, int tail, int size)  void intel_ring_update_space(struct intel_ring *ring)  { -	ring->space = __intel_ring_space(ring->head, ring->tail, ring->size); +	ring->space = __intel_ring_space(ring->head, ring->emit, ring->size);  }  static int @@ -774,8 +774,8 @@ static void i9xx_submit_request(struct drm_i915_gem_request *request)  	i915_gem_request_submit(request); -	assert_ring_tail_valid(request->ring, request->tail); -	I915_WRITE_TAIL(request->engine, request->tail); +	I915_WRITE_TAIL(request->engine, +			intel_ring_set_tail(request->ring, request->tail));  }  static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req, u32 *cs) @@ -1316,11 +1316,23 @@ err:  	return PTR_ERR(addr);  } +void intel_ring_reset(struct intel_ring *ring, u32 tail) +{ +	GEM_BUG_ON(!list_empty(&ring->request_list)); +	ring->tail = tail; +	ring->head = tail; +	ring->emit = tail; +	intel_ring_update_space(ring); +} +  void intel_ring_unpin(struct intel_ring *ring)  {  	GEM_BUG_ON(!ring->vma);  	GEM_BUG_ON(!ring->vaddr); +	/* Discard any unused bytes beyond that submitted to hw. */ +	intel_ring_reset(ring, ring->tail); +  	if (i915_vma_is_map_and_fenceable(ring->vma))  		i915_vma_unpin_iomap(ring->vma);  	else @@ -1562,8 +1574,9 @@ void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)  	struct intel_engine_cs *engine;  	enum intel_engine_id id; +	/* Restart from the beginning of the rings for convenience */  	for_each_engine(engine, dev_priv, id) -		engine->buffer->head = engine->buffer->tail; +		intel_ring_reset(engine->buffer, 0);  }  static int ring_request_alloc(struct drm_i915_gem_request *request) @@ -1616,7 +1629,7 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)  		unsigned space;  		/* Would completion of this request free enough space? */ -		space = __intel_ring_space(target->postfix, ring->tail, +		space = __intel_ring_space(target->postfix, ring->emit,  					   ring->size);  		if (space >= bytes)  			break; @@ -1641,8 +1654,8 @@ static int wait_for_space(struct drm_i915_gem_request *req, int bytes)  u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)  {  	struct intel_ring *ring = req->ring; -	int remain_actual = ring->size - ring->tail; -	int remain_usable = ring->effective_size - ring->tail; +	int remain_actual = ring->size - ring->emit; +	int remain_usable = ring->effective_size - ring->emit;  	int bytes = num_dwords * sizeof(u32);  	int total_bytes, wait_bytes;  	bool need_wrap = false; @@ -1678,17 +1691,17 @@ u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)  	if (unlikely(need_wrap)) {  		GEM_BUG_ON(remain_actual > ring->space); -		GEM_BUG_ON(ring->tail + remain_actual > ring->size); +		GEM_BUG_ON(ring->emit + remain_actual > ring->size);  		/* Fill the tail with MI_NOOP */ -		memset(ring->vaddr + ring->tail, 0, remain_actual); -		ring->tail = 0; +		memset(ring->vaddr + ring->emit, 0, remain_actual); +		ring->emit = 0;  		ring->space -= remain_actual;  	} -	GEM_BUG_ON(ring->tail > ring->size - bytes); -	cs = ring->vaddr + ring->tail; -	ring->tail += bytes; +	GEM_BUG_ON(ring->emit > ring->size - bytes); +	cs = ring->vaddr + ring->emit; +	ring->emit += bytes;  	ring->space -= bytes;  	GEM_BUG_ON(ring->space < 0); @@ -1699,7 +1712,7 @@ u32 *intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)  int intel_ring_cacheline_align(struct drm_i915_gem_request *req)  {  	int num_dwords = -		(req->ring->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); +		(req->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);  	u32 *cs;  	if (num_dwords == 0) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index a82a0807f64d..f7144fe09613 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -145,6 +145,7 @@ struct intel_ring {  	u32 head;  	u32 tail; +	u32 emit;  	int space;  	int size; @@ -488,6 +489,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)  struct intel_ring *  intel_engine_create_ring(struct intel_engine_cs *engine, int size);  int intel_ring_pin(struct intel_ring *ring, unsigned int offset_bias); +void intel_ring_reset(struct intel_ring *ring, u32 tail); +void intel_ring_update_space(struct intel_ring *ring);  void intel_ring_unpin(struct intel_ring *ring);  void intel_ring_free(struct intel_ring *ring); @@ -511,7 +514,7 @@ intel_ring_advance(struct drm_i915_gem_request *req, u32 *cs)  	 * reserved for the command packet (i.e. the value passed to  	 * intel_ring_begin()).  	 */ -	GEM_BUG_ON((req->ring->vaddr + req->ring->tail) != cs); +	GEM_BUG_ON((req->ring->vaddr + req->ring->emit) != cs);  }  static inline u32 @@ -540,7 +543,19 @@ assert_ring_tail_valid(const struct intel_ring *ring, unsigned int tail)  	GEM_BUG_ON(tail >= ring->size);  } -void intel_ring_update_space(struct intel_ring *ring); +static inline unsigned int +intel_ring_set_tail(struct intel_ring *ring, unsigned int tail) +{ +	/* Whilst writes to the tail are strictly order, there is no +	 * serialisation between readers and the writers. The tail may be +	 * read by i915_gem_request_retire() just as it is being updated +	 * by execlists, as although the breadcrumb is complete, the context +	 * switch hasn't been seen. +	 */ +	assert_ring_tail_valid(ring, tail); +	ring->tail = tail; +	return tail; +}  void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 8c87c717c7cd..e6517edcd16b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -83,10 +83,13 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,   */  void intel_pipe_update_start(struct intel_crtc *crtc)  { +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;  	long timeout = msecs_to_jiffies_timeout(1);  	int scanline, min, max, vblank_start;  	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); +	bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && +		intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DSI);  	DEFINE_WAIT(wait);  	vblank_start = adjusted_mode->crtc_vblank_start; @@ -139,6 +142,24 @@ void intel_pipe_update_start(struct intel_crtc *crtc)  	drm_crtc_vblank_put(&crtc->base); +	/* +	 * On VLV/CHV DSI the scanline counter would appear to +	 * increment approx. 1/3 of a scanline before start of vblank. +	 * The registers still get latched at start of vblank however. +	 * This means we must not write any registers on the first +	 * line of vblank (since not the whole line is actually in +	 * vblank). And unfortunately we can't use the interrupt to +	 * wait here since it will fire too soon. We could use the +	 * frame start interrupt instead since it will fire after the +	 * critical scanline, but that would require more changes +	 * in the interrupt code. So for now we'll just do the nasty +	 * thing and poll for the bad scanline to pass us by. +	 * +	 * FIXME figure out if BXT+ DSI suffers from this as well +	 */ +	while (need_vlv_dsi_wa && scanline == vblank_start) +		scanline = intel_get_crtc_scanline(crtc); +  	crtc->debug.scanline_start = scanline;  	crtc->debug.start_vbl_time = ktime_get();  	crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc); diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index 4b7f73aeddac..f84115261ae7 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -59,8 +59,6 @@ struct drm_i915_gem_request;   *                available in the work queue (note, the queue is shared,   *                not per-engine). It is OK for this to be nonzero, but   *                it should not be huge! - *   q_fail: failed to enqueue a work item. This should never happen, - *           because we check for space beforehand.   *   b_fail: failed to ring the doorbell. This should never happen, unless   *           somehow the hardware misbehaves, or maybe if the GuC firmware   *           crashes? We probably need to reset the GPU to recover. diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 1afb8b06e3e1..12b85b3278cd 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -320,7 +320,7 @@ static unsigned long max_dwords(struct drm_i915_gem_object *obj)  static int igt_ctx_exec(void *arg)  {  	struct drm_i915_private *i915 = arg; -	struct drm_i915_gem_object *obj; +	struct drm_i915_gem_object *obj = NULL;  	struct drm_file *file;  	IGT_TIMEOUT(end_time);  	LIST_HEAD(objects); @@ -359,7 +359,7 @@ static int igt_ctx_exec(void *arg)  		}  		for_each_engine(engine, i915, id) { -			if (dw == 0) { +			if (!obj) {  				obj = create_test_object(ctx, file, &objects);  				if (IS_ERR(obj)) {  					err = PTR_ERR(obj); @@ -376,8 +376,10 @@ static int igt_ctx_exec(void *arg)  				goto out_unlock;  			} -			if (++dw == max_dwords(obj)) +			if (++dw == max_dwords(obj)) { +				obj = NULL;  				dw = 0; +			}  			ndwords++;  		}  		ncontexts++; diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 8fb801fab039..8b05ecb8fdef 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -673,7 +673,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)  		ret = drm_of_find_panel_or_bridge(child,  						  imx_ldb->lvds_mux ? 4 : 2, 0,  						  &channel->panel, &channel->bridge); -		if (ret) +		if (ret && ret != -ENODEV)  			return ret;  		/* panel ddc only if there is no bridge */ diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 808b995a990f..b5cc6e12334c 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -19,6 +19,7 @@  #include <drm/drm_of.h>  #include <linux/clk.h>  #include <linux/component.h> +#include <linux/iopoll.h>  #include <linux/irq.h>  #include <linux/of.h>  #include <linux/of_platform.h> @@ -900,16 +901,12 @@ static int mtk_dsi_host_detach(struct mipi_dsi_host *host,  static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)  { -	u32 timeout_ms = 500000; /* total 1s ~ 2s timeout */ - -	while (timeout_ms--) { -		if (!(readl(dsi->regs + DSI_INTSTA) & DSI_BUSY)) -			break; - -		usleep_range(2, 4); -	} +	int ret; +	u32 val; -	if (timeout_ms == 0) { +	ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY), +				 4, 2000000); +	if (ret) {  		DRM_WARN("polling dsi wait not busy timeout!\n");  		mtk_dsi_enable(dsi); diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 41a1c03b0347..0a4ffd724146 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1062,7 +1062,7 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,  	}  	err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer)); -	if (err) { +	if (err < 0) {  		dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",  			err);  		return err; diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 75382f5f0fce..10b227d83e9a 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -152,7 +152,7 @@ static struct regmap_config meson_regmap_config = {  	.max_register   = 0x1000,  }; -static int meson_drv_bind(struct device *dev) +static int meson_drv_bind_master(struct device *dev, bool has_components)  {  	struct platform_device *pdev = to_platform_device(dev);  	struct meson_drm *priv; @@ -233,10 +233,12 @@ static int meson_drv_bind(struct device *dev)  	if (ret)  		goto free_drm; -	ret = component_bind_all(drm->dev, drm); -	if (ret) { -		dev_err(drm->dev, "Couldn't bind all components\n"); -		goto free_drm; +	if (has_components) { +		ret = component_bind_all(drm->dev, drm); +		if (ret) { +			dev_err(drm->dev, "Couldn't bind all components\n"); +			goto free_drm; +		}  	}  	ret = meson_plane_create(priv); @@ -276,6 +278,11 @@ free_drm:  	return ret;  } +static int meson_drv_bind(struct device *dev) +{ +	return meson_drv_bind_master(dev, true); +} +  static void meson_drv_unbind(struct device *dev)  {  	struct drm_device *drm = dev_get_drvdata(dev); @@ -357,6 +364,9 @@ static int meson_drv_probe(struct platform_device *pdev)  		count += meson_probe_remote(pdev, &match, np, remote);  	} +	if (count && !match) +		return meson_drv_bind_master(&pdev->dev, false); +  	/* If some endpoints were found, initialize the nodes */  	if (count) {  		dev_info(&pdev->dev, "Queued %d outputs on vpu\n", count); diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index adb411a078e8..f4b53588e071 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1173,7 +1173,10 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,  	if (IS_G200_SE(mdev)) { -		if (mdev->unique_rev_id >= 0x02) { +		if  (mdev->unique_rev_id >= 0x04) { +			WREG8(MGAREG_CRTCEXT_INDEX, 0x06); +			WREG8(MGAREG_CRTCEXT_DATA, 0); +		} else if (mdev->unique_rev_id >= 0x02) {  			u8 hi_pri_lvl;  			u32 bpp;  			u32 mb; @@ -1639,6 +1642,10 @@ static int mga_vga_mode_valid(struct drm_connector *connector,  			if (mga_vga_calculate_mode_bandwidth(mode, bpp)  				> (30100 * 1024))  				return MODE_BANDWIDTH; +		} else { +			if (mga_vga_calculate_mode_bandwidth(mode, bpp) +				> (55000 * 1024)) +				return MODE_BANDWIDTH;  		}  	} else if (mdev->type == G200_WB) {  		if (mode->hdisplay > 1280) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 5b8e23d051f2..0a31cd6d01ce 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -13,6 +13,7 @@ config DRM_MSM  	select QCOM_SCM  	select SND_SOC_HDMI_CODEC if SND_SOC  	select SYNC_FILE +	select PM_OPP  	default y  	help  	  DRM/KMS driver for MSM/snapdragon. diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c index f8f48d014978..9c34d7824988 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_mdss.c @@ -116,7 +116,7 @@ static int mdss_hw_irqdomain_map(struct irq_domain *d, unsigned int irq,  	return 0;  } -static struct irq_domain_ops mdss_hw_irqdomain_ops = { +static const struct irq_domain_ops mdss_hw_irqdomain_ops = {  	.map = mdss_hw_irqdomain_map,  	.xlate = irq_domain_xlate_onecell,  }; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index a38c5fe6cc19..7d3741215387 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -225,9 +225,10 @@ mdp5_plane_duplicate_state(struct drm_plane *plane)  	mdp5_state = kmemdup(to_mdp5_plane_state(plane->state),  			sizeof(*mdp5_state), GFP_KERNEL); +	if (!mdp5_state) +		return NULL; -	if (mdp5_state && mdp5_state->base.fb) -		drm_framebuffer_reference(mdp5_state->base.fb); +	__drm_atomic_helper_plane_duplicate_state(plane, &mdp5_state->base);  	return &mdp5_state->base;  } @@ -444,6 +445,10 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,  			mdp5_pipe_release(state->state, old_hwpipe);  			mdp5_pipe_release(state->state, old_right_hwpipe);  		} +	} else { +		mdp5_pipe_release(state->state, mdp5_state->hwpipe); +		mdp5_pipe_release(state->state, mdp5_state->r_hwpipe); +		mdp5_state->hwpipe = mdp5_state->r_hwpipe = NULL;  	}  	return 0; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 87b5695d4034..9d498eb81906 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -830,6 +830,7 @@ static struct drm_driver msm_driver = {  	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,  	.gem_prime_export   = drm_gem_prime_export,  	.gem_prime_import   = drm_gem_prime_import, +	.gem_prime_res_obj  = msm_gem_prime_res_obj,  	.gem_prime_pin      = msm_gem_prime_pin,  	.gem_prime_unpin    = msm_gem_prime_unpin,  	.gem_prime_get_sg_table = msm_gem_prime_get_sg_table, diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 28b6f9ba5066..1b26ca626528 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -224,6 +224,7 @@ struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj);  void *msm_gem_prime_vmap(struct drm_gem_object *obj);  void msm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);  int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); +struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj);  struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,  		struct dma_buf_attachment *attach, struct sg_table *sg);  int msm_gem_prime_pin(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c index 3f299c537b77..a2f89bac9c16 100644 --- a/drivers/gpu/drm/msm/msm_fence.c +++ b/drivers/gpu/drm/msm/msm_fence.c @@ -99,8 +99,8 @@ void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)  }  struct msm_fence { -	struct msm_fence_context *fctx;  	struct dma_fence base; +	struct msm_fence_context *fctx;  };  static inline struct msm_fence *to_msm_fence(struct dma_fence *fence) @@ -130,19 +130,13 @@ static bool msm_fence_signaled(struct dma_fence *fence)  	return fence_completed(f->fctx, f->base.seqno);  } -static void msm_fence_release(struct dma_fence *fence) -{ -	struct msm_fence *f = to_msm_fence(fence); -	kfree_rcu(f, base.rcu); -} -  static const struct dma_fence_ops msm_fence_ops = {  	.get_driver_name = msm_fence_get_driver_name,  	.get_timeline_name = msm_fence_get_timeline_name,  	.enable_signaling = msm_fence_enable_signaling,  	.signaled = msm_fence_signaled,  	.wait = dma_fence_default_wait, -	.release = msm_fence_release, +	.release = dma_fence_free,  };  struct dma_fence * diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 68e509b3b9e4..50289a23baf8 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -758,6 +758,8 @@ static int msm_gem_new_impl(struct drm_device *dev,  	struct msm_gem_object *msm_obj;  	bool use_vram = false; +	WARN_ON(!mutex_is_locked(&dev->struct_mutex)); +  	switch (flags & MSM_BO_CACHE_MASK) {  	case MSM_BO_UNCACHED:  	case MSM_BO_CACHED: @@ -853,7 +855,11 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,  	size = PAGE_ALIGN(dmabuf->size); +	/* Take mutex so we can modify the inactive list in msm_gem_new_impl */ +	mutex_lock(&dev->struct_mutex);  	ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj); +	mutex_unlock(&dev->struct_mutex); +  	if (ret)  		goto fail; diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c index 60bb290700ce..13403c6da6c7 100644 --- a/drivers/gpu/drm/msm/msm_gem_prime.c +++ b/drivers/gpu/drm/msm/msm_gem_prime.c @@ -70,3 +70,10 @@ void msm_gem_prime_unpin(struct drm_gem_object *obj)  	if (!obj->import_attach)  		msm_gem_put_pages(obj);  } + +struct reservation_object *msm_gem_prime_res_obj(struct drm_gem_object *obj) +{ +	struct msm_gem_object *msm_obj = to_msm_bo(obj); + +	return msm_obj->resv; +} diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 1c545ebe6a5a..7832e6421d25 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -410,12 +410,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,  		if (!in_fence)  			return -EINVAL; -		/* TODO if we get an array-fence due to userspace merging multiple -		 * fences, we need a way to determine if all the backing fences -		 * are from our own context.. +		/* +		 * Wait if the fence is from a foreign context, or if the fence +		 * array contains any fence from a foreign context.  		 */ - -		if (in_fence->context != gpu->fctx->context) { +		if (!dma_fence_match_context(in_fence, gpu->fctx->context)) {  			ret = dma_fence_wait(in_fence, true);  			if (ret)  				return ret; @@ -496,8 +495,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,  			goto out;  		} -		if ((submit_cmd.size + submit_cmd.submit_offset) >= -				msm_obj->base.size) { +		if (!submit_cmd.size || +			((submit_cmd.size + submit_cmd.submit_offset) > +				msm_obj->base.size)) {  			DRM_ERROR("invalid cmdstream size: %u\n", submit_cmd.size);  			ret = -EINVAL;  			goto out; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 97b9c38c6b3f..0fdc88d79ca8 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -549,9 +549,9 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu)  		gpu->grp_clks[i] = get_clock(dev, name);  		/* Remember the key clocks that we need to control later */ -		if (!strcmp(name, "core")) +		if (!strcmp(name, "core") || !strcmp(name, "core_clk"))  			gpu->core_clk = gpu->grp_clks[i]; -		else if (!strcmp(name, "rbbmtimer")) +		else if (!strcmp(name, "rbbmtimer") || !strcmp(name, "rbbmtimer_clk"))  			gpu->rbbmtimer_clk = gpu->grp_clks[i];  		++i; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index 1144e0c9e894..0abe77675b76 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -35,6 +35,13 @@  #include "mxsfb_drv.h"  #include "mxsfb_regs.h" +#define MXS_SET_ADDR		0x4 +#define MXS_CLR_ADDR		0x8 +#define MODULE_CLKGATE		BIT(30) +#define MODULE_SFTRST		BIT(31) +/* 1 second delay should be plenty of time for block reset */ +#define RESET_TIMEOUT		1000000 +  static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)  {  	return (val & mxsfb->devdata->hs_wdth_mask) << @@ -159,6 +166,36 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)  		clk_disable_unprepare(mxsfb->clk_disp_axi);  } +/* + * Clear the bit and poll it cleared.  This is usually called with + * a reset address and mask being either SFTRST(bit 31) or CLKGATE + * (bit 30). + */ +static int clear_poll_bit(void __iomem *addr, u32 mask) +{ +	u32 reg; + +	writel(mask, addr + MXS_CLR_ADDR); +	return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT); +} + +static int mxsfb_reset_block(void __iomem *reset_addr) +{ +	int ret; + +	ret = clear_poll_bit(reset_addr, MODULE_SFTRST); +	if (ret) +		return ret; + +	writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR); + +	ret = clear_poll_bit(reset_addr, MODULE_SFTRST); +	if (ret) +		return ret; + +	return clear_poll_bit(reset_addr, MODULE_CLKGATE); +} +  static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)  {  	struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode; @@ -173,6 +210,11 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)  	 */  	mxsfb_enable_axi_clk(mxsfb); +	/* Mandatory eLCDIF reset as per the Reference Manual */ +	err = mxsfb_reset_block(mxsfb->base); +	if (err) +		return; +  	/* Clear the FIFOs */  	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h index 6a567fe347b3..820a4805916f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h @@ -4,6 +4,7 @@  struct nvkm_alarm {  	struct list_head head; +	struct list_head exec;  	u64 timestamp;  	void (*func)(struct nvkm_alarm *);  }; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 36268e1802b5..15a13d09d431 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -80,7 +80,7 @@ int nouveau_modeset = -1;  module_param_named(modeset, nouveau_modeset, int, 0400);  MODULE_PARM_DESC(runpm, "disable (0), force enable (1), optimus only default (-1)"); -int nouveau_runtime_pm = -1; +static int nouveau_runtime_pm = -1;  module_param_named(runpm, nouveau_runtime_pm, int, 0400);  static struct drm_driver driver_stub; @@ -495,7 +495,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)  	nouveau_fbcon_init(dev);  	nouveau_led_init(dev); -	if (nouveau_runtime_pm != 0) { +	if (nouveau_pmops_runtime()) {  		pm_runtime_use_autosuspend(dev->dev);  		pm_runtime_set_autosuspend_delay(dev->dev, 5000);  		pm_runtime_set_active(dev->dev); @@ -527,7 +527,7 @@ nouveau_drm_unload(struct drm_device *dev)  {  	struct nouveau_drm *drm = nouveau_drm(dev); -	if (nouveau_runtime_pm != 0) { +	if (nouveau_pmops_runtime()) {  		pm_runtime_get_sync(dev->dev);  		pm_runtime_forbid(dev->dev);  	} @@ -726,6 +726,14 @@ nouveau_pmops_thaw(struct device *dev)  	return nouveau_do_resume(drm_dev, false);  } +bool +nouveau_pmops_runtime() +{ +	if (nouveau_runtime_pm == -1) +		return nouveau_is_optimus() || nouveau_is_v1_dsm(); +	return nouveau_runtime_pm == 1; +} +  static int  nouveau_pmops_runtime_suspend(struct device *dev)  { @@ -733,14 +741,7 @@ nouveau_pmops_runtime_suspend(struct device *dev)  	struct drm_device *drm_dev = pci_get_drvdata(pdev);  	int ret; -	if (nouveau_runtime_pm == 0) { -		pm_runtime_forbid(dev); -		return -EBUSY; -	} - -	/* are we optimus enabled? */ -	if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) { -		DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); +	if (!nouveau_pmops_runtime()) {  		pm_runtime_forbid(dev);  		return -EBUSY;  	} @@ -765,8 +766,10 @@ nouveau_pmops_runtime_resume(struct device *dev)  	struct nvif_device *device = &nouveau_drm(drm_dev)->client.device;  	int ret; -	if (nouveau_runtime_pm == 0) -		return -EINVAL; +	if (!nouveau_pmops_runtime()) { +		pm_runtime_forbid(dev); +		return -EBUSY; +	}  	pci_set_power_state(pdev, PCI_D0);  	pci_restore_state(pdev); @@ -796,14 +799,7 @@ nouveau_pmops_runtime_idle(struct device *dev)  	struct nouveau_drm *drm = nouveau_drm(drm_dev);  	struct drm_crtc *crtc; -	if (nouveau_runtime_pm == 0) { -		pm_runtime_forbid(dev); -		return -EBUSY; -	} - -	/* are we optimus enabled? */ -	if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) { -		DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); +	if (!nouveau_pmops_runtime()) {  		pm_runtime_forbid(dev);  		return -EBUSY;  	} diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index eadec2f49ad3..a11b6aaed325 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -108,8 +108,6 @@ nouveau_cli(struct drm_file *fpriv)  #include <nvif/object.h>  #include <nvif/device.h> -extern int nouveau_runtime_pm; -  struct nouveau_drm {  	struct nouveau_cli client;  	struct drm_device *dev; @@ -195,6 +193,7 @@ nouveau_drm(struct drm_device *dev)  int nouveau_pmops_suspend(struct device *);  int nouveau_pmops_resume(struct device *); +bool nouveau_pmops_runtime(void);  #include <nvkm/core/tegra.h> diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c index a4aacbc0cec8..02fe0efb9e16 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vga.c +++ b/drivers/gpu/drm/nouveau/nouveau_vga.c @@ -87,7 +87,7 @@ void  nouveau_vga_init(struct nouveau_drm *drm)  {  	struct drm_device *dev = drm->dev; -	bool runtime = false; +	bool runtime = nouveau_pmops_runtime();  	/* only relevant for PCI devices */  	if (!dev->pdev) @@ -99,10 +99,6 @@ nouveau_vga_init(struct nouveau_drm *drm)  	if (pci_is_thunderbolt_attached(dev->pdev))  		return; -	if (nouveau_runtime_pm == 1) -		runtime = true; -	if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) -		runtime = true;  	vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, runtime);  	if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus()) @@ -113,18 +109,13 @@ void  nouveau_vga_fini(struct nouveau_drm *drm)  {  	struct drm_device *dev = drm->dev; -	bool runtime = false; +	bool runtime = nouveau_pmops_runtime();  	vga_client_register(dev->pdev, NULL, NULL, NULL);  	if (pci_is_thunderbolt_attached(dev->pdev))  		return; -	if (nouveau_runtime_pm == 1) -		runtime = true; -	if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm())) -		runtime = true; -  	vga_switcheroo_unregister_client(dev->pdev);  	if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())  		vga_switcheroo_fini_domain_pm_ops(drm->dev->dev); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index a7663249b3ba..06e564a9ccb2 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -2107,7 +2107,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)  					asyc->set.dither = true;  			}  		} else { -			asyc->set.mask = ~0; +			if (asyc) +				asyc->set.mask = ~0;  			asyh->set.mask = ~0;  		} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index f2a86eae0a0d..2437f7d41ca2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -50,7 +50,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)  		/* Move to completed list.  We'll drop the lock before  		 * executing the callback so it can reschedule itself.  		 */ -		list_move_tail(&alarm->head, &exec); +		list_del_init(&alarm->head); +		list_add(&alarm->exec, &exec);  	}  	/* Shut down interrupt if no more pending alarms. */ @@ -59,8 +60,8 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)  	spin_unlock_irqrestore(&tmr->lock, flags);  	/* Execute completed callbacks. */ -	list_for_each_entry_safe(alarm, atemp, &exec, head) { -		list_del_init(&alarm->head); +	list_for_each_entry_safe(alarm, atemp, &exec, exec) { +		list_del(&alarm->exec);  		alarm->func(alarm);  	}  } diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 008c145b7f29..ca44233ceacc 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -9267,8 +9267,11 @@ static void dce8_program_watermarks(struct radeon_device *rdev,  	u32 tmp, wm_mask;  	if (radeon_crtc->base.enabled && num_heads && mode) { -		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); +		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000, +					    (u32)mode->clock); +		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000, +					  (u32)mode->clock); +		line_time = min(line_time, (u32)65535);  		/* watermark for high clocks */  		if ((rdev->pm.pm_method == PM_METHOD_DPM) && diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 0bf103536404..534637203e70 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2266,8 +2266,11 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,  	fixed20_12 a, b, c;  	if (radeon_crtc->base.enabled && num_heads && mode) { -		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); +		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000, +					    (u32)mode->clock); +		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000, +					  (u32)mode->clock); +		line_time = min(line_time, (u32)65535);  		priority_a_cnt = 0;  		priority_b_cnt = 0;  		dram_channels = evergreen_get_number_of_dram_channels(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 432480ff9d22..3178ba0c537c 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -3393,6 +3393,13 @@ void radeon_combios_asic_init(struct drm_device *dev)  	    rdev->pdev->subsystem_vendor == 0x103c &&  	    rdev->pdev->subsystem_device == 0x280a)  		return; +	/* quirk for rs4xx Toshiba Sattellite L20-183 latop to make it resume +	 * - it hangs on resume inside the dynclk 1 table. +	 */ +	if (rdev->family == CHIP_RS400 && +	    rdev->pdev->subsystem_vendor == 0x1179 && +	    rdev->pdev->subsystem_device == 0xff31) +	        return;  	/* DYN CLK 1 */  	table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 6ecf42783d4b..0a6444d72000 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -136,6 +136,10 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = {  	 * https://bugzilla.kernel.org/show_bug.cgi?id=51381  	 */  	{ PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX }, +	/* Asus K53TK laptop with AMD A6-3420M APU and Radeon 7670m GPU +	 * https://bugs.freedesktop.org/show_bug.cgi?id=101491 +	 */ +	{ PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },  	/* macbook pro 8.2 */  	{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },  	{ 0, 0, 0, 0, 0 }, diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 7431eb4a11b7..d34d1cf33895 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -621,7 +621,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,  	}  	/* TODO: is this still necessary on NI+ ? */ -	if ((cmd == 0 || cmd == 1 || cmd == 0x3) && +	if ((cmd == 0 || cmd == 0x3) &&  	    (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {  		DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",  			  start, end); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 76d1888528e6..5303f25d5280 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2284,8 +2284,11 @@ static void dce6_program_watermarks(struct radeon_device *rdev,  	fixed20_12 a, b, c;  	if (radeon_crtc->base.enabled && num_heads && mode) { -		active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; -		line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); +		active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000, +					    (u32)mode->clock); +		line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000, +					  (u32)mode->clock); +		line_time = min(line_time, (u32)65535);  		priority_a_cnt = 0;  		priority_b_cnt = 0; diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index d8fa7a9c9240..ce5f2d1f9994 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -245,8 +245,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,  				      struct drm_connector_state *conn_state)  {  	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); -	struct rockchip_dp_device *dp = to_dp(encoder); -	int ret;  	/*  	 * The hardware IC designed that VOP must output the RGB10 video @@ -258,16 +256,6 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,  	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;  	s->output_type = DRM_MODE_CONNECTOR_eDP; -	if (dp->data->chip_type == RK3399_EDP) { -		/* -		 * For RK3399, VOP Lit must code the out mode to RGB888, -		 * VOP Big must code the out mode to RGB10. -		 */ -		ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, -							encoder); -		if (ret > 0) -			s->output_mode = ROCKCHIP_OUT_MODE_P888; -	}  	return 0;  } diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index a2169dd3d26b..14fa1f8351e8 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -615,7 +615,6 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)  {  	struct cdn_dp_device *dp = encoder_to_dp(encoder);  	int ret, val; -	struct rockchip_crtc_state *state;  	ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);  	if (ret < 0) { @@ -625,14 +624,10 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)  	DRM_DEV_DEBUG_KMS(dp->dev, "vop %s output to cdn-dp\n",  			  (ret) ? "LIT" : "BIG"); -	state = to_rockchip_crtc_state(encoder->crtc->state); -	if (ret) { +	if (ret)  		val = DP_SEL_VOP_LIT | (DP_SEL_VOP_LIT << 16); -		state->output_mode = ROCKCHIP_OUT_MODE_P888; -	} else { +	else  		val = DP_SEL_VOP_LIT << 16; -		state->output_mode = ROCKCHIP_OUT_MODE_AAAA; -	}  	ret = cdn_dp_grf_write(dp, GRF_SOC_CON9, val);  	if (ret) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 3f7a82d1e095..45589d6ce65e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -875,6 +875,7 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc,  static void vop_crtc_enable(struct drm_crtc *crtc)  {  	struct vop *vop = to_vop(crtc); +	const struct vop_data *vop_data = vop->data;  	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);  	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;  	u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start; @@ -967,6 +968,13 @@ static void vop_crtc_enable(struct drm_crtc *crtc)  		DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n",  			      s->output_type);  	} + +	/* +	 * if vop is not support RGB10 output, need force RGB10 to RGB888. +	 */ +	if (s->output_mode == ROCKCHIP_OUT_MODE_AAAA && +	    !(vop_data->feature & VOP_FEATURE_OUTPUT_RGB10)) +		s->output_mode = ROCKCHIP_OUT_MODE_P888;  	VOP_CTRL_SET(vop, out_mode, s->output_mode);  	VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 5a4faa85dbd2..9979fd0c2282 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -142,6 +142,9 @@ struct vop_data {  	const struct vop_intr *intr;  	const struct vop_win_data *win;  	unsigned int win_size; + +#define VOP_FEATURE_OUTPUT_RGB10	BIT(0) +	u64 feature;  };  /* interrupt define */ diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 0da44442aab0..bafd698a28b1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -275,6 +275,7 @@ static const struct vop_intr rk3288_vop_intr = {  static const struct vop_data rk3288_vop = {  	.init_table = rk3288_init_reg_table,  	.table_size = ARRAY_SIZE(rk3288_init_reg_table), +	.feature = VOP_FEATURE_OUTPUT_RGB10,  	.intr = &rk3288_vop_intr,  	.ctrl = &rk3288_ctrl_data,  	.win = rk3288_vop_win_data, @@ -343,6 +344,7 @@ static const struct vop_reg_data rk3399_init_reg_table[] = {  static const struct vop_data rk3399_vop_big = {  	.init_table = rk3399_init_reg_table,  	.table_size = ARRAY_SIZE(rk3399_init_reg_table), +	.feature = VOP_FEATURE_OUTPUT_RGB10,  	.intr = &rk3399_vop_intr,  	.ctrl = &rk3399_ctrl_data,  	/* diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 9a1e34e48f64..81f86a67c10d 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -451,18 +451,6 @@ fail:  #ifdef CONFIG_DRM_TEGRA_STAGING -static struct tegra_drm_context * -tegra_drm_file_get_context(struct tegra_drm_file *file, u32 id) -{ -	struct tegra_drm_context *context; - -	mutex_lock(&file->lock); -	context = idr_find(&file->contexts, id); -	mutex_unlock(&file->lock); - -	return context; -} -  static int tegra_gem_create(struct drm_device *drm, void *data,  			    struct drm_file *file)  { @@ -551,7 +539,7 @@ static int tegra_client_open(struct tegra_drm_file *fpriv,  	if (err < 0)  		return err; -	err = idr_alloc(&fpriv->contexts, context, 0, 0, GFP_KERNEL); +	err = idr_alloc(&fpriv->contexts, context, 1, 0, GFP_KERNEL);  	if (err < 0) {  		client->ops->close_channel(context);  		return err; @@ -606,7 +594,7 @@ static int tegra_close_channel(struct drm_device *drm, void *data,  	mutex_lock(&fpriv->lock); -	context = tegra_drm_file_get_context(fpriv, args->context); +	context = idr_find(&fpriv->contexts, args->context);  	if (!context) {  		err = -EINVAL;  		goto unlock; @@ -631,7 +619,7 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,  	mutex_lock(&fpriv->lock); -	context = tegra_drm_file_get_context(fpriv, args->context); +	context = idr_find(&fpriv->contexts, args->context);  	if (!context) {  		err = -ENODEV;  		goto unlock; @@ -660,7 +648,7 @@ static int tegra_submit(struct drm_device *drm, void *data,  	mutex_lock(&fpriv->lock); -	context = tegra_drm_file_get_context(fpriv, args->context); +	context = idr_find(&fpriv->contexts, args->context);  	if (!context) {  		err = -ENODEV;  		goto unlock; @@ -685,7 +673,7 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,  	mutex_lock(&fpriv->lock); -	context = tegra_drm_file_get_context(fpriv, args->context); +	context = idr_find(&fpriv->contexts, args->context);  	if (!context) {  		err = -ENODEV;  		goto unlock; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c index 13db8a2851ed..1f013d45c9e9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c @@ -321,6 +321,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)  	list_for_each_entry_safe(entry, next, &man->list, head)  		vmw_cmdbuf_res_free(man, entry); +	drm_ht_remove(&man->resources);  	kfree(man);  } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 130d51c5ec6a..4b948fba9eec 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -41,9 +41,9 @@  #include <drm/ttm/ttm_module.h>  #include "vmwgfx_fence.h" -#define VMWGFX_DRIVER_DATE "20170221" +#define VMWGFX_DRIVER_DATE "20170607"  #define VMWGFX_DRIVER_MAJOR 2 -#define VMWGFX_DRIVER_MINOR 12 +#define VMWGFX_DRIVER_MINOR 13  #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_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index b6a0806b06bf..a1c68e6a689e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -368,6 +368,8 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv,  				return fifo_state->static_buffer;  			else {  				fifo_state->dynamic_buffer = vmalloc(bytes); +				if (!fifo_state->dynamic_buffer) +					goto out_err;  				return fifo_state->dynamic_buffer;  			}  		} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index ef9f3a2a4030..1d2db5d912b0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -274,108 +274,6 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)  } - -/** - * vmw_du_cursor_plane_update() - Update cursor image and location - * - * @plane: plane object to update - * @crtc: owning CRTC of @plane - * @fb: framebuffer to flip onto plane - * @crtc_x: x offset of plane on crtc - * @crtc_y: y offset of plane on crtc - * @crtc_w: width of plane rectangle on crtc - * @crtc_h: height of plane rectangle on crtc - * @src_x: Not used - * @src_y: Not used - * @src_w: Not used - * @src_h: Not used - * - * - * RETURNS: - * Zero on success, error code on failure - */ -int vmw_du_cursor_plane_update(struct drm_plane *plane, -			       struct drm_crtc *crtc, -			       struct drm_framebuffer *fb, -			       int crtc_x, int crtc_y, -			       unsigned int crtc_w, -			       unsigned int crtc_h, -			       uint32_t src_x, uint32_t src_y, -			       uint32_t src_w, uint32_t src_h) -{ -	struct vmw_private *dev_priv = vmw_priv(crtc->dev); -	struct vmw_display_unit *du = vmw_crtc_to_du(crtc); -	struct vmw_surface *surface = NULL; -	struct vmw_dma_buffer *dmabuf = NULL; -	s32 hotspot_x, hotspot_y; -	int ret; - -	hotspot_x = du->hotspot_x + fb->hot_x; -	hotspot_y = du->hotspot_y + fb->hot_y; - -	/* A lot of the code assumes this */ -	if (crtc_w != 64 || crtc_h != 64) { -		ret = -EINVAL; -		goto out; -	} - -	if (vmw_framebuffer_to_vfb(fb)->dmabuf) -		dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer; -	else -		surface = vmw_framebuffer_to_vfbs(fb)->surface; - -	if (surface && !surface->snooper.image) { -		DRM_ERROR("surface not suitable for cursor\n"); -		ret = -EINVAL; -		goto out; -	} - -	/* setup new image */ -	ret = 0; -	if (surface) { -		/* vmw_user_surface_lookup takes one reference */ -		du->cursor_surface = surface; - -		du->cursor_age = du->cursor_surface->snooper.age; - -		ret = vmw_cursor_update_image(dev_priv, surface->snooper.image, -					      64, 64, hotspot_x, hotspot_y); -	} else if (dmabuf) { -		/* vmw_user_surface_lookup takes one reference */ -		du->cursor_dmabuf = dmabuf; - -		ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h, -					       hotspot_x, hotspot_y); -	} else { -		vmw_cursor_update_position(dev_priv, false, 0, 0); -		goto out; -	} - -	if (!ret) { -		du->cursor_x = crtc_x + du->set_gui_x; -		du->cursor_y = crtc_y + du->set_gui_y; - -		vmw_cursor_update_position(dev_priv, true, -					   du->cursor_x + hotspot_x, -					   du->cursor_y + hotspot_y); -	} - -out: -	return ret; -} - - -int vmw_du_cursor_plane_disable(struct drm_plane *plane) -{ -	if (plane->fb) { -		drm_framebuffer_unreference(plane->fb); -		plane->fb = NULL; -	} - -	return -EINVAL; -} - -  void vmw_du_cursor_plane_destroy(struct drm_plane *plane)  {  	vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0); @@ -473,18 +371,6 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,  void -vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane, -				   struct drm_plane_state *old_state) -{ -	struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc; -	struct vmw_private *dev_priv = vmw_priv(crtc->dev); - -	drm_atomic_set_fb_for_plane(plane->state, NULL); -	vmw_cursor_update_position(dev_priv, false, 0, 0); -} - - -void  vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,  				  struct drm_plane_state *old_state)  { @@ -1498,6 +1384,7 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,  	 */  	if (vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)  &&  	    dmabuf && only_2d && +	    mode_cmd->width > 64 &&  /* Don't create a proxy for cursor */  	    dev_priv->active_display_unit == vmw_du_screen_target) {  		ret = vmw_create_dmabuf_proxy(dev_priv->dev, mode_cmd,  					      dmabuf, &surface); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 13f2f1d2818a..5f8d678ae675 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -256,10 +256,6 @@ int vmw_du_crtc_gamma_set(struct drm_crtc *crtc,  			   u16 *r, u16 *g, u16 *b,  			   uint32_t size,  			   struct drm_modeset_acquire_ctx *ctx); -int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv, -			    uint32_t handle, uint32_t width, uint32_t height, -			    int32_t hot_x, int32_t hot_y); -int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);  int vmw_du_connector_set_property(struct drm_connector *connector,  				  struct drm_property *property,  				  uint64_t val); @@ -339,15 +335,6 @@ void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,  /* Universal Plane Helpers */  void vmw_du_primary_plane_destroy(struct drm_plane *plane);  void vmw_du_cursor_plane_destroy(struct drm_plane *plane); -int vmw_du_cursor_plane_disable(struct drm_plane *plane); -int vmw_du_cursor_plane_update(struct drm_plane *plane, -			       struct drm_crtc *crtc, -			       struct drm_framebuffer *fb, -			       int crtc_x, int crtc_y, -			       unsigned int crtc_w, -			       unsigned int crtc_h, -			       uint32_t src_x, uint32_t src_y, -			       uint32_t src_w, uint32_t src_h);  /* Atomic Helpers */  int vmw_du_primary_plane_atomic_check(struct drm_plane *plane, @@ -356,8 +343,6 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,  				     struct drm_plane_state *state);  void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,  				       struct drm_plane_state *old_state); -void vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane, -					struct drm_plane_state *old_state);  int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,  				   struct drm_plane_state *new_state);  void vmw_du_plane_cleanup_fb(struct drm_plane *plane, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index bad31bdf09b6..50be1f034f9e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -56,6 +56,8 @@ enum stdu_content_type {   * @right: Right side of bounding box.   * @top: Top side of bounding box.   * @bottom: Bottom side of bounding box. + * @fb_left: Left side of the framebuffer/content bounding box + * @fb_top: Top of the framebuffer/content bounding box   * @buf: DMA buffer when DMA-ing between buffer and screen targets.   * @sid: Surface ID when copying between surface and screen targets.   */ @@ -63,6 +65,7 @@ struct vmw_stdu_dirty {  	struct vmw_kms_dirty base;  	SVGA3dTransferType  transfer;  	s32 left, right, top, bottom; +	s32 fb_left, fb_top;  	u32 pitch;  	union {  		struct vmw_dma_buffer *buf; @@ -647,7 +650,7 @@ static void vmw_stdu_dmabuf_fifo_commit(struct vmw_kms_dirty *dirty)   *   * @dirty: The closure structure.   * - * This function calculates the bounding box for all the incoming clips + * This function calculates the bounding box for all the incoming clips.   */  static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)  { @@ -656,11 +659,19 @@ static void vmw_stdu_dmabuf_cpu_clip(struct vmw_kms_dirty *dirty)  	dirty->num_hits = 1; -	/* Calculate bounding box */ +	/* Calculate destination bounding box */  	ddirty->left = min_t(s32, ddirty->left, dirty->unit_x1);  	ddirty->top = min_t(s32, ddirty->top, dirty->unit_y1);  	ddirty->right = max_t(s32, ddirty->right, dirty->unit_x2);  	ddirty->bottom = max_t(s32, ddirty->bottom, dirty->unit_y2); + +	/* +	 * Calculate content bounding box.  We only need the top-left +	 * coordinate because width and height will be the same as the +	 * destination bounding box above +	 */ +	ddirty->fb_left = min_t(s32, ddirty->fb_left, dirty->fb_x); +	ddirty->fb_top  = min_t(s32, ddirty->fb_top, dirty->fb_y);  } @@ -697,11 +708,11 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)  	/* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */  	src_pitch = stdu->display_srf->base_size.width * stdu->cpp;  	src = ttm_kmap_obj_virtual(&stdu->host_map, ¬_used); -	src += dirty->unit_y1 * src_pitch + dirty->unit_x1 * stdu->cpp; +	src += ddirty->top * src_pitch + ddirty->left * stdu->cpp;  	dst_pitch = ddirty->pitch;  	dst = ttm_kmap_obj_virtual(&stdu->guest_map, ¬_used); -	dst += dirty->fb_y * dst_pitch + dirty->fb_x * stdu->cpp; +	dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp;  	/* Figure out the real direction */ @@ -760,7 +771,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)  	}  out_cleanup: -	ddirty->left = ddirty->top = S32_MAX; +	ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;  	ddirty->right = ddirty->bottom = S32_MIN;  } @@ -812,6 +823,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,  		SVGA3D_READ_HOST_VRAM;  	ddirty.left = ddirty.top = S32_MAX;  	ddirty.right = ddirty.bottom = S32_MIN; +	ddirty.fb_left = ddirty.fb_top = S32_MAX;  	ddirty.pitch = vfb->base.pitches[0];  	ddirty.buf = buf;  	ddirty.base.fifo_commit = vmw_stdu_dmabuf_fifo_commit; @@ -1355,6 +1367,11 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,  		DRM_ERROR("Failed to bind surface to STDU.\n");  	else  		crtc->primary->fb = plane->state->fb; + +	ret = vmw_stdu_update_st(dev_priv, stdu); + +	if (ret) +		DRM_ERROR("Failed to update STDU.\n");  } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 7681341fe32b..6b70bd259953 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -1274,11 +1274,14 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,  	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;  	int ret;  	uint32_t size; -	uint32_t backup_handle; +	uint32_t backup_handle = 0;  	if (req->multisample_count != 0)  		return -EINVAL; +	if (req->mip_levels > DRM_VMW_MAX_MIP_LEVELS) +		return -EINVAL; +  	if (unlikely(vmw_user_surface_size == 0))  		vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +  			128; @@ -1314,12 +1317,16 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,  		ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,  					     &res->backup,  					     &user_srf->backup_base); -		if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE < -		    res->backup_size) { -			DRM_ERROR("Surface backup buffer is too small.\n"); -			vmw_dmabuf_unreference(&res->backup); -			ret = -EINVAL; -			goto out_unlock; +		if (ret == 0) { +			if (res->backup->base.num_pages * PAGE_SIZE < +			    res->backup_size) { +				DRM_ERROR("Surface backup buffer is too small.\n"); +				vmw_dmabuf_unreference(&res->backup); +				ret = -EINVAL; +				goto out_unlock; +			} else { +				backup_handle = req->buffer_handle; +			}  		}  	} else if (req->drm_surface_flags & drm_vmw_surface_flag_create_buffer)  		ret = vmw_user_dmabuf_alloc(dev_priv, tfile, @@ -1491,7 +1498,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,  				 dev_priv->stdu_max_height);  		if (size.width > max_width || size.height > max_height) { -			DRM_ERROR("%ux%u\n, exeeds max surface size %ux%u", +			DRM_ERROR("%ux%u\n, exceeds max surface size %ux%u",  				  size.width, size.height,  				  max_width, max_height);  			return -EINVAL; diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index f05ebb14fa63..ac65f52850a6 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -172,7 +172,7 @@ static int host1x_probe(struct platform_device *pdev)  	host->rst = devm_reset_control_get(&pdev->dev, "host1x");  	if (IS_ERR(host->rst)) { -		err = PTR_ERR(host->clk); +		err = PTR_ERR(host->rst);  		dev_err(&pdev->dev, "failed to get reset: %d\n", err);  		return err;  	} diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 16d556816b5f..2fb5f432a54c 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -725,15 +725,16 @@ void ipu_set_ic_src_mux(struct ipu_soc *ipu, int csi_id, bool vdi)  	spin_lock_irqsave(&ipu->lock, flags);  	val = ipu_cm_read(ipu, IPU_CONF); -	if (vdi) { +	if (vdi)  		val |= IPU_CONF_IC_INPUT; -	} else { +	else  		val &= ~IPU_CONF_IC_INPUT; -		if (csi_id == 1) -			val |= IPU_CONF_CSI_SEL; -		else -			val &= ~IPU_CONF_CSI_SEL; -	} + +	if (csi_id == 1) +		val |= IPU_CONF_CSI_SEL; +	else +		val &= ~IPU_CONF_CSI_SEL; +  	ipu_cm_write(ipu, val, IPU_CONF);  	spin_unlock_irqrestore(&ipu->lock, flags); diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c index c55563379e2e..c35f74c83065 100644 --- a/drivers/gpu/ipu-v3/ipu-pre.c +++ b/drivers/gpu/ipu-v3/ipu-pre.c @@ -131,8 +131,6 @@ int ipu_pre_get(struct ipu_pre *pre)  	if (pre->in_use)  		return -EBUSY; -	clk_prepare_enable(pre->clk_axi); -  	/* first get the engine out of reset and remove clock gating */  	writel(0, pre->regs + IPU_PRE_CTRL); @@ -149,12 +147,7 @@ int ipu_pre_get(struct ipu_pre *pre)  void ipu_pre_put(struct ipu_pre *pre)  { -	u32 val; - -	val = IPU_PRE_CTRL_SFTRST | IPU_PRE_CTRL_CLKGATE; -	writel(val, pre->regs + IPU_PRE_CTRL); - -	clk_disable_unprepare(pre->clk_axi); +	writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);  	pre->in_use = false;  } @@ -249,6 +242,8 @@ static int ipu_pre_probe(struct platform_device *pdev)  	if (!pre->buffer_virt)  		return -ENOMEM; +	clk_prepare_enable(pre->clk_axi); +  	pre->dev = dev;  	platform_set_drvdata(pdev, pre);  	mutex_lock(&ipu_pre_list_mutex); @@ -268,6 +263,8 @@ static int ipu_pre_remove(struct platform_device *pdev)  	available_pres--;  	mutex_unlock(&ipu_pre_list_mutex); +	clk_disable_unprepare(pre->clk_axi); +  	if (pre->buffer_virt)  		gen_pool_free(pre->iram, (unsigned long)pre->buffer_virt,  			      IPU_PRE_MAX_WIDTH * IPU_PRE_NUM_SCANLINES * 4); | 
