diff options
Diffstat (limited to 'drivers/gpu')
114 files changed, 1100 insertions, 722 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index a028661d9e20..92b11de19581 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c @@ -576,6 +576,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {  	{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },  	{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },  	{ 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX }, +	{ 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },  	{ 0, 0, 0, 0, 0 },  }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8a078f4ae73d..7ff3a28fc903 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1701,8 +1701,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)  		amdgpu_xgmi_add_device(adev);  	amdgpu_amdkfd_device_init(adev); -	if (amdgpu_sriov_vf(adev)) +	if (amdgpu_sriov_vf(adev)) { +		amdgpu_virt_init_data_exchange(adev);  		amdgpu_virt_release_full_gpu(adev, true); +	}  	return 0;  } @@ -2632,9 +2634,6 @@ fence_driver_init:  		goto failed;  	} -	if (amdgpu_sriov_vf(adev)) -		amdgpu_virt_init_data_exchange(adev); -  	amdgpu_fbdev_init(adev);  	r = amdgpu_pm_sysfs_init(adev); @@ -2798,7 +2797,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)  			struct drm_framebuffer *fb = crtc->primary->fb;  			struct amdgpu_bo *robj; -			if (amdgpu_crtc->cursor_bo) { +			if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {  				struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);  				r = amdgpu_bo_reserve(aobj, true);  				if (r == 0) { @@ -2906,7 +2905,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)  		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {  			struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); -			if (amdgpu_crtc->cursor_bo) { +			if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {  				struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);  				r = amdgpu_bo_reserve(aobj, true);  				if (r == 0) { @@ -3226,6 +3225,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,  	r = amdgpu_ib_ring_tests(adev);  error: +	amdgpu_virt_init_data_exchange(adev);  	amdgpu_virt_release_full_gpu(adev, true);  	if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {  		atomic_inc(&adev->vram_lost_counter); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 15ce7e681d67..b083b219b1a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -188,10 +188,12 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,  		goto cleanup;  	} -	r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev)); -	if (unlikely(r != 0)) { -		DRM_ERROR("failed to pin new abo buffer before flip\n"); -		goto unreserve; +	if (!adev->enable_virtual_display) { +		r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev)); +		if (unlikely(r != 0)) { +			DRM_ERROR("failed to pin new abo buffer before flip\n"); +			goto unreserve; +		}  	}  	r = amdgpu_ttm_alloc_gart(&new_abo->tbo); @@ -211,7 +213,8 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,  	amdgpu_bo_get_tiling_flags(new_abo, &tiling_flags);  	amdgpu_bo_unreserve(new_abo); -	work->base = amdgpu_bo_gpu_offset(new_abo); +	if (!adev->enable_virtual_display) +		work->base = amdgpu_bo_gpu_offset(new_abo);  	work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +  		amdgpu_get_vblank_counter_kms(dev, work->crtc_id); @@ -242,9 +245,10 @@ pflip_cleanup:  		goto cleanup;  	}  unpin: -	if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) { -		DRM_ERROR("failed to unpin new abo in error path\n"); -	} +	if (!adev->enable_virtual_display) +		if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) +			DRM_ERROR("failed to unpin new abo in error path\n"); +  unreserve:  	amdgpu_bo_unreserve(new_abo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 1f61ed95727c..0ed41a9d2d77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1686,7 +1686,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,  		effective_mode &= ~S_IWUSR;  	if ((adev->flags & AMD_IS_APU) && -	    (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || +	    (attr == &sensor_dev_attr_power1_average.dev_attr.attr || +	     attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||  	     attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||  	     attr == &sensor_dev_attr_power1_cap.dev_attr.attr))  		return 0; @@ -2008,6 +2009,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)  int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)  { +	struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;  	int ret;  	if (adev->pm.sysfs_initialized) @@ -2091,12 +2093,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)  				"pp_power_profile_mode\n");  		return ret;  	} -	ret = device_create_file(adev->dev, -			&dev_attr_pp_od_clk_voltage); -	if (ret) { -		DRM_ERROR("failed to create device file	" -				"pp_od_clk_voltage\n"); -		return ret; +	if (hwmgr->od_enabled) { +		ret = device_create_file(adev->dev, +				&dev_attr_pp_od_clk_voltage); +		if (ret) { +			DRM_ERROR("failed to create device file	" +					"pp_od_clk_voltage\n"); +			return ret; +		}  	}  	ret = device_create_file(adev->dev,  			&dev_attr_gpu_busy_percent); @@ -2118,6 +2122,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)  void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)  { +	struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; +  	if (adev->pm.dpm_enabled == 0)  		return; @@ -2138,8 +2144,9 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)  	device_remove_file(adev->dev, &dev_attr_pp_mclk_od);  	device_remove_file(adev->dev,  			&dev_attr_pp_power_profile_mode); -	device_remove_file(adev->dev, -			&dev_attr_pp_od_clk_voltage); +	if (hwmgr->od_enabled) +		device_remove_file(adev->dev, +				&dev_attr_pp_od_clk_voltage);  	device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c index 71913a18d142..a38e0fb4a6fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c @@ -38,6 +38,7 @@  #include "amdgpu_gem.h"  #include <drm/amdgpu_drm.h>  #include <linux/dma-buf.h> +#include <linux/dma-fence-array.h>  /**   * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table @@ -187,6 +188,48 @@ error:  	return ERR_PTR(ret);  } +static int +__reservation_object_make_exclusive(struct reservation_object *obj) +{ +	struct dma_fence **fences; +	unsigned int count; +	int r; + +	if (!reservation_object_get_list(obj)) /* no shared fences to convert */ +		return 0; + +	r = reservation_object_get_fences_rcu(obj, NULL, &count, &fences); +	if (r) +		return r; + +	if (count == 0) { +		/* Now that was unexpected. */ +	} else if (count == 1) { +		reservation_object_add_excl_fence(obj, fences[0]); +		dma_fence_put(fences[0]); +		kfree(fences); +	} else { +		struct dma_fence_array *array; + +		array = dma_fence_array_create(count, fences, +					       dma_fence_context_alloc(1), 0, +					       false); +		if (!array) +			goto err_fences_put; + +		reservation_object_add_excl_fence(obj, &array->base); +		dma_fence_put(&array->base); +	} + +	return 0; + +err_fences_put: +	while (count--) +		dma_fence_put(fences[count]); +	kfree(fences); +	return -ENOMEM; +} +  /**   * amdgpu_gem_map_attach - &dma_buf_ops.attach implementation   * @dma_buf: Shared DMA buffer @@ -218,16 +261,16 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,  	if (attach->dev->driver != adev->dev->driver) {  		/* -		 * Wait for all shared fences to complete before we switch to future -		 * use of exclusive fence on this prime shared bo. +		 * We only create shared fences for internal use, but importers +		 * of the dmabuf rely on exclusive fences for implicitly +		 * tracking write hazards. As any of the current fences may +		 * correspond to a write, we need to convert all existing +		 * fences on the reservation object into a single exclusive +		 * fence.  		 */ -		r = reservation_object_wait_timeout_rcu(bo->tbo.resv, -							true, false, -							MAX_SCHEDULE_TIMEOUT); -		if (unlikely(r < 0)) { -			DRM_DEBUG_PRIME("Fence wait failed: %li\n", r); +		r = __reservation_object_make_exclusive(bo->tbo.resv); +		if (r)  			goto error_unreserve; -		}  	}  	/* pin buffer into GTT */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 8fab0d637ee5..3a9b48b227ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -90,8 +90,10 @@ static int psp_sw_fini(void *handle)  	adev->psp.sos_fw = NULL;  	release_firmware(adev->psp.asd_fw);  	adev->psp.asd_fw = NULL; -	release_firmware(adev->psp.ta_fw); -	adev->psp.ta_fw = NULL; +	if (adev->psp.ta_fw) { +		release_firmware(adev->psp.ta_fw); +		adev->psp.ta_fw = NULL; +	}  	return 0;  } @@ -435,6 +437,9 @@ static int psp_xgmi_initialize(struct psp_context *psp)  	struct ta_xgmi_shared_memory *xgmi_cmd;  	int ret; +	if (!psp->adev->psp.ta_fw) +		return -ENOENT; +  	if (!psp->xgmi_context.initialized) {  		ret = psp_xgmi_init_shared_buf(psp);  		if (ret) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index e73d152659a2..7c108e687683 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -847,9 +847,6 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,  	bp->size = amdgpu_vm_bo_size(adev, level);  	bp->byte_align = AMDGPU_GPU_PAGE_SIZE;  	bp->domain = AMDGPU_GEM_DOMAIN_VRAM; -	if (bp->size <= PAGE_SIZE && adev->asic_type >= CHIP_VEGA10 && -	    adev->flags & AMD_IS_APU) -		bp->domain |= AMDGPU_GEM_DOMAIN_GTT;  	bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain);  	bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |  		AMDGPU_GEM_CREATE_CPU_GTT_USWC; @@ -3366,14 +3363,15 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,  			 struct amdgpu_task_info *task_info)  {  	struct amdgpu_vm *vm; +	unsigned long flags; -	spin_lock(&adev->vm_manager.pasid_lock); +	spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);  	vm = idr_find(&adev->vm_manager.pasid_idr, pasid);  	if (vm)  		*task_info = vm->task_info; -	spin_unlock(&adev->vm_manager.pasid_lock); +	spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);  }  /** diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index fdace004544d..e4cc1d48eaab 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -167,19 +167,6 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc)  	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);  	dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); -	if (crtc->primary->fb) { -		int r; -		struct amdgpu_bo *abo; - -		abo = gem_to_amdgpu_bo(crtc->primary->fb->obj[0]); -		r = amdgpu_bo_reserve(abo, true); -		if (unlikely(r)) -			DRM_ERROR("failed to reserve abo before unpin\n"); -		else { -			amdgpu_bo_unpin(abo); -			amdgpu_bo_unreserve(abo); -		} -	}  	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;  	amdgpu_crtc->encoder = NULL; @@ -692,7 +679,9 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev,  	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);  	drm_crtc_vblank_put(&amdgpu_crtc->base); -	schedule_work(&works->unpin_work); +	amdgpu_bo_unref(&works->old_abo); +	kfree(works->shared); +	kfree(works);  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 381f593b0cda..57cb3a51bda7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4233,7 +4233,6 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)  	u32 tmp;  	u32 rb_bufsz;  	u64 rb_addr, rptr_addr, wptr_gpu_addr; -	int r;  	/* Set the write pointer delay */  	WREG32(mmCP_RB_WPTR_DELAY, 0); @@ -4278,9 +4277,8 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)  	amdgpu_ring_clear_ring(ring);  	gfx_v8_0_cp_gfx_start(adev);  	ring->sched.ready = true; -	r = amdgpu_ring_test_helper(ring); -	return r; +	return 0;  }  static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable) @@ -4369,10 +4367,9 @@ static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev)  		amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));  	} -	r = amdgpu_ring_test_helper(kiq_ring); -	if (r) -		DRM_ERROR("KCQ enable failed\n"); -	return r; +	amdgpu_ring_commit(kiq_ring); + +	return 0;  }  static int gfx_v8_0_deactivate_hqd(struct amdgpu_device *adev, u32 req) @@ -4709,16 +4706,32 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev)  	if (r)  		goto done; -	/* Test KCQs - reversing the order of rings seems to fix ring test failure -	 * after GPU reset -	 */ -	for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) { +done: +	return r; +} + +static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev) +{ +	int r, i; +	struct amdgpu_ring *ring; + +	/* collect all the ring_tests here, gfx, kiq, compute */ +	ring = &adev->gfx.gfx_ring[0]; +	r = amdgpu_ring_test_helper(ring); +	if (r) +		return r; + +	ring = &adev->gfx.kiq.ring; +	r = amdgpu_ring_test_helper(ring); +	if (r) +		return r; + +	for (i = 0; i < adev->gfx.num_compute_rings; i++) {  		ring = &adev->gfx.compute_ring[i]; -		r = amdgpu_ring_test_helper(ring); +		amdgpu_ring_test_helper(ring);  	} -done: -	return r; +	return 0;  }  static int gfx_v8_0_cp_resume(struct amdgpu_device *adev) @@ -4739,6 +4752,11 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)  	r = gfx_v8_0_kcq_resume(adev);  	if (r)  		return r; + +	r = gfx_v8_0_cp_test_all_rings(adev); +	if (r) +		return r; +  	gfx_v8_0_enable_gui_idle_interrupt(adev, true);  	return 0; @@ -5086,6 +5104,8 @@ static int gfx_v8_0_post_soft_reset(void *handle)  	    REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX))  		gfx_v8_0_cp_gfx_resume(adev); +	gfx_v8_0_cp_test_all_rings(adev); +  	adev->gfx.rlc.funcs->start(adev);  	return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 7556716038d3..fbca0494f871 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] =  	SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x4a2c0e68),  	SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0xb5d3f197),  	SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000), -	SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff) +	SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff), +	SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800), +	SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800), +	SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)  };  static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] = @@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =  	SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x00030000, 0x00020000),  	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x01000107),  	SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x00001800, 0x00000800), -	SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080), -	SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800), -	SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800), -	SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000) +	SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080)  };  static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] = @@ -3587,6 +3587,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev  {  	uint32_t data, def; +	amdgpu_gfx_rlc_enter_safe_mode(adev); +  	/* It is disabled by HW by default */  	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {  		/* 1 - RLC_CGTT_MGCG_OVERRIDE */ @@ -3651,6 +3653,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev  			WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);  		}  	} + +	amdgpu_gfx_rlc_exit_safe_mode(adev);  }  static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 8cbb4655896a..b11a1c17a7f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -174,7 +174,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,  			return r;  		}  		/* Retrieve checksum from mailbox2 */ -		if (req == IDH_REQ_GPU_INIT_ACCESS) { +		if (req == IDH_REQ_GPU_INIT_ACCESS || req == IDH_REQ_GPU_RESET_ACCESS) {  			adev->virt.fw_reserve.checksum_key =  				RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,  					mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2)); diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index 4cd31a276dcd..186db182f924 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -93,7 +93,20 @@ static void nbio_v7_4_enable_doorbell_aperture(struct amdgpu_device *adev,  static void nbio_v7_4_enable_doorbell_selfring_aperture(struct amdgpu_device *adev,  							bool enable)  { +	u32 tmp = 0; +	if (enable) { +		tmp = REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_EN, 1) | +		      REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_MODE, 1) | +		      REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_SIZE, 0); + +		WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_LOW, +			     lower_32_bits(adev->doorbell.base)); +		WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_HIGH, +			     upper_32_bits(adev->doorbell.base)); +	} + +	WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_CNTL, tmp);  }  static void nbio_v7_4_ih_doorbell_range(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index 0c6e7f9b143f..189fcb004579 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -152,18 +152,22 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)  	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);  	err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); -	if (err) -		goto out2; - -	err = amdgpu_ucode_validate(adev->psp.ta_fw); -	if (err) -		goto out2; - -	ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; -	adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version); -	adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes); -	adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr + -		le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); +	if (err) { +		release_firmware(adev->psp.ta_fw); +		adev->psp.ta_fw = NULL; +		dev_info(adev->dev, +			 "psp v11.0: Failed to load firmware \"%s\"\n", fw_name); +	} else { +		err = amdgpu_ucode_validate(adev->psp.ta_fw); +		if (err) +			goto out2; + +		ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; +		adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version); +		adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes); +		adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr + +			le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); +	}  	return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index fd0bfe140ee0..6811a5d05b27 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -78,7 +78,6 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {  	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),  	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),  	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000), -	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),  	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),  	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100),  	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000), @@ -96,6 +95,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {  static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {  	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),  	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002), +	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),  	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),  	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002)  }; @@ -103,6 +103,7 @@ static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {  static const struct soc15_reg_golden golden_settings_sdma_vg12[] = {  	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),  	SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001), +	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),  	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),  	SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001)  }; diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 8849b74078d6..9b639974c70c 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -729,11 +729,13 @@ static int soc15_common_early_init(void *handle)  	case CHIP_RAVEN:  		adev->asic_funcs = &soc15_asic_funcs;  		if (adev->rev_id >= 0x8) -			adev->external_rev_id = adev->rev_id + 0x81; +			adev->external_rev_id = adev->rev_id + 0x79;  		else if (adev->pdev->device == 0x15d8)  			adev->external_rev_id = adev->rev_id + 0x41; +		else if (adev->rev_id == 1) +			adev->external_rev_id = adev->rev_id + 0x20;  		else -			adev->external_rev_id = 0x1; +			adev->external_rev_id = adev->rev_id + 0x01;  		if (adev->rev_id >= 0x8) {  			adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | diff --git a/drivers/gpu/drm/amd/amdkfd/Kconfig b/drivers/gpu/drm/amd/amdkfd/Kconfig index fbf0ee5201c3..c3613604a4f8 100644 --- a/drivers/gpu/drm/amd/amdkfd/Kconfig +++ b/drivers/gpu/drm/amd/amdkfd/Kconfig @@ -4,8 +4,8 @@  config HSA_AMD  	bool "HSA kernel driver for AMD GPU devices" -	depends on DRM_AMDGPU && X86_64 -	imply AMD_IOMMU_V2 +	depends on DRM_AMDGPU && (X86_64 || ARM64) +	imply AMD_IOMMU_V2 if X86_64  	select MMU_NOTIFIER  	help  	  Enable this if you want to use HSA features on AMD GPU devices. diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index b7bc7d7d048f..2e7c44955f43 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -863,6 +863,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,  	return 0;  } +#ifdef CONFIG_X86_64  static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,  				uint32_t *num_entries,  				struct crat_subtype_iolink *sub_type_hdr) @@ -905,6 +906,7 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,  	return 0;  } +#endif  /* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU   * @@ -920,7 +922,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)  	struct crat_subtype_generic *sub_type_hdr;  	int avail_size = *size;  	int numa_node_id; +#ifdef CONFIG_X86_64  	uint32_t entries = 0; +#endif  	int ret = 0;  	if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU) @@ -982,6 +986,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)  			sub_type_hdr->length);  		/* Fill in Subtype: IO Link */ +#ifdef CONFIG_X86_64  		ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size,  				&entries,  				(struct crat_subtype_iolink *)sub_type_hdr); @@ -992,6 +997,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)  		sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +  				sub_type_hdr->length * entries); +#else +		pr_info("IO link not available for non x86 platforms\n"); +#endif  		crat_table->num_domains++;  	} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 5f5b2acedbac..09da91644f9f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)   *		the GPU device is not already present in the topology device   *		list then return NULL. This means a new topology device has to   *		be created for this GPU. - * TODO: Rather than assiging @gpu to first topology device withtout - *		gpu attached, it will better to have more stringent check.   */  static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)  { @@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)  	struct kfd_topology_device *out_dev = NULL;  	down_write(&topology_lock); -	list_for_each_entry(dev, &topology_device_list, list) +	list_for_each_entry(dev, &topology_device_list, list) { +		/* Discrete GPUs need their own topology device list +		 * entries. Don't assign them to CPU/APU nodes. +		 */ +		if (!gpu->device_info->needs_iommu_device && +		    dev->node_props.cpu_cores_count) +			continue; +  		if (!dev->gpu && (dev->node_props.simd_count > 0)) {  			dev->gpu = gpu;  			out_dev = dev;  			break;  		} +	}  	up_write(&topology_lock);  	return out_dev;  } @@ -1392,7 +1398,6 @@ int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev)  static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)  { -	const struct cpuinfo_x86 *cpuinfo;  	int first_cpu_of_numa_node;  	if (!cpumask || cpumask == cpu_none_mask) @@ -1400,9 +1405,11 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)  	first_cpu_of_numa_node = cpumask_first(cpumask);  	if (first_cpu_of_numa_node >= nr_cpu_ids)  		return -1; -	cpuinfo = &cpu_data(first_cpu_of_numa_node); - -	return cpuinfo->apicid; +#ifdef CONFIG_X86_64 +	return cpu_data(first_cpu_of_numa_node).apicid; +#else +	return first_cpu_of_numa_node; +#endif  }  /* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a9a28dbc3e24..0b392bfca284 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -699,22 +699,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)  {  	struct amdgpu_dm_connector *aconnector;  	struct drm_connector *connector; +	struct drm_dp_mst_topology_mgr *mgr; +	int ret; +	bool need_hotplug = false;  	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); -	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { -		   aconnector = to_amdgpu_dm_connector(connector); -		   if (aconnector->dc_link->type == dc_connection_mst_branch && -				   !aconnector->mst_port) { +	list_for_each_entry(connector, &dev->mode_config.connector_list, +			    head) { +		aconnector = to_amdgpu_dm_connector(connector); +		if (aconnector->dc_link->type != dc_connection_mst_branch || +		    aconnector->mst_port) +			continue; -			   if (suspend) -				   drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr); -			   else -				   drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr); -		   } +		mgr = &aconnector->mst_mgr; + +		if (suspend) { +			drm_dp_mst_topology_mgr_suspend(mgr); +		} else { +			ret = drm_dp_mst_topology_mgr_resume(mgr); +			if (ret < 0) { +				drm_dp_mst_topology_mgr_set_mst(mgr, false); +				need_hotplug = true; +			} +		}  	}  	drm_modeset_unlock(&dev->mode_config.connection_mutex); + +	if (need_hotplug) +		drm_kms_helper_hotplug_event(dev);  }  /** @@ -898,7 +912,6 @@ static int dm_resume(void *handle)  	struct drm_plane_state *new_plane_state;  	struct dm_plane_state *dm_new_plane_state;  	enum dc_connection_type new_connection_type = dc_connection_none; -	int ret;  	int i;  	/* power on hardware */ @@ -971,13 +984,13 @@ static int dm_resume(void *handle)  		}  	} -	ret = drm_atomic_helper_resume(ddev, dm->cached_state); +	drm_atomic_helper_resume(ddev, dm->cached_state);  	dm->cached_state = NULL;  	amdgpu_dm_irq_resume_late(adev); -	return ret; +	return 0;  }  /** @@ -1759,7 +1772,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)  		+ caps.min_input_signal * 0x101;  	if (dc_link_set_backlight_level(dm->backlight_link, -			brightness, 0, 0)) +			brightness, 0))  		return 0;  	else  		return 1; @@ -4069,7 +4082,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,  	}  	if (connector_type == DRM_MODE_CONNECTOR_HDMIA || -	    connector_type == DRM_MODE_CONNECTOR_DisplayPort) { +	    connector_type == DRM_MODE_CONNECTOR_DisplayPort || +	    connector_type == DRM_MODE_CONNECTOR_eDP) {  		drm_connector_attach_vrr_capable_property(  			&aconnector->base);  	} @@ -5920,7 +5934,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,  	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {  		if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&  		    !new_crtc_state->color_mgmt_changed && -		    !new_crtc_state->vrr_enabled) +		    old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)  			continue;  		if (!new_crtc_state->enable) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 9a7ac58eb18e..ddd75a4d8ba5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -671,6 +671,25 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us  	return bytes_from_user;  } +/* + * Returns the min and max vrr vfreq through the connector's debugfs file. + * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range + */ +static int vrr_range_show(struct seq_file *m, void *data) +{ +	struct drm_connector *connector = m->private; +	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + +	if (connector->status != connector_status_connected) +		return -ENODEV; + +	seq_printf(m, "Min: %u\n", (unsigned int)aconnector->min_vfreq); +	seq_printf(m, "Max: %u\n", (unsigned int)aconnector->max_vfreq); + +	return 0; +} +DEFINE_SHOW_ATTRIBUTE(vrr_range); +  static const struct file_operations dp_link_settings_debugfs_fops = {  	.owner = THIS_MODULE,  	.read = dp_link_settings_read, @@ -697,7 +716,8 @@ static const struct {  } dp_debugfs_entries[] = {  		{"link_settings", &dp_link_settings_debugfs_fops},  		{"phy_settings", &dp_phy_settings_debugfs_fop}, -		{"test_pattern", &dp_phy_test_pattern_fops} +		{"test_pattern", &dp_phy_test_pattern_fops}, +		{"vrr_range", &vrr_range_fops}  };  int connector_debugfs_init(struct amdgpu_dm_connector *connector) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 52deacf39841..b0265dbebd4c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2190,8 +2190,7 @@ int dc_link_get_backlight_level(const struct dc_link *link)  bool dc_link_set_backlight_level(const struct dc_link *link,  		uint32_t backlight_pwm_u16_16, -		uint32_t frame_ramp, -		const struct dc_stream_state *stream) +		uint32_t frame_ramp)  {  	struct dc  *core_dc = link->ctx->dc;  	struct abm *abm = core_dc->res_pool->abm; @@ -2206,10 +2205,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link,  		(abm->funcs->set_backlight_level_pwm == NULL))  		return false; -	if (stream) -		((struct dc_stream_state *)stream)->bl_pwm_level = -				backlight_pwm_u16_16; -  	use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);  	DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n", @@ -2637,11 +2632,6 @@ void core_link_enable_stream(  		if (dc_is_dp_signal(pipe_ctx->stream->signal))  			enable_stream_features(pipe_ctx); - -		dc_link_set_backlight_level(pipe_ctx->stream->sink->link, -				pipe_ctx->stream->bl_pwm_level, -				0, -				pipe_ctx->stream);  	}  } diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 29f19d57ff7a..b2243e0dad1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -146,8 +146,7 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_   */  bool dc_link_set_backlight_level(const struct dc_link *dc_link,  		uint32_t backlight_pwm_u16_16, -		uint32_t frame_ramp, -		const struct dc_stream_state *stream); +		uint32_t frame_ramp);  int dc_link_get_backlight_level(const struct dc_link *dc_link); diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index be34d638e15d..d70c9e1cda3d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -91,7 +91,6 @@ struct dc_stream_state {  	/* DMCU info */  	unsigned int abm_level; -	unsigned int bl_pwm_level;  	/* from core_stream struct */  	struct dc_context *ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c index afd287f08bc9..19801bdba0d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c @@ -591,7 +591,15 @@ static void dce11_pplib_apply_display_requirements(  			dc,  			context->bw.dce.sclk_khz); -	pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz; +	/* +	 * As workaround for >4x4K lightup set dcfclock to min_engine_clock value. +	 * This is not required for less than 5 displays, +	 * thus don't request decfclk in dc to avoid impact +	 * on power saving. +	 * +	 */ +	pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4)? +			pp_display_cfg->min_engine_clock_khz : 0;  	pp_display_cfg->min_engine_clock_deep_sleep_khz  			= context->bw.dce.sclk_deep_sleep_khz; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 4bf24758217f..8f09b8625c5d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1000,7 +1000,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)  		pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); -		if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) +		if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)  			/*this is the first audio. apply the PME w/a in order to wake AZ from D3*/  			pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);  		/* un-mute audio */ @@ -1017,6 +1017,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)  	pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(  			pipe_ctx->stream_res.stream_enc, true);  	if (pipe_ctx->stream_res.audio) { +		struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; +  		if (option != KEEP_ACQUIRED_RESOURCE ||  				!dc->debug.az_endpoint_mute_only) {  			/*only disalbe az_endpoint if power down or free*/ @@ -1036,6 +1038,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)  			update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);  			pipe_ctx->stream_res.audio = NULL;  		} +		if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) +			/*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ +			pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);  		/* TODO: notify audio driver for if audio modes list changed  		 * add audio mode list change flag */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c index dcb3c5530236..cd1ebe57ed59 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c @@ -463,7 +463,7 @@ void dpp1_set_cursor_position(  	if (src_y_offset >= (int)param->viewport.height)  		cur_en = 0;  /* not visible beyond bottom edge*/ -	if (src_y_offset < 0) +	if (src_y_offset + (int)height <= 0)  		cur_en = 0;  /* not visible beyond top edge*/  	REG_UPDATE(CURSOR0_CONTROL, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index 345af015d061..d1acd7165bc8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -1140,7 +1140,7 @@ void hubp1_cursor_set_position(  	if (src_y_offset >= (int)param->viewport.height)  		cur_en = 0;  /* not visible beyond bottom edge*/ -	if (src_y_offset < 0) //+ (int)hubp->curs_attr.height +	if (src_y_offset + (int)hubp->curs_attr.height <= 0)  		cur_en = 0;  /* not visible beyond top edge*/  	if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 91e015e14355..58a12ddf12f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2355,29 +2355,22 @@ static void dcn10_apply_ctx_for_surface(  			top_pipe_to_program->plane_state->update_flags.bits.full_update)  		for (i = 0; i < dc->res_pool->pipe_count; i++) {  			struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - +			tg = pipe_ctx->stream_res.tg;  			/* Skip inactive pipes and ones already updated */  			if (!pipe_ctx->stream || pipe_ctx->stream == stream -					|| !pipe_ctx->plane_state) +					|| !pipe_ctx->plane_state +					|| !tg->funcs->is_tg_enabled(tg))  				continue; -			pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg); +			tg->funcs->lock(tg);  			pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(  				pipe_ctx->plane_res.hubp,  				&pipe_ctx->dlg_regs,  				&pipe_ctx->ttu_regs); -		} - -	for (i = 0; i < dc->res_pool->pipe_count; i++) { -		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; -		if (!pipe_ctx->stream || pipe_ctx->stream == stream -				|| !pipe_ctx->plane_state) -			continue; - -		dcn10_pipe_control_lock(dc, pipe_ctx, false); -	} +			tg->funcs->unlock(tg); +		}  	if (num_planes == 0)  		false_optc_underflow_wa(dc, stream, tg); diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c index 00f63b7dd32f..c11a443dcbc8 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -57,6 +57,7 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le  #define NUM_POWER_FN_SEGS 8  #define NUM_BL_CURVE_SEGS 16 +#pragma pack(push, 1)  /* NOTE: iRAM is 256B in size */  struct iram_table_v_2 {  	/* flags                      */ @@ -100,6 +101,7 @@ struct iram_table_v_2 {  	uint8_t dummy8;							/* 0xfe       */  	uint8_t dummy9;							/* 0xff       */  }; +#pragma pack(pop)  static uint16_t backlight_8_to_16(unsigned int backlight_8bit)  { diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 1479ea1dc3e7..789c4f288485 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -127,12 +127,13 @@ enum amd_pp_task {  };  enum PP_SMC_POWER_PROFILE { -	PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x0, -	PP_SMC_POWER_PROFILE_POWERSAVING  = 0x1, -	PP_SMC_POWER_PROFILE_VIDEO        = 0x2, -	PP_SMC_POWER_PROFILE_VR           = 0x3, -	PP_SMC_POWER_PROFILE_COMPUTE      = 0x4, -	PP_SMC_POWER_PROFILE_CUSTOM       = 0x5, +	PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT = 0x0, +	PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x1, +	PP_SMC_POWER_PROFILE_POWERSAVING  = 0x2, +	PP_SMC_POWER_PROFILE_VIDEO        = 0x3, +	PP_SMC_POWER_PROFILE_VR           = 0x4, +	PP_SMC_POWER_PROFILE_COMPUTE      = 0x5, +	PP_SMC_POWER_PROFILE_CUSTOM       = 0x6,  };  enum { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 0173d0480024..310b102a9292 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -64,17 +64,19 @@ static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr);  static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr)  { -	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 2; -	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 0; -	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 1; -	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 3; -	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 4; - -	hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_POWERSAVING; -	hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_VIDEO; -	hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; -	hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VR; -	hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_COMPUTE; +	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; +	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1; +	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2; +	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3; +	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4; +	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5; + +	hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; +	hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; +	hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING; +	hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO; +	hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR; +	hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;  }  int hwmgr_early_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c index f95c5f50eb0f..5273de3c5b98 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c @@ -1033,6 +1033,7 @@ static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,  		break;  	case amd_pp_dpp_clock:  		pclk_vol_table = pinfo->vdd_dep_on_dppclk; +		break;  	default:  		return -EINVAL;  	} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index d91390459326..c8f5c00dd1e7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -77,8 +77,9 @@  #define PCIE_BUS_CLK                10000  #define TCLK                        (PCIE_BUS_CLK / 10) -static const struct profile_mode_setting smu7_profiling[6] = -					{{1, 0, 100, 30, 1, 0, 100, 10}, +static const struct profile_mode_setting smu7_profiling[7] = +					{{0, 0, 0, 0, 0, 0, 0, 0}, +					 {1, 0, 100, 30, 1, 0, 100, 10},  					 {1, 10, 0, 30, 0, 0, 0, 0},  					 {0, 0, 0, 0, 1, 10, 16, 31},  					 {1, 0, 11, 50, 1, 0, 100, 10}, @@ -4889,7 +4890,8 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)  	uint32_t i, size = 0;  	uint32_t len; -	static const char *profile_name[6] = {"3D_FULL_SCREEN", +	static const char *profile_name[7] = {"BOOTUP_DEFAULT", +					"3D_FULL_SCREEN",  					"POWER_SAVING",  					"VIDEO",  					"VR", diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 79c86247d0ac..91e3bbe6d61d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -804,9 +804,9 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)  	hwmgr->backend = data; -	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO]; -	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO; -	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO; +	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; +	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; +	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;  	vega10_set_default_registry_data(hwmgr);  	data->disable_dpm_mask = 0xff; @@ -4668,13 +4668,15 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)  {  	struct vega10_hwmgr *data = hwmgr->backend;  	uint32_t i, size = 0; -	static const uint8_t profile_mode_setting[5][4] = {{70, 60, 1, 3,}, +	static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,}, +						{70, 60, 1, 3,},  						{90, 60, 0, 0,},  						{70, 60, 0, 0,},  						{70, 90, 0, 0,},  						{30, 60, 0, 6,},  						}; -	static const char *profile_name[6] = {"3D_FULL_SCREEN", +	static const char *profile_name[7] = {"BOOTUP_DEFAULT", +					"3D_FULL_SCREEN",  					"POWER_SAVING",  					"VIDEO",  					"VR", diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c index b8747a5c9204..99d596dc0e89 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c @@ -32,6 +32,7 @@  #include "vega10_pptable.h"  #define NUM_DSPCLK_LEVELS 8 +#define VEGA10_ENGINECLOCK_HARDMAX 198000  static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,  		enum phm_platform_caps cap) @@ -258,7 +259,26 @@ static int init_over_drive_limits(  		struct pp_hwmgr *hwmgr,  		const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)  { -	hwmgr->platform_descriptor.overdriveLimit.engineClock = +	const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = +			(const ATOM_Vega10_GFXCLK_Dependency_Table *) +			(((unsigned long) powerplay_table) + +			le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); +	bool is_acg_enabled = false; +	ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; + +	if (gfxclk_dep_table->ucRevId == 1) { +		patom_record_v2 = +			(ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries; +		is_acg_enabled = +			(bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable; +	} + +	if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX && +		!is_acg_enabled) +		hwmgr->platform_descriptor.overdriveLimit.engineClock = +			VEGA10_ENGINECLOCK_HARDMAX; +	else +		hwmgr->platform_descriptor.overdriveLimit.engineClock =  			le32_to_cpu(powerplay_table->ulMaxODEngineClock);  	hwmgr->platform_descriptor.overdriveLimit.memoryClock =  			le32_to_cpu(powerplay_table->ulMaxODMemoryClock); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index 54364444ecd1..0c8212902275 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -753,6 +753,22 @@ static int vega12_init_smc_table(struct pp_hwmgr *hwmgr)  	return 0;  } +static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr) +{ +	uint32_t result; + +	PP_ASSERT_WITH_CODE( +		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc) == 0, +		"[Run_ACG_BTC] Attempt to run ACG BTC failed!", +		return -EINVAL); + +	result = smum_get_argument(hwmgr); +	PP_ASSERT_WITH_CODE(result == 1, +			"Failed to run ACG BTC!", return -EINVAL); + +	return 0; +} +  static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)  {  	struct vega12_hwmgr *data = @@ -931,6 +947,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)  			"Failed to initialize SMC table!",  			result = tmp_result); +	tmp_result = vega12_run_acg_btc(hwmgr); +	PP_ASSERT_WITH_CODE(!tmp_result, +			"Failed to run ACG BTC!", +			result = tmp_result); +  	result = vega12_enable_all_smu_features(hwmgr);  	PP_ASSERT_WITH_CODE(!result,  			"Failed to enable all smu features!", diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 26154f9b2178..82935a3bd950 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -390,9 +390,9 @@ static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)  	hwmgr->backend = data; -	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO]; -	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO; -	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO; +	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; +	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; +	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;  	vega20_set_default_registry_data(hwmgr); @@ -980,6 +980,9 @@ static int vega20_od8_set_feature_capabilities(  	    pp_table->FanZeroRpmEnable)  		od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL; +	if (!od_settings->overdrive8_capabilities) +		hwmgr->od_enabled = false; +  	return 0;  } @@ -1689,13 +1692,6 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_  					(PPCLK_UCLK << 16) | (min_freq & 0xffff))),  					"Failed to set soft min memclk !",  					return ret); - -		min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level; -		PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( -					hwmgr, PPSMC_MSG_SetHardMinByFreq, -					(PPCLK_UCLK << 16) | (min_freq & 0xffff))), -					"Failed to set hard min memclk !", -					return ret);  	}  	if (data->smu_features[GNLD_DPM_UVD].enabled && @@ -2248,6 +2244,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,  		soft_min_level = mask ? (ffs(mask) - 1) : 0;  		soft_max_level = mask ? (fls(mask) - 1) : 0; +		if (soft_max_level >= data->dpm_table.gfx_table.count) { +			pr_err("Clock level specified %d is over max allowed %d\n", +					soft_max_level, +					data->dpm_table.gfx_table.count - 1); +			return -EINVAL; +		} +  		data->dpm_table.gfx_table.dpm_state.soft_min_level =  			data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;  		data->dpm_table.gfx_table.dpm_state.soft_max_level = @@ -2268,6 +2271,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,  		soft_min_level = mask ? (ffs(mask) - 1) : 0;  		soft_max_level = mask ? (fls(mask) - 1) : 0; +		if (soft_max_level >= data->dpm_table.mem_table.count) { +			pr_err("Clock level specified %d is over max allowed %d\n", +					soft_max_level, +					data->dpm_table.mem_table.count - 1); +			return -EINVAL; +		} +  		data->dpm_table.mem_table.dpm_state.soft_min_level =  			data->dpm_table.mem_table.dpm_levels[soft_min_level].value;  		data->dpm_table.mem_table.dpm_state.soft_max_level = @@ -3261,6 +3271,9 @@ static int conv_power_profile_to_pplib_workload(int power_profile)  	int pplib_workload = 0;  	switch (power_profile) { +	case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: +		pplib_workload = WORKLOAD_DEFAULT_BIT; +		break;  	case PP_SMC_POWER_PROFILE_FULLSCREEN3D:  		pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;  		break; @@ -3290,6 +3303,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)  	uint32_t i, size = 0;  	uint16_t workload_type = 0;  	static const char *profile_name[] = { +					"BOOTUP_DEFAULT",  					"3D_FULL_SCREEN",  					"POWER_SAVING",  					"VIDEO", diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 0d298a0409f5..8cb831b6a016 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -705,7 +705,7 @@ enum PP_TABLE_VERSION {  /**   * The main hardware manager structure.   */ -#define Workload_Policy_Max 5 +#define Workload_Policy_Max 6  struct pp_hwmgr {  	void *adev; diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 8e28e738cb52..e6403b9549f1 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -98,6 +98,8 @@  #define DP0_STARTVAL		0x064c  #define DP0_ACTIVEVAL		0x0650  #define DP0_SYNCVAL		0x0654 +#define SYNCVAL_HS_POL_ACTIVE_LOW	(1 << 15) +#define SYNCVAL_VS_POL_ACTIVE_LOW	(1 << 31)  #define DP0_MISC		0x0658  #define TU_SIZE_RECOMMENDED		(63) /* LSCLK cycles per TU */  #define BPC_6				(0 << 5) @@ -142,6 +144,8 @@  #define DP0_LTLOOPCTRL		0x06d8  #define DP0_SNKLTCTRL		0x06e4 +#define DP1_SRCCTRL		0x07a0 +  /* PHY */  #define DP_PHY_CTRL		0x0800  #define DP_PHY_RST			BIT(28)  /* DP PHY Global Soft Reset */ @@ -150,6 +154,7 @@  #define PHY_M1_RST			BIT(12)  /* Reset PHY1 Main Channel */  #define PHY_RDY				BIT(16)  /* PHY Main Channels Ready */  #define PHY_M0_RST			BIT(8)   /* Reset PHY0 Main Channel */ +#define PHY_2LANE			BIT(2)   /* PHY Enable 2 lanes */  #define PHY_A0_EN			BIT(1)   /* PHY Aux Channel0 Enable */  #define PHY_M0_EN			BIT(0)   /* PHY Main Channel0 Enable */ @@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc)  	unsigned long rate;  	u32 value;  	int ret; +	u32 dp_phy_ctrl;  	rate = clk_get_rate(tc->refclk);  	switch (rate) { @@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc)  	value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;  	tc_write(SYS_PLLPARAM, value); -	tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN); +	dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN; +	if (tc->link.base.num_lanes == 2) +		dp_phy_ctrl |= PHY_2LANE; +	tc_write(DP_PHY_CTRL, dp_phy_ctrl);  	/*  	 * Initially PLLs are in bypass. Force PLL parameter update, @@ -719,7 +728,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)  	tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay)); -	tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0)); +	tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) | +		 ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) | +		 ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0));  	tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |  		 DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888); @@ -829,12 +840,11 @@ static int tc_main_link_setup(struct tc_data *tc)  	if (!tc->mode)  		return -EINVAL; -	/* from excel file - DP0_SrcCtrl */ -	tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B | -		 DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 | -		 DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT); -	/* from excel file - DP1_SrcCtrl */ -	tc_write(0x07a0, 0x00003083); +	tc_write(DP0_SRCCTRL, tc_srcctrl(tc)); +	/* SSCG and BW27 on DP1 must be set to the same as on DP0 */ +	tc_write(DP1_SRCCTRL, +		 (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) | +		 ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));  	rate = clk_get_rate(tc->refclk);  	switch (rate) { @@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc)  	}  	value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;  	tc_write(SYS_PLLPARAM, value); +  	/* Setup Main Link */ -	dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN |  PHY_M0_EN; +	dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN; +	if (tc->link.base.num_lanes == 2) +		dp_phy_ctrl |= PHY_2LANE;  	tc_write(DP_PHY_CTRL, dp_phy_ctrl);  	msleep(100); @@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,  static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector,  				   struct drm_display_mode *mode)  { +	struct tc_data *tc = connector_to_tc(connector); +	u32 req, avail; +	u32 bits_per_pixel = 24; +  	/* DPI interface clock limitation: upto 154 MHz */  	if (mode->clock > 154000)  		return MODE_CLOCK_HIGH; +	req = mode->clock * bits_per_pixel / 8; +	avail = tc->link.base.num_lanes * tc->link.base.rate; + +	if (req > avail) +		return MODE_BAD; +  	return MODE_OK;  } @@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge)  	/* Create eDP connector */  	drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);  	ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs, -				 DRM_MODE_CONNECTOR_eDP); +				 tc->panel ? DRM_MODE_CONNECTOR_eDP : +				 DRM_MODE_CONNECTOR_DisplayPort);  	if (ret)  		return ret; @@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge)  	drm_display_info_set_bus_formats(&tc->connector.display_info,  					 &bus_format, 1); +	tc->connector.display_info.bus_flags = +		DRM_BUS_FLAG_DE_HIGH | +		DRM_BUS_FLAG_PIXDATA_NEGEDGE | +		DRM_BUS_FLAG_SYNC_NEGEDGE;  	drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder);  	return 0; diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index c40889888a16..9a1f41adfc67 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1296,12 +1296,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,  			(arg->flags & DRM_MODE_PAGE_FLIP_EVENT))  		return -EINVAL; -	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); -  	state = drm_atomic_state_alloc(dev);  	if (!state)  		return -ENOMEM; +	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);  	state->acquire_ctx = &ctx;  	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 2d6c491a0542..516e82d0ed50 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1273,6 +1273,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {  	{ OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_CONSTANT_N) },  	/* LG LP140WF6-SPM1 eDP panel */  	{ OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) }, +	/* Apple panels need some additional handling to support PSR */ +	{ OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) }  };  #undef OUI diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d3af098b0922..d73703a695e8 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1621,6 +1621,64 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1,  	       var_1->transp.msb_right == var_2->transp.msb_right;  } +static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var, +					 u8 depth) +{ +	switch (depth) { +	case 8: +		var->red.offset = 0; +		var->green.offset = 0; +		var->blue.offset = 0; +		var->red.length = 8; /* 8bit DAC */ +		var->green.length = 8; +		var->blue.length = 8; +		var->transp.offset = 0; +		var->transp.length = 0; +		break; +	case 15: +		var->red.offset = 10; +		var->green.offset = 5; +		var->blue.offset = 0; +		var->red.length = 5; +		var->green.length = 5; +		var->blue.length = 5; +		var->transp.offset = 15; +		var->transp.length = 1; +		break; +	case 16: +		var->red.offset = 11; +		var->green.offset = 5; +		var->blue.offset = 0; +		var->red.length = 5; +		var->green.length = 6; +		var->blue.length = 5; +		var->transp.offset = 0; +		break; +	case 24: +		var->red.offset = 16; +		var->green.offset = 8; +		var->blue.offset = 0; +		var->red.length = 8; +		var->green.length = 8; +		var->blue.length = 8; +		var->transp.offset = 0; +		var->transp.length = 0; +		break; +	case 32: +		var->red.offset = 16; +		var->green.offset = 8; +		var->blue.offset = 0; +		var->red.length = 8; +		var->green.length = 8; +		var->blue.length = 8; +		var->transp.offset = 24; +		var->transp.length = 8; +		break; +	default: +		break; +	} +} +  /**   * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var   * @var: screeninfo to check @@ -1632,9 +1690,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,  	struct drm_fb_helper *fb_helper = info->par;  	struct drm_framebuffer *fb = fb_helper->fb; -	if (var->pixclock != 0 || in_dbg_master()) +	if (in_dbg_master())  		return -EINVAL; +	if (var->pixclock != 0) { +		DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n"); +		var->pixclock = 0; +	} +  	if ((drm_format_info_block_width(fb->format, 0) > 1) ||  	    (drm_format_info_block_height(fb->format, 0) > 1))  		return -EINVAL; @@ -1655,6 +1718,20 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,  	}  	/* +	 * Workaround for SDL 1.2, which is known to be setting all pixel format +	 * fields values to zero in some cases. We treat this situation as a +	 * kind of "use some reasonable autodetected values". +	 */ +	if (!var->red.offset     && !var->green.offset    && +	    !var->blue.offset    && !var->transp.offset   && +	    !var->red.length     && !var->green.length    && +	    !var->blue.length    && !var->transp.length   && +	    !var->red.msb_right  && !var->green.msb_right && +	    !var->blue.msb_right && !var->transp.msb_right) { +		drm_fb_helper_fill_pixel_fmt(var, fb->format->depth); +	} + +	/*  	 * drm fbdev emulation doesn't support changing the pixel format at all,  	 * so reject all pixel format changing requests.  	 */ @@ -1967,59 +2044,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe  	info->var.yoffset = 0;  	info->var.activate = FB_ACTIVATE_NOW; -	switch (fb->format->depth) { -	case 8: -		info->var.red.offset = 0; -		info->var.green.offset = 0; -		info->var.blue.offset = 0; -		info->var.red.length = 8; /* 8bit DAC */ -		info->var.green.length = 8; -		info->var.blue.length = 8; -		info->var.transp.offset = 0; -		info->var.transp.length = 0; -		break; -	case 15: -		info->var.red.offset = 10; -		info->var.green.offset = 5; -		info->var.blue.offset = 0; -		info->var.red.length = 5; -		info->var.green.length = 5; -		info->var.blue.length = 5; -		info->var.transp.offset = 15; -		info->var.transp.length = 1; -		break; -	case 16: -		info->var.red.offset = 11; -		info->var.green.offset = 5; -		info->var.blue.offset = 0; -		info->var.red.length = 5; -		info->var.green.length = 6; -		info->var.blue.length = 5; -		info->var.transp.offset = 0; -		break; -	case 24: -		info->var.red.offset = 16; -		info->var.green.offset = 8; -		info->var.blue.offset = 0; -		info->var.red.length = 8; -		info->var.green.length = 8; -		info->var.blue.length = 8; -		info->var.transp.offset = 0; -		info->var.transp.length = 0; -		break; -	case 32: -		info->var.red.offset = 16; -		info->var.green.offset = 8; -		info->var.blue.offset = 0; -		info->var.red.length = 8; -		info->var.green.length = 8; -		info->var.blue.length = 8; -		info->var.transp.offset = 24; -		info->var.transp.length = 8; -		break; -	default: -		break; -	} +	drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth);  	info->var.xres = fb_width;  	info->var.yres = fb_height; diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index 99cba8ea5d82..5df1256618cc 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c @@ -528,7 +528,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,  	object_count = cl->object_count; -	object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), object_count * sizeof(__u32)); +	object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), +			array_size(object_count, sizeof(__u32)));  	if (IS_ERR(object_ids))  		return PTR_ERR(object_ids); diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index cd9bc0ce9be0..004191d01772 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -459,11 +459,11 @@ static int set_property_atomic(struct drm_mode_object *obj,  	struct drm_modeset_acquire_ctx ctx;  	int ret; -	drm_modeset_acquire_init(&ctx, 0); -  	state = drm_atomic_state_alloc(dev);  	if (!state)  		return -ENOMEM; + +	drm_modeset_acquire_init(&ctx, 0);  	state->acquire_ctx = &ctx;  retry:  	if (prop == state->dev->mode_config.dpms_property) { diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 24a750436559..f91e02c87fd8 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -758,7 +758,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode)  	if (mode->hsync)  		return mode->hsync; -	if (mode->htotal < 0) +	if (mode->htotal <= 0)  		return 0;  	calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */ diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index a9d9df6c85ad..693748ad8b88 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -61,8 +61,9 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali  		return NULL;  	dmah->size = size; -	dmah->vaddr = dma_zalloc_coherent(&dev->pdev->dev, size, &dmah->busaddr, -						GFP_KERNEL | __GFP_COMP); +	dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size, +					 &dmah->busaddr, +					 GFP_KERNEL | __GFP_COMP);  	if (dmah->vaddr == NULL) {  		kfree(dmah); diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index b5475c91e2ef..e9f343b124b0 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -2799,6 +2799,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  	MMIO_DFH(_MMIO(0xe2a0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(_MMIO(0xe2b0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(_MMIO(0xe2c0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(_MMIO(0x21f0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  	return 0;  } diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index 5af11cf1b482..e1675a00df12 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -41,7 +41,7 @@ struct intel_gvt_mpt {  	int (*host_init)(struct device *dev, void *gvt, const void *ops);  	void (*host_exit)(struct device *dev, void *gvt);  	int (*attach_vgpu)(void *vgpu, unsigned long *handle); -	void (*detach_vgpu)(unsigned long handle); +	void (*detach_vgpu)(void *vgpu);  	int (*inject_msi)(unsigned long handle, u32 addr, u16 data);  	unsigned long (*from_virt_to_mfn)(void *p);  	int (*enable_page_track)(unsigned long handle, u64 gfn); diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index c1072143da1d..dd3dfd00f4e6 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -996,7 +996,7 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)  {  	unsigned int index;  	u64 virtaddr; -	unsigned long req_size, pgoff = 0; +	unsigned long req_size, pgoff, req_start;  	pgprot_t pg_prot;  	struct intel_vgpu *vgpu = mdev_get_drvdata(mdev); @@ -1014,7 +1014,17 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)  	pg_prot = vma->vm_page_prot;  	virtaddr = vma->vm_start;  	req_size = vma->vm_end - vma->vm_start; -	pgoff = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT; +	pgoff = vma->vm_pgoff & +		((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1); +	req_start = pgoff << PAGE_SHIFT; + +	if (!intel_vgpu_in_aperture(vgpu, req_start)) +		return -EINVAL; +	if (req_start + req_size > +	    vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu)) +		return -EINVAL; + +	pgoff = (gvt_aperture_pa_base(vgpu->gvt) >> PAGE_SHIFT) + pgoff;  	return remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot);  } @@ -1662,9 +1672,21 @@ static int kvmgt_attach_vgpu(void *vgpu, unsigned long *handle)  	return 0;  } -static void kvmgt_detach_vgpu(unsigned long handle) +static void kvmgt_detach_vgpu(void *p_vgpu)  { -	/* nothing to do here */ +	int i; +	struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu; + +	if (!vgpu->vdev.region) +		return; + +	for (i = 0; i < vgpu->vdev.num_regions; i++) +		if (vgpu->vdev.region[i].ops->release) +			vgpu->vdev.region[i].ops->release(vgpu, +					&vgpu->vdev.region[i]); +	vgpu->vdev.num_regions = 0; +	kfree(vgpu->vdev.region); +	vgpu->vdev.region = NULL;  }  static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data) diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index 67f19992b226..3ed34123d8d1 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -101,7 +101,7 @@ static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu)  	if (!intel_gvt_host.mpt->detach_vgpu)  		return; -	intel_gvt_host.mpt->detach_vgpu(vgpu->handle); +	intel_gvt_host.mpt->detach_vgpu(vgpu);  }  #define MSI_CAP_CONTROL(offset) (offset + 2) diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 1ad8c5e1455d..55bb7885e228 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -332,6 +332,9 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)  	i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj);  	i915_gem_object_put(wa_ctx->indirect_ctx.obj); + +	wa_ctx->indirect_ctx.obj = NULL; +	wa_ctx->indirect_ctx.shadow_va = NULL;  }  static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, @@ -356,6 +359,33 @@ static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,  	return 0;  } +static int +intel_gvt_workload_req_alloc(struct intel_vgpu_workload *workload) +{ +	struct intel_vgpu *vgpu = workload->vgpu; +	struct intel_vgpu_submission *s = &vgpu->submission; +	struct i915_gem_context *shadow_ctx = s->shadow_ctx; +	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; +	struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id]; +	struct i915_request *rq; +	int ret = 0; + +	lockdep_assert_held(&dev_priv->drm.struct_mutex); + +	if (workload->req) +		goto out; + +	rq = i915_request_alloc(engine, shadow_ctx); +	if (IS_ERR(rq)) { +		gvt_vgpu_err("fail to allocate gem request\n"); +		ret = PTR_ERR(rq); +		goto out; +	} +	workload->req = i915_request_get(rq); +out: +	return ret; +} +  /**   * intel_gvt_scan_and_shadow_workload - audit the workload by scanning and   * shadow it as well, include ringbuffer,wa_ctx and ctx. @@ -372,12 +402,11 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)  	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;  	struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id];  	struct intel_context *ce; -	struct i915_request *rq;  	int ret;  	lockdep_assert_held(&dev_priv->drm.struct_mutex); -	if (workload->req) +	if (workload->shadow)  		return 0;  	ret = set_context_ppgtt_from_shadow(workload, shadow_ctx); @@ -417,22 +446,8 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)  			goto err_shadow;  	} -	rq = i915_request_alloc(engine, shadow_ctx); -	if (IS_ERR(rq)) { -		gvt_vgpu_err("fail to allocate gem request\n"); -		ret = PTR_ERR(rq); -		goto err_shadow; -	} -	workload->req = i915_request_get(rq); - -	ret = populate_shadow_context(workload); -	if (ret) -		goto err_req; - +	workload->shadow = true;  	return 0; -err_req: -	rq = fetch_and_zero(&workload->req); -	i915_request_put(rq);  err_shadow:  	release_shadow_wa_ctx(&workload->wa_ctx);  err_unpin: @@ -671,23 +686,31 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)  	mutex_lock(&vgpu->vgpu_lock);  	mutex_lock(&dev_priv->drm.struct_mutex); +	ret = intel_gvt_workload_req_alloc(workload); +	if (ret) +		goto err_req; +  	ret = intel_gvt_scan_and_shadow_workload(workload);  	if (ret)  		goto out; -	ret = prepare_workload(workload); +	ret = populate_shadow_context(workload); +	if (ret) { +		release_shadow_wa_ctx(&workload->wa_ctx); +		goto out; +	} +	ret = prepare_workload(workload);  out: -	if (ret) -		workload->status = ret; -  	if (!IS_ERR_OR_NULL(workload->req)) {  		gvt_dbg_sched("ring id %d submit workload to i915 %p\n",  				ring_id, workload->req);  		i915_request_add(workload->req);  		workload->dispatched = true;  	} - +err_req: +	if (ret) +		workload->status = ret;  	mutex_unlock(&dev_priv->drm.struct_mutex);  	mutex_unlock(&vgpu->vgpu_lock);  	return ret; @@ -891,11 +914,6 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)  	list_del_init(&workload->list); -	if (!workload->status) { -		release_shadow_batch_buffer(workload); -		release_shadow_wa_ctx(&workload->wa_ctx); -	} -  	if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) {  		/* if workload->status is not successful means HW GPU  		 * has occurred GPU hang or something wrong with i915/GVT, @@ -1263,6 +1281,9 @@ void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload)  {  	struct intel_vgpu_submission *s = &workload->vgpu->submission; +	release_shadow_batch_buffer(workload); +	release_shadow_wa_ctx(&workload->wa_ctx); +  	if (workload->shadow_mm)  		intel_vgpu_mm_put(workload->shadow_mm); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index ca5529d0e48e..2065cba59aab 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -83,6 +83,7 @@ struct intel_vgpu_workload {  	struct i915_request *req;  	/* if this workload has been dispatched to i915? */  	bool dispatched; +	bool shadow;      /* if workload has done shadow of guest request */  	int status;  	struct intel_vgpu_mm *shadow_mm; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 38dcee1ca062..40a61ef9aac1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -984,8 +984,8 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)  	intel_runtime_pm_get(i915);  	gpu = i915_capture_gpu_state(i915);  	intel_runtime_pm_put(i915); -	if (!gpu) -		return -ENOMEM; +	if (IS_ERR(gpu)) +		return PTR_ERR(gpu);  	file->private_data = gpu;  	return 0; @@ -1018,7 +1018,13 @@ i915_error_state_write(struct file *filp,  static int i915_error_state_open(struct inode *inode, struct file *file)  { -	file->private_data = i915_first_error_state(inode->i_private); +	struct i915_gpu_state *error; + +	error = i915_first_error_state(inode->i_private); +	if (IS_ERR(error)) +		return PTR_ERR(error); + +	file->private_data  = error;  	return 0;  } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 216f52b744a6..c882ea94172c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1824,6 +1824,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,  	return 0;  } +static inline bool +__vma_matches(struct vm_area_struct *vma, struct file *filp, +	      unsigned long addr, unsigned long size) +{ +	if (vma->vm_file != filp) +		return false; + +	return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size; +} +  /**   * i915_gem_mmap_ioctl - Maps the contents of an object, returning the address   *			 it is mapped to. @@ -1882,7 +1892,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,  			return -EINTR;  		}  		vma = find_vma(mm, addr); -		if (vma) +		if (vma && __vma_matches(vma, obj->base.filp, addr, args->size))  			vma->vm_page_prot =  				pgprot_writecombine(vm_get_page_prot(vma->vm_flags));  		else diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index add1fe7aeb93..bd17dd1f5da5 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2075,6 +2075,7 @@ static struct i915_vma *pd_vma_create(struct gen6_hw_ppgtt *ppgtt, int size)  int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)  {  	struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base); +	int err;  	/*  	 * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt @@ -2090,9 +2091,17 @@ int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)  	 * allocator works in address space sizes, so it's multiplied by page  	 * size. We allocate at the top of the GTT to avoid fragmentation.  	 */ -	return i915_vma_pin(ppgtt->vma, -			    0, GEN6_PD_ALIGN, -			    PIN_GLOBAL | PIN_HIGH); +	err = i915_vma_pin(ppgtt->vma, +			   0, GEN6_PD_ALIGN, +			   PIN_GLOBAL | PIN_HIGH); +	if (err) +		goto unpin; + +	return 0; + +unpin: +	ppgtt->pin_count = 0; +	return err;  }  void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 07465123c166..3f9ce403c755 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1907,9 +1907,16 @@ i915_capture_gpu_state(struct drm_i915_private *i915)  {  	struct i915_gpu_state *error; +	/* Check if GPU capture has been disabled */ +	error = READ_ONCE(i915->gpu_error.first_error); +	if (IS_ERR(error)) +		return error; +  	error = kzalloc(sizeof(*error), GFP_ATOMIC); -	if (!error) -		return NULL; +	if (!error) { +		i915_disable_error_state(i915, -ENOMEM); +		return ERR_PTR(-ENOMEM); +	}  	kref_init(&error->ref);  	error->i915 = i915; @@ -1945,11 +1952,8 @@ void i915_capture_error_state(struct drm_i915_private *i915,  		return;  	error = i915_capture_gpu_state(i915); -	if (!error) { -		DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); -		i915_disable_error_state(i915, -ENOMEM); +	if (IS_ERR(error))  		return; -	}  	i915_error_capture_msg(i915, error, engine_mask, error_msg);  	DRM_INFO("%s\n", error->error_msg); @@ -1987,7 +1991,7 @@ i915_first_error_state(struct drm_i915_private *i915)  	spin_lock_irq(&i915->gpu_error.lock);  	error = i915->gpu_error.first_error; -	if (error) +	if (!IS_ERR_OR_NULL(error))  		i915_gpu_state_get(error);  	spin_unlock_irq(&i915->gpu_error.lock); @@ -2000,10 +2004,11 @@ void i915_reset_error_state(struct drm_i915_private *i915)  	spin_lock_irq(&i915->gpu_error.lock);  	error = i915->gpu_error.first_error; -	i915->gpu_error.first_error = NULL; +	if (error != ERR_PTR(-ENODEV)) /* if disabled, always disabled */ +		i915->gpu_error.first_error = NULL;  	spin_unlock_irq(&i915->gpu_error.lock); -	if (!IS_ERR(error)) +	if (!IS_ERR_OR_NULL(error))  		i915_gpu_state_put(error);  } diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index d6c8f8fdfda5..017fc602a10e 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -594,7 +594,8 @@ static void i915_pmu_enable(struct perf_event *event)  	 * Update the bitmask of enabled events and increment  	 * the event reference counter.  	 */ -	GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); +	BUILD_BUG_ON(ARRAY_SIZE(i915->pmu.enable_count) != I915_PMU_MASK_BITS); +	GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));  	GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);  	i915->pmu.enable |= BIT_ULL(bit);  	i915->pmu.enable_count[bit]++; @@ -615,11 +616,16 @@ static void i915_pmu_enable(struct perf_event *event)  		engine = intel_engine_lookup_user(i915,  						  engine_event_class(event),  						  engine_event_instance(event)); -		GEM_BUG_ON(!engine); -		engine->pmu.enable |= BIT(sample); -		GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); +		BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) != +			     I915_ENGINE_SAMPLE_COUNT); +		BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) != +			     I915_ENGINE_SAMPLE_COUNT); +		GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count)); +		GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));  		GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0); + +		engine->pmu.enable |= BIT(sample);  		engine->pmu.enable_count[sample]++;  	} @@ -649,9 +655,11 @@ static void i915_pmu_disable(struct perf_event *event)  		engine = intel_engine_lookup_user(i915,  						  engine_event_class(event),  						  engine_event_instance(event)); -		GEM_BUG_ON(!engine); -		GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); + +		GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count)); +		GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));  		GEM_BUG_ON(engine->pmu.enable_count[sample] == 0); +  		/*  		 * Decrement the reference count and clear the enabled  		 * bitmask when the last listener on an event goes away. @@ -660,7 +668,7 @@ static void i915_pmu_disable(struct perf_event *event)  			engine->pmu.enable &= ~BIT(sample);  	} -	GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); +	GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));  	GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);  	/*  	 * Decrement the reference count and clear the enabled diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index 7f164ca3db12..b3728c5f13e7 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h @@ -31,6 +31,8 @@ enum {  	((1 << I915_PMU_SAMPLE_BITS) + \  	 (I915_PMU_LAST + 1 - __I915_PMU_OTHER(0))) +#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1) +  struct i915_pmu_sample {  	u64 cur;  }; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0a7d60509ca7..067054cf4a86 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1790,7 +1790,7 @@ enum i915_power_well_id {  #define _CNL_PORT_TX_C_LN0_OFFSET		0x162C40  #define _CNL_PORT_TX_D_LN0_OFFSET		0x162E40  #define _CNL_PORT_TX_F_LN0_OFFSET		0x162840 -#define _CNL_PORT_TX_DW_GRP(port, dw)	(_PICK((port), \ +#define _CNL_PORT_TX_DW_GRP(dw, port)	(_PICK((port), \  					       _CNL_PORT_TX_AE_GRP_OFFSET, \  					       _CNL_PORT_TX_B_GRP_OFFSET, \  					       _CNL_PORT_TX_B_GRP_OFFSET, \ @@ -1798,7 +1798,7 @@ enum i915_power_well_id {  					       _CNL_PORT_TX_AE_GRP_OFFSET, \  					       _CNL_PORT_TX_F_GRP_OFFSET) + \  					       4 * (dw)) -#define _CNL_PORT_TX_DW_LN0(port, dw)	(_PICK((port), \ +#define _CNL_PORT_TX_DW_LN0(dw, port)	(_PICK((port), \  					       _CNL_PORT_TX_AE_LN0_OFFSET, \  					       _CNL_PORT_TX_B_LN0_OFFSET, \  					       _CNL_PORT_TX_B_LN0_OFFSET, \ @@ -1834,9 +1834,9 @@ enum i915_power_well_id {  #define _CNL_PORT_TX_DW4_LN0_AE		0x162450  #define _CNL_PORT_TX_DW4_LN1_AE		0x1624D0 -#define CNL_PORT_TX_DW4_GRP(port)	_MMIO(_CNL_PORT_TX_DW_GRP((port), 4)) -#define CNL_PORT_TX_DW4_LN0(port)	_MMIO(_CNL_PORT_TX_DW_LN0((port), 4)) -#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \ +#define CNL_PORT_TX_DW4_GRP(port)	_MMIO(_CNL_PORT_TX_DW_GRP(4, (port))) +#define CNL_PORT_TX_DW4_LN0(port)	_MMIO(_CNL_PORT_TX_DW_LN0(4, (port))) +#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \  					   ((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \  						    _CNL_PORT_TX_DW4_LN0_AE)))  #define ICL_PORT_TX_DW4_AUX(port)	_MMIO(_ICL_PORT_TX_DW_AUX(4, port)) @@ -1864,8 +1864,12 @@ enum i915_power_well_id {  #define   RTERM_SELECT(x)		((x) << 3)  #define   RTERM_SELECT_MASK		(0x7 << 3) -#define CNL_PORT_TX_DW7_GRP(port)	_MMIO(_CNL_PORT_TX_DW_GRP((port), 7)) -#define CNL_PORT_TX_DW7_LN0(port)	_MMIO(_CNL_PORT_TX_DW_LN0((port), 7)) +#define CNL_PORT_TX_DW7_GRP(port)	_MMIO(_CNL_PORT_TX_DW_GRP(7, (port))) +#define CNL_PORT_TX_DW7_LN0(port)	_MMIO(_CNL_PORT_TX_DW_LN0(7, (port))) +#define ICL_PORT_TX_DW7_AUX(port)	_MMIO(_ICL_PORT_TX_DW_AUX(7, port)) +#define ICL_PORT_TX_DW7_GRP(port)	_MMIO(_ICL_PORT_TX_DW_GRP(7, port)) +#define ICL_PORT_TX_DW7_LN0(port)	_MMIO(_ICL_PORT_TX_DW_LN(7, 0, port)) +#define ICL_PORT_TX_DW7_LN(port, ln)	_MMIO(_ICL_PORT_TX_DW_LN(7, ln, port))  #define   N_SCALAR(x)			((x) << 24)  #define   N_SCALAR_MASK			(0x7F << 24) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 535caebd9813..c0cfe7ae2ba5 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -521,7 +521,9 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,  	ssize_t ret;  	gpu = i915_first_error_state(i915); -	if (gpu) { +	if (IS_ERR(gpu)) { +		ret = PTR_ERR(gpu); +	} else if (gpu) {  		ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count);  		i915_gpu_state_put(gpu);  	} else { diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f3e1d6a0b7dd..7edce1b7b348 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -494,103 +494,58 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = {  	{ 0x2, 0x7F, 0x3F, 0x00, 0x00 },	/* 400   400      0.0   */  }; -struct icl_combo_phy_ddi_buf_trans { -	u32 dw2_swing_select; -	u32 dw2_swing_scalar; -	u32 dw4_scaling; -}; - -/* Voltage Swing Programming for VccIO 0.85V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = { -				/* Voltage mV  db    */ -	{ 0x2, 0x98, 0x0018 },	/* 400         0.0   */ -	{ 0x2, 0x98, 0x3015 },	/* 400         3.5   */ -	{ 0x2, 0x98, 0x6012 },	/* 400         6.0   */ -	{ 0x2, 0x98, 0x900F },	/* 400         9.5   */ -	{ 0xB, 0x70, 0x0018 },	/* 600         0.0   */ -	{ 0xB, 0x70, 0x3015 },	/* 600         3.5   */ -	{ 0xB, 0x70, 0x6012 },	/* 600         6.0   */ -	{ 0x5, 0x00, 0x0018 },	/* 800         0.0   */ -	{ 0x5, 0x00, 0x3015 },	/* 800         3.5   */ -	{ 0x6, 0x98, 0x0018 },	/* 1200        0.0   */ -}; - -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 0.85V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = { -				/* Voltage mV  db    */ -	{ 0x0, 0x00, 0x00 },	/* 200         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 200         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         6.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 250         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 350         0.0   */ -}; - -/* Voltage Swing Programming for VccIO 0.95V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = { -				/* Voltage mV  db    */ -	{ 0x2, 0x98, 0x0018 },	/* 400         0.0   */ -	{ 0x2, 0x98, 0x3015 },	/* 400         3.5   */ -	{ 0x2, 0x98, 0x6012 },	/* 400         6.0   */ -	{ 0x2, 0x98, 0x900F },	/* 400         9.5   */ -	{ 0x4, 0x98, 0x0018 },	/* 600         0.0   */ -	{ 0x4, 0x98, 0x3015 },	/* 600         3.5   */ -	{ 0x4, 0x98, 0x6012 },	/* 600         6.0   */ -	{ 0x5, 0x76, 0x0018 },	/* 800         0.0   */ -	{ 0x5, 0x76, 0x3015 },	/* 800         3.5   */ -	{ 0x6, 0x98, 0x0018 },	/* 1200        0.0   */ +/* icl_combo_phy_ddi_translations */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = { +						/* NT mV Trans mV db    */ +	{ 0xA, 0x35, 0x3F, 0x00, 0x00 },	/* 350   350      0.0   */ +	{ 0xA, 0x4F, 0x37, 0x00, 0x08 },	/* 350   500      3.1   */ +	{ 0xC, 0x71, 0x2F, 0x00, 0x10 },	/* 350   700      6.0   */ +	{ 0x6, 0x7F, 0x2B, 0x00, 0x14 },	/* 350   900      8.2   */ +	{ 0xA, 0x4C, 0x3F, 0x00, 0x00 },	/* 500   500      0.0   */ +	{ 0xC, 0x73, 0x34, 0x00, 0x0B },	/* 500   700      2.9   */ +	{ 0x6, 0x7F, 0x2F, 0x00, 0x10 },	/* 500   900      5.1   */ +	{ 0xC, 0x6C, 0x3C, 0x00, 0x03 },	/* 650   700      0.6   */ +	{ 0x6, 0x7F, 0x35, 0x00, 0x0A },	/* 600   900      3.5   */ +	{ 0x6, 0x7F, 0x3F, 0x00, 0x00 },	/* 900   900      0.0   */  }; -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 0.95V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = { -				/* Voltage mV  db    */ -	{ 0x0, 0x00, 0x00 },	/* 200         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 200         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         6.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 250         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 350         0.0   */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = { +						/* NT mV Trans mV db    */ +	{ 0x0, 0x7F, 0x3F, 0x00, 0x00 },	/* 200   200      0.0   */ +	{ 0x8, 0x7F, 0x38, 0x00, 0x07 },	/* 200   250      1.9   */ +	{ 0x1, 0x7F, 0x33, 0x00, 0x0C },	/* 200   300      3.5   */ +	{ 0x9, 0x7F, 0x31, 0x00, 0x0E },	/* 200   350      4.9   */ +	{ 0x8, 0x7F, 0x3F, 0x00, 0x00 },	/* 250   250      0.0   */ +	{ 0x1, 0x7F, 0x38, 0x00, 0x07 },	/* 250   300      1.6   */ +	{ 0x9, 0x7F, 0x35, 0x00, 0x0A },	/* 250   350      2.9   */ +	{ 0x1, 0x7F, 0x3F, 0x00, 0x00 },	/* 300   300      0.0   */ +	{ 0x9, 0x7F, 0x38, 0x00, 0x07 },	/* 300   350      1.3   */ +	{ 0x9, 0x7F, 0x3F, 0x00, 0x00 },	/* 350   350      0.0   */  }; -/* Voltage Swing Programming for VccIO 1.05V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = { -				/* Voltage mV  db    */ -	{ 0x2, 0x98, 0x0018 },	/* 400         0.0   */ -	{ 0x2, 0x98, 0x3015 },	/* 400         3.5   */ -	{ 0x2, 0x98, 0x6012 },	/* 400         6.0   */ -	{ 0x2, 0x98, 0x900F },	/* 400         9.5   */ -	{ 0x4, 0x98, 0x0018 },	/* 600         0.0   */ -	{ 0x4, 0x98, 0x3015 },	/* 600         3.5   */ -	{ 0x4, 0x98, 0x6012 },	/* 600         6.0   */ -	{ 0x5, 0x71, 0x0018 },	/* 800         0.0   */ -	{ 0x5, 0x71, 0x3015 },	/* 800         3.5   */ -	{ 0x6, 0x98, 0x0018 },	/* 1200        0.0   */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = { +						/* NT mV Trans mV db    */ +	{ 0xA, 0x35, 0x3F, 0x00, 0x00 },	/* 350   350      0.0   */ +	{ 0xA, 0x4F, 0x37, 0x00, 0x08 },	/* 350   500      3.1   */ +	{ 0xC, 0x71, 0x2F, 0x00, 0x10 },	/* 350   700      6.0   */ +	{ 0x6, 0x7F, 0x2B, 0x00, 0x14 },	/* 350   900      8.2   */ +	{ 0xA, 0x4C, 0x3F, 0x00, 0x00 },	/* 500   500      0.0   */ +	{ 0xC, 0x73, 0x34, 0x00, 0x0B },	/* 500   700      2.9   */ +	{ 0x6, 0x7F, 0x2F, 0x00, 0x10 },	/* 500   900      5.1   */ +	{ 0xC, 0x6C, 0x3C, 0x00, 0x03 },	/* 650   700      0.6   */ +	{ 0x6, 0x7F, 0x35, 0x00, 0x0A },	/* 600   900      3.5   */ +	{ 0x6, 0x7F, 0x3F, 0x00, 0x00 },	/* 900   900      0.0   */  }; -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 1.05V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = { -				/* Voltage mV  db    */ -	{ 0x0, 0x00, 0x00 },	/* 200         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 200         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         6.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 250         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 350         0.0   */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = { +						/* NT mV Trans mV db    */ +	{ 0xA, 0x60, 0x3F, 0x00, 0x00 },	/* 450   450      0.0   */ +	{ 0xB, 0x73, 0x36, 0x00, 0x09 },	/* 450   650      3.2   */ +	{ 0x6, 0x7F, 0x31, 0x00, 0x0E },	/* 450   850      5.5   */ +	{ 0xB, 0x73, 0x3F, 0x00, 0x00 },	/* 650   650      0.0   ALS */ +	{ 0x6, 0x7F, 0x37, 0x00, 0x08 },	/* 650   850      2.3   */ +	{ 0x6, 0x7F, 0x3F, 0x00, 0x00 },	/* 850   850      0.0   */ +	{ 0x6, 0x7F, 0x35, 0x00, 0x0A },	/* 600   850      3.0   */  };  struct icl_mg_phy_ddi_buf_trans { @@ -871,43 +826,23 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)  	}  } -static const struct icl_combo_phy_ddi_buf_trans * +static const struct cnl_ddi_buf_trans *  icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port, -			int type, int *n_entries) +			int type, int rate, int *n_entries)  { -	u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK; - -	if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { -		switch (voltage) { -		case VOLTAGE_INFO_0_85V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V); -			return icl_combo_phy_ddi_translations_edp_0_85V; -		case VOLTAGE_INFO_0_95V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V); -			return icl_combo_phy_ddi_translations_edp_0_95V; -		case VOLTAGE_INFO_1_05V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V); -			return icl_combo_phy_ddi_translations_edp_1_05V; -		default: -			MISSING_CASE(voltage); -			return NULL; -		} -	} else { -		switch (voltage) { -		case VOLTAGE_INFO_0_85V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V); -			return icl_combo_phy_ddi_translations_dp_hdmi_0_85V; -		case VOLTAGE_INFO_0_95V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V); -			return icl_combo_phy_ddi_translations_dp_hdmi_0_95V; -		case VOLTAGE_INFO_1_05V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V); -			return icl_combo_phy_ddi_translations_dp_hdmi_1_05V; -		default: -			MISSING_CASE(voltage); -			return NULL; -		} +	if (type == INTEL_OUTPUT_HDMI) { +		*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi); +		return icl_combo_phy_ddi_translations_hdmi; +	} else if (rate > 540000 && type == INTEL_OUTPUT_EDP) { +		*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3); +		return icl_combo_phy_ddi_translations_edp_hbr3; +	} else if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { +		*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2); +		return icl_combo_phy_ddi_translations_edp_hbr2;  	} + +	*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2); +	return icl_combo_phy_ddi_translations_dp_hbr2;  }  static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) @@ -918,8 +853,8 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por  	if (IS_ICELAKE(dev_priv)) {  		if (intel_port_is_combophy(dev_priv, port)) -			icl_get_combo_buf_trans(dev_priv, port, -						INTEL_OUTPUT_HDMI, &n_entries); +			icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI, +						0, &n_entries);  		else  			n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);  		default_entry = n_entries - 1; @@ -1086,7 +1021,7 @@ static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,  			return DDI_CLK_SEL_TBT_810;  		default:  			MISSING_CASE(clock); -			break; +			return DDI_CLK_SEL_NONE;  		}  	case DPLL_ID_ICL_MGPLL1:  	case DPLL_ID_ICL_MGPLL2: @@ -2275,13 +2210,14 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,  u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);  	enum port port = encoder->port;  	int n_entries;  	if (IS_ICELAKE(dev_priv)) {  		if (intel_port_is_combophy(dev_priv, port))  			icl_get_combo_buf_trans(dev_priv, port, encoder->type, -						&n_entries); +						intel_dp->link_rate, &n_entries);  		else  			n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);  	} else if (IS_CANNONLAKE(dev_priv)) { @@ -2462,14 +2398,15 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,  }  static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv, -					 u32 level, enum port port, int type) +					u32 level, enum port port, int type, +					int rate)  { -	const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL; +	const struct cnl_ddi_buf_trans *ddi_translations = NULL;  	u32 n_entries, val;  	int ln;  	ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type, -						   &n_entries); +						   rate, &n_entries);  	if (!ddi_translations)  		return; @@ -2478,34 +2415,23 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,  		level = n_entries - 1;  	} -	/* Set PORT_TX_DW5 Rterm Sel to 110b. */ +	/* Set PORT_TX_DW5 */  	val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); -	val &= ~RTERM_SELECT_MASK; +	val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK | +		  TAP2_DISABLE | TAP3_DISABLE); +	val |= SCALING_MODE_SEL(0x2);  	val |= RTERM_SELECT(0x6); -	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); - -	/* Program PORT_TX_DW5 */ -	val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); -	/* Set DisableTap2 and DisableTap3 if MIPI DSI -	 * Clear DisableTap2 and DisableTap3 for all other Ports -	 */ -	if (type == INTEL_OUTPUT_DSI) { -		val |= TAP2_DISABLE; -		val |= TAP3_DISABLE; -	} else { -		val &= ~TAP2_DISABLE; -		val &= ~TAP3_DISABLE; -	} +	val |= TAP3_DISABLE;  	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);  	/* Program PORT_TX_DW2 */  	val = I915_READ(ICL_PORT_TX_DW2_LN0(port));  	val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |  		 RCOMP_SCALAR_MASK); -	val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select); -	val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select); +	val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel); +	val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);  	/* Program Rcomp scalar for every table entry */ -	val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar); +	val |= RCOMP_SCALAR(0x98);  	I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);  	/* Program PORT_TX_DW4 */ @@ -2514,9 +2440,17 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,  		val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));  		val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |  			 CURSOR_COEFF_MASK); -		val |= ddi_translations[level].dw4_scaling; +		val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1); +		val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2); +		val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);  		I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);  	} + +	/* Program PORT_TX_DW7 */ +	val = I915_READ(ICL_PORT_TX_DW7_LN0(port)); +	val &= ~N_SCALAR_MASK; +	val |= N_SCALAR(ddi_translations[level].dw7_n_scalar); +	I915_WRITE(ICL_PORT_TX_DW7_GRP(port), val);  }  static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder, @@ -2581,7 +2515,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,  	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);  	/* 5. Program swing and de-emphasis */ -	icl_ddi_combo_vswing_program(dev_priv, level, port, type); +	icl_ddi_combo_vswing_program(dev_priv, level, port, type, rate);  	/* 6. Set training enable to trigger update */  	val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3da9c0f9e948..248128126422 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15415,16 +15415,45 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,  	}  } +static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) +{ +	struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev); + +	/* +	 * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram +	 * the hardware when a high res displays plugged in. DPLL P +	 * divider is zero, and the pipe timings are bonkers. We'll +	 * try to disable everything in that case. +	 * +	 * FIXME would be nice to be able to sanitize this state +	 * without several WARNs, but for now let's take the easy +	 * road. +	 */ +	return IS_GEN6(dev_priv) && +		crtc_state->base.active && +		crtc_state->shared_dpll && +		crtc_state->port_clock == 0; +} +  static void intel_sanitize_encoder(struct intel_encoder *encoder)  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	struct intel_connector *connector; +	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); +	struct intel_crtc_state *crtc_state = crtc ? +		to_intel_crtc_state(crtc->base.state) : NULL;  	/* We need to check both for a crtc link (meaning that the  	 * encoder is active and trying to read from a pipe) and the  	 * pipe itself being active. */ -	bool has_active_crtc = encoder->base.crtc && -		to_intel_crtc(encoder->base.crtc)->active; +	bool has_active_crtc = crtc_state && +		crtc_state->base.active; + +	if (crtc_state && has_bogus_dpll_config(crtc_state)) { +		DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n", +			      pipe_name(crtc->pipe)); +		has_active_crtc = false; +	}  	connector = intel_encoder_find_connector(encoder);  	if (connector && !has_active_crtc) { @@ -15435,16 +15464,25 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)  		/* Connector is active, but has no active pipe. This is  		 * fallout from our resume register restoring. Disable  		 * the encoder manually again. */ -		if (encoder->base.crtc) { -			struct drm_crtc_state *crtc_state = encoder->base.crtc->state; +		if (crtc_state) { +			struct drm_encoder *best_encoder;  			DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",  				      encoder->base.base.id,  				      encoder->base.name); + +			/* avoid oopsing in case the hooks consult best_encoder */ +			best_encoder = connector->base.state->best_encoder; +			connector->base.state->best_encoder = &encoder->base; +  			if (encoder->disable) -				encoder->disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state); +				encoder->disable(encoder, crtc_state, +						 connector->base.state);  			if (encoder->post_disable) -				encoder->post_disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state); +				encoder->post_disable(encoder, crtc_state, +						      connector->base.state); + +			connector->base.state->best_encoder = best_encoder;  		}  		encoder->base.crtc = NULL; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fdd2cbc56fa3..22a74608c6e4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -304,9 +304,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)  static int icl_max_source_rate(struct intel_dp *intel_dp)  {  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);  	enum port port = dig_port->base.port; -	if (port == PORT_B) +	if (intel_port_is_combophy(dev_priv, port) && +	    !intel_dp_is_edp(intel_dp))  		return 540000;  	return 810000; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f94a04b4ad87..e9ddeaf05a14 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -209,6 +209,16 @@ struct intel_fbdev {  	unsigned long vma_flags;  	async_cookie_t cookie;  	int preferred_bpp; + +	/* Whether or not fbdev hpd processing is temporarily suspended */ +	bool hpd_suspended : 1; +	/* Set when a hotplug was received while HPD processing was +	 * suspended +	 */ +	bool hpd_waiting : 1; + +	/* Protects hpd_suspended */ +	struct mutex hpd_lock;  };  struct intel_encoder { diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index fb5bb5b32a60..7f365ac0b549 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -679,6 +679,7 @@ int intel_fbdev_init(struct drm_device *dev)  	if (ifbdev == NULL)  		return -ENOMEM; +	mutex_init(&ifbdev->hpd_lock);  	drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);  	if (!intel_fbdev_init_bios(dev, ifbdev)) @@ -752,6 +753,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv)  	intel_fbdev_destroy(ifbdev);  } +/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD + * processing, fbdev will perform a full connector reprobe if a hotplug event + * was received while HPD was suspended. + */ +static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state) +{ +	bool send_hpd = false; + +	mutex_lock(&ifbdev->hpd_lock); +	ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED; +	send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting; +	ifbdev->hpd_waiting = false; +	mutex_unlock(&ifbdev->hpd_lock); + +	if (send_hpd) { +		DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n"); +		drm_fb_helper_hotplug_event(&ifbdev->helper); +	} +} +  void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)  {  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -773,6 +794,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous  		 */  		if (state != FBINFO_STATE_RUNNING)  			flush_work(&dev_priv->fbdev_suspend_work); +  		console_lock();  	} else {  		/* @@ -800,17 +822,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous  	drm_fb_helper_set_suspend(&ifbdev->helper, state);  	console_unlock(); + +	intel_fbdev_hpd_set_suspend(ifbdev, state);  }  void intel_fbdev_output_poll_changed(struct drm_device *dev)  {  	struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; +	bool send_hpd;  	if (!ifbdev)  		return;  	intel_fbdev_sync(ifbdev); -	if (ifbdev->vma || ifbdev->helper.deferred_setup) + +	mutex_lock(&ifbdev->hpd_lock); +	send_hpd = !ifbdev->hpd_suspended; +	ifbdev->hpd_waiting = true; +	mutex_unlock(&ifbdev->hpd_lock); + +	if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))  		drm_fb_helper_hotplug_event(&ifbdev->helper);  } diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 4be167dcd209..eab9341a5152 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -303,6 +303,7 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine)  	 */  	if (!(prio & I915_PRIORITY_NEWCLIENT)) {  		prio |= I915_PRIORITY_NEWCLIENT; +		active->sched.attr.priority = prio;  		list_move_tail(&active->sched.link,  			       i915_sched_lookup_priolist(engine, prio));  	} @@ -645,6 +646,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)  		int i;  		priolist_for_each_request_consume(rq, rn, p, i) { +			GEM_BUG_ON(last && +				   need_preempt(engine, last, rq_prio(rq))); +  			/*  			 * Can we combine this request with the current port?  			 * It has to be the same context/ringbuffer and not @@ -2244,6 +2248,8 @@ static int logical_ring_init(struct intel_engine_cs *engine)  	if (ret)  		return ret; +	intel_engine_init_workarounds(engine); +  	if (HAS_LOGICAL_RING_ELSQ(i915)) {  		execlists->submit_reg = i915->regs +  			i915_mmio_reg_offset(RING_EXECLIST_SQ_CONTENTS(engine)); @@ -2310,7 +2316,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine)  	}  	intel_engine_init_whitelist(engine); -	intel_engine_init_workarounds(engine);  	return 0;  } diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index b8f106d9ecf8..3ac20153705a 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -55,7 +55,12 @@  struct opregion_header {  	u8 signature[16];  	u32 size; -	u32 opregion_ver; +	struct { +		u8 rsvd; +		u8 revision; +		u8 minor; +		u8 major; +	}  __packed over;  	u8 bios_ver[32];  	u8 vbios_ver[16];  	u8 driver_ver[16]; @@ -119,7 +124,8 @@ struct opregion_asle {  	u64 fdss;  	u32 fdsp;  	u32 stat; -	u64 rvda;	/* Physical address of raw vbt data */ +	u64 rvda;	/* Physical (2.0) or relative from opregion (2.1+) +			 * address of raw VBT data. */  	u32 rvds;	/* Size of raw vbt data */  	u8 rsvd[58];  } __packed; @@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)  	opregion->header = base;  	opregion->lid_state = base + ACPI_CLID; +	DRM_DEBUG_DRIVER("ACPI OpRegion version %u.%u.%u\n", +			 opregion->header->over.major, +			 opregion->header->over.minor, +			 opregion->header->over.revision); +  	mboxes = opregion->header->mboxes;  	if (mboxes & MBOX_ACPI) {  		DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); @@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)  	if (dmi_check_system(intel_no_opregion_vbt))  		goto out; -	if (opregion->header->opregion_ver >= 2 && opregion->asle && +	if (opregion->header->over.major >= 2 && opregion->asle &&  	    opregion->asle->rvda && opregion->asle->rvds) { -		opregion->rvda = memremap(opregion->asle->rvda, -					  opregion->asle->rvds, +		resource_size_t rvda = opregion->asle->rvda; + +		/* +		 * opregion 2.0: rvda is the physical VBT address. +		 * +		 * opregion 2.1+: rvda is unsigned, relative offset from +		 * opregion base, and should never point within opregion. +		 */ +		if (opregion->header->over.major > 2 || +		    opregion->header->over.minor >= 1) { +			WARN_ON(rvda < OPREGION_SIZE); + +			rvda += asls; +		} + +		opregion->rvda = memremap(rvda, opregion->asle->rvds,  					  MEMREMAP_WB); +  		vbt = opregion->rvda;  		vbt_size = opregion->asle->rvds;  		if (intel_bios_is_valid_vbt(vbt, vbt_size)) { @@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)  			goto out;  		} else {  			DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n"); +			memunmap(opregion->rvda); +			opregion->rvda = NULL;  		}  	} diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 419e56342523..f71970df9936 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -274,10 +274,16 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)  	DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",  		      intel_dp->psr_dpcd[0]); +	if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) { +		DRM_DEBUG_KMS("PSR support not currently available for this panel\n"); +		return; +	} +  	if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {  		DRM_DEBUG_KMS("Panel lacks power state control, PSR cannot be enabled\n");  		return;  	} +  	dev_priv->psr.sink_support = true;  	dev_priv->psr.sink_sync_latency =  		intel_dp_get_sink_sync_latency(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 72edaa7ff411..a1a7cc29fdd1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -415,16 +415,17 @@ struct intel_engine_cs {  		/**  		 * @enable_count: Reference count for the enabled samplers.  		 * -		 * Index number corresponds to the bit number from @enable. +		 * Index number corresponds to @enum drm_i915_pmu_engine_sample.  		 */ -		unsigned int enable_count[I915_PMU_SAMPLE_BITS]; +		unsigned int enable_count[I915_ENGINE_SAMPLE_COUNT];  		/**  		 * @sample: Counter values for sampling events.  		 *  		 * Our internal timer stores the current counters in this field. +		 * +		 * Index number corresponds to @enum drm_i915_pmu_engine_sample.  		 */ -#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1) -		struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX]; +		struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_COUNT];  	} pmu;  	/* diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index d2e003d8f3db..5170a0f5fe7b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -494,7 +494,7 @@ skl_program_plane(struct intel_plane *plane,  	keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha); -	keymsk = key->channel_mask & 0x3ffffff; +	keymsk = key->channel_mask & 0x7ffffff;  	if (alpha < 0xff)  		keymsk |= PLANE_KEYMSK_ALPHA_ENABLE; diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 2c5bbe317353..e31e263cf86b 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -643,8 +643,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)  		int bus_format;  		ret = of_property_read_u32(child, "reg", &i); -		if (ret || i < 0 || i > 1) -			return -EINVAL; +		if (ret || i < 0 || i > 1) { +			ret = -EINVAL; +			goto free_child; +		}  		if (!of_device_is_available(child))  			continue; @@ -657,7 +659,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)  		channel = &imx_ldb->channel[i];  		channel->ldb = imx_ldb;  		channel->chno = i; -		channel->child = child;  		/*  		 * The output port is port@4 with an external 4-port mux or @@ -667,13 +668,13 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)  						  imx_ldb->lvds_mux ? 4 : 2, 0,  						  &channel->panel, &channel->bridge);  		if (ret && ret != -ENODEV) -			return ret; +			goto free_child;  		/* panel ddc only if there is no bridge */  		if (!channel->bridge) {  			ret = imx_ldb_panel_ddc(dev, channel, child);  			if (ret) -				return ret; +				goto free_child;  		}  		bus_format = of_get_bus_format(dev, child); @@ -689,18 +690,26 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)  		if (bus_format < 0) {  			dev_err(dev, "could not determine data mapping: %d\n",  				bus_format); -			return bus_format; +			ret = bus_format; +			goto free_child;  		}  		channel->bus_format = bus_format; +		channel->child = child;  		ret = imx_ldb_register(drm, channel); -		if (ret) -			return ret; +		if (ret) { +			channel->child = NULL; +			goto free_child; +		}  	}  	dev_set_drvdata(dev, imx_ldb);  	return 0; + +free_child: +	of_node_put(child); +	return ret;  }  static void imx_ldb_unbind(struct device *dev, struct device *master, diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index c390924de93d..21e964f6ab5c 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -370,9 +370,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,  	if (ret)  		return ret; -	/* CRTC should be enabled */ +	/* nothing to check when disabling or disabled */  	if (!crtc_state->enable) -		return -EINVAL; +		return 0;  	switch (plane->type) {  	case DRM_PLANE_TYPE_PRIMARY: diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index 75d97f1b2e8f..4f5c67f70c4d 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c @@ -46,7 +46,6 @@ struct meson_crtc {  	struct drm_crtc base;  	struct drm_pending_vblank_event *event;  	struct meson_drm *priv; -	bool enabled;  };  #define to_meson_crtc(x) container_of(x, struct meson_crtc, base) @@ -82,7 +81,8 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {  }; -static void meson_crtc_enable(struct drm_crtc *crtc) +static void meson_crtc_atomic_enable(struct drm_crtc *crtc, +				     struct drm_crtc_state *old_state)  {  	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);  	struct drm_crtc_state *crtc_state = crtc->state; @@ -108,20 +108,6 @@ static void meson_crtc_enable(struct drm_crtc *crtc)  	drm_crtc_vblank_on(crtc); -	meson_crtc->enabled = true; -} - -static void meson_crtc_atomic_enable(struct drm_crtc *crtc, -				     struct drm_crtc_state *old_state) -{ -	struct meson_crtc *meson_crtc = to_meson_crtc(crtc); -	struct meson_drm *priv = meson_crtc->priv; - -	DRM_DEBUG_DRIVER("\n"); - -	if (!meson_crtc->enabled) -		meson_crtc_enable(crtc); -  	priv->viu.osd1_enabled = true;  } @@ -153,8 +139,6 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,  		crtc->state->event = NULL;  	} - -	meson_crtc->enabled = false;  }  static void meson_crtc_atomic_begin(struct drm_crtc *crtc, @@ -163,9 +147,6 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,  	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);  	unsigned long flags; -	if (crtc->state->enable && !meson_crtc->enabled) -		meson_crtc_enable(crtc); -  	if (crtc->state->event) {  		WARN_ON(drm_crtc_vblank_get(crtc) != 0); diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 3ee4d4a4ecba..12ff47b13668 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -75,6 +75,10 @@ static const struct drm_mode_config_funcs meson_mode_config_funcs = {  	.fb_create           = drm_gem_fb_create,  }; +static const struct drm_mode_config_helper_funcs meson_mode_config_helpers = { +	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, +}; +  static irqreturn_t meson_irq(int irq, void *arg)  {  	struct drm_device *dev = arg; @@ -266,6 +270,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)  	drm->mode_config.max_width = 3840;  	drm->mode_config.max_height = 2160;  	drm->mode_config.funcs = &meson_mode_config_funcs; +	drm->mode_config.helper_private	= &meson_mode_config_helpers;  	/* Hardware Initialization */ @@ -388,8 +393,10 @@ static int meson_probe_remote(struct platform_device *pdev,  		remote_node = of_graph_get_remote_port_parent(ep);  		if (!remote_node ||  		    remote_node == parent || /* Ignore parent endpoint */ -		    !of_device_is_available(remote_node)) +		    !of_device_is_available(remote_node)) { +			of_node_put(remote_node);  			continue; +		}  		count += meson_probe_remote(pdev, match, remote, remote_node); @@ -408,10 +415,13 @@ static int meson_drv_probe(struct platform_device *pdev)  	for_each_endpoint_of_node(np, ep) {  		remote = of_graph_get_remote_port_parent(ep); -		if (!remote || !of_device_is_available(remote)) +		if (!remote || !of_device_is_available(remote)) { +			of_node_put(remote);  			continue; +		}  		count += meson_probe_remote(pdev, &match, np, remote); +		of_node_put(remote);  	}  	if (count && !match) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 5beb83d1cf87..ce1b3cc4bf6d 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -944,7 +944,7 @@ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq)  	np = dev_pm_opp_get_of_node(opp);  	if (np) { -		of_property_read_u32(np, "qcom,level", &val); +		of_property_read_u32(np, "opp-level", &val);  		of_node_put(np);  	} diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 2e4372ef17a3..2cfee1a4fe0b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -765,7 +765,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,  	adreno_gpu->rev = config->rev;  	adreno_gpu_config.ioname = "kgsl_3d0_reg_memory"; -	adreno_gpu_config.irqname = "kgsl_3d0_irq";  	adreno_gpu_config.va_start = SZ_16M;  	adreno_gpu_config.va_end = 0xffffffff; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index fd75870eb17f..6aefcd6db46b 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -365,19 +365,6 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,  			&pdpu->pipe_qos_cfg);  } -static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) -{ -	struct dpu_plane *pdpu = to_dpu_plane(plane); -	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); - -	if (!pdpu->is_rt_pipe) -		return; - -	pm_runtime_get_sync(&dpu_kms->pdev->dev); -	_dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL); -	pm_runtime_put_sync(&dpu_kms->pdev->dev); -} -  /**   * _dpu_plane_set_ot_limit - set OT limit for the given plane   * @plane:		Pointer to drm plane @@ -1248,6 +1235,19 @@ static void dpu_plane_reset(struct drm_plane *plane)  }  #ifdef CONFIG_DEBUG_FS +static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) +{ +	struct dpu_plane *pdpu = to_dpu_plane(plane); +	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane); + +	if (!pdpu->is_rt_pipe) +		return; + +	pm_runtime_get_sync(&dpu_kms->pdev->dev); +	_dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL); +	pm_runtime_put_sync(&dpu_kms->pdev->dev); +} +  static ssize_t _dpu_plane_danger_read(struct file *file,  			char __user *buff, size_t count, loff_t *ppos)  { diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 9cd6a96c6bf2..927e5d86f7c1 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -250,7 +250,8 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace,  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,  		struct msm_gem_vma *vma);  int msm_gem_map_vma(struct msm_gem_address_space *aspace, -		struct msm_gem_vma *vma, struct sg_table *sgt, int npages); +		struct msm_gem_vma *vma, int prot, +		struct sg_table *sgt, int npages);  void msm_gem_close_vma(struct msm_gem_address_space *aspace,  		struct msm_gem_vma *vma); @@ -333,6 +334,7 @@ void msm_gem_kernel_put(struct drm_gem_object *bo,  struct drm_gem_object *msm_gem_import(struct drm_device *dev,  		struct dma_buf *dmabuf, struct sg_table *sgt); +__printf(2, 3)  void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...);  int msm_framebuffer_prepare(struct drm_framebuffer *fb, @@ -396,12 +398,14 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);  int msm_debugfs_late_init(struct drm_device *dev);  int msm_rd_debugfs_init(struct drm_minor *minor);  void msm_rd_debugfs_cleanup(struct msm_drm_private *priv); +__printf(3, 4)  void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,  		const char *fmt, ...);  int msm_perf_debugfs_init(struct drm_minor *minor);  void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);  #else  static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } +__printf(3, 4)  static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,  		const char *fmt, ...) {}  static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {} diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 51a95da694d8..c8886d3071fa 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -391,6 +391,10 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,  	struct msm_gem_object *msm_obj = to_msm_bo(obj);  	struct msm_gem_vma *vma;  	struct page **pages; +	int prot = IOMMU_READ; + +	if (!(msm_obj->flags & MSM_BO_GPU_READONLY)) +		prot |= IOMMU_WRITE;  	WARN_ON(!mutex_is_locked(&msm_obj->lock)); @@ -405,8 +409,8 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,  	if (IS_ERR(pages))  		return PTR_ERR(pages); -	return msm_gem_map_vma(aspace, vma, msm_obj->sgt, -			obj->size >> PAGE_SHIFT); +	return msm_gem_map_vma(aspace, vma, prot, +			msm_obj->sgt, obj->size >> PAGE_SHIFT);  }  /* get iova and pin it. Should have a matching put */ diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 557360788084..49c04829cf34 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -68,7 +68,8 @@ void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,  int  msm_gem_map_vma(struct msm_gem_address_space *aspace, -		struct msm_gem_vma *vma, struct sg_table *sgt, int npages) +		struct msm_gem_vma *vma, int prot, +		struct sg_table *sgt, int npages)  {  	unsigned size = npages << PAGE_SHIFT;  	int ret = 0; @@ -86,7 +87,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,  	if (aspace->mmu)  		ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt, -				size, IOMMU_READ | IOMMU_WRITE); +				size, prot);  	if (ret)  		vma->mapped = false; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 5f3eff304355..10babd18e286 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -900,7 +900,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,  	}  	/* Get Interrupt: */ -	gpu->irq = platform_get_irq_byname(pdev, config->irqname); +	gpu->irq = platform_get_irq(pdev, 0);  	if (gpu->irq < 0) {  		ret = gpu->irq;  		DRM_DEV_ERROR(drm->dev, "failed to get irq: %d\n", ret); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index efb49bb64191..ca17086f72c9 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -31,7 +31,6 @@ struct msm_gpu_state;  struct msm_gpu_config {  	const char *ioname; -	const char *irqname;  	uint64_t va_start;  	uint64_t va_end;  	unsigned int nr_rings; @@ -63,7 +62,7 @@ struct msm_gpu_funcs {  	struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu);  	void (*recover)(struct msm_gpu *gpu);  	void (*destroy)(struct msm_gpu *gpu); -#ifdef CONFIG_DEBUG_FS +#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)  	/* show GPU status in debugfs: */  	void (*show)(struct msm_gpu *gpu, struct msm_gpu_state *state,  			struct drm_printer *p); diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index 90e9d0a48dc0..d21172933d92 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c @@ -115,7 +115,9 @@ static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)  		char *fptr = &fifo->buf[fifo->head];  		int n; -		wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0); +		wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open); +		if (!rd->open) +			return;  		/* Note that smp_load_acquire() is not strictly required  		 * as CIRC_SPACE_TO_END() does not access the tail more @@ -213,7 +215,10 @@ out:  static int rd_release(struct inode *inode, struct file *file)  {  	struct msm_rd_state *rd = inode->i_private; +  	rd->open = false; +	wake_up_all(&rd->fifo_event); +  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 5f5be6368aed..c7a94c94dbf3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -253,6 +253,9 @@ nouveau_backlight_init(struct drm_connector *connector)  	case NV_DEVICE_INFO_V0_FERMI:  	case NV_DEVICE_INFO_V0_KEPLER:  	case NV_DEVICE_INFO_V0_MAXWELL: +	case NV_DEVICE_INFO_V0_PASCAL: +	case NV_DEVICE_INFO_V0_VOLTA: +	case NV_DEVICE_INFO_V0_TURING:  		ret = nv50_backlight_init(nv_encoder, &props, &ops);  		break;  	default: diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index bfbc9341e0c2..d9edb5785813 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2435,6 +2435,38 @@ nv140_chipset = {  };  static const struct nvkm_device_chip +nv162_chipset = { +	.name = "TU102", +	.bar = tu104_bar_new, +	.bios = nvkm_bios_new, +	.bus = gf100_bus_new, +	.devinit = tu104_devinit_new, +	.fault = tu104_fault_new, +	.fb = gv100_fb_new, +	.fuse = gm107_fuse_new, +	.gpio = gk104_gpio_new, +	.i2c = gm200_i2c_new, +	.ibus = gm200_ibus_new, +	.imem = nv50_instmem_new, +	.ltc = gp102_ltc_new, +	.mc = tu104_mc_new, +	.mmu = tu104_mmu_new, +	.pci = gp100_pci_new, +	.pmu = gp102_pmu_new, +	.therm = gp100_therm_new, +	.timer = gk20a_timer_new, +	.top = gk104_top_new, +	.ce[0] = tu104_ce_new, +	.ce[1] = tu104_ce_new, +	.ce[2] = tu104_ce_new, +	.ce[3] = tu104_ce_new, +	.ce[4] = tu104_ce_new, +	.disp = tu104_disp_new, +	.dma = gv100_dma_new, +	.fifo = tu104_fifo_new, +}; + +static const struct nvkm_device_chip  nv164_chipset = {  	.name = "TU104",  	.bar = tu104_bar_new, @@ -2950,6 +2982,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,  		case 0x138: device->chip = &nv138_chipset; break;  		case 0x13b: device->chip = &nv13b_chipset; break;  		case 0x140: device->chip = &nv140_chipset; break; +		case 0x162: device->chip = &nv162_chipset; break;  		case 0x164: device->chip = &nv164_chipset; break;  		case 0x166: device->chip = &nv166_chipset; break;  		default: diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c index 816ccaedfc73..8675613e142b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c @@ -22,6 +22,7 @@  #include <engine/falcon.h>  #include <core/gpuobj.h> +#include <subdev/mc.h>  #include <subdev/timer.h>  #include <engine/fifo.h> @@ -107,8 +108,10 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)  		}  	} -	nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000); -	nvkm_wr32(device, base + 0x014, 0xffffffff); +	if (nvkm_mc_enabled(device, engine->subdev.index)) { +		nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000); +		nvkm_wr32(device, base + 0x014, 0xffffffff); +	}  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index 3695cde669f8..07914e36939e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -132,11 +132,12 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)  			duty = nvkm_therm_update_linear(therm);  			break;  		case NVBIOS_THERM_FAN_OTHER: -			if (therm->cstate) +			if (therm->cstate) {  				duty = therm->cstate; -			else +				poll = false; +			} else {  				duty = nvkm_therm_update_linear_fallback(therm); -			poll = false; +			}  			break;  		}  		immd = false; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 00a9c2ab9e6c..64fb788b6647 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -1406,7 +1406,7 @@ static void dsi_pll_disable(struct dss_pll *pll)  static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)  { -	struct dsi_data *dsi = p; +	struct dsi_data *dsi = s->private;  	struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;  	enum dss_clk_source dispc_clk_src, dsi_clk_src;  	int dsi_module = dsi->module_id; @@ -1467,7 +1467,7 @@ static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)  #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS  static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)  { -	struct dsi_data *dsi = p; +	struct dsi_data *dsi = s->private;  	unsigned long flags;  	struct dsi_irq_stats stats; @@ -1558,7 +1558,7 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)  static int dsi_dump_dsi_regs(struct seq_file *s, void *p)  { -	struct dsi_data *dsi = p; +	struct dsi_data *dsi = s->private;  	if (dsi_runtime_get(dsi))  		return 0; @@ -4751,6 +4751,17 @@ static int dsi_set_config(struct omap_dss_device *dssdev,  	dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;  	dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;  	dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH; +	/* +	 * HACK: These flags should be handled through the omap_dss_device bus +	 * flags, but this will only be possible when the DSI encoder will be +	 * converted to the omapdrm-managed encoder model. +	 */ +	dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE; +	dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE; +	dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW; +	dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH; +	dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE; +	dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;  	dss_mgr_set_timings(&dsi->output, &dsi->vm); @@ -5083,15 +5094,15 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)  	snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1);  	dsi->debugfs.regs = dss_debugfs_create_file(dss, name, -						    dsi_dump_dsi_regs, &dsi); +						    dsi_dump_dsi_regs, dsi);  #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS  	snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1);  	dsi->debugfs.irqs = dss_debugfs_create_file(dss, name, -						    dsi_dump_dsi_irqs, &dsi); +						    dsi_dump_dsi_irqs, dsi);  #endif  	snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1);  	dsi->debugfs.clks = dss_debugfs_create_file(dss, name, -						    dsi_dump_dsi_clocks, &dsi); +						    dsi_dump_dsi_clocks, dsi);  	return 0;  } @@ -5104,8 +5115,6 @@ static void dsi_unbind(struct device *dev, struct device *master, void *data)  	dss_debugfs_remove_file(dsi->debugfs.irqs);  	dss_debugfs_remove_file(dsi->debugfs.regs); -	of_platform_depopulate(dev); -  	WARN_ON(dsi->scp_clk_refcount > 0);  	dss_pll_unregister(&dsi->pll); @@ -5457,6 +5466,8 @@ static int dsi_remove(struct platform_device *pdev)  	dsi_uninit_output(dsi); +	of_platform_depopulate(&pdev->dev); +  	pm_runtime_disable(&pdev->dev);  	if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) { diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 13c8a662f9b4..ccb090f3ab30 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -250,14 +250,10 @@ static struct drm_driver qxl_driver = {  #if defined(CONFIG_DEBUG_FS)  	.debugfs_init = qxl_debugfs_init,  #endif -	.prime_handle_to_fd = drm_gem_prime_handle_to_fd, -	.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_pin = qxl_gem_prime_pin,  	.gem_prime_unpin = qxl_gem_prime_unpin, -	.gem_prime_get_sg_table = qxl_gem_prime_get_sg_table, -	.gem_prime_import_sg_table = qxl_gem_prime_import_sg_table,  	.gem_prime_vmap = qxl_gem_prime_vmap,  	.gem_prime_vunmap = qxl_gem_prime_vunmap,  	.gem_prime_mmap = qxl_gem_prime_mmap, diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c index a55dece118b2..df65d3c1a7b8 100644 --- a/drivers/gpu/drm/qxl/qxl_prime.c +++ b/drivers/gpu/drm/qxl/qxl_prime.c @@ -38,20 +38,6 @@ void qxl_gem_prime_unpin(struct drm_gem_object *obj)  	WARN_ONCE(1, "not implemented");  } -struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj) -{ -	WARN_ONCE(1, "not implemented"); -	return ERR_PTR(-ENOSYS); -} - -struct drm_gem_object *qxl_gem_prime_import_sg_table( -	struct drm_device *dev, struct dma_buf_attachment *attach, -	struct sg_table *table) -{ -	WARN_ONCE(1, "not implemented"); -	return ERR_PTR(-ENOSYS); -} -  void *qxl_gem_prime_vmap(struct drm_gem_object *obj)  {  	WARN_ONCE(1, "not implemented"); diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index d587779a80b4..a97294ac96d5 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -5676,7 +5676,7 @@ int ci_dpm_init(struct radeon_device *rdev)  	u16 data_offset, size;  	u8 frev, crev;  	struct ci_power_info *pi; -	enum pci_bus_speed speed_cap; +	enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;  	struct pci_dev *root = rdev->pdev->bus->self;  	int ret; @@ -5685,7 +5685,8 @@ int ci_dpm_init(struct radeon_device *rdev)  		return -ENOMEM;  	rdev->pm.dpm.priv = pi; -	speed_cap = pcie_get_speed_cap(root); +	if (!pci_is_root_bus(rdev->pdev->bus)) +		speed_cap = pcie_get_speed_cap(root);  	if (speed_cap == PCI_SPEED_UNKNOWN) {  		pi->sys_pcie_mask = 0;  	} else { diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 8fb60b3af015..0a785ef0ab66 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -6899,7 +6899,7 @@ int si_dpm_init(struct radeon_device *rdev)  	struct ni_power_info *ni_pi;  	struct si_power_info *si_pi;  	struct atom_clock_dividers dividers; -	enum pci_bus_speed speed_cap; +	enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;  	struct pci_dev *root = rdev->pdev->bus->self;  	int ret; @@ -6911,7 +6911,8 @@ int si_dpm_init(struct radeon_device *rdev)  	eg_pi = &ni_pi->eg;  	pi = &eg_pi->rv7xx; -	speed_cap = pcie_get_speed_cap(root); +	if (!pci_is_root_bus(rdev->pdev->bus)) +		speed_cap = pcie_get_speed_cap(root);  	if (speed_cap == PCI_SPEED_UNKNOWN) {  		si_pi->sys_pcie_mask = 0;  	} else { diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index 96ac1458a59c..c0351abf83a3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -1,17 +1,8 @@ -//SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: GPL-2.0  /*   * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd   * Author:   *      Sandy Huang <hjc@rock-chips.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details.   */  #include <drm/drmP.h> @@ -113,8 +104,10 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,  		child_count++;  		ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id,  						  &panel, &bridge); -		if (!ret) +		if (!ret) { +			of_node_put(endpoint);  			break; +		}  	}  	of_node_put(port); diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.h b/drivers/gpu/drm/rockchip/rockchip_rgb.h index 38b52e63b2b0..27b9635124bc 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.h +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.h @@ -1,17 +1,8 @@ -//SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0 */  /*   * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd   * Author:   *      Sandy Huang <hjc@rock-chips.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details.   */  #ifdef CONFIG_ROCKCHIP_RGB diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 4463d3826ecb..e2942c9a11a7 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -440,13 +440,10 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)  	while ((entity->dependency =  			sched->ops->dependency(sched_job, entity))) { +		trace_drm_sched_job_wait_dep(sched_job, entity->dependency); -		if (drm_sched_entity_add_dependency_cb(entity)) { - -			trace_drm_sched_job_wait_dep(sched_job, -						     entity->dependency); +		if (drm_sched_entity_add_dependency_cb(entity))  			return NULL; -		}  	}  	/* skip jobs from entity that marked guilty */ diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 9e9255ee59cd..a021bab11a4f 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -786,17 +786,18 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,  		remote = of_graph_get_remote_port_parent(ep);  		if (!remote)  			continue; +		of_node_put(remote);  		/* does this node match any registered engines? */  		list_for_each_entry(frontend, &drv->frontend_list, list) {  			if (remote == frontend->node) { -				of_node_put(remote);  				of_node_put(port); +				of_node_put(ep);  				return frontend;  			}  		}  	} - +	of_node_put(port);  	return ERR_PTR(-EINVAL);  } diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index 061d2e0d9011..416da5376701 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c @@ -92,6 +92,8 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)  	val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);  	val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;  	writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG); + +	clk_disable_unprepare(hdmi->tmds_clk);  }  static void sun4i_hdmi_enable(struct drm_encoder *encoder) @@ -102,6 +104,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)  	DRM_DEBUG_DRIVER("Enabling the HDMI Output\n"); +	clk_prepare_enable(hdmi->tmds_clk); +  	sun4i_hdmi_setup_avi_infoframes(hdmi, mode);  	val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);  	val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END); diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 0420f5c978b9..cf45d0f940f9 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -761,6 +761,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,  			return PTR_ERR(tcon->sclk0);  		}  	} +	clk_prepare_enable(tcon->sclk0);  	if (tcon->quirks->has_channel_1) {  		tcon->sclk1 = devm_clk_get(dev, "tcon-ch1"); @@ -775,6 +776,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,  static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)  { +	clk_disable_unprepare(tcon->sclk0);  	clk_disable_unprepare(tcon->clk);  } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index f7f32a885af7..2d1aaca49105 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -127,14 +127,10 @@ static struct drm_driver driver = {  #if defined(CONFIG_DEBUG_FS)  	.debugfs_init = virtio_gpu_debugfs_init,  #endif -	.prime_handle_to_fd = drm_gem_prime_handle_to_fd, -	.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_pin = virtgpu_gem_prime_pin,  	.gem_prime_unpin = virtgpu_gem_prime_unpin, -	.gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table, -	.gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,  	.gem_prime_vmap = virtgpu_gem_prime_vmap,  	.gem_prime_vunmap = virtgpu_gem_prime_vunmap,  	.gem_prime_mmap = virtgpu_gem_prime_mmap, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 1deb41d42ea4..0c15000f926e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -372,10 +372,6 @@ int virtio_gpu_object_wait(struct virtio_gpu_object *bo, bool no_wait);  /* virtgpu_prime.c */  int virtgpu_gem_prime_pin(struct drm_gem_object *obj);  void virtgpu_gem_prime_unpin(struct drm_gem_object *obj); -struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj); -struct drm_gem_object *virtgpu_gem_prime_import_sg_table( -	struct drm_device *dev, struct dma_buf_attachment *attach, -	struct sg_table *sgt);  void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj);  void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);  int virtgpu_gem_prime_mmap(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 86ce0ae93f59..c59ec34c80a5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -39,20 +39,6 @@ void virtgpu_gem_prime_unpin(struct drm_gem_object *obj)  	WARN_ONCE(1, "not implemented");  } -struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj) -{ -	WARN_ONCE(1, "not implemented"); -	return ERR_PTR(-ENODEV); -} - -struct drm_gem_object *virtgpu_gem_prime_import_sg_table( -	struct drm_device *dev, struct dma_buf_attachment *attach, -	struct sg_table *table) -{ -	WARN_ONCE(1, "not implemented"); -	return ERR_PTR(-ENODEV); -} -  void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj)  {  	struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c index 9d9e8146db90..d7b409a3c0f8 100644 --- a/drivers/gpu/drm/vkms/vkms_crc.c +++ b/drivers/gpu/drm/vkms/vkms_crc.c @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ +  #include "vkms_drv.h"  #include <linux/crc32.h>  #include <drm/drm_atomic.h> diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 177bbcb38306..eb56ee893761 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -1,10 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+  #include "vkms_drv.h"  #include <drm/drm_atomic_helper.h> diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 83087877565c..7dcbecb5fac2 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -1,9 +1,4 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+  /**   * DOC: vkms (Virtual Kernel Modesetting) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index e4469cd3d254..81f1cfbeb936 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +  #ifndef _VKMS_DRV_H_  #define _VKMS_DRV_H_ diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c index 80311daed47a..138b0bb325cf 100644 --- a/drivers/gpu/drm/vkms/vkms_gem.c +++ b/drivers/gpu/drm/vkms/vkms_gem.c @@ -1,10 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+  #include <linux/shmem_fs.h> diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 271a0eb9042c..4173e4f48334 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -1,10 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+  #include "vkms_drv.h"  #include <drm/drm_crtc_helper.h> diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 418817600ad1..0e67d2d42f0c 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -1,10 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+  #include "vkms_drv.h"  #include <drm/drm_plane_helper.h> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 25afb1d594e3..7ef5dcb06104 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -26,6 +26,7 @@   **************************************************************************/  #include <linux/module.h>  #include <linux/console.h> +#include <linux/dma-mapping.h>  #include <drm/drmP.h>  #include "vmwgfx_drv.h" @@ -34,7 +35,6 @@  #include <drm/ttm/ttm_placement.h>  #include <drm/ttm/ttm_bo_driver.h>  #include <drm/ttm/ttm_module.h> -#include <linux/intel-iommu.h>  #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"  #define VMWGFX_CHIP_SVGAII 0 @@ -546,6 +546,21 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)  }  /** + * vmw_assume_iommu - Figure out whether coherent dma-remapping might be + * taking place. + * @dev: Pointer to the struct drm_device. + * + * Return: true if iommu present, false otherwise. + */ +static bool vmw_assume_iommu(struct drm_device *dev) +{ +	const struct dma_map_ops *ops = get_dma_ops(dev->dev); + +	return !dma_is_direct(ops) && ops && +		ops->map_page != dma_direct_map_page; +} + +/**   * vmw_dma_select_mode - Determine how DMA mappings should be set up for this   * system.   * @@ -565,55 +580,27 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)  		[vmw_dma_alloc_coherent] = "Using coherent TTM pages.",  		[vmw_dma_map_populate] = "Keeping DMA mappings.",  		[vmw_dma_map_bind] = "Giving up DMA mappings early."}; -#ifdef CONFIG_X86 -	const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev); -#ifdef CONFIG_INTEL_IOMMU -	if (intel_iommu_enabled) { +	if (vmw_force_coherent) +		dev_priv->map_mode = vmw_dma_alloc_coherent; +	else if (vmw_assume_iommu(dev_priv->dev))  		dev_priv->map_mode = vmw_dma_map_populate; -		goto out_fixup; -	} -#endif - -	if (!(vmw_force_iommu || vmw_force_coherent)) { +	else if (!vmw_force_iommu)  		dev_priv->map_mode = vmw_dma_phys; -		DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); -		return 0; -	} - -	dev_priv->map_mode = vmw_dma_map_populate; - -	if (dma_ops && dma_ops->sync_single_for_cpu) +	else if (IS_ENABLED(CONFIG_SWIOTLB) && swiotlb_nr_tbl())  		dev_priv->map_mode = vmw_dma_alloc_coherent; -#ifdef CONFIG_SWIOTLB -	if (swiotlb_nr_tbl() == 0) +	else  		dev_priv->map_mode = vmw_dma_map_populate; -#endif -#ifdef CONFIG_INTEL_IOMMU -out_fixup: -#endif -	if (dev_priv->map_mode == vmw_dma_map_populate && -	    vmw_restrict_iommu) +	if (dev_priv->map_mode == vmw_dma_map_populate && vmw_restrict_iommu)  		dev_priv->map_mode = vmw_dma_map_bind; -	if (vmw_force_coherent) -		dev_priv->map_mode = vmw_dma_alloc_coherent; - -#if !defined(CONFIG_SWIOTLB) && !defined(CONFIG_INTEL_IOMMU) -	/* -	 * No coherent page pool -	 */ -	if (dev_priv->map_mode == vmw_dma_alloc_coherent) +	/* No TTM coherent page pool? FIXME: Ask TTM instead! */ +        if (!(IS_ENABLED(CONFIG_SWIOTLB) || IS_ENABLED(CONFIG_INTEL_IOMMU)) && +	    (dev_priv->map_mode == vmw_dma_alloc_coherent))  		return -EINVAL; -#endif - -#else /* CONFIG_X86 */ -	dev_priv->map_mode = vmw_dma_map_populate; -#endif /* CONFIG_X86 */  	DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); -  	return 0;  } @@ -625,24 +612,20 @@ out_fixup:   * With 32-bit we can only handle 32 bit PFNs. Optionally set that   * restriction also for 64-bit systems.   */ -#ifdef CONFIG_INTEL_IOMMU  static int vmw_dma_masks(struct vmw_private *dev_priv)  {  	struct drm_device *dev = dev_priv->dev; +	int ret = 0; -	if (intel_iommu_enabled && +	ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)); +	if (dev_priv->map_mode != vmw_dma_phys &&  	    (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {  		DRM_INFO("Restricting DMA addresses to 44 bits.\n"); -		return dma_set_mask(dev->dev, DMA_BIT_MASK(44)); +		return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));  	} -	return 0; -} -#else -static int vmw_dma_masks(struct vmw_private *dev_priv) -{ -	return 0; + +	return ret;  } -#endif  static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)  { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index f2d13a72c05d..88b8178d4687 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -3570,7 +3570,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,  		*p_fence = NULL;  	} -	return 0; +	return ret;  }  /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b351fb5214d3..ed2f67822f45 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1646,7 +1646,7 @@ static int vmw_kms_check_topology(struct drm_device *dev,  		struct drm_connector_state *conn_state;  		struct vmw_connector_state *vmw_conn_state; -		if (!du->pref_active) { +		if (!du->pref_active && new_crtc_state->enable) {  			ret = -EINVAL;  			goto clean;  		} @@ -2554,8 +2554,8 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,  				      user_fence_rep)  {  	struct vmw_fence_obj *fence = NULL; -	uint32_t handle; -	int ret; +	uint32_t handle = 0; +	int ret = 0;  	if (file_priv || user_fence_rep || vmw_validation_has_bos(ctx) ||  	    out_fence) diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 474b00e19697..0a7d4395d427 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -898,8 +898,8 @@ static struct ipu_devtype ipu_type_imx51 = {  	.cpmem_ofs = 0x1f000000,  	.srm_ofs = 0x1f040000,  	.tpm_ofs = 0x1f060000, -	.csi0_ofs = 0x1f030000, -	.csi1_ofs = 0x1f038000, +	.csi0_ofs = 0x1e030000, +	.csi1_ofs = 0x1e038000,  	.ic_ofs = 0x1e020000,  	.disp0_ofs = 0x1e040000,  	.disp1_ofs = 0x1e048000, @@ -914,8 +914,8 @@ static struct ipu_devtype ipu_type_imx53 = {  	.cpmem_ofs = 0x07000000,  	.srm_ofs = 0x07040000,  	.tpm_ofs = 0x07060000, -	.csi0_ofs = 0x07030000, -	.csi1_ofs = 0x07038000, +	.csi0_ofs = 0x06030000, +	.csi1_ofs = 0x06038000,  	.ic_ofs = 0x06020000,  	.disp0_ofs = 0x06040000,  	.disp1_ofs = 0x06048000, diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c index 2f8db9d62551..4a28f3fbb0a2 100644 --- a/drivers/gpu/ipu-v3/ipu-pre.c +++ b/drivers/gpu/ipu-v3/ipu-pre.c @@ -106,6 +106,7 @@ struct ipu_pre {  	void			*buffer_virt;  	bool			in_use;  	unsigned int		safe_window_end; +	unsigned int		last_bufaddr;  };  static DEFINE_MUTEX(ipu_pre_list_mutex); @@ -185,6 +186,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,  	writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);  	writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); +	pre->last_bufaddr = bufaddr;  	val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |  	      IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) | @@ -242,7 +244,11 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)  	unsigned short current_yblock;  	u32 val; +	if (bufaddr == pre->last_bufaddr) +		return; +  	writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); +	pre->last_bufaddr = bufaddr;  	do {  		if (time_after(jiffies, timeout)) { diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig index b677e5d524e6..d5f1d8e1c6f8 100644 --- a/drivers/gpu/vga/Kconfig +++ b/drivers/gpu/vga/Kconfig @@ -21,6 +21,7 @@ config VGA_SWITCHEROO  	bool "Laptop Hybrid Graphics - GPU switching support"  	depends on X86  	depends on ACPI +	depends on PCI  	select VGA_ARB  	help  	  Many laptops released in 2008/9/10 have two GPUs with a multiplexer  | 

