diff options
Diffstat (limited to 'drivers/gpu')
105 files changed, 1870 insertions, 917 deletions
diff --git a/drivers/gpu/drm/amd/acp/Makefile b/drivers/gpu/drm/amd/acp/Makefile index 8363cb57915b..8a08e81ee90d 100644 --- a/drivers/gpu/drm/amd/acp/Makefile +++ b/drivers/gpu/drm/amd/acp/Makefile @@ -3,6 +3,4 @@  # of AMDSOC/AMDGPU drm driver.  # It provides the HW control for ACP related functionalities. -subdir-ccflags-y += -I$(AMDACPPATH)/ -I$(AMDACPPATH)/include -  AMD_ACP_FILES := $(AMDACPPATH)/acp_hw.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index d2d0f60ff36d..99424cb8020b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -240,6 +240,8 @@ free_partial_kdata:  	for (; i >= 0; i--)  		drm_free_large(p->chunks[i].kdata);  	kfree(p->chunks); +	p->chunks = NULL; +	p->nchunks = 0;  put_ctx:  	amdgpu_ctx_put(p->ctx);  free_chunk: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6abb238b25c9..de0cf3315484 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -475,7 +475,7 @@ static int amdgpu_wb_init(struct amdgpu_device *adev)  	int r;  	if (adev->wb.wb_obj == NULL) { -		r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * 4, +		r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t),  					    PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,  					    &adev->wb.wb_obj, &adev->wb.gpu_addr,  					    (void **)&adev->wb.wb); @@ -488,7 +488,7 @@ static int amdgpu_wb_init(struct amdgpu_device *adev)  		memset(&adev->wb.used, 0, sizeof(adev->wb.used));  		/* clear wb memory */ -		memset((char *)adev->wb.wb, 0, AMDGPU_GPU_PAGE_SIZE); +		memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t));  	}  	return 0; @@ -2094,8 +2094,11 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)  	}  	r = amdgpu_late_init(adev); -	if (r) +	if (r) { +		if (fbcon) +			console_unlock();  		return r; +	}  	/* pin cursors */  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -2587,7 +2590,7 @@ static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,  		use_bank = 0;  	} -	*pos &= 0x3FFFF; +	*pos &= (1UL << 22) - 1;  	if (use_bank) {  		if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || @@ -2663,7 +2666,7 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,  		use_bank = 0;  	} -	*pos &= 0x3FFFF; +	*pos &= (1UL << 22) - 1;  	if (use_bank) {  		if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 75fc376ba735..b76cd699eb0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -59,9 +59,10 @@   * - 3.7.0 - Add support for VCE clock list packet   * - 3.8.0 - Add support raster config init in the kernel   * - 3.9.0 - Add support for memory query info about VRAM and GTT. + * - 3.10.0 - Add support for new fences ioctl, new gem ioctl flags   */  #define KMS_DRIVER_MAJOR	3 -#define KMS_DRIVER_MINOR	9 +#define KMS_DRIVER_MINOR	10  #define KMS_DRIVER_PATCHLEVEL	0  int amdgpu_vram_limit = 0; @@ -420,6 +421,7 @@ static const struct pci_device_id pciidlist[] = {  	{0x1002, 0x6985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},  	{0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},  	{0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, +	{0x1002, 0x6995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},  	{0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},  	{0, 0, 0} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 51d759463384..106cf83c2e6b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -202,6 +202,27 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,  	bool kernel = false;  	int r; +	/* reject invalid gem flags */ +	if (args->in.domain_flags & ~(AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | +				      AMDGPU_GEM_CREATE_NO_CPU_ACCESS | +				      AMDGPU_GEM_CREATE_CPU_GTT_USWC | +				      AMDGPU_GEM_CREATE_VRAM_CLEARED| +				      AMDGPU_GEM_CREATE_SHADOW | +				      AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) { +		r = -EINVAL; +		goto error_unlock; +	} +	/* reject invalid gem domains */ +	if (args->in.domains & ~(AMDGPU_GEM_DOMAIN_CPU | +				 AMDGPU_GEM_DOMAIN_GTT | +				 AMDGPU_GEM_DOMAIN_VRAM | +				 AMDGPU_GEM_DOMAIN_GDS | +				 AMDGPU_GEM_DOMAIN_GWS | +				 AMDGPU_GEM_DOMAIN_OA)) { +		r = -EINVAL; +		goto error_unlock; +	} +  	/* create a gem object to contain this object in */  	if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS |  	    AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 31375bdde6f1..011800f621c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -788,7 +788,7 @@ static int sdma_v3_0_start(struct amdgpu_device *adev)  		}  	} -	/* disble sdma engine before programing it */ +	/* disable sdma engine before programing it */  	sdma_v3_0_ctx_switch_enable(adev, false);  	sdma_v3_0_enable(adev, false); diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index f55e45b52fbc..c5dec210d529 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -3464,6 +3464,16 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,  		    (adev->pdev->device == 0x6667)) {  			max_sclk = 75000;  		} +	} else if (adev->asic_type == CHIP_OLAND) { +		if ((adev->pdev->revision == 0xC7) || +		    (adev->pdev->revision == 0x80) || +		    (adev->pdev->revision == 0x81) || +		    (adev->pdev->revision == 0x83) || +		    (adev->pdev->revision == 0x87) || +		    (adev->pdev->device == 0x6604) || +		    (adev->pdev->device == 0x6605)) { +			max_sclk = 75000; +		}  	}  	if (rps->vce_active) { diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 50bdb24ef8d6..4a785d6acfb9 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1051,7 +1051,7 @@ static int vi_common_early_init(void *handle)  		/* rev0 hardware requires workarounds to support PG */  		adev->pg_flags = 0;  		if (adev->rev_id != 0x00) { -			adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG | +			adev->pg_flags |=  				AMD_PG_SUPPORT_GFX_SMG |  				AMD_PG_SUPPORT_GFX_PIPELINE |  				AMD_PG_SUPPORT_CP | diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c index 8cf71f3c6d0e..261b828ad590 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c @@ -178,7 +178,7 @@ int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)  	if (bgate) {  		cgs_set_powergating_state(hwmgr->device,  						AMD_IP_BLOCK_TYPE_VCE, -						AMD_PG_STATE_UNGATE); +						AMD_PG_STATE_GATE);  		cgs_set_clockgating_state(hwmgr->device,  				AMD_IP_BLOCK_TYPE_VCE,  				AMD_CG_STATE_GATE); diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 08e6a71f5d05..294b53697334 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -63,8 +63,7 @@ static void malidp_crtc_enable(struct drm_crtc *crtc)  	clk_prepare_enable(hwdev->pxlclk); -	/* mclk needs to be set to the same or higher rate than pxlclk */ -	clk_set_rate(hwdev->mclk, crtc->state->adjusted_mode.crtc_clock * 1000); +	/* We rely on firmware to set mclk to a sensible level. */  	clk_set_rate(hwdev->pxlclk, crtc->state->adjusted_mode.crtc_clock * 1000);  	hwdev->modeset(hwdev, &vm); diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 488aedf5b58d..9f5513006eee 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -83,7 +83,7 @@ static const struct malidp_layer malidp550_layers[] = {  	{ DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0 },  	{ DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE },  	{ DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0 }, -	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, 0 }, +	{ DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE },  };  #define MALIDP_DE_DEFAULT_PREFETCH_START	5 diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 414aada10fe5..d5aec082294c 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -37,6 +37,8 @@  #define   LAYER_V_VAL(x)		(((x) & 0x1fff) << 16)  #define MALIDP_LAYER_COMP_SIZE		0x010  #define MALIDP_LAYER_OFFSET		0x014 +#define MALIDP550_LS_ENABLE		0x01c +#define MALIDP550_LS_R1_IN_SIZE		0x020  /*   * This 4-entry look-up-table is used to determine the full 8-bit alpha value @@ -242,6 +244,11 @@ static void malidp_de_plane_update(struct drm_plane *plane,  			LAYER_V_VAL(plane->state->crtc_y),  			mp->layer->base + MALIDP_LAYER_OFFSET); +	if (mp->layer->id == DE_SMART) +		malidp_hw_write(mp->hwdev, +				LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h), +				mp->layer->base + MALIDP550_LS_R1_IN_SIZE); +  	/* first clear the rotation bits */  	val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);  	val &= ~LAYER_ROT_MASK; @@ -330,9 +337,16 @@ int malidp_de_planes_init(struct drm_device *drm)  		plane->hwdev = malidp->dev;  		plane->layer = &map->layers[i]; -		/* Skip the features which the SMART layer doesn't have */ -		if (id == DE_SMART) +		if (id == DE_SMART) { +			/* +			 * Enable the first rectangle in the SMART layer to be +			 * able to use it as a drm plane. +			 */ +			malidp_hw_write(malidp->dev, 1, +					plane->layer->base + MALIDP550_LS_ENABLE); +			/* Skip the features which the SMART layer doesn't have. */  			continue; +		}  		drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags);  		malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index aff6d4a84e99..b816067a65c5 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h @@ -84,6 +84,7 @@  /* Stride register offsets relative to Lx_BASE */  #define MALIDP_DE_LG_STRIDE		0x18  #define MALIDP_DE_LV_STRIDE0		0x18 +#define MALIDP550_DE_LS_R1_STRIDE	0x28  /* macros to set values into registers */  #define MALIDP_DE_H_FRONTPORCH(x)	(((x) & 0xfff) << 0) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index c8baab9bee0d..ba58f1b11d1e 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -148,6 +148,9 @@ static const struct edid_quirk {  	/* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */  	{ "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC }, + +	/* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/ +	{ "ETR", 13896, EDID_QUIRK_FORCE_8BPC },  };  /* diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index f6d4d9700734..324a688b3f30 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1260,9 +1260,9 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,  	 * to KMS, hence fail if different settings are requested.  	 */  	if (var->bits_per_pixel != fb->format->cpp[0] * 8 || -	    var->xres != fb->width || var->yres != fb->height || -	    var->xres_virtual != fb->width || var->yres_virtual != fb->height) { -		DRM_DEBUG("fb userspace requested width/height/bpp different than current fb " +	    var->xres > fb->width || var->yres > fb->height || +	    var->xres_virtual > fb->width || var->yres_virtual > fb->height) { +		DRM_DEBUG("fb requested width/height/bpp can't fit in current fb "  			  "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",  			  var->xres, var->yres, var->bits_per_pixel,  			  var->xres_virtual, var->yres_virtual, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 130d7d517a19..b78d9239e48f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -1311,15 +1311,15 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,  		goto out_pm_put;  	} +	mutex_lock(&gpu->lock); +  	fence = etnaviv_gpu_fence_alloc(gpu);  	if (!fence) {  		event_free(gpu, event);  		ret = -ENOMEM; -		goto out_pm_put; +		goto out_unlock;  	} -	mutex_lock(&gpu->lock); -  	gpu->event[event].fence = fence;  	submit->fence = fence->seqno;  	gpu->active_fence = submit->fence; @@ -1357,6 +1357,7 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,  	hangcheck_timer_reset(gpu);  	ret = 0; +out_unlock:  	mutex_unlock(&gpu->lock);  out_pm_put: diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 0fd6f7a18364..c0e8d3302292 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -68,6 +68,8 @@ struct decon_context {  	unsigned long			flags;  	unsigned long			out_type;  	int				first_win; +	spinlock_t			vblank_lock; +	u32				frame_id;  };  static const uint32_t decon_formats[] = { @@ -103,7 +105,7 @@ static int decon_enable_vblank(struct exynos_drm_crtc *crtc)  		if (ctx->out_type & IFTYPE_I80)  			val |= VIDINTCON0_FRAMEDONE;  		else -			val |= VIDINTCON0_INTFRMEN; +			val |= VIDINTCON0_INTFRMEN | VIDINTCON0_FRAMESEL_FP;  		writel(val, ctx->addr + DECON_VIDINTCON0);  	} @@ -122,14 +124,56 @@ static void decon_disable_vblank(struct exynos_drm_crtc *crtc)  		writel(0, ctx->addr + DECON_VIDINTCON0);  } +/* return number of starts/ends of frame transmissions since reset */ +static u32 decon_get_frame_count(struct decon_context *ctx, bool end) +{ +	u32 frm, pfrm, status, cnt = 2; + +	/* To get consistent result repeat read until frame id is stable. +	 * Usually the loop will be executed once, in rare cases when the loop +	 * is executed at frame change time 2nd pass will be needed. +	 */ +	frm = readl(ctx->addr + DECON_CRFMID); +	do { +		status = readl(ctx->addr + DECON_VIDCON1); +		pfrm = frm; +		frm = readl(ctx->addr + DECON_CRFMID); +	} while (frm != pfrm && --cnt); + +	/* CRFMID is incremented on BPORCH in case of I80 and on VSYNC in case +	 * of RGB, it should be taken into account. +	 */ +	if (!frm) +		return 0; + +	switch (status & (VIDCON1_VSTATUS_MASK | VIDCON1_I80_ACTIVE)) { +	case VIDCON1_VSTATUS_VS: +		if (!(ctx->out_type & IFTYPE_I80)) +			--frm; +		break; +	case VIDCON1_VSTATUS_BP: +		--frm; +		break; +	case VIDCON1_I80_ACTIVE: +	case VIDCON1_VSTATUS_AC: +		if (end) +			--frm; +		break; +	default: +		break; +	} + +	return frm; +} +  static void decon_setup_trigger(struct decon_context *ctx)  {  	if (!(ctx->out_type & (IFTYPE_I80 | I80_HW_TRG)))  		return;  	if (!(ctx->out_type & I80_HW_TRG)) { -		writel(TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN -		       | TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN, +		writel(TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F | +		       TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN,  		       ctx->addr + DECON_TRIGCON);  		return;  	} @@ -365,11 +409,14 @@ static void decon_disable_plane(struct exynos_drm_crtc *crtc,  static void decon_atomic_flush(struct exynos_drm_crtc *crtc)  {  	struct decon_context *ctx = crtc->ctx; +	unsigned long flags;  	int i;  	if (test_bit(BIT_SUSPENDED, &ctx->flags))  		return; +	spin_lock_irqsave(&ctx->vblank_lock, flags); +  	for (i = ctx->first_win; i < WINDOWS_NR; i++)  		decon_shadow_protect_win(ctx, i, false); @@ -378,11 +425,18 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc)  	if (ctx->out_type & IFTYPE_I80)  		set_bit(BIT_WIN_UPDATED, &ctx->flags); + +	ctx->frame_id = decon_get_frame_count(ctx, true); + +	exynos_crtc_handle_event(crtc); + +	spin_unlock_irqrestore(&ctx->vblank_lock, flags);  }  static void decon_swreset(struct decon_context *ctx)  {  	unsigned int tries; +	unsigned long flags;  	writel(0, ctx->addr + DECON_VIDCON0);  	for (tries = 2000; tries; --tries) { @@ -400,6 +454,10 @@ static void decon_swreset(struct decon_context *ctx)  	WARN(tries == 0, "failed to software reset DECON\n"); +	spin_lock_irqsave(&ctx->vblank_lock, flags); +	ctx->frame_id = 0; +	spin_unlock_irqrestore(&ctx->vblank_lock, flags); +  	if (!(ctx->out_type & IFTYPE_HDMI))  		return; @@ -578,6 +636,24 @@ static const struct component_ops decon_component_ops = {  	.unbind = decon_unbind,  }; +static void decon_handle_vblank(struct decon_context *ctx) +{ +	u32 frm; + +	spin_lock(&ctx->vblank_lock); + +	frm = decon_get_frame_count(ctx, true); + +	if (frm != ctx->frame_id) { +		/* handle only if incremented, take care of wrap-around */ +		if ((s32)(frm - ctx->frame_id) > 0) +			drm_crtc_handle_vblank(&ctx->crtc->base); +		ctx->frame_id = frm; +	} + +	spin_unlock(&ctx->vblank_lock); +} +  static irqreturn_t decon_irq_handler(int irq, void *dev_id)  {  	struct decon_context *ctx = dev_id; @@ -598,7 +674,7 @@ static irqreturn_t decon_irq_handler(int irq, void *dev_id)  			    (VIDOUT_INTERLACE_EN_F | VIDOUT_INTERLACE_FIELD_F))  				return IRQ_HANDLED;  		} -		drm_crtc_handle_vblank(&ctx->crtc->base); +		decon_handle_vblank(ctx);  	}  out: @@ -671,6 +747,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev)  	__set_bit(BIT_SUSPENDED, &ctx->flags);  	ctx->dev = dev;  	ctx->out_type = (unsigned long)of_device_get_match_data(dev); +	spin_lock_init(&ctx->vblank_lock);  	if (ctx->out_type & IFTYPE_HDMI) {  		ctx->first_win = 1; @@ -678,7 +755,7 @@ static int exynos5433_decon_probe(struct platform_device *pdev)  		ctx->out_type |= IFTYPE_I80;  	} -	if (ctx->out_type | I80_HW_TRG) { +	if (ctx->out_type & I80_HW_TRG) {  		ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,  							"samsung,disp-sysreg");  		if (IS_ERR(ctx->sysreg)) { diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index f9ab19e205e2..48811806fa27 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -526,6 +526,7 @@ static void decon_atomic_flush(struct exynos_drm_crtc *crtc)  	for (i = 0; i < WINDOWS_NR; i++)  		decon_shadow_protect_win(ctx, i, false); +	exynos_crtc_handle_event(crtc);  }  static void decon_init(struct decon_context *ctx) diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 5367b6664fe3..c65f4509932c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -85,16 +85,28 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,  				     struct drm_crtc_state *old_crtc_state)  {  	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); -	struct drm_pending_vblank_event *event; -	unsigned long flags;  	if (exynos_crtc->ops->atomic_flush)  		exynos_crtc->ops->atomic_flush(exynos_crtc); +} + +static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { +	.enable		= exynos_drm_crtc_enable, +	.disable	= exynos_drm_crtc_disable, +	.mode_set_nofb	= exynos_drm_crtc_mode_set_nofb, +	.atomic_check	= exynos_crtc_atomic_check, +	.atomic_begin	= exynos_crtc_atomic_begin, +	.atomic_flush	= exynos_crtc_atomic_flush, +}; + +void exynos_crtc_handle_event(struct exynos_drm_crtc *exynos_crtc) +{ +	struct drm_crtc *crtc = &exynos_crtc->base; +	struct drm_pending_vblank_event *event = crtc->state->event; +	unsigned long flags; -	event = crtc->state->event;  	if (event) {  		crtc->state->event = NULL; -  		spin_lock_irqsave(&crtc->dev->event_lock, flags);  		if (drm_crtc_vblank_get(crtc) == 0)  			drm_crtc_arm_vblank_event(crtc, event); @@ -105,15 +117,6 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,  } -static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { -	.enable		= exynos_drm_crtc_enable, -	.disable	= exynos_drm_crtc_disable, -	.mode_set_nofb	= exynos_drm_crtc_mode_set_nofb, -	.atomic_check	= exynos_crtc_atomic_check, -	.atomic_begin	= exynos_crtc_atomic_begin, -	.atomic_flush	= exynos_crtc_atomic_flush, -}; -  static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)  {  	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h index 6a581a8af465..abd5d6ceac0c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h @@ -40,4 +40,6 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,   */  void exynos_drm_crtc_te_handler(struct drm_crtc *crtc); +void exynos_crtc_handle_event(struct exynos_drm_crtc *exynos_crtc); +  #endif diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 812e2ec0761d..d7ef26370e67 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -86,7 +86,7 @@  #define DSIM_SYNC_INFORM		(1 << 27)  #define DSIM_EOT_DISABLE		(1 << 28)  #define DSIM_MFLUSH_VS			(1 << 29) -/* This flag is valid only for exynos3250/3472/4415/5260/5430 */ +/* This flag is valid only for exynos3250/3472/5260/5430 */  #define DSIM_CLKLANE_STOP		(1 << 30)  /* DSIM_ESCMODE */ @@ -473,17 +473,6 @@ static const struct exynos_dsi_driver_data exynos4_dsi_driver_data = {  	.reg_values = reg_values,  }; -static const struct exynos_dsi_driver_data exynos4415_dsi_driver_data = { -	.reg_ofs = exynos_reg_ofs, -	.plltmr_reg = 0x58, -	.has_clklane_stop = 1, -	.num_clks = 2, -	.max_freq = 1000, -	.wait_for_reset = 1, -	.num_bits_resol = 11, -	.reg_values = reg_values, -}; -  static const struct exynos_dsi_driver_data exynos5_dsi_driver_data = {  	.reg_ofs = exynos_reg_ofs,  	.plltmr_reg = 0x58, @@ -521,8 +510,6 @@ static const struct of_device_id exynos_dsi_of_match[] = {  	  .data = &exynos3_dsi_driver_data },  	{ .compatible = "samsung,exynos4210-mipi-dsi",  	  .data = &exynos4_dsi_driver_data }, -	{ .compatible = "samsung,exynos4415-mipi-dsi", -	  .data = &exynos4415_dsi_driver_data },  	{ .compatible = "samsung,exynos5410-mipi-dsi",  	  .data = &exynos5_dsi_driver_data },  	{ .compatible = "samsung,exynos5422-mipi-dsi", @@ -979,7 +966,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi,  	bool first = !xfer->tx_done;  	u32 reg; -	dev_dbg(dev, "< xfer %p: tx len %u, done %u, rx len %u, done %u\n", +	dev_dbg(dev, "< xfer %pK: tx len %u, done %u, rx len %u, done %u\n",  		xfer, length, xfer->tx_done, xfer->rx_len, xfer->rx_done);  	if (length > DSI_TX_FIFO_SIZE) @@ -1177,7 +1164,7 @@ static bool exynos_dsi_transfer_finish(struct exynos_dsi *dsi)  	spin_unlock_irqrestore(&dsi->transfer_lock, flags);  	dev_dbg(dsi->dev, -		"> xfer %p, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n", +		"> xfer %pK, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n",  		xfer, xfer->packet.payload_length, xfer->tx_done, xfer->rx_len,  		xfer->rx_done); @@ -1348,9 +1335,12 @@ static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi)  	int te_gpio_irq;  	dsi->te_gpio = of_get_named_gpio(dsi->panel_node, "te-gpios", 0); +	if (dsi->te_gpio == -ENOENT) +		return 0; +  	if (!gpio_is_valid(dsi->te_gpio)) { -		dev_err(dsi->dev, "no te-gpios specified\n");  		ret = dsi->te_gpio; +		dev_err(dsi->dev, "cannot get te-gpios, %d\n", ret);  		goto out;  	} diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index 95871577015d..5b18b5c5fdf2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -1695,7 +1695,7 @@ static int fimc_probe(struct platform_device *pdev)  		goto err_put_clk;  	} -	DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv); +	DRM_DEBUG_KMS("id[%d]ippdrv[%pK]\n", ctx->id, ippdrv);  	spin_lock_init(&ctx->lock);  	platform_set_drvdata(pdev, ctx); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index a9fa444c6053..3f04d72c448d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -71,10 +71,10 @@  #define TRIGCON				0x1A4  #define TRGMODE_ENABLE			(1 << 0)  #define SWTRGCMD_ENABLE			(1 << 1) -/* Exynos3250, 3472, 4415, 5260 5410, 5420 and 5422 only supported. */ +/* Exynos3250, 3472, 5260 5410, 5420 and 5422 only supported. */  #define HWTRGEN_ENABLE			(1 << 3)  #define HWTRGMASK_ENABLE		(1 << 4) -/* Exynos3250, 3472, 4415, 5260, 5420 and 5422 only supported. */ +/* Exynos3250, 3472, 5260, 5420 and 5422 only supported. */  #define HWTRIGEN_PER_ENABLE		(1 << 31)  /* display mode change control register except exynos4 */ @@ -138,18 +138,6 @@ static struct fimd_driver_data exynos4_fimd_driver_data = {  	.has_vtsel = 1,  }; -static struct fimd_driver_data exynos4415_fimd_driver_data = { -	.timing_base = 0x20000, -	.lcdblk_offset = 0x210, -	.lcdblk_vt_shift = 10, -	.lcdblk_bypass_shift = 1, -	.trg_type = I80_HW_TRG, -	.has_shadowcon = 1, -	.has_vidoutcon = 1, -	.has_vtsel = 1, -	.has_trigger_per_te = 1, -}; -  static struct fimd_driver_data exynos5_fimd_driver_data = {  	.timing_base = 0x20000,  	.lcdblk_offset = 0x214, @@ -210,8 +198,6 @@ static const struct of_device_id fimd_driver_dt_match[] = {  	  .data = &exynos3_fimd_driver_data },  	{ .compatible = "samsung,exynos4210-fimd",  	  .data = &exynos4_fimd_driver_data }, -	{ .compatible = "samsung,exynos4415-fimd", -	  .data = &exynos4415_fimd_driver_data },  	{ .compatible = "samsung,exynos5250-fimd",  	  .data = &exynos5_fimd_driver_data },  	{ .compatible = "samsung,exynos5420-fimd", @@ -257,7 +243,7 @@ static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)  			val |= VIDINTCON0_INT_FRAME;  			val &= ~VIDINTCON0_FRAMESEL0_MASK; -			val |= VIDINTCON0_FRAMESEL0_VSYNC; +			val |= VIDINTCON0_FRAMESEL0_FRONTPORCH;  			val &= ~VIDINTCON0_FRAMESEL1_MASK;  			val |= VIDINTCON0_FRAMESEL1_NONE;  		} @@ -723,6 +709,8 @@ static void fimd_atomic_flush(struct exynos_drm_crtc *crtc)  	for (i = 0; i < WINDOWS_NR; i++)  		fimd_shadow_protect_win(ctx, i, false); + +	exynos_crtc_handle_event(crtc);  }  static void fimd_update_plane(struct exynos_drm_crtc *crtc, diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 4c28f7ffcc4d..55a1579d11b3 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -218,7 +218,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct drm_device *dev,  		return ERR_PTR(ret);  	} -	DRM_DEBUG_KMS("created file object = %p\n", obj->filp); +	DRM_DEBUG_KMS("created file object = %pK\n", obj->filp);  	return exynos_gem;  } diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index bef57987759d..0506b2b17ac1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -1723,7 +1723,7 @@ static int gsc_probe(struct platform_device *pdev)  		return ret;  	} -	DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv); +	DRM_DEBUG_KMS("id[%d]ippdrv[%pK]\n", ctx->id, ippdrv);  	mutex_init(&ctx->lock);  	platform_set_drvdata(pdev, ctx); diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 9c84ee76f18a..3edda18cc2d2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c @@ -208,7 +208,7 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)  	 * e.g PAUSE state, queue buf, command control.  	 */  	list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { -		DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n", count++, ippdrv); +		DRM_DEBUG_KMS("count[%d]ippdrv[%pK]\n", count++, ippdrv);  		mutex_lock(&ippdrv->cmd_lock);  		list_for_each_entry(c_node, &ippdrv->cmd_list, list) { @@ -388,7 +388,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,  	}  	property->prop_id = ret; -	DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%p]\n", +	DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%pK]\n",  		property->prop_id, property->cmd, ippdrv);  	/* stored property information and ippdrv in private data */ @@ -518,7 +518,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,  {  	int i; -	DRM_DEBUG_KMS("node[%p]\n", m_node); +	DRM_DEBUG_KMS("node[%pK]\n", m_node);  	if (!m_node) {  		DRM_ERROR("invalid dequeue node.\n"); @@ -562,7 +562,7 @@ static struct drm_exynos_ipp_mem_node  	m_node->buf_id = qbuf->buf_id;  	INIT_LIST_HEAD(&m_node->list); -	DRM_DEBUG_KMS("m_node[%p]ops_id[%d]\n", m_node, qbuf->ops_id); +	DRM_DEBUG_KMS("m_node[%pK]ops_id[%d]\n", m_node, qbuf->ops_id);  	DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id);  	for_each_ipp_planar(i) { @@ -659,7 +659,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,  	mutex_lock(&c_node->event_lock);  	list_for_each_entry_safe(e, te, &c_node->event_list, base.link) { -		DRM_DEBUG_KMS("count[%d]e[%p]\n", count++, e); +		DRM_DEBUG_KMS("count[%d]e[%pK]\n", count++, e);  		/*  		 * qbuf == NULL condition means all event deletion. @@ -750,7 +750,7 @@ static struct drm_exynos_ipp_mem_node  	/* find memory node from memory list */  	list_for_each_entry(m_node, head, list) { -		DRM_DEBUG_KMS("count[%d]m_node[%p]\n", count++, m_node); +		DRM_DEBUG_KMS("count[%d]m_node[%pK]\n", count++, m_node);  		/* compare buffer id */  		if (m_node->buf_id == qbuf->buf_id) @@ -767,7 +767,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,  	struct exynos_drm_ipp_ops *ops = NULL;  	int ret = 0; -	DRM_DEBUG_KMS("node[%p]\n", m_node); +	DRM_DEBUG_KMS("node[%pK]\n", m_node);  	if (!m_node) {  		DRM_ERROR("invalid queue node.\n"); @@ -1232,7 +1232,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,  			m_node = list_first_entry(head,  				struct drm_exynos_ipp_mem_node, list); -			DRM_DEBUG_KMS("m_node[%p]\n", m_node); +			DRM_DEBUG_KMS("m_node[%pK]\n", m_node);  			ret = ipp_set_mem_node(ippdrv, c_node, m_node);  			if (ret) { @@ -1601,7 +1601,7 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)  		}  		ippdrv->prop_list.ipp_id = ret; -		DRM_DEBUG_KMS("count[%d]ippdrv[%p]ipp_id[%d]\n", +		DRM_DEBUG_KMS("count[%d]ippdrv[%pK]ipp_id[%d]\n",  			count++, ippdrv, ret);  		/* store parent device for node */ @@ -1659,7 +1659,7 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,  	file_priv->ipp_dev = dev; -	DRM_DEBUG_KMS("done priv[%p]\n", dev); +	DRM_DEBUG_KMS("done priv[%pK]\n", dev);  	return 0;  } @@ -1676,7 +1676,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,  		mutex_lock(&ippdrv->cmd_lock);  		list_for_each_entry_safe(c_node, tc_node,  			&ippdrv->cmd_list, list) { -			DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n", +			DRM_DEBUG_KMS("count[%d]ippdrv[%pK]\n",  				count++, ippdrv);  			if (c_node->filp == file) { diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index 6591e406084c..79282a820ecc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -748,7 +748,7 @@ static int rotator_probe(struct platform_device *pdev)  		goto err_ippdrv_register;  	} -	DRM_DEBUG_KMS("ippdrv[%p]\n", ippdrv); +	DRM_DEBUG_KMS("ippdrv[%pK]\n", ippdrv);  	platform_set_drvdata(pdev, rot); diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 57fe514d5c5b..5d9a62a87eec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -170,6 +170,7 @@ static const struct exynos_drm_crtc_ops vidi_crtc_ops = {  	.enable_vblank = vidi_enable_vblank,  	.disable_vblank = vidi_disable_vblank,  	.update_plane = vidi_update_plane, +	.atomic_flush = exynos_crtc_handle_event,  };  static void vidi_fake_vblank_timer(unsigned long arg) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 72143ac10525..25edb635a197 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1012,6 +1012,7 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc)  		return;  	mixer_vsync_set_update(mixer_ctx, true); +	exynos_crtc_handle_event(crtc);  }  static void mixer_enable(struct exynos_drm_crtc *crtc) diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index 3b6caaca9751..325618d969fe 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -242,7 +242,7 @@ static int alloc_resource(struct intel_vgpu *vgpu,  	const char *item;  	if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) { -		gvt_err("Invalid vGPU creation params\n"); +		gvt_vgpu_err("Invalid vGPU creation params\n");  		return -EINVAL;  	} @@ -285,9 +285,9 @@ static int alloc_resource(struct intel_vgpu *vgpu,  	return 0;  no_enough_resource: -	gvt_err("vgpu%d: fail to allocate resource %s\n", vgpu->id, item); -	gvt_err("vgpu%d: request %luMB avail %luMB max %luMB taken %luMB\n", -		vgpu->id, BYTES_TO_MB(request), BYTES_TO_MB(avail), +	gvt_vgpu_err("fail to allocate resource %s\n", item); +	gvt_vgpu_err("request %luMB avail %luMB max %luMB taken %luMB\n", +		BYTES_TO_MB(request), BYTES_TO_MB(avail),  		BYTES_TO_MB(max), BYTES_TO_MB(taken));  	return -ENOSPC;  } diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index 4a6a2ed65732..40af17ec6312 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -41,6 +41,54 @@ enum {  	INTEL_GVT_PCI_BAR_MAX,  }; +/* bitmap for writable bits (RW or RW1C bits, but cannot co-exist in one + * byte) byte by byte in standard pci configuration space. (not the full + * 256 bytes.) + */ +static const u8 pci_cfg_space_rw_bmp[PCI_INTERRUPT_LINE + 4] = { +	[PCI_COMMAND]		= 0xff, 0x07, +	[PCI_STATUS]		= 0x00, 0xf9, /* the only one RW1C byte */ +	[PCI_CACHE_LINE_SIZE]	= 0xff, +	[PCI_BASE_ADDRESS_0 ... PCI_CARDBUS_CIS - 1] = 0xff, +	[PCI_ROM_ADDRESS]	= 0x01, 0xf8, 0xff, 0xff, +	[PCI_INTERRUPT_LINE]	= 0xff, +}; + +/** + * vgpu_pci_cfg_mem_write - write virtual cfg space memory + * + * Use this function to write virtual cfg space memory. + * For standard cfg space, only RW bits can be changed, + * and we emulates the RW1C behavior of PCI_STATUS register. + */ +static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off, +				   u8 *src, unsigned int bytes) +{ +	u8 *cfg_base = vgpu_cfg_space(vgpu); +	u8 mask, new, old; +	int i = 0; + +	for (; i < bytes && (off + i < sizeof(pci_cfg_space_rw_bmp)); i++) { +		mask = pci_cfg_space_rw_bmp[off + i]; +		old = cfg_base[off + i]; +		new = src[i] & mask; + +		/** +		 * The PCI_STATUS high byte has RW1C bits, here +		 * emulates clear by writing 1 for these bits. +		 * Writing a 0b to RW1C bits has no effect. +		 */ +		if (off + i == PCI_STATUS + 1) +			new = (~new & old) & mask; + +		cfg_base[off + i] = (old & ~mask) | new; +	} + +	/* For other configuration space directly copy as it is. */ +	if (i < bytes) +		memcpy(cfg_base + off + i, src + i, bytes - i); +} +  /**   * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read   * @@ -123,7 +171,7 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu,  	u8 changed = old ^ new;  	int ret; -	memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); +	vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);  	if (!(changed & PCI_COMMAND_MEMORY))  		return 0; @@ -274,10 +322,10 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,  		if (ret)  			return ret; -		memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); +		vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);  		break;  	default: -		memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); +		vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);  		break;  	}  	return 0; diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index b9c8e2407682..2b92cc8a7d1a 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -668,7 +668,7 @@ static inline void print_opcode(u32 cmd, int ring_id)  	if (d_info == NULL)  		return; -	gvt_err("opcode=0x%x %s sub_ops:", +	gvt_dbg_cmd("opcode=0x%x %s sub_ops:",  			cmd >> (32 - d_info->op_len), d_info->name);  	for (i = 0; i < d_info->nr_sub_op; i++) @@ -693,23 +693,23 @@ static void parser_exec_state_dump(struct parser_exec_state *s)  	int cnt = 0;  	int i; -	gvt_err("  vgpu%d RING%d: ring_start(%08lx) ring_end(%08lx)" +	gvt_dbg_cmd("  vgpu%d RING%d: ring_start(%08lx) ring_end(%08lx)"  			" ring_head(%08lx) ring_tail(%08lx)\n", s->vgpu->id,  			s->ring_id, s->ring_start, s->ring_start + s->ring_size,  			s->ring_head, s->ring_tail); -	gvt_err("  %s %s ip_gma(%08lx) ", +	gvt_dbg_cmd("  %s %s ip_gma(%08lx) ",  			s->buf_type == RING_BUFFER_INSTRUCTION ?  			"RING_BUFFER" : "BATCH_BUFFER",  			s->buf_addr_type == GTT_BUFFER ?  			"GTT" : "PPGTT", s->ip_gma);  	if (s->ip_va == NULL) { -		gvt_err(" ip_va(NULL)"); +		gvt_dbg_cmd(" ip_va(NULL)");  		return;  	} -	gvt_err("  ip_va=%p: %08x %08x %08x %08x\n", +	gvt_dbg_cmd("  ip_va=%p: %08x %08x %08x %08x\n",  			s->ip_va, cmd_val(s, 0), cmd_val(s, 1),  			cmd_val(s, 2), cmd_val(s, 3)); @@ -817,6 +817,25 @@ static bool is_shadowed_mmio(unsigned int offset)  	return ret;  } +static inline bool is_force_nonpriv_mmio(unsigned int offset) +{ +	return (offset >= 0x24d0 && offset < 0x2500); +} + +static int force_nonpriv_reg_handler(struct parser_exec_state *s, +				     unsigned int offset, unsigned int index) +{ +	struct intel_gvt *gvt = s->vgpu->gvt; +	unsigned int data = cmd_val(s, index + 1); + +	if (!intel_gvt_in_force_nonpriv_whitelist(gvt, data)) { +		gvt_err("Unexpected forcenonpriv 0x%x LRI write, value=0x%x\n", +			offset, data); +		return -EINVAL; +	} +	return 0; +} +  static int cmd_reg_handler(struct parser_exec_state *s,  	unsigned int offset, unsigned int index, char *cmd)  { @@ -824,23 +843,26 @@ static int cmd_reg_handler(struct parser_exec_state *s,  	struct intel_gvt *gvt = vgpu->gvt;  	if (offset + 4 > gvt->device_info.mmio_size) { -		gvt_err("%s access to (%x) outside of MMIO range\n", +		gvt_vgpu_err("%s access to (%x) outside of MMIO range\n",  				cmd, offset);  		return -EINVAL;  	}  	if (!intel_gvt_mmio_is_cmd_access(gvt, offset)) { -		gvt_err("vgpu%d: %s access to non-render register (%x)\n", -				s->vgpu->id, cmd, offset); +		gvt_vgpu_err("%s access to non-render register (%x)\n", +				cmd, offset);  		return 0;  	}  	if (is_shadowed_mmio(offset)) { -		gvt_err("vgpu%d: found access of shadowed MMIO %x\n", -				s->vgpu->id, offset); +		gvt_vgpu_err("found access of shadowed MMIO %x\n", offset);  		return 0;  	} +	if (is_force_nonpriv_mmio(offset) && +	    force_nonpriv_reg_handler(s, offset, index)) +		return -EINVAL; +  	if (offset == i915_mmio_reg_offset(DERRMR) ||  		offset == i915_mmio_reg_offset(FORCEWAKE_MT)) {  		/* Writing to HW VGT_PVINFO_PAGE offset will be discarded */ @@ -1008,7 +1030,7 @@ static int cmd_handler_pipe_control(struct parser_exec_state *s)  			ret = cmd_reg_handler(s, 0x2358, 1, "pipe_ctrl");  		else if (post_sync == 1) {  			/* check ggtt*/ -			if ((cmd_val(s, 2) & (1 << 2))) { +			if ((cmd_val(s, 1) & PIPE_CONTROL_GLOBAL_GTT_IVB)) {  				gma = cmd_val(s, 2) & GENMASK(31, 3);  				if (gmadr_bytes == 8)  					gma |= (cmd_gma_hi(s, 3)) << 32; @@ -1129,6 +1151,7 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s,  		struct mi_display_flip_command_info *info)  {  	struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; +	struct intel_vgpu *vgpu = s->vgpu;  	u32 dword0 = cmd_val(s, 0);  	u32 dword1 = cmd_val(s, 1);  	u32 dword2 = cmd_val(s, 2); @@ -1167,7 +1190,7 @@ static int skl_decode_mi_display_flip(struct parser_exec_state *s,  		break;  	default: -		gvt_err("unknown plane code %d\n", plane); +		gvt_vgpu_err("unknown plane code %d\n", plane);  		return -EINVAL;  	} @@ -1274,25 +1297,26 @@ static int update_plane_mmio_from_mi_display_flip(  static int cmd_handler_mi_display_flip(struct parser_exec_state *s)  {  	struct mi_display_flip_command_info info; +	struct intel_vgpu *vgpu = s->vgpu;  	int ret;  	int i;  	int len = cmd_length(s);  	ret = decode_mi_display_flip(s, &info);  	if (ret) { -		gvt_err("fail to decode MI display flip command\n"); +		gvt_vgpu_err("fail to decode MI display flip command\n");  		return ret;  	}  	ret = check_mi_display_flip(s, &info);  	if (ret) { -		gvt_err("invalid MI display flip command\n"); +		gvt_vgpu_err("invalid MI display flip command\n");  		return ret;  	}  	ret = update_plane_mmio_from_mi_display_flip(s, &info);  	if (ret) { -		gvt_err("fail to update plane mmio\n"); +		gvt_vgpu_err("fail to update plane mmio\n");  		return ret;  	} @@ -1350,7 +1374,8 @@ static inline int cmd_address_audit(struct parser_exec_state *s,  	int ret;  	if (op_size > max_surface_size) { -		gvt_err("command address audit fail name %s\n", s->info->name); +		gvt_vgpu_err("command address audit fail name %s\n", +			s->info->name);  		return -EINVAL;  	} @@ -1367,7 +1392,7 @@ static inline int cmd_address_audit(struct parser_exec_state *s,  	}  	return 0;  err: -	gvt_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n", +	gvt_vgpu_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n",  			s->info->name, guest_gma, op_size);  	pr_err("cmd dump: "); @@ -1412,8 +1437,10 @@ static int cmd_handler_mi_store_data_imm(struct parser_exec_state *s)  static inline int unexpected_cmd(struct parser_exec_state *s)  { -	gvt_err("vgpu%d: Unexpected %s in command buffer!\n", -			s->vgpu->id, s->info->name); +	struct intel_vgpu *vgpu = s->vgpu; + +	gvt_vgpu_err("Unexpected %s in command buffer!\n", s->info->name); +  	return -EINVAL;  } @@ -1516,7 +1543,7 @@ static int copy_gma_to_hva(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm,  	while (gma != end_gma) {  		gpa = intel_vgpu_gma_to_gpa(mm, gma);  		if (gpa == INTEL_GVT_INVALID_ADDR) { -			gvt_err("invalid gma address: %lx\n", gma); +			gvt_vgpu_err("invalid gma address: %lx\n", gma);  			return -EFAULT;  		} @@ -1557,6 +1584,7 @@ static uint32_t find_bb_size(struct parser_exec_state *s)  	uint32_t bb_size = 0;  	uint32_t cmd_len = 0;  	bool met_bb_end = false; +	struct intel_vgpu *vgpu = s->vgpu;  	u32 cmd;  	/* get the start gm address of the batch buffer */ @@ -1565,7 +1593,7 @@ static uint32_t find_bb_size(struct parser_exec_state *s)  	info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);  	if (info == NULL) { -		gvt_err("unknown cmd 0x%x, opcode=0x%x\n", +		gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",  				cmd, get_opcode(cmd, s->ring_id));  		return -EINVAL;  	} @@ -1574,7 +1602,7 @@ static uint32_t find_bb_size(struct parser_exec_state *s)  				gma, gma + 4, &cmd);  		info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);  		if (info == NULL) { -			gvt_err("unknown cmd 0x%x, opcode=0x%x\n", +			gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",  				cmd, get_opcode(cmd, s->ring_id));  			return -EINVAL;  		} @@ -1599,6 +1627,7 @@ static uint32_t find_bb_size(struct parser_exec_state *s)  static int perform_bb_shadow(struct parser_exec_state *s)  {  	struct intel_shadow_bb_entry *entry_obj; +	struct intel_vgpu *vgpu = s->vgpu;  	unsigned long gma = 0;  	uint32_t bb_size;  	void *dst = NULL; @@ -1633,7 +1662,7 @@ static int perform_bb_shadow(struct parser_exec_state *s)  	ret = i915_gem_object_set_to_cpu_domain(entry_obj->obj, false);  	if (ret) { -		gvt_err("failed to set shadow batch to CPU\n"); +		gvt_vgpu_err("failed to set shadow batch to CPU\n");  		goto unmap_src;  	} @@ -1645,7 +1674,7 @@ static int perform_bb_shadow(struct parser_exec_state *s)  			      gma, gma + bb_size,  			      dst);  	if (ret) { -		gvt_err("fail to copy guest ring buffer\n"); +		gvt_vgpu_err("fail to copy guest ring buffer\n");  		goto unmap_src;  	} @@ -1676,15 +1705,16 @@ static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s)  {  	bool second_level;  	int ret = 0; +	struct intel_vgpu *vgpu = s->vgpu;  	if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) { -		gvt_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n"); +		gvt_vgpu_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n");  		return -EINVAL;  	}  	second_level = BATCH_BUFFER_2ND_LEVEL_BIT(cmd_val(s, 0)) == 1;  	if (second_level && (s->buf_type != BATCH_BUFFER_INSTRUCTION)) { -		gvt_err("Jumping to 2nd level BB from RB is not allowed\n"); +		gvt_vgpu_err("Jumping to 2nd level BB from RB is not allowed\n");  		return -EINVAL;  	} @@ -1702,7 +1732,7 @@ static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s)  	if (batch_buffer_needs_scan(s)) {  		ret = perform_bb_shadow(s);  		if (ret < 0) -			gvt_err("invalid shadow batch buffer\n"); +			gvt_vgpu_err("invalid shadow batch buffer\n");  	} else {  		/* emulate a batch buffer end to do return right */  		ret = cmd_handler_mi_batch_buffer_end(s); @@ -2429,6 +2459,7 @@ static int cmd_parser_exec(struct parser_exec_state *s)  	int ret = 0;  	cycles_t t0, t1, t2;  	struct parser_exec_state s_before_advance_custom; +	struct intel_vgpu *vgpu = s->vgpu;  	t0 = get_cycles(); @@ -2436,7 +2467,7 @@ static int cmd_parser_exec(struct parser_exec_state *s)  	info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);  	if (info == NULL) { -		gvt_err("unknown cmd 0x%x, opcode=0x%x\n", +		gvt_vgpu_err("unknown cmd 0x%x, opcode=0x%x\n",  				cmd, get_opcode(cmd, s->ring_id));  		return -EINVAL;  	} @@ -2452,7 +2483,7 @@ static int cmd_parser_exec(struct parser_exec_state *s)  	if (info->handler) {  		ret = info->handler(s);  		if (ret < 0) { -			gvt_err("%s handler error\n", info->name); +			gvt_vgpu_err("%s handler error\n", info->name);  			return ret;  		}  	} @@ -2463,7 +2494,7 @@ static int cmd_parser_exec(struct parser_exec_state *s)  	if (!(info->flag & F_IP_ADVANCE_CUSTOM)) {  		ret = cmd_advance_default(s);  		if (ret) { -			gvt_err("%s IP advance error\n", info->name); +			gvt_vgpu_err("%s IP advance error\n", info->name);  			return ret;  		}  	} @@ -2486,6 +2517,7 @@ static int command_scan(struct parser_exec_state *s,  	unsigned long gma_head, gma_tail, gma_bottom;  	int ret = 0; +	struct intel_vgpu *vgpu = s->vgpu;  	gma_head = rb_start + rb_head;  	gma_tail = rb_start + rb_tail; @@ -2497,7 +2529,7 @@ static int command_scan(struct parser_exec_state *s,  		if (s->buf_type == RING_BUFFER_INSTRUCTION) {  			if (!(s->ip_gma >= rb_start) ||  				!(s->ip_gma < gma_bottom)) { -				gvt_err("ip_gma %lx out of ring scope." +				gvt_vgpu_err("ip_gma %lx out of ring scope."  					"(base:0x%lx, bottom: 0x%lx)\n",  					s->ip_gma, rb_start,  					gma_bottom); @@ -2505,7 +2537,7 @@ static int command_scan(struct parser_exec_state *s,  				return -EINVAL;  			}  			if (gma_out_of_range(s->ip_gma, gma_head, gma_tail)) { -				gvt_err("ip_gma %lx out of range." +				gvt_vgpu_err("ip_gma %lx out of range."  					"base 0x%lx head 0x%lx tail 0x%lx\n",  					s->ip_gma, rb_start,  					rb_head, rb_tail); @@ -2515,7 +2547,7 @@ static int command_scan(struct parser_exec_state *s,  		}  		ret = cmd_parser_exec(s);  		if (ret) { -			gvt_err("cmd parser error\n"); +			gvt_vgpu_err("cmd parser error\n");  			parser_exec_state_dump(s);  			break;  		} @@ -2639,7 +2671,7 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)  				gma_head, gma_top,  				workload->shadow_ring_buffer_va);  		if (ret) { -			gvt_err("fail to copy guest ring buffer\n"); +			gvt_vgpu_err("fail to copy guest ring buffer\n");  			return ret;  		}  		copy_len = gma_top - gma_head; @@ -2651,7 +2683,7 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)  			gma_head, gma_tail,  			workload->shadow_ring_buffer_va + copy_len);  	if (ret) { -		gvt_err("fail to copy guest ring buffer\n"); +		gvt_vgpu_err("fail to copy guest ring buffer\n");  		return ret;  	}  	ring->tail += workload->rb_len; @@ -2662,16 +2694,17 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)  int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)  {  	int ret; +	struct intel_vgpu *vgpu = workload->vgpu;  	ret = shadow_workload_ring_buffer(workload);  	if (ret) { -		gvt_err("fail to shadow workload ring_buffer\n"); +		gvt_vgpu_err("fail to shadow workload ring_buffer\n");  		return ret;  	}  	ret = scan_workload(workload);  	if (ret) { -		gvt_err("scan workload error\n"); +		gvt_vgpu_err("scan workload error\n");  		return ret;  	}  	return 0; @@ -2681,6 +2714,7 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)  {  	int ctx_size = wa_ctx->indirect_ctx.size;  	unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma; +	struct intel_vgpu *vgpu = wa_ctx->workload->vgpu;  	struct drm_i915_gem_object *obj;  	int ret = 0;  	void *map; @@ -2694,14 +2728,14 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)  	/* get the va of the shadow batch buffer */  	map = i915_gem_object_pin_map(obj, I915_MAP_WB);  	if (IS_ERR(map)) { -		gvt_err("failed to vmap shadow indirect ctx\n"); +		gvt_vgpu_err("failed to vmap shadow indirect ctx\n");  		ret = PTR_ERR(map);  		goto put_obj;  	}  	ret = i915_gem_object_set_to_cpu_domain(obj, false);  	if (ret) { -		gvt_err("failed to set shadow indirect ctx to CPU\n"); +		gvt_vgpu_err("failed to set shadow indirect ctx to CPU\n");  		goto unmap_src;  	} @@ -2710,7 +2744,7 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)  				guest_gma, guest_gma + ctx_size,  				map);  	if (ret) { -		gvt_err("fail to copy guest indirect ctx\n"); +		gvt_vgpu_err("fail to copy guest indirect ctx\n");  		goto unmap_src;  	} @@ -2744,13 +2778,14 @@ static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)  int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)  {  	int ret; +	struct intel_vgpu *vgpu = wa_ctx->workload->vgpu;  	if (wa_ctx->indirect_ctx.size == 0)  		return 0;  	ret = shadow_indirect_ctx(wa_ctx);  	if (ret) { -		gvt_err("fail to shadow indirect ctx\n"); +		gvt_vgpu_err("fail to shadow indirect ctx\n");  		return ret;  	} @@ -2758,7 +2793,7 @@ int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)  	ret = scan_wa_ctx(wa_ctx);  	if (ret) { -		gvt_err("scan wa ctx error\n"); +		gvt_vgpu_err("scan wa ctx error\n");  		return ret;  	} diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index 68cba7bd980a..b0cff4dc2684 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h @@ -27,6 +27,14 @@  #define gvt_err(fmt, args...) \  	DRM_ERROR("gvt: "fmt, ##args) +#define gvt_vgpu_err(fmt, args...)					\ +do {									\ +	if (IS_ERR_OR_NULL(vgpu))					\ +		DRM_DEBUG_DRIVER("gvt: "fmt, ##args);			\ +	else								\ +		DRM_DEBUG_DRIVER("gvt: vgpu %d: "fmt, vgpu->id, ##args);\ +} while (0) +  #define gvt_dbg_core(fmt, args...) \  	DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args) diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index 6d8fde880c39..5419ae6ec633 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -83,44 +83,80 @@ static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)  	return 0;  } +static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = { +	{ +/* EDID with 1024x768 as its resolution */ +		/*Header*/ +		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +		/* Vendor & Product Identification */ +		0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17, +		/* Version & Revision */ +		0x01, 0x04, +		/* Basic Display Parameters & Features */ +		0xa5, 0x34, 0x20, 0x78, 0x23, +		/* Color Characteristics */ +		0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54, +		/* Established Timings: maximum resolution is 1024x768 */ +		0x21, 0x08, 0x00, +		/* Standard Timings. All invalid */ +		0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, +		0x00, 0x40, 0x00, 0x00, 0x00, 0x01, +		/* 18 Byte Data Blocks 1: invalid */ +		0x00, 0x00, 0x80, 0xa0, 0x70, 0xb0, +		0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, +		/* 18 Byte Data Blocks 2: invalid */ +		0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a, +		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +		/* 18 Byte Data Blocks 3: invalid */ +		0x00, 0x00, 0x00, 0xfc, 0x00, 0x48, +		0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20, +		/* 18 Byte Data Blocks 4: invalid */ +		0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30, +		0x44, 0x58, 0x51, 0x0a, 0x20, 0x20, +		/* Extension Block Count */ +		0x00, +		/* Checksum */ +		0xef, +	}, +	{  /* EDID with 1920x1200 as its resolution */ -static unsigned char virtual_dp_monitor_edid[] = { -	/*Header*/ -	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, -	/* Vendor & Product Identification */ -	0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17, -	/* Version & Revision */ -	0x01, 0x04, -	/* Basic Display Parameters & Features */ -	0xa5, 0x34, 0x20, 0x78, 0x23, -	/* Color Characteristics */ -	0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54, -	/* Established Timings: maximum resolution is 1024x768 */ -	0x21, 0x08, 0x00, -	/* -	 * Standard Timings. -	 * below new resolutions can be supported: -	 * 1920x1080, 1280x720, 1280x960, 1280x1024, -	 * 1440x900, 1600x1200, 1680x1050 -	 */ -	0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x40, 0x81, 0x80, 0x95, 0x00, -	0xa9, 0x40, 0xb3, 0x00, 0x01, 0x01, -	/* 18 Byte Data Blocks 1: max resolution is 1920x1200 */ -	0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, -	0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, -	/* 18 Byte Data Blocks 2: invalid */ -	0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a, -	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, -	/* 18 Byte Data Blocks 3: invalid */ -	0x00, 0x00, 0x00, 0xfc, 0x00, 0x48, -	0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20, -	/* 18 Byte Data Blocks 4: invalid */ -	0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30, -	0x44, 0x58, 0x51, 0x0a, 0x20, 0x20, -	/* Extension Block Count */ -	0x00, -	/* Checksum */ -	0x45, +		/*Header*/ +		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +		/* Vendor & Product Identification */ +		0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17, +		/* Version & Revision */ +		0x01, 0x04, +		/* Basic Display Parameters & Features */ +		0xa5, 0x34, 0x20, 0x78, 0x23, +		/* Color Characteristics */ +		0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54, +		/* Established Timings: maximum resolution is 1024x768 */ +		0x21, 0x08, 0x00, +		/* +		 * Standard Timings. +		 * below new resolutions can be supported: +		 * 1920x1080, 1280x720, 1280x960, 1280x1024, +		 * 1440x900, 1600x1200, 1680x1050 +		 */ +		0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x40, 0x81, 0x80, 0x95, 0x00, +		0xa9, 0x40, 0xb3, 0x00, 0x01, 0x01, +		/* 18 Byte Data Blocks 1: max resolution is 1920x1200 */ +		0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, +		0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, +		/* 18 Byte Data Blocks 2: invalid */ +		0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a, +		0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +		/* 18 Byte Data Blocks 3: invalid */ +		0x00, 0x00, 0x00, 0xfc, 0x00, 0x48, +		0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20, +		/* 18 Byte Data Blocks 4: invalid */ +		0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30, +		0x44, 0x58, 0x51, 0x0a, 0x20, 0x20, +		/* Extension Block Count */ +		0x00, +		/* Checksum */ +		0x45, +	},  };  #define DPCD_HEADER_SIZE        0xb @@ -140,14 +176,20 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)  		vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT |  				SDE_PORTE_HOTPLUG_SPT); -	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) +	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {  		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT; +		vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED; +	} -	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) +	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {  		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT; +		vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIC_DETECTED; +	} -	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D)) +	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D)) {  		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT; +		vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDID_DETECTED; +	}  	if (IS_SKYLAKE(dev_priv) &&  			intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) { @@ -160,6 +202,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)  				GEN8_PORT_DP_A_HOTPLUG;  		else  			vgpu_vreg(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT; + +		vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_A)) |= DDI_INIT_DISPLAY_DETECTED;  	}  } @@ -175,10 +219,13 @@ static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num)  }  static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num, -		int type) +				    int type, unsigned int resolution)  {  	struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num); +	if (WARN_ON(resolution >= GVT_EDID_NUM)) +		return -EINVAL; +  	port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL);  	if (!port->edid)  		return -ENOMEM; @@ -189,7 +236,7 @@ static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,  		return -ENOMEM;  	} -	memcpy(port->edid->edid_block, virtual_dp_monitor_edid, +	memcpy(port->edid->edid_block, virtual_dp_monitor_edid[resolution],  			EDID_SIZE);  	port->edid->data_valid = true; @@ -322,16 +369,18 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu)   * Zero on success, negative error code if failed.   *   */ -int intel_vgpu_init_display(struct intel_vgpu *vgpu) +int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution)  {  	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;  	intel_vgpu_init_i2c_edid(vgpu);  	if (IS_SKYLAKE(dev_priv)) -		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D); +		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D, +						resolution);  	else -		return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B); +		return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B, +						resolution);  }  /** diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h index 8b234ea961f6..d73de22102e2 100644 --- a/drivers/gpu/drm/i915/gvt/display.h +++ b/drivers/gpu/drm/i915/gvt/display.h @@ -154,10 +154,28 @@ struct intel_vgpu_port {  	int type;  }; +enum intel_vgpu_edid { +	GVT_EDID_1024_768, +	GVT_EDID_1920_1200, +	GVT_EDID_NUM, +}; + +static inline char *vgpu_edid_str(enum intel_vgpu_edid id) +{ +	switch (id) { +	case GVT_EDID_1024_768: +		return "1024x768"; +	case GVT_EDID_1920_1200: +		return "1920x1200"; +	default: +		return ""; +	} +} +  void intel_gvt_emulate_vblank(struct intel_gvt *gvt);  void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt); -int intel_vgpu_init_display(struct intel_vgpu *vgpu); +int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution);  void intel_vgpu_reset_display(struct intel_vgpu *vgpu);  void intel_vgpu_clean_display(struct intel_vgpu *vgpu); diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c index bda85dff7b2a..42cd09ec63fa 100644 --- a/drivers/gpu/drm/i915/gvt/edid.c +++ b/drivers/gpu/drm/i915/gvt/edid.c @@ -52,16 +52,16 @@ static unsigned char edid_get_byte(struct intel_vgpu *vgpu)  	unsigned char chr = 0;  	if (edid->state == I2C_NOT_SPECIFIED || !edid->slave_selected) { -		gvt_err("Driver tries to read EDID without proper sequence!\n"); +		gvt_vgpu_err("Driver tries to read EDID without proper sequence!\n");  		return 0;  	}  	if (edid->current_edid_read >= EDID_SIZE) { -		gvt_err("edid_get_byte() exceeds the size of EDID!\n"); +		gvt_vgpu_err("edid_get_byte() exceeds the size of EDID!\n");  		return 0;  	}  	if (!edid->edid_available) { -		gvt_err("Reading EDID but EDID is not available!\n"); +		gvt_vgpu_err("Reading EDID but EDID is not available!\n");  		return 0;  	} @@ -72,7 +72,7 @@ static unsigned char edid_get_byte(struct intel_vgpu *vgpu)  		chr = edid_data->edid_block[edid->current_edid_read];  		edid->current_edid_read++;  	} else { -		gvt_err("No EDID available during the reading?\n"); +		gvt_vgpu_err("No EDID available during the reading?\n");  	}  	return chr;  } @@ -223,7 +223,7 @@ static int gmbus1_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  			vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_ACTIVE;  			break;  		default: -			gvt_err("Unknown/reserved GMBUS cycle detected!\n"); +			gvt_vgpu_err("Unknown/reserved GMBUS cycle detected!\n");  			break;  		}  		/* @@ -292,8 +292,7 @@ static int gmbus3_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,  		 */  	} else {  		memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); -		gvt_err("vgpu%d: warning: gmbus3 read with nothing returned\n", -				vgpu->id); +		gvt_vgpu_err("warning: gmbus3 read with nothing returned\n");  	}  	return 0;  } @@ -496,7 +495,8 @@ void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,  			unsigned char val = edid_get_byte(vgpu);  			aux_data_for_write = (val << 16); -		} +		} else +			aux_data_for_write = (0xff << 16);  	}  	/* write the return value in AUX_CH_DATA reg which includes:  	 * ACK of I2C_WRITE diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 46eb9fd3c03f..d186c157f65f 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -172,6 +172,7 @@ static int emulate_execlist_ctx_schedule_out(  		struct intel_vgpu_execlist *execlist,  		struct execlist_ctx_descriptor_format *ctx)  { +	struct intel_vgpu *vgpu = execlist->vgpu;  	struct intel_vgpu_execlist_slot *running = execlist->running_slot;  	struct intel_vgpu_execlist_slot *pending = execlist->pending_slot;  	struct execlist_ctx_descriptor_format *ctx0 = &running->ctx[0]; @@ -183,7 +184,7 @@ static int emulate_execlist_ctx_schedule_out(  	gvt_dbg_el("schedule out context id %x\n", ctx->context_id);  	if (WARN_ON(!same_context(ctx, execlist->running_context))) { -		gvt_err("schedule out context is not running context," +		gvt_vgpu_err("schedule out context is not running context,"  				"ctx id %x running ctx id %x\n",  				ctx->context_id,  				execlist->running_context->context_id); @@ -254,7 +255,7 @@ static struct intel_vgpu_execlist_slot *get_next_execlist_slot(  	status.udw = vgpu_vreg(vgpu, status_reg + 4);  	if (status.execlist_queue_full) { -		gvt_err("virtual execlist slots are full\n"); +		gvt_vgpu_err("virtual execlist slots are full\n");  		return NULL;  	} @@ -270,11 +271,12 @@ static int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist,  	struct execlist_ctx_descriptor_format *ctx0, *ctx1;  	struct execlist_context_status_format status; +	struct intel_vgpu *vgpu = execlist->vgpu;  	gvt_dbg_el("emulate schedule-in\n");  	if (!slot) { -		gvt_err("no available execlist slot\n"); +		gvt_vgpu_err("no available execlist slot\n");  		return -EINVAL;  	} @@ -375,7 +377,6 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload)  		vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, 4, 0);  		if (IS_ERR(vma)) { -			gvt_err("Cannot pin\n");  			return;  		} @@ -428,7 +429,6 @@ static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)  	vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL,  				       0, CACHELINE_BYTES, 0);  	if (IS_ERR(vma)) { -		gvt_err("Cannot pin indirect ctx obj\n");  		return;  	} @@ -561,6 +561,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload)  {  	struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc;  	struct intel_vgpu_mm *mm; +	struct intel_vgpu *vgpu = workload->vgpu;  	int page_table_level;  	u32 pdp[8]; @@ -569,7 +570,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload)  	} else if (desc->addressing_mode == 3) { /* legacy 64 bit */  		page_table_level = 4;  	} else { -		gvt_err("Advanced Context mode(SVM) is not supported!\n"); +		gvt_vgpu_err("Advanced Context mode(SVM) is not supported!\n");  		return -EINVAL;  	} @@ -583,7 +584,7 @@ static int prepare_mm(struct intel_vgpu_workload *workload)  		mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT,  				pdp, page_table_level, 0);  		if (IS_ERR(mm)) { -			gvt_err("fail to create mm object.\n"); +			gvt_vgpu_err("fail to create mm object.\n");  			return PTR_ERR(mm);  		}  	} @@ -609,7 +610,7 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,  	ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,  			(u32)((desc->lrca + 1) << GTT_PAGE_SHIFT));  	if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) { -		gvt_err("invalid guest context LRCA: %x\n", desc->lrca); +		gvt_vgpu_err("invalid guest context LRCA: %x\n", desc->lrca);  		return -EINVAL;  	} @@ -724,8 +725,7 @@ int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id)  			continue;  		if (!desc[i]->privilege_access) { -			gvt_err("vgpu%d: unexpected GGTT elsp submission\n", -					vgpu->id); +			gvt_vgpu_err("unexpected GGTT elsp submission\n");  			return -EINVAL;  		} @@ -735,15 +735,13 @@ int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id)  	}  	if (!valid_desc_bitmap) { -		gvt_err("vgpu%d: no valid desc in a elsp submission\n", -				vgpu->id); +		gvt_vgpu_err("no valid desc in a elsp submission\n");  		return -EINVAL;  	}  	if (!test_bit(0, (void *)&valid_desc_bitmap) &&  			test_bit(1, (void *)&valid_desc_bitmap)) { -		gvt_err("vgpu%d: weird elsp submission, desc 0 is not valid\n", -				vgpu->id); +		gvt_vgpu_err("weird elsp submission, desc 0 is not valid\n");  		return -EINVAL;  	} @@ -752,8 +750,7 @@ int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id)  		ret = submit_context(vgpu, ring_id, &valid_desc[i],  				emulate_schedule_in);  		if (ret) { -			gvt_err("vgpu%d: fail to schedule workload\n", -					vgpu->id); +			gvt_vgpu_err("fail to schedule workload\n");  			return ret;  		}  		emulate_schedule_in = false; @@ -778,7 +775,8 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)  			_EL_OFFSET_STATUS_PTR);  	ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg); -	ctx_status_ptr.read_ptr = ctx_status_ptr.write_ptr = 0x7; +	ctx_status_ptr.read_ptr = 0; +	ctx_status_ptr.write_ptr = 0x7;  	vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;  } diff --git a/drivers/gpu/drm/i915/gvt/firmware.c b/drivers/gpu/drm/i915/gvt/firmware.c index 1cb29b2d7dc6..dce8d15f706f 100644 --- a/drivers/gpu/drm/i915/gvt/firmware.c +++ b/drivers/gpu/drm/i915/gvt/firmware.c @@ -75,12 +75,12 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)  	struct gvt_firmware_header *h;  	void *firmware;  	void *p; -	unsigned long size; +	unsigned long size, crc32_start;  	int i;  	int ret; -	size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1; -	firmware = vmalloc(size); +	size = sizeof(*h) + info->mmio_size + info->cfg_space_size; +	firmware = vzalloc(size);  	if (!firmware)  		return -ENOMEM; @@ -112,6 +112,9 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)  	memcpy(gvt->firmware.mmio, p, info->mmio_size); +	crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4; +	h->crc32 = crc32_le(0, firmware + crc32_start, size - crc32_start); +  	firmware_attr.size = size;  	firmware_attr.private = firmware; @@ -234,7 +237,7 @@ int intel_gvt_load_firmware(struct intel_gvt *gvt)  	firmware->mmio = mem; -	sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%04x.golden_hw_state", +	sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%02x.golden_hw_state",  		 GVT_FIRMWARE_PATH, pdev->vendor, pdev->device,  		 pdev->revision); diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 28c92346db0e..b832bea64e03 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -49,8 +49,8 @@ bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size)  {  	if ((!vgpu_gmadr_is_valid(vgpu, addr)) || (size  			&& !vgpu_gmadr_is_valid(vgpu, addr + size - 1))) { -		gvt_err("vgpu%d: invalid range gmadr 0x%llx size 0x%x\n", -				vgpu->id, addr, size); +		gvt_vgpu_err("invalid range gmadr 0x%llx size 0x%x\n", +				addr, size);  		return false;  	}  	return true; @@ -430,7 +430,7 @@ static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p,  	mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);  	if (mfn == INTEL_GVT_INVALID_ADDR) { -		gvt_err("fail to translate gfn: 0x%lx\n", gfn); +		gvt_vgpu_err("fail to translate gfn: 0x%lx\n", gfn);  		return -ENXIO;  	} @@ -611,7 +611,7 @@ static inline int init_shadow_page(struct intel_vgpu *vgpu,  	daddr = dma_map_page(kdev, p->page, 0, 4096, PCI_DMA_BIDIRECTIONAL);  	if (dma_mapping_error(kdev, daddr)) { -		gvt_err("fail to map dma addr\n"); +		gvt_vgpu_err("fail to map dma addr\n");  		return -EINVAL;  	} @@ -735,7 +735,7 @@ retry:  		if (reclaim_one_mm(vgpu->gvt))  			goto retry; -		gvt_err("fail to allocate ppgtt shadow page\n"); +		gvt_vgpu_err("fail to allocate ppgtt shadow page\n");  		return ERR_PTR(-ENOMEM);  	} @@ -750,14 +750,14 @@ retry:  	 */  	ret = init_shadow_page(vgpu, &spt->shadow_page, type);  	if (ret) { -		gvt_err("fail to initialize shadow page for spt\n"); +		gvt_vgpu_err("fail to initialize shadow page for spt\n");  		goto err;  	}  	ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page,  			gfn, ppgtt_write_protection_handler, NULL);  	if (ret) { -		gvt_err("fail to initialize guest page for spt\n"); +		gvt_vgpu_err("fail to initialize guest page for spt\n");  		goto err;  	} @@ -776,8 +776,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page(  	if (p)  		return shadow_page_to_ppgtt_spt(p); -	gvt_err("vgpu%d: fail to find ppgtt shadow page: 0x%lx\n", -			vgpu->id, mfn); +	gvt_vgpu_err("fail to find ppgtt shadow page: 0x%lx\n", mfn);  	return NULL;  } @@ -827,8 +826,8 @@ static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu,  	}  	s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e));  	if (!s) { -		gvt_err("vgpu%d: fail to find shadow page: mfn: 0x%lx\n", -				vgpu->id, ops->get_pfn(e)); +		gvt_vgpu_err("fail to find shadow page: mfn: 0x%lx\n", +				ops->get_pfn(e));  		return -ENXIO;  	}  	return ppgtt_invalidate_shadow_page(s); @@ -836,6 +835,7 @@ static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu,  static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)  { +	struct intel_vgpu *vgpu = spt->vgpu;  	struct intel_gvt_gtt_entry e;  	unsigned long index;  	int ret; @@ -854,7 +854,7 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)  	for_each_present_shadow_entry(spt, &e, index) {  		if (!gtt_type_is_pt(get_next_pt_type(e.type))) { -			gvt_err("GVT doesn't support pse bit for now\n"); +			gvt_vgpu_err("GVT doesn't support pse bit for now\n");  			return -EINVAL;  		}  		ret = ppgtt_invalidate_shadow_page_by_shadow_entry( @@ -868,8 +868,8 @@ release:  	ppgtt_free_shadow_page(spt);  	return 0;  fail: -	gvt_err("vgpu%d: fail: shadow page %p shadow entry 0x%llx type %d\n", -			spt->vgpu->id, spt, e.val64, e.type); +	gvt_vgpu_err("fail: shadow page %p shadow entry 0x%llx type %d\n", +			spt, e.val64, e.type);  	return ret;  } @@ -914,8 +914,8 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(  	}  	return s;  fail: -	gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", -			vgpu->id, s, we->val64, we->type); +	gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n", +			s, we->val64, we->type);  	return ERR_PTR(ret);  } @@ -953,7 +953,7 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)  	for_each_present_guest_entry(spt, &ge, i) {  		if (!gtt_type_is_pt(get_next_pt_type(ge.type))) { -			gvt_err("GVT doesn't support pse bit now\n"); +			gvt_vgpu_err("GVT doesn't support pse bit now\n");  			ret = -EINVAL;  			goto fail;  		} @@ -969,8 +969,8 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)  	}  	return 0;  fail: -	gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", -			vgpu->id, spt, ge.val64, ge.type); +	gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n", +			spt, ge.val64, ge.type);  	return ret;  } @@ -999,7 +999,7 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,  		struct intel_vgpu_ppgtt_spt *s =  			ppgtt_find_shadow_page(vgpu, ops->get_pfn(&e));  		if (!s) { -			gvt_err("fail to find guest page\n"); +			gvt_vgpu_err("fail to find guest page\n");  			ret = -ENXIO;  			goto fail;  		} @@ -1011,8 +1011,8 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,  	ppgtt_set_shadow_entry(spt, &e, index);  	return 0;  fail: -	gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", -			vgpu->id, spt, e.val64, e.type); +	gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n", +			spt, e.val64, e.type);  	return ret;  } @@ -1046,8 +1046,8 @@ static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt,  	}  	return 0;  fail: -	gvt_err("vgpu%d: fail: spt %p guest entry 0x%llx type %d\n", vgpu->id, -			spt, we->val64, we->type); +	gvt_vgpu_err("fail: spt %p guest entry 0x%llx type %d\n", +		spt, we->val64, we->type);  	return ret;  } @@ -1250,8 +1250,8 @@ static int ppgtt_handle_guest_write_page_table(  	}  	return 0;  fail: -	gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d.\n", -			vgpu->id, spt, we->val64, we->type); +	gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d.\n", +			spt, we->val64, we->type);  	return ret;  } @@ -1493,7 +1493,7 @@ static int shadow_mm(struct intel_vgpu_mm *mm)  		spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge);  		if (IS_ERR(spt)) { -			gvt_err("fail to populate guest root pointer\n"); +			gvt_vgpu_err("fail to populate guest root pointer\n");  			ret = PTR_ERR(spt);  			goto fail;  		} @@ -1566,7 +1566,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,  	ret = gtt->mm_alloc_page_table(mm);  	if (ret) { -		gvt_err("fail to allocate page table for mm\n"); +		gvt_vgpu_err("fail to allocate page table for mm\n");  		goto fail;  	} @@ -1584,7 +1584,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,  	}  	return mm;  fail: -	gvt_err("fail to create mm\n"); +	gvt_vgpu_err("fail to create mm\n");  	if (mm)  		intel_gvt_mm_unreference(mm);  	return ERR_PTR(ret); @@ -1760,7 +1760,7 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)  			mm->page_table_level, gma, gpa);  	return gpa;  err: -	gvt_err("invalid mm type: %d gma %lx\n", mm->type, gma); +	gvt_vgpu_err("invalid mm type: %d gma %lx\n", mm->type, gma);  	return INTEL_GVT_INVALID_ADDR;  } @@ -1825,11 +1825,8 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,  	gma = g_gtt_index << GTT_PAGE_SHIFT;  	/* the VM may configure the whole GM space when ballooning is used */ -	if (WARN_ONCE(!vgpu_gmadr_is_valid(vgpu, gma), -				"vgpu%d: found oob ggtt write, offset %x\n", -				vgpu->id, off)) { +	if (!vgpu_gmadr_is_valid(vgpu, gma))  		return 0; -	}  	ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index); @@ -1839,13 +1836,16 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,  	if (ops->test_present(&e)) {  		ret = gtt_entry_p2m(vgpu, &e, &m);  		if (ret) { -			gvt_err("vgpu%d: fail to translate guest gtt entry\n", -					vgpu->id); -			return ret; +			gvt_vgpu_err("fail to translate guest gtt entry\n"); +			/* guest driver may read/write the entry when partial +			 * update the entry in this situation p2m will fail +			 * settting the shadow entry to point to a scratch page +			 */ +			ops->set_pfn(&m, gvt->gtt.scratch_ggtt_mfn);  		}  	} else {  		m = e; -		m.val64 = 0; +		ops->set_pfn(&m, gvt->gtt.scratch_ggtt_mfn);  	}  	ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index); @@ -1896,14 +1896,14 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu,  	scratch_pt = (void *)get_zeroed_page(GFP_KERNEL);  	if (!scratch_pt) { -		gvt_err("fail to allocate scratch page\n"); +		gvt_vgpu_err("fail to allocate scratch page\n");  		return -ENOMEM;  	}  	daddr = dma_map_page(dev, virt_to_page(scratch_pt), 0,  			4096, PCI_DMA_BIDIRECTIONAL);  	if (dma_mapping_error(dev, daddr)) { -		gvt_err("fail to dmamap scratch_pt\n"); +		gvt_vgpu_err("fail to dmamap scratch_pt\n");  		__free_page(virt_to_page(scratch_pt));  		return -ENOMEM;  	} @@ -2006,7 +2006,7 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)  	ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT,  			NULL, 1, 0);  	if (IS_ERR(ggtt_mm)) { -		gvt_err("fail to create mm for ggtt.\n"); +		gvt_vgpu_err("fail to create mm for ggtt.\n");  		return PTR_ERR(ggtt_mm);  	} @@ -2015,6 +2015,22 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)  	return create_scratch_page_tree(vgpu);  } +static void intel_vgpu_free_mm(struct intel_vgpu *vgpu, int type) +{ +	struct list_head *pos, *n; +	struct intel_vgpu_mm *mm; + +	list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) { +		mm = container_of(pos, struct intel_vgpu_mm, list); +		if (mm->type == type) { +			vgpu->gvt->gtt.mm_free_page_table(mm); +			list_del(&mm->list); +			list_del(&mm->lru_list); +			kfree(mm); +		} +	} +} +  /**   * intel_vgpu_clean_gtt - clean up per-vGPU graphics memory virulization   * @vgpu: a vGPU @@ -2027,19 +2043,11 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)   */  void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu)  { -	struct list_head *pos, *n; -	struct intel_vgpu_mm *mm; -  	ppgtt_free_all_shadow_page(vgpu);  	release_scratch_page_tree(vgpu); -	list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) { -		mm = container_of(pos, struct intel_vgpu_mm, list); -		vgpu->gvt->gtt.mm_free_page_table(mm); -		list_del(&mm->list); -		list_del(&mm->lru_list); -		kfree(mm); -	} +	intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT); +	intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_GGTT);  }  static void clean_spt_oos(struct intel_gvt *gvt) @@ -2071,7 +2079,6 @@ static int setup_spt_oos(struct intel_gvt *gvt)  	for (i = 0; i < preallocated_oos_pages; i++) {  		oos_page = kzalloc(sizeof(*oos_page), GFP_KERNEL);  		if (!oos_page) { -			gvt_err("fail to pre-allocate oos page\n");  			ret = -ENOMEM;  			goto fail;  		} @@ -2161,7 +2168,7 @@ int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,  		mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_PPGTT,  				pdp, page_table_level, 0);  		if (IS_ERR(mm)) { -			gvt_err("fail to create mm\n"); +			gvt_vgpu_err("fail to create mm\n");  			return PTR_ERR(mm);  		}  	} @@ -2191,7 +2198,7 @@ int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,  	mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp);  	if (!mm) { -		gvt_err("fail to find ppgtt instance.\n"); +		gvt_vgpu_err("fail to find ppgtt instance.\n");  		return -EINVAL;  	}  	intel_gvt_mm_unreference(mm); @@ -2322,6 +2329,13 @@ void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr)  	int i;  	ppgtt_free_all_shadow_page(vgpu); + +	/* Shadow pages are only created when there is no page +	 * table tracking data, so remove page tracking data after +	 * removing the shadow pages. +	 */ +	intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT); +  	if (!dmlr)  		return; diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 3b9d59e457ba..ef3baa0c4754 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -52,6 +52,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {  	.vgpu_create = intel_gvt_create_vgpu,  	.vgpu_destroy = intel_gvt_destroy_vgpu,  	.vgpu_reset = intel_gvt_reset_vgpu, +	.vgpu_activate = intel_gvt_activate_vgpu, +	.vgpu_deactivate = intel_gvt_deactivate_vgpu,  };  /** diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index e227caf5859e..becae2fa3b29 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -143,6 +143,8 @@ struct intel_vgpu {  	int id;  	unsigned long handle; /* vGPU handle used by hypervisor MPT modules */  	bool active; +	bool pv_notified; +	bool failsafe;  	bool resetting;  	void *sched_data; @@ -160,7 +162,6 @@ struct intel_vgpu {  	atomic_t running_workload_num;  	DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);  	struct i915_gem_context *shadow_ctx; -	struct notifier_block shadow_ctx_notifier_block;  #if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)  	struct { @@ -203,18 +204,18 @@ struct intel_gvt_firmware {  };  struct intel_gvt_opregion { -	void __iomem *opregion_va; +	void *opregion_va;  	u32 opregion_pa;  };  #define NR_MAX_INTEL_VGPU_TYPES 20  struct intel_vgpu_type {  	char name[16]; -	unsigned int max_instance;  	unsigned int avail_instance;  	unsigned int low_gm_size;  	unsigned int high_gm_size;  	unsigned int fence; +	enum intel_vgpu_edid resolution;  };  struct intel_gvt { @@ -231,6 +232,7 @@ struct intel_gvt {  	struct intel_gvt_gtt gtt;  	struct intel_gvt_opregion opregion;  	struct intel_gvt_workload_scheduler scheduler; +	struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];  	DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);  	struct intel_vgpu_type *types;  	unsigned int num_types; @@ -317,6 +319,7 @@ struct intel_vgpu_creation_params {  	__u64 low_gm_sz;  /* in MB */  	__u64 high_gm_sz; /* in MB */  	__u64 fence_sz; +	__u64 resolution;  	__s32 primary;  	__u64 vgpu_id;  }; @@ -379,7 +382,8 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu);  void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,  				 unsigned int engine_mask);  void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu); - +void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu); +void intel_gvt_deactivate_vgpu(struct intel_vgpu *vgpu);  /* validating GM functions */  #define vgpu_gmadr_is_aperture(vgpu, gmadr) \ @@ -446,9 +450,16 @@ struct intel_gvt_ops {  				struct intel_vgpu_type *);  	void (*vgpu_destroy)(struct intel_vgpu *);  	void (*vgpu_reset)(struct intel_vgpu *); +	void (*vgpu_activate)(struct intel_vgpu *); +	void (*vgpu_deactivate)(struct intel_vgpu *);  }; +enum { +	GVT_FAILSAFE_UNSUPPORTED_GUEST, +	GVT_FAILSAFE_INSUFFICIENT_RESOURCE, +}; +  #include "mpt.h"  #endif diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 1d450627ff65..6da9ae1618e3 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -121,6 +121,7 @@ static int new_mmio_info(struct intel_gvt *gvt,  		info->size = size;  		info->length = (i + 4) < end ? 4 : (end - i);  		info->addr_mask = addr_mask; +		info->ro_mask = ro_mask;  		info->device = device;  		info->read = read ? read : intel_vgpu_default_mmio_read;  		info->write = write ? write : intel_vgpu_default_mmio_write; @@ -150,15 +151,42 @@ static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg)  #define fence_num_to_offset(num) \  	(num * 8 + i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) + +static void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason) +{ +	switch (reason) { +	case GVT_FAILSAFE_UNSUPPORTED_GUEST: +		pr_err("Detected your guest driver doesn't support GVT-g.\n"); +		break; +	case GVT_FAILSAFE_INSUFFICIENT_RESOURCE: +		pr_err("Graphics resource is not enough for the guest\n"); +	default: +		break; +	} +	pr_err("Now vgpu %d will enter failsafe mode.\n", vgpu->id); +	vgpu->failsafe = true; +} +  static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu,  		unsigned int fence_num, void *p_data, unsigned int bytes)  {  	if (fence_num >= vgpu_fence_sz(vgpu)) { -		gvt_err("vgpu%d: found oob fence register access\n", -				vgpu->id); -		gvt_err("vgpu%d: total fence num %d access fence num %d\n", -				vgpu->id, vgpu_fence_sz(vgpu), fence_num); + +		/* When guest access oob fence regs without access +		 * pv_info first, we treat guest not supporting GVT, +		 * and we will let vgpu enter failsafe mode. +		 */ +		if (!vgpu->pv_notified) +			enter_failsafe_mode(vgpu, +					GVT_FAILSAFE_UNSUPPORTED_GUEST); + +		if (!vgpu->mmio.disable_warn_untrack) { +			gvt_vgpu_err("found oob fence register access\n"); +			gvt_vgpu_err("total fence %d, access fence %d\n", +					vgpu_fence_sz(vgpu), fence_num); +		}  		memset(p_data, 0, bytes); +		return -EINVAL;  	}  	return 0;  } @@ -219,7 +247,7 @@ static int mul_force_wake_write(struct intel_vgpu *vgpu,  			break;  		default:  			/*should not hit here*/ -			gvt_err("invalid forcewake offset 0x%x\n", offset); +			gvt_vgpu_err("invalid forcewake offset 0x%x\n", offset);  			return -EINVAL;  		}  	} else { @@ -369,6 +397,74 @@ static int pipeconf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  	return 0;  } +/* ascendingly sorted */ +static i915_reg_t force_nonpriv_white_list[] = { +	GEN9_CS_DEBUG_MODE1, //_MMIO(0x20ec) +	GEN9_CTX_PREEMPT_REG,//_MMIO(0x2248) +	GEN8_CS_CHICKEN1,//_MMIO(0x2580) +	_MMIO(0x2690), +	_MMIO(0x2694), +	_MMIO(0x2698), +	_MMIO(0x4de0), +	_MMIO(0x4de4), +	_MMIO(0x4dfc), +	GEN7_COMMON_SLICE_CHICKEN1,//_MMIO(0x7010) +	_MMIO(0x7014), +	HDC_CHICKEN0,//_MMIO(0x7300) +	GEN8_HDC_CHICKEN1,//_MMIO(0x7304) +	_MMIO(0x7700), +	_MMIO(0x7704), +	_MMIO(0x7708), +	_MMIO(0x770c), +	_MMIO(0xb110), +	GEN8_L3SQCREG4,//_MMIO(0xb118) +	_MMIO(0xe100), +	_MMIO(0xe18c), +	_MMIO(0xe48c), +	_MMIO(0xe5f4), +}; + +/* a simple bsearch */ +static inline bool in_whitelist(unsigned int reg) +{ +	int left = 0, right = ARRAY_SIZE(force_nonpriv_white_list); +	i915_reg_t *array = force_nonpriv_white_list; + +	while (left < right) { +		int mid = (left + right)/2; + +		if (reg > array[mid].reg) +			left = mid + 1; +		else if (reg < array[mid].reg) +			right = mid; +		else +			return true; +	} +	return false; +} + +static int force_nonpriv_write(struct intel_vgpu *vgpu, +	unsigned int offset, void *p_data, unsigned int bytes) +{ +	u32 reg_nonpriv = *(u32 *)p_data; +	int ret = -EINVAL; + +	if ((bytes != 4) || ((offset & (bytes - 1)) != 0)) { +		gvt_err("vgpu(%d) Invalid FORCE_NONPRIV offset %x(%dB)\n", +			vgpu->id, offset, bytes); +		return ret; +	} + +	if (in_whitelist(reg_nonpriv)) { +		ret = intel_vgpu_default_mmio_write(vgpu, offset, p_data, +			bytes); +	} else { +		gvt_err("vgpu(%d) Invalid FORCE_NONPRIV write %x\n", +			vgpu->id, reg_nonpriv); +	} +	return ret; +} +  static int ddi_buf_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  		void *p_data, unsigned int bytes)  { @@ -432,7 +528,7 @@ static int check_fdi_rx_train_status(struct intel_vgpu *vgpu,  		fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_2;  		fdi_iir_check_bits = FDI_RX_SYMBOL_LOCK;  	} else { -		gvt_err("Invalid train pattern %d\n", train_pattern); +		gvt_vgpu_err("Invalid train pattern %d\n", train_pattern);  		return -EINVAL;  	} @@ -490,7 +586,7 @@ static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu,  	else if (FDI_RX_IMR_TO_PIPE(offset) != INVALID_INDEX)  		index = FDI_RX_IMR_TO_PIPE(offset);  	else { -		gvt_err("Unsupport registers %x\n", offset); +		gvt_vgpu_err("Unsupport registers %x\n", offset);  		return -EINVAL;  	} @@ -720,7 +816,7 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,  	u32 data;  	if (!dpy_is_valid_port(port_index)) { -		gvt_err("GVT(%d): Unsupported DP port access!\n", vgpu->id); +		gvt_vgpu_err("Unsupported DP port access!\n");  		return 0;  	} @@ -874,6 +970,14 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,  	return 0;  } +static int mbctl_write(struct intel_vgpu *vgpu, unsigned int offset, +		void *p_data, unsigned int bytes) +{ +	*(u32 *)p_data &= (~GEN6_MBCTL_ENABLE_BOOT_FETCH); +	write_vreg(vgpu, offset, p_data, bytes); +	return 0; +} +  static int vga_control_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  		void *p_data, unsigned int bytes)  { @@ -918,8 +1022,7 @@ static void write_virtual_sbi_register(struct intel_vgpu *vgpu,  	if (i == num) {  		if (num == SBI_REG_MAX) { -			gvt_err("vgpu%d: SBI caching meets maximum limits\n", -					vgpu->id); +			gvt_vgpu_err("SBI caching meets maximum limits\n");  			return;  		}  		display->sbi.number++; @@ -999,8 +1102,9 @@ static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,  		break;  	}  	if (invalid_read) -		gvt_err("invalid pvinfo read: [%x:%x] = %x\n", +		gvt_vgpu_err("invalid pvinfo read: [%x:%x] = %x\n",  				offset, bytes, *(u32 *)p_data); +	vgpu->pv_notified = true;  	return 0;  } @@ -1026,7 +1130,7 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification)  	case 1:	/* Remove this in guest driver. */  		break;  	default: -		gvt_err("Invalid PV notification %d\n", notification); +		gvt_vgpu_err("Invalid PV notification %d\n", notification);  	}  	return ret;  } @@ -1039,7 +1143,7 @@ static int send_display_ready_uevent(struct intel_vgpu *vgpu, int ready)  	char vmid_str[20];  	char display_ready_str[20]; -	snprintf(display_ready_str, 20, "GVT_DISPLAY_READY=%d\n", ready); +	snprintf(display_ready_str, 20, "GVT_DISPLAY_READY=%d", ready);  	env[0] = display_ready_str;  	snprintf(vmid_str, 20, "VMID=%d", vgpu->id); @@ -1078,8 +1182,11 @@ static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  	case _vgtif_reg(execlist_context_descriptor_lo):  	case _vgtif_reg(execlist_context_descriptor_hi):  		break; +	case _vgtif_reg(rsv5[0])..._vgtif_reg(rsv5[3]): +		enter_failsafe_mode(vgpu, GVT_FAILSAFE_INSUFFICIENT_RESOURCE); +		break;  	default: -		gvt_err("invalid pvinfo write offset %x bytes %x data %x\n", +		gvt_vgpu_err("invalid pvinfo write offset %x bytes %x data %x\n",  				offset, bytes, data);  		break;  	} @@ -1203,26 +1310,37 @@ static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset,  	u32 *data0 = &vgpu_vreg(vgpu, GEN6_PCODE_DATA);  	switch (cmd) { -	case 0x6: -		/** -		 * "Read memory latency" command on gen9. -		 * Below memory latency values are read -		 * from skylake platform. -		 */ -		if (!*data0) -			*data0 = 0x1e1a1100; -		else -			*data0 = 0x61514b3d; +	case GEN9_PCODE_READ_MEM_LATENCY: +		if (IS_SKYLAKE(vgpu->gvt->dev_priv)) { +			/** +			 * "Read memory latency" command on gen9. +			 * Below memory latency values are read +			 * from skylake platform. +			 */ +			if (!*data0) +				*data0 = 0x1e1a1100; +			else +				*data0 = 0x61514b3d; +		} +		break; +	case SKL_PCODE_CDCLK_CONTROL: +		if (IS_SKYLAKE(vgpu->gvt->dev_priv)) +			*data0 = SKL_CDCLK_READY_FOR_CHANGE;  		break; -	case 0x5: +	case GEN6_PCODE_READ_RC6VIDS:  		*data0 |= 0x1;  		break;  	}  	gvt_dbg_core("VM(%d) write %x to mailbox, return data0 %x\n",  		     vgpu->id, value, *data0); - -	value &= ~(1 << 31); +	/** +	 * PCODE_READY clear means ready for pcode read/write, +	 * PCODE_ERROR_MASK clear means no error happened. In GVT-g we +	 * always emulate as pcode read/write success and ready for access +	 * anytime, since we don't touch real physical registers here. +	 */ +	value &= ~(GEN6_PCODE_READY | GEN6_PCODE_ERROR_MASK);  	return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes);  } @@ -1302,7 +1420,8 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  	if (execlist->elsp_dwords.index == 3) {  		ret = intel_vgpu_submit_execlist(vgpu, ring_id);  		if(ret) -			gvt_err("fail submit workload on ring %d\n", ring_id); +			gvt_vgpu_err("fail submit workload on ring %d\n", +				ring_id);  	}  	++execlist->elsp_dwords.index; @@ -1318,6 +1437,17 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  	bool enable_execlist;  	write_vreg(vgpu, offset, p_data, bytes); + +	/* when PPGTT mode enabled, we will check if guest has called +	 * pvinfo, if not, we will treat this guest as non-gvtg-aware +	 * guest, and stop emulating its cfg space, mmio, gtt, etc. +	 */ +	if (((data & _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)) || +			(data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE))) +			&& !vgpu->pv_notified) { +		enter_failsafe_mode(vgpu, GVT_FAILSAFE_UNSUPPORTED_GUEST); +		return 0; +	}  	if ((data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE))  			|| (data & _MASKED_BIT_DISABLE(GFX_RUN_LIST_ENABLE))) {  		enable_execlist = !!(data & GFX_RUN_LIST_ENABLE); @@ -1400,6 +1530,9 @@ static int ring_reset_ctl_write(struct intel_vgpu *vgpu,  #define MMIO_GM(reg, d, r, w) \  	MMIO_F(reg, 4, F_GMADR, 0xFFFFF000, 0, d, r, w) +#define MMIO_GM_RDR(reg, d, r, w) \ +	MMIO_F(reg, 4, F_GMADR | F_CMD_ACCESS, 0xFFFFF000, 0, d, r, w) +  #define MMIO_RO(reg, d, f, rm, r, w) \  	MMIO_F(reg, 4, F_RO | f, 0, rm, d, r, w) @@ -1419,6 +1552,9 @@ static int ring_reset_ctl_write(struct intel_vgpu *vgpu,  #define MMIO_RING_GM(prefix, d, r, w) \  	MMIO_RING_F(prefix, 4, F_GMADR, 0xFFFF0000, 0, d, r, w) +#define MMIO_RING_GM_RDR(prefix, d, r, w) \ +	MMIO_RING_F(prefix, 4, F_GMADR | F_CMD_ACCESS, 0xFFFF0000, 0, d, r, w) +  #define MMIO_RING_RO(prefix, d, f, rm, r, w) \  	MMIO_RING_F(prefix, 4, F_RO | f, 0, rm, d, r, w) @@ -1427,73 +1563,81 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)  	struct drm_i915_private *dev_priv = gvt->dev_priv;  	int ret; -	MMIO_RING_DFH(RING_IMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler); +	MMIO_RING_DFH(RING_IMR, D_ALL, F_CMD_ACCESS, NULL, +		intel_vgpu_reg_imr_handler);  	MMIO_DFH(SDEIMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler);  	MMIO_DFH(SDEIER, D_ALL, 0, NULL, intel_vgpu_reg_ier_handler);  	MMIO_DFH(SDEIIR, D_ALL, 0, NULL, intel_vgpu_reg_iir_handler);  	MMIO_D(SDEISR, D_ALL); -	MMIO_RING_D(RING_HWSTAM, D_ALL); +	MMIO_RING_DFH(RING_HWSTAM, D_ALL, F_CMD_ACCESS, NULL, NULL); -	MMIO_GM(RENDER_HWS_PGA_GEN7, D_ALL, NULL, NULL); -	MMIO_GM(BSD_HWS_PGA_GEN7, D_ALL, NULL, NULL); -	MMIO_GM(BLT_HWS_PGA_GEN7, D_ALL, NULL, NULL); -	MMIO_GM(VEBOX_HWS_PGA_GEN7, D_ALL, NULL, NULL); +	MMIO_GM_RDR(RENDER_HWS_PGA_GEN7, D_ALL, NULL, NULL); +	MMIO_GM_RDR(BSD_HWS_PGA_GEN7, D_ALL, NULL, NULL); +	MMIO_GM_RDR(BLT_HWS_PGA_GEN7, D_ALL, NULL, NULL); +	MMIO_GM_RDR(VEBOX_HWS_PGA_GEN7, D_ALL, NULL, NULL);  #define RING_REG(base) (base + 0x28) -	MMIO_RING_D(RING_REG, D_ALL); +	MMIO_RING_DFH(RING_REG, D_ALL, F_CMD_ACCESS, NULL, NULL);  #undef RING_REG  #define RING_REG(base) (base + 0x134) -	MMIO_RING_D(RING_REG, D_ALL); +	MMIO_RING_DFH(RING_REG, D_ALL, F_CMD_ACCESS, NULL, NULL);  #undef RING_REG -	MMIO_GM(0x2148, D_ALL, NULL, NULL); -	MMIO_GM(CCID, D_ALL, NULL, NULL); -	MMIO_GM(0x12198, D_ALL, NULL, NULL); +	MMIO_GM_RDR(0x2148, D_ALL, NULL, NULL); +	MMIO_GM_RDR(CCID, D_ALL, NULL, NULL); +	MMIO_GM_RDR(0x12198, D_ALL, NULL, NULL);  	MMIO_D(GEN7_CXT_SIZE, D_ALL); -	MMIO_RING_D(RING_TAIL, D_ALL); -	MMIO_RING_D(RING_HEAD, D_ALL); -	MMIO_RING_D(RING_CTL, D_ALL); -	MMIO_RING_D(RING_ACTHD, D_ALL); -	MMIO_RING_GM(RING_START, D_ALL, NULL, NULL); +	MMIO_RING_DFH(RING_TAIL, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_RING_DFH(RING_HEAD, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_RING_DFH(RING_CTL, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_RING_DFH(RING_ACTHD, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_RING_GM_RDR(RING_START, D_ALL, NULL, NULL);  	/* RING MODE */  #define RING_REG(base) (base + 0x29c) -	MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, ring_mode_mmio_write); +	MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, +		ring_mode_mmio_write);  #undef RING_REG -	MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK, NULL, NULL); -	MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK, NULL, NULL); +	MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK | F_CMD_ACCESS, +		NULL, NULL); +	MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK | F_CMD_ACCESS, +			NULL, NULL);  	MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS,  			ring_timestamp_mmio_read, NULL);  	MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS,  			ring_timestamp_mmio_read, NULL); -	MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK, NULL, NULL); -	MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK, NULL, NULL); +	MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK | F_CMD_ACCESS, +		NULL, NULL);  	MMIO_DFH(CACHE_MODE_1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(CACHE_MODE_0, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x2124, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); -	MMIO_DFH(0x20dc, D_ALL, F_MODE_MASK, NULL, NULL); -	MMIO_DFH(_3D_CHICKEN3, D_ALL, F_MODE_MASK, NULL, NULL); -	MMIO_DFH(0x2088, D_ALL, F_MODE_MASK, NULL, NULL); -	MMIO_DFH(0x20e4, D_ALL, F_MODE_MASK, NULL, NULL); -	MMIO_DFH(0x2470, D_ALL, F_MODE_MASK, NULL, NULL); -	MMIO_D(GAM_ECOCHK, D_ALL); -	MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK, NULL, NULL); +	MMIO_DFH(0x20dc, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(_3D_CHICKEN3, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x2088, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x20e4, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x2470, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(GAM_ECOCHK, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, +		NULL, NULL);  	MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); -	MMIO_D(0x9030, D_ALL); -	MMIO_D(0x20a0, D_ALL); -	MMIO_D(0x2420, D_ALL); -	MMIO_D(0x2430, D_ALL); -	MMIO_D(0x2434, D_ALL); -	MMIO_D(0x2438, D_ALL); -	MMIO_D(0x243c, D_ALL); -	MMIO_DFH(0x7018, D_ALL, F_MODE_MASK, NULL, NULL); +	MMIO_DFH(0x9030, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x20a0, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x2420, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x2430, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x2434, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x2438, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x243c, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x7018, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(HALF_SLICE_CHICKEN3, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); -	MMIO_DFH(0xe100, D_ALL, F_MODE_MASK, NULL, NULL); +	MMIO_DFH(GEN7_HALF_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);  	/* display */  	MMIO_F(0x60220, 0x20, 0, 0, 0, D_ALL, NULL, NULL); @@ -2022,8 +2166,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)  	MMIO_D(FORCEWAKE_ACK, D_ALL);  	MMIO_D(GEN6_GT_CORE_STATUS, D_ALL);  	MMIO_D(GEN6_GT_THREAD_STATUS_REG, D_ALL); -	MMIO_D(GTFIFODBG, D_ALL); -	MMIO_D(GTFIFOCTL, D_ALL); +	MMIO_DFH(GTFIFODBG, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(GTFIFOCTL, D_ALL, F_CMD_ACCESS, NULL, NULL);  	MMIO_DH(FORCEWAKE_MT, D_PRE_SKL, NULL, mul_force_wake_write);  	MMIO_DH(FORCEWAKE_ACK_HSW, D_HSW | D_BDW, NULL, NULL);  	MMIO_D(ECOBUS, D_ALL); @@ -2080,7 +2224,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)  	MMIO_F(0x4f000, 0x90, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_D(GEN6_PCODE_MAILBOX, D_PRE_SKL); +	MMIO_D(GEN6_PCODE_MAILBOX, D_PRE_BDW);  	MMIO_D(GEN6_PCODE_DATA, D_ALL);  	MMIO_D(0x13812c, D_ALL);  	MMIO_DH(GEN7_ERR_INT, D_ALL, NULL, NULL); @@ -2102,7 +2246,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)  	MMIO_D(0x7180, D_ALL);  	MMIO_D(0x7408, D_ALL);  	MMIO_D(0x7c00, D_ALL); -	MMIO_D(GEN6_MBCTL, D_ALL); +	MMIO_DH(GEN6_MBCTL, D_ALL, NULL, mbctl_write);  	MMIO_D(0x911c, D_ALL);  	MMIO_D(0x9120, D_ALL);  	MMIO_DFH(GEN7_UCGCTL4, D_ALL, F_CMD_ACCESS, NULL, NULL); @@ -2159,36 +2303,35 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)  	MMIO_D(0x1a054, D_ALL);  	MMIO_D(0x44070, D_ALL); - -	MMIO_D(0x215c, D_HSW_PLUS); +	MMIO_DFH(0x215c, D_HSW_PLUS, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0x2178, D_ALL, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0x217c, D_ALL, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0x12178, D_ALL, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0x1217c, D_ALL, F_CMD_ACCESS, NULL, NULL); -	MMIO_F(0x2290, 8, 0, 0, 0, D_HSW_PLUS, NULL, NULL); -	MMIO_D(GEN7_OACONTROL, D_HSW); +	MMIO_F(0x2290, 8, F_CMD_ACCESS, 0, 0, D_HSW_PLUS, NULL, NULL); +	MMIO_DFH(GEN7_OACONTROL, D_HSW, F_CMD_ACCESS, NULL, NULL);  	MMIO_D(0x2b00, D_BDW_PLUS);  	MMIO_D(0x2360, D_BDW_PLUS); -	MMIO_F(0x5200, 32, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(0x5240, 32, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(0x5280, 16, 0, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(0x5200, 32, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(0x5240, 32, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(0x5280, 16, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL);  	MMIO_DFH(0x1c17c, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0x1c178, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); -	MMIO_D(BCS_SWCTRL, D_ALL); +	MMIO_DFH(BCS_SWCTRL, D_ALL, F_CMD_ACCESS, NULL, NULL); -	MMIO_F(HS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(DS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(IA_VERTICES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(IA_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(VS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(GS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(GS_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(CL_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(CL_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(PS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); -	MMIO_F(PS_DEPTH_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(HS_INVOCATION_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(DS_INVOCATION_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(IA_VERTICES_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(IA_PRIMITIVES_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(VS_INVOCATION_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(GS_INVOCATION_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(GS_PRIMITIVES_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(CL_INVOCATION_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(CL_PRIMITIVES_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(PS_INVOCATION_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL); +	MMIO_F(PS_DEPTH_COUNT, 8, F_CMD_ACCESS, 0, 0, D_ALL, NULL, NULL);  	MMIO_DH(0x4260, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);  	MMIO_DH(0x4264, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);  	MMIO_DH(0x4268, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); @@ -2196,6 +2339,17 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)  	MMIO_DH(0x4270, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);  	MMIO_DFH(0x4094, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(ARB_MODE, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_RING_GM_RDR(RING_BBADDR, D_ALL, NULL, NULL); +	MMIO_DFH(0x2220, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x12220, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x22220, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_RING_DFH(RING_SYNC_1, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_RING_DFH(RING_SYNC_0, D_ALL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x22178, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x1a178, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x1a17c, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x2217c, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  	return 0;  } @@ -2204,7 +2358,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  	struct drm_i915_private *dev_priv = gvt->dev_priv;  	int ret; -	MMIO_DH(RING_IMR(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, +	MMIO_DFH(RING_IMR(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, NULL,  			intel_vgpu_reg_imr_handler);  	MMIO_DH(GEN8_GT_IMR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); @@ -2269,24 +2423,31 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  	MMIO_DH(GEN8_MASTER_IRQ, D_BDW_PLUS, NULL,  		intel_vgpu_reg_master_irq_handler); -	MMIO_D(RING_HWSTAM(GEN8_BSD2_RING_BASE), D_BDW_PLUS); -	MMIO_D(0x1c134, D_BDW_PLUS); +	MMIO_DFH(RING_HWSTAM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, +		F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x1c134, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); -	MMIO_D(RING_TAIL(GEN8_BSD2_RING_BASE), D_BDW_PLUS); -	MMIO_D(RING_HEAD(GEN8_BSD2_RING_BASE),  D_BDW_PLUS); -	MMIO_GM(RING_START(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL); -	MMIO_D(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS); -	MMIO_D(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS); -	MMIO_D(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS); -	MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, ring_mode_mmio_write); -	MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, -			NULL, NULL); -	MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, -			NULL, NULL); +	MMIO_DFH(RING_TAIL(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, +		NULL, NULL); +	MMIO_DFH(RING_HEAD(GEN8_BSD2_RING_BASE),  D_BDW_PLUS, +		F_CMD_ACCESS, NULL, NULL); +	MMIO_GM_RDR(RING_START(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL); +	MMIO_DFH(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, +		NULL, NULL); +	MMIO_DFH(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS, +		F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS, +		F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, +		ring_mode_mmio_write); +	MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, +		F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, +		F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS,  			ring_timestamp_mmio_read, NULL); -	MMIO_RING_D(RING_ACTHD_UDW, D_BDW_PLUS); +	MMIO_RING_DFH(RING_ACTHD_UDW, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  #define RING_REG(base) (base + 0xd0)  	MMIO_RING_F(RING_REG, 4, F_RO, 0, @@ -2303,13 +2464,16 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  #undef RING_REG  #define RING_REG(base) (base + 0x234) -	MMIO_RING_F(RING_REG, 8, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL); -	MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0, ~0LL, D_BDW_PLUS, NULL, NULL); +	MMIO_RING_F(RING_REG, 8, F_RO | F_CMD_ACCESS, 0, ~0, D_BDW_PLUS, +		NULL, NULL); +	MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO | F_CMD_ACCESS, 0, +		~0LL, D_BDW_PLUS, NULL, NULL);  #undef RING_REG  #define RING_REG(base) (base + 0x244) -	MMIO_RING_D(RING_REG, D_BDW_PLUS); -	MMIO_D(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS); +	MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, +		NULL, NULL);  #undef RING_REG  #define RING_REG(base) (base + 0x370) @@ -2331,6 +2495,8 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  	MMIO_D(GEN7_MISCCPCTL, D_BDW_PLUS);  	MMIO_D(0x1c054, D_BDW_PLUS); +	MMIO_DH(GEN6_PCODE_MAILBOX, D_BDW_PLUS, NULL, mailbox_write); +  	MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS);  	MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS); @@ -2341,14 +2507,14 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  	MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL);  #undef RING_REG -	MMIO_RING_GM(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL); -	MMIO_GM(0x1c080, D_BDW_PLUS, NULL, NULL); +	MMIO_RING_GM_RDR(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL); +	MMIO_GM_RDR(RING_HWS_PGA(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL);  	MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); -	MMIO_D(CHICKEN_PIPESL_1(PIPE_A), D_BDW); -	MMIO_D(CHICKEN_PIPESL_1(PIPE_B), D_BDW); -	MMIO_D(CHICKEN_PIPESL_1(PIPE_C), D_BDW); +	MMIO_D(CHICKEN_PIPESL_1(PIPE_A), D_BDW_PLUS); +	MMIO_D(CHICKEN_PIPESL_1(PIPE_B), D_BDW_PLUS); +	MMIO_D(CHICKEN_PIPESL_1(PIPE_C), D_BDW_PLUS);  	MMIO_D(WM_MISC, D_BDW);  	MMIO_D(BDW_EDP_PSR_BASE, D_BDW); @@ -2362,27 +2528,31 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  	MMIO_D(GEN8_EU_DISABLE1, D_BDW_PLUS);  	MMIO_D(GEN8_EU_DISABLE2, D_BDW_PLUS); -	MMIO_D(0xfdc, D_BDW); -	MMIO_DFH(GEN8_ROW_CHICKEN, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); -	MMIO_D(GEN7_ROW_CHICKEN2, D_BDW_PLUS); -	MMIO_D(GEN8_UCGCTL6, D_BDW_PLUS); +	MMIO_D(0xfdc, D_BDW_PLUS); +	MMIO_DFH(GEN8_ROW_CHICKEN, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, +		NULL, NULL); +	MMIO_DFH(GEN7_ROW_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, +		NULL, NULL); +	MMIO_DFH(GEN8_UCGCTL6, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); -	MMIO_D(0xb1f0, D_BDW); -	MMIO_D(0xb1c0, D_BDW); +	MMIO_DFH(0xb1f0, D_BDW, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xb1c0, D_BDW, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(GEN8_L3SQCREG4, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); -	MMIO_D(0xb100, D_BDW); -	MMIO_D(0xb10c, D_BDW); +	MMIO_DFH(0xb100, D_BDW, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xb10c, D_BDW, F_CMD_ACCESS, NULL, NULL);  	MMIO_D(0xb110, D_BDW); -	MMIO_DFH(0x24d0, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); -	MMIO_DFH(0x24d4, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); -	MMIO_DFH(0x24d8, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); -	MMIO_DFH(0x24dc, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_F(0x24d0, 48, F_CMD_ACCESS, 0, 0, D_BDW_PLUS, +		NULL, force_nonpriv_write); + +	MMIO_D(0x22040, D_BDW_PLUS); +	MMIO_D(0x44484, D_BDW_PLUS); +	MMIO_D(0x4448c, D_BDW_PLUS); -	MMIO_D(0x83a4, D_BDW); +	MMIO_DFH(0x83a4, D_BDW, F_CMD_ACCESS, NULL, NULL);  	MMIO_D(GEN8_L3_LRA_1_GPGPU, D_BDW_PLUS); -	MMIO_D(0x8430, D_BDW); +	MMIO_DFH(0x8430, D_BDW, F_CMD_ACCESS, NULL, NULL);  	MMIO_D(0x110000, D_BDW_PLUS); @@ -2394,10 +2564,19 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)  	MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(HALF_SLICE_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); -	MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); +	MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); -	MMIO_D(0x2248, D_BDW); +	MMIO_DFH(0x2248, D_BDW, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe220, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe230, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe240, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe260, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe270, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe280, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe2a0, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe2b0, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0xe2c0, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  	return 0;  } @@ -2420,7 +2599,6 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)  	MMIO_D(HSW_PWR_WELL_BIOS, D_SKL);  	MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, skl_power_well_ctl_write); -	MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL, NULL, mailbox_write);  	MMIO_D(0xa210, D_SKL_PLUS);  	MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS);  	MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); @@ -2578,16 +2756,16 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)  	MMIO_F(0xb020, 0x80, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL);  	MMIO_D(0xd08, D_SKL); -	MMIO_D(0x20e0, D_SKL); -	MMIO_D(0x20ec, D_SKL); +	MMIO_DFH(0x20e0, D_SKL, F_MODE_MASK, NULL, NULL); +	MMIO_DFH(0x20ec, D_SKL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);  	/* TRTT */ -	MMIO_D(0x4de0, D_SKL); -	MMIO_D(0x4de4, D_SKL); -	MMIO_D(0x4de8, D_SKL); -	MMIO_D(0x4dec, D_SKL); -	MMIO_D(0x4df0, D_SKL); -	MMIO_DH(0x4df4, D_SKL, NULL, gen9_trtte_write); +	MMIO_DFH(0x4de0, D_SKL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x4de4, D_SKL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x4de8, D_SKL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x4dec, D_SKL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x4df0, D_SKL, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(0x4df4, D_SKL, F_CMD_ACCESS, NULL, gen9_trtte_write);  	MMIO_DH(0x4dfc, D_SKL, NULL, gen9_trtt_chicken_write);  	MMIO_D(0x45008, D_SKL); @@ -2611,7 +2789,7 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)  	MMIO_D(0x65f08, D_SKL);  	MMIO_D(0x320f0, D_SKL); -	MMIO_D(_REG_VCS2_EXCC, D_SKL); +	MMIO_DFH(_REG_VCS2_EXCC, D_SKL, F_CMD_ACCESS, NULL, NULL);  	MMIO_D(0x70034, D_SKL);  	MMIO_D(0x71034, D_SKL);  	MMIO_D(0x72034, D_SKL); @@ -2624,6 +2802,9 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)  	MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL);  	MMIO_D(0x44500, D_SKL); +	MMIO_DFH(GEN9_CSFE_CHICKEN1_RCS, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); +	MMIO_DFH(GEN8_HDC_CHICKEN1, D_SKL, F_MODE_MASK | F_CMD_ACCESS, +		NULL, NULL);  	return 0;  } @@ -2813,3 +2994,20 @@ int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  	write_vreg(vgpu, offset, p_data, bytes);  	return 0;  } + +/** + * intel_gvt_in_force_nonpriv_whitelist - if a mmio is in whitelist to be + * force-nopriv register + * + * @gvt: a GVT device + * @offset: register offset + * + * Returns: + * True if the register is in force-nonpriv whitelist; + * False if outside; + */ +bool intel_gvt_in_force_nonpriv_whitelist(struct intel_gvt *gvt, +					  unsigned int offset) +{ +	return in_whitelist(offset); +} diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 0f7f5d97f582..e466259034e2 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -96,10 +96,10 @@ static int gvt_dma_map_iova(struct intel_vgpu *vgpu, kvm_pfn_t pfn,  	struct device *dev = &vgpu->gvt->dev_priv->drm.pdev->dev;  	dma_addr_t daddr; -	page = pfn_to_page(pfn); -	if (is_error_page(page)) +	if (unlikely(!pfn_valid(pfn)))  		return -EFAULT; +	page = pfn_to_page(pfn);  	daddr = dma_map_page(dev, page, 0, PAGE_SIZE,  			PCI_DMA_BIDIRECTIONAL);  	if (dma_mapping_error(dev, daddr)) @@ -295,10 +295,10 @@ static ssize_t description_show(struct kobject *kobj, struct device *dev,  		return 0;  	return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n" -				"fence: %d\n", -				BYTES_TO_MB(type->low_gm_size), -				BYTES_TO_MB(type->high_gm_size), -				type->fence); +		       "fence: %d\nresolution: %s\n", +		       BYTES_TO_MB(type->low_gm_size), +		       BYTES_TO_MB(type->high_gm_size), +		       type->fence, vgpu_edid_str(type->resolution));  }  static MDEV_TYPE_ATTR_RO(available_instances); @@ -426,7 +426,7 @@ static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,  static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)  { -	struct intel_vgpu *vgpu; +	struct intel_vgpu *vgpu = NULL;  	struct intel_vgpu_type *type;  	struct device *pdev;  	void *gvt; @@ -437,7 +437,7 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)  	type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));  	if (!type) { -		gvt_err("failed to find type %s to create\n", +		gvt_vgpu_err("failed to find type %s to create\n",  						kobject_name(kobj));  		ret = -EINVAL;  		goto out; @@ -446,7 +446,7 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)  	vgpu = intel_gvt_ops->vgpu_create(gvt, type);  	if (IS_ERR_OR_NULL(vgpu)) {  		ret = vgpu == NULL ? -EFAULT : PTR_ERR(vgpu); -		gvt_err("failed to create intel vgpu: %d\n", ret); +		gvt_vgpu_err("failed to create intel vgpu: %d\n", ret);  		goto out;  	} @@ -526,7 +526,8 @@ static int intel_vgpu_open(struct mdev_device *mdev)  	ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, &events,  				&vgpu->vdev.iommu_notifier);  	if (ret != 0) { -		gvt_err("vfio_register_notifier for iommu failed: %d\n", ret); +		gvt_vgpu_err("vfio_register_notifier for iommu failed: %d\n", +			ret);  		goto out;  	} @@ -534,7 +535,8 @@ static int intel_vgpu_open(struct mdev_device *mdev)  	ret = vfio_register_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY, &events,  				&vgpu->vdev.group_notifier);  	if (ret != 0) { -		gvt_err("vfio_register_notifier for group failed: %d\n", ret); +		gvt_vgpu_err("vfio_register_notifier for group failed: %d\n", +			ret);  		goto undo_iommu;  	} @@ -542,6 +544,8 @@ static int intel_vgpu_open(struct mdev_device *mdev)  	if (ret)  		goto undo_group; +	intel_gvt_ops->vgpu_activate(vgpu); +  	atomic_set(&vgpu->vdev.released, 0);  	return ret; @@ -567,6 +571,8 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)  	if (atomic_cmpxchg(&vgpu->vdev.released, 0, 1))  		return; +	intel_gvt_ops->vgpu_deactivate(vgpu); +  	ret = vfio_unregister_notifier(mdev_dev(vgpu->vdev.mdev), VFIO_IOMMU_NOTIFY,  					&vgpu->vdev.iommu_notifier);  	WARN(ret, "vfio_unregister_notifier for iommu failed: %d\n", ret); @@ -635,7 +641,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,  	if (index >= VFIO_PCI_NUM_REGIONS) { -		gvt_err("invalid index: %u\n", index); +		gvt_vgpu_err("invalid index: %u\n", index);  		return -EINVAL;  	} @@ -669,7 +675,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,  	case VFIO_PCI_VGA_REGION_INDEX:  	case VFIO_PCI_ROM_REGION_INDEX:  	default: -		gvt_err("unsupported region: %u\n", index); +		gvt_vgpu_err("unsupported region: %u\n", index);  	}  	return ret == 0 ? count : ret; @@ -861,7 +867,7 @@ static int intel_vgpu_set_msi_trigger(struct intel_vgpu *vgpu,  		trigger = eventfd_ctx_fdget(fd);  		if (IS_ERR(trigger)) { -			gvt_err("eventfd_ctx_fdget failed\n"); +			gvt_vgpu_err("eventfd_ctx_fdget failed\n");  			return PTR_ERR(trigger);  		}  		vgpu->vdev.msi_trigger = trigger; @@ -1120,7 +1126,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,  			ret = vfio_set_irqs_validate_and_prepare(&hdr, max,  						VFIO_PCI_NUM_IRQS, &data_size);  			if (ret) { -				gvt_err("intel:vfio_set_irqs_validate_and_prepare failed\n"); +				gvt_vgpu_err("intel:vfio_set_irqs_validate_and_prepare failed\n");  				return -EINVAL;  			}  			if (data_size) { @@ -1310,7 +1316,7 @@ static int kvmgt_guest_init(struct mdev_device *mdev)  	kvm = vgpu->vdev.kvm;  	if (!kvm || kvm->mm != current->mm) { -		gvt_err("KVM is required to use Intel vGPU\n"); +		gvt_vgpu_err("KVM is required to use Intel vGPU\n");  		return -ESRCH;  	} @@ -1324,6 +1330,7 @@ static int kvmgt_guest_init(struct mdev_device *mdev)  	vgpu->handle = (unsigned long)info;  	info->vgpu = vgpu;  	info->kvm = kvm; +	kvm_get_kvm(info->kvm);  	kvmgt_protect_table_init(info);  	gvt_cache_init(vgpu); @@ -1337,12 +1344,8 @@ static int kvmgt_guest_init(struct mdev_device *mdev)  static bool kvmgt_guest_exit(struct kvmgt_guest_info *info)  { -	if (!info) { -		gvt_err("kvmgt_guest_info invalid\n"); -		return false; -	} -  	kvm_page_track_unregister_notifier(info->kvm, &info->track_node); +	kvm_put_kvm(info->kvm);  	kvmgt_protect_table_destroy(info);  	gvt_cache_destroy(info->vgpu);  	vfree(info); @@ -1383,12 +1386,14 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)  	unsigned long iova, pfn;  	struct kvmgt_guest_info *info;  	struct device *dev; +	struct intel_vgpu *vgpu;  	int rc;  	if (!handle_valid(handle))  		return INTEL_GVT_INVALID_ADDR;  	info = (struct kvmgt_guest_info *)handle; +	vgpu = info->vgpu;  	iova = gvt_cache_find(info->vgpu, gfn);  	if (iova != INTEL_GVT_INVALID_ADDR)  		return iova; @@ -1397,13 +1402,14 @@ static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)  	dev = mdev_dev(info->vgpu->vdev.mdev);  	rc = vfio_pin_pages(dev, &gfn, 1, IOMMU_READ | IOMMU_WRITE, &pfn);  	if (rc != 1) { -		gvt_err("vfio_pin_pages failed for gfn 0x%lx: %d\n", gfn, rc); +		gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx: %d\n", +			gfn, rc);  		return INTEL_GVT_INVALID_ADDR;  	}  	/* transfer to host iova for GFX to use DMA */  	rc = gvt_dma_map_iova(info->vgpu, pfn, &iova);  	if (rc) { -		gvt_err("gvt_dma_map_iova failed for gfn: 0x%lx\n", gfn); +		gvt_vgpu_err("gvt_dma_map_iova failed for gfn: 0x%lx\n", gfn);  		vfio_unpin_pages(dev, &gfn, 1);  		return INTEL_GVT_INVALID_ADDR;  	} @@ -1417,7 +1423,7 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,  {  	struct kvmgt_guest_info *info;  	struct kvm *kvm; -	int ret; +	int idx, ret;  	bool kthread = current->mm == NULL;  	if (!handle_valid(handle)) @@ -1429,8 +1435,10 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,  	if (kthread)  		use_mm(kvm->mm); +	idx = srcu_read_lock(&kvm->srcu);  	ret = write ? kvm_write_guest(kvm, gpa, buf, len) :  		      kvm_read_guest(kvm, gpa, buf, len); +	srcu_read_unlock(&kvm->srcu, idx);  	if (kthread)  		unuse_mm(kvm->mm); diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 4df078bc5d04..1ba3bdb09341 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -57,6 +57,58 @@ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa)  	(reg >= gvt->device_info.gtt_start_offset \  	 && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt)) +static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa, +		void *p_data, unsigned int bytes, bool read) +{ +	struct intel_gvt *gvt = NULL; +	void *pt = NULL; +	unsigned int offset = 0; + +	if (!vgpu || !p_data) +		return; + +	gvt = vgpu->gvt; +	mutex_lock(&gvt->lock); +	offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa); +	if (reg_is_mmio(gvt, offset)) { +		if (read) +			intel_vgpu_default_mmio_read(vgpu, offset, p_data, +					bytes); +		else +			intel_vgpu_default_mmio_write(vgpu, offset, p_data, +					bytes); +	} else if (reg_is_gtt(gvt, offset) && +			vgpu->gtt.ggtt_mm->virtual_page_table) { +		offset -= gvt->device_info.gtt_start_offset; +		pt = vgpu->gtt.ggtt_mm->virtual_page_table + offset; +		if (read) +			memcpy(p_data, pt, bytes); +		else +			memcpy(pt, p_data, bytes); + +	} else if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { +		struct intel_vgpu_guest_page *gp; + +		/* Since we enter the failsafe mode early during guest boot, +		 * guest may not have chance to set up its ppgtt table, so +		 * there should not be any wp pages for guest. Keep the wp +		 * related code here in case we need to handle it in furture. +		 */ +		gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); +		if (gp) { +			/* remove write protection to prevent furture traps */ +			intel_vgpu_clean_guest_page(vgpu, gp); +			if (read) +				intel_gvt_hypervisor_read_gpa(vgpu, pa, +						p_data, bytes); +			else +				intel_gvt_hypervisor_write_gpa(vgpu, pa, +						p_data, bytes); +		} +	} +	mutex_unlock(&gvt->lock); +} +  /**   * intel_vgpu_emulate_mmio_read - emulate MMIO read   * @vgpu: a vGPU @@ -75,6 +127,11 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,  	unsigned int offset = 0;  	int ret = -EINVAL; + +	if (vgpu->failsafe) { +		failsafe_emulate_mmio_rw(vgpu, pa, p_data, bytes, true); +		return 0; +	}  	mutex_lock(&gvt->lock);  	if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { @@ -85,10 +142,10 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,  			ret = intel_gvt_hypervisor_read_gpa(vgpu, pa,  					p_data, bytes);  			if (ret) { -				gvt_err("vgpu%d: guest page read error %d, " +				gvt_vgpu_err("guest page read error %d, "  					"gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n", -					vgpu->id, ret, -					gp->gfn, pa, *(u32 *)p_data, bytes); +					ret, gp->gfn, pa, *(u32 *)p_data, +					bytes);  			}  			mutex_unlock(&gvt->lock);  			return ret; @@ -143,14 +200,13 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,  		ret = intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);  		if (!vgpu->mmio.disable_warn_untrack) { -			gvt_err("vgpu%d: read untracked MMIO %x(%dB) val %x\n", -				vgpu->id, offset, bytes, *(u32 *)p_data); +			gvt_vgpu_err("read untracked MMIO %x(%dB) val %x\n", +				offset, bytes, *(u32 *)p_data);  			if (offset == 0x206c) { -				gvt_err("------------------------------------------\n"); -				gvt_err("vgpu%d: likely triggers a gfx reset\n", -					vgpu->id); -				gvt_err("------------------------------------------\n"); +				gvt_vgpu_err("------------------------------------------\n"); +				gvt_vgpu_err("likely triggers a gfx reset\n"); +				gvt_vgpu_err("------------------------------------------\n");  				vgpu->mmio.disable_warn_untrack = true;  			}  		} @@ -163,8 +219,8 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,  	mutex_unlock(&gvt->lock);  	return 0;  err: -	gvt_err("vgpu%d: fail to emulate MMIO read %08x len %d\n", -			vgpu->id, offset, bytes); +	gvt_vgpu_err("fail to emulate MMIO read %08x len %d\n", +			offset, bytes);  	mutex_unlock(&gvt->lock);  	return ret;  } @@ -188,6 +244,11 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,  	u32 old_vreg = 0, old_sreg = 0;  	int ret = -EINVAL; +	if (vgpu->failsafe) { +		failsafe_emulate_mmio_rw(vgpu, pa, p_data, bytes, false); +		return 0; +	} +  	mutex_lock(&gvt->lock);  	if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { @@ -197,10 +258,11 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,  		if (gp) {  			ret = gp->handler(gp, pa, p_data, bytes);  			if (ret) { -				gvt_err("vgpu%d: guest page write error %d, " -					"gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n", -					vgpu->id, ret, -					gp->gfn, pa, *(u32 *)p_data, bytes); +				gvt_err("guest page write error %d, " +					"gfn 0x%lx, pa 0x%llx, " +					"var 0x%x, len %d\n", +					ret, gp->gfn, pa, +					*(u32 *)p_data, bytes);  			}  			mutex_unlock(&gvt->lock);  			return ret; @@ -236,7 +298,7 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,  	mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4));  	if (!mmio && !vgpu->mmio.disable_warn_untrack) -		gvt_err("vgpu%d: write untracked MMIO %x len %d val %x\n", +		gvt_dbg_mmio("vgpu%d: write untracked MMIO %x len %d val %x\n",  				vgpu->id, offset, bytes, *(u32 *)p_data);  	if (!intel_gvt_mmio_is_unalign(gvt, offset)) { @@ -267,8 +329,8 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,  			/* all register bits are RO. */  			if (ro_mask == ~(u64)0) { -				gvt_err("vgpu%d: try to write RO reg %x\n", -						vgpu->id, offset); +				gvt_vgpu_err("try to write RO reg %x\n", +					offset);  				ret = 0;  				goto out;  			} @@ -298,8 +360,8 @@ out:  	mutex_unlock(&gvt->lock);  	return 0;  err: -	gvt_err("vgpu%d: fail to emulate MMIO write %08x len %d\n", -			vgpu->id, offset, bytes); +	gvt_vgpu_err("fail to emulate MMIO write %08x len %d\n", offset, +		     bytes);  	mutex_unlock(&gvt->lock);  	return ret;  } @@ -322,6 +384,8 @@ void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu)  	/* set the bit 0:2(Core C-State ) to C0 */  	vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0; + +	vgpu->mmio.disable_warn_untrack = false;  }  /** diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h index 3bc620f56f35..a3a027025cd0 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.h +++ b/drivers/gpu/drm/i915/gvt/mmio.h @@ -107,4 +107,7 @@ int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,  				 void *p_data, unsigned int bytes);  int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,  				  void *p_data, unsigned int bytes); + +bool intel_gvt_in_force_nonpriv_whitelist(struct intel_gvt *gvt, +					  unsigned int offset);  #endif diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c index d9fb41ab7119..311799136d7f 100644 --- a/drivers/gpu/drm/i915/gvt/opregion.c +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -27,7 +27,6 @@  static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)  { -	void __iomem *host_va = vgpu->gvt->opregion.opregion_va;  	u8 *buf;  	int i; @@ -43,8 +42,8 @@ static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)  	if (!vgpu_opregion(vgpu)->va)  		return -ENOMEM; -	memcpy_fromio(vgpu_opregion(vgpu)->va, host_va, -			INTEL_GVT_OPREGION_SIZE); +	memcpy(vgpu_opregion(vgpu)->va, vgpu->gvt->opregion.opregion_va, +	       INTEL_GVT_OPREGION_SIZE);  	for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)  		vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i; @@ -68,14 +67,15 @@ static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)  		mfn = intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu)->va  			+ i * PAGE_SIZE);  		if (mfn == INTEL_GVT_INVALID_ADDR) { -			gvt_err("fail to get MFN from VA\n"); +			gvt_vgpu_err("fail to get MFN from VA\n");  			return -EINVAL;  		}  		ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu,  				vgpu_opregion(vgpu)->gfn[i],  				mfn, 1, map);  		if (ret) { -			gvt_err("fail to map GFN to MFN, errno: %d\n", ret); +			gvt_vgpu_err("fail to map GFN to MFN, errno: %d\n", +				ret);  			return ret;  		}  	} @@ -288,7 +288,7 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)  	parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM;  	if (!(swsci & SWSCI_SCI_SELECT)) { -		gvt_err("vgpu%d: requesting SMI service\n", vgpu->id); +		gvt_vgpu_err("requesting SMI service\n");  		return 0;  	}  	/* ignore non 0->1 trasitions */ @@ -301,9 +301,8 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)  	func = GVT_OPREGION_FUNC(*scic);  	subfunc = GVT_OPREGION_SUBFUNC(*scic);  	if (!querying_capabilities(*scic)) { -		gvt_err("vgpu%d: requesting runtime service: func \"%s\"," +		gvt_vgpu_err("requesting runtime service: func \"%s\","  				" subfunc \"%s\"\n", -				vgpu->id,  				opregion_func_name(func),  				opregion_subfunc_name(subfunc));  		/* diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index 2b3a642284b6..0beb83563b08 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -53,6 +53,14 @@ static struct render_mmio gen8_render_mmio_list[] = {  	{RCS, _MMIO(0x24d4), 0, false},  	{RCS, _MMIO(0x24d8), 0, false},  	{RCS, _MMIO(0x24dc), 0, false}, +	{RCS, _MMIO(0x24e0), 0, false}, +	{RCS, _MMIO(0x24e4), 0, false}, +	{RCS, _MMIO(0x24e8), 0, false}, +	{RCS, _MMIO(0x24ec), 0, false}, +	{RCS, _MMIO(0x24f0), 0, false}, +	{RCS, _MMIO(0x24f4), 0, false}, +	{RCS, _MMIO(0x24f8), 0, false}, +	{RCS, _MMIO(0x24fc), 0, false},  	{RCS, _MMIO(0x7004), 0xffff, true},  	{RCS, _MMIO(0x7008), 0xffff, true},  	{RCS, _MMIO(0x7000), 0xffff, true}, @@ -76,6 +84,14 @@ static struct render_mmio gen9_render_mmio_list[] = {  	{RCS, _MMIO(0x24d4), 0, false},  	{RCS, _MMIO(0x24d8), 0, false},  	{RCS, _MMIO(0x24dc), 0, false}, +	{RCS, _MMIO(0x24e0), 0, false}, +	{RCS, _MMIO(0x24e4), 0, false}, +	{RCS, _MMIO(0x24e8), 0, false}, +	{RCS, _MMIO(0x24ec), 0, false}, +	{RCS, _MMIO(0x24f0), 0, false}, +	{RCS, _MMIO(0x24f4), 0, false}, +	{RCS, _MMIO(0x24f8), 0, false}, +	{RCS, _MMIO(0x24fc), 0, false},  	{RCS, _MMIO(0x7004), 0xffff, true},  	{RCS, _MMIO(0x7008), 0xffff, true},  	{RCS, _MMIO(0x7000), 0xffff, true}, @@ -151,7 +167,7 @@ static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id)  	I915_WRITE_FW(reg, 0x1);  	if (wait_for_atomic((I915_READ_FW(reg) == 0), 50)) -		gvt_err("timeout in invalidate ring (%d) tlb\n", ring_id); +		gvt_vgpu_err("timeout in invalidate ring (%d) tlb\n", ring_id);  	else  		vgpu_vreg(vgpu, regs[ring_id]) = 0; @@ -191,7 +207,7 @@ static void load_mocs(struct intel_vgpu *vgpu, int ring_id)  		l3_offset.reg = 0xb020;  		for (i = 0; i < 32; i++) {  			gen9_render_mocs_L3[i] = I915_READ(l3_offset); -			I915_WRITE(l3_offset, vgpu_vreg(vgpu, offset)); +			I915_WRITE(l3_offset, vgpu_vreg(vgpu, l3_offset));  			POSTING_READ(l3_offset);  			l3_offset.reg += 4;  		} diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index 06c9584ac5f0..34b9acdf3479 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -101,7 +101,7 @@ struct tbs_sched_data {  	struct list_head runq_head;  }; -#define GVT_DEFAULT_TIME_SLICE (1 * HZ / 1000) +#define GVT_DEFAULT_TIME_SLICE (msecs_to_jiffies(1))  static void tbs_sched_func(struct work_struct *work)  { @@ -223,7 +223,7 @@ static void tbs_sched_start_schedule(struct intel_vgpu *vgpu)  		return;  	list_add_tail(&vgpu_data->list, &sched_data->runq_head); -	schedule_delayed_work(&sched_data->work, sched_data->period); +	schedule_delayed_work(&sched_data->work, 0);  }  static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu) diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index d6b6d0efdd1a..a44782412f2c 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -84,7 +84,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)  				(u32)((workload->ctx_desc.lrca + i) <<  				GTT_PAGE_SHIFT));  		if (context_gpa == INTEL_GVT_INVALID_ADDR) { -			gvt_err("Invalid guest context descriptor\n"); +			gvt_vgpu_err("Invalid guest context descriptor\n");  			return -EINVAL;  		} @@ -127,18 +127,24 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)  	return 0;  } +static inline bool is_gvt_request(struct drm_i915_gem_request *req) +{ +	return i915_gem_context_force_single_submission(req->ctx); +} +  static int shadow_context_status_change(struct notifier_block *nb,  		unsigned long action, void *data)  { -	struct intel_vgpu *vgpu = container_of(nb, -			struct intel_vgpu, shadow_ctx_notifier_block); -	struct drm_i915_gem_request *req = -		(struct drm_i915_gem_request *)data; -	struct intel_gvt_workload_scheduler *scheduler = -		&vgpu->gvt->scheduler; +	struct drm_i915_gem_request *req = (struct drm_i915_gem_request *)data; +	struct intel_gvt *gvt = container_of(nb, struct intel_gvt, +				shadow_ctx_notifier_block[req->engine->id]); +	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;  	struct intel_vgpu_workload *workload =  		scheduler->current_workload[req->engine->id]; +	if (!is_gvt_request(req) || unlikely(!workload)) +		return NOTIFY_OK; +  	switch (action) {  	case INTEL_CONTEXT_SCHEDULE_IN:  		intel_gvt_load_render_mmio(workload->vgpu, @@ -148,6 +154,15 @@ static int shadow_context_status_change(struct notifier_block *nb,  	case INTEL_CONTEXT_SCHEDULE_OUT:  		intel_gvt_restore_render_mmio(workload->vgpu,  					      workload->ring_id); +		/* If the status is -EINPROGRESS means this workload +		 * doesn't meet any issue during dispatching so when +		 * get the SCHEDULE_OUT set the status to be zero for +		 * good. If the status is NOT -EINPROGRESS means there +		 * is something wrong happened during dispatching and +		 * the status should not be set to zero +		 */ +		if (workload->status == -EINPROGRESS) +			workload->status = 0;  		atomic_set(&workload->shadow_ctx_active, 0);  		break;  	default: @@ -163,7 +178,9 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)  	int ring_id = workload->ring_id;  	struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;  	struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; +	struct intel_engine_cs *engine = dev_priv->engine[ring_id];  	struct drm_i915_gem_request *rq; +	struct intel_vgpu *vgpu = workload->vgpu;  	int ret;  	gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n", @@ -175,9 +192,24 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)  	mutex_lock(&dev_priv->drm.struct_mutex); +	/* pin shadow context by gvt even the shadow context will be pinned +	 * when i915 alloc request. That is because gvt will update the guest +	 * context from shadow context when workload is completed, and at that +	 * moment, i915 may already unpined the shadow context to make the +	 * shadow_ctx pages invalid. So gvt need to pin itself. After update +	 * the guest context, gvt can unpin the shadow_ctx safely. +	 */ +	ret = engine->context_pin(engine, shadow_ctx); +	if (ret) { +		gvt_vgpu_err("fail to pin shadow context\n"); +		workload->status = ret; +		mutex_unlock(&dev_priv->drm.struct_mutex); +		return ret; +	} +  	rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx);  	if (IS_ERR(rq)) { -		gvt_err("fail to allocate gem request\n"); +		gvt_vgpu_err("fail to allocate gem request\n");  		ret = PTR_ERR(rq);  		goto out;  	} @@ -190,9 +222,12 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)  	if (ret)  		goto out; -	ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx); -	if (ret) -		goto out; +	if ((workload->ring_id == RCS) && +	    (workload->wa_ctx.indirect_ctx.size != 0)) { +		ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx); +		if (ret) +			goto out; +	}  	ret = populate_shadow_context(workload);  	if (ret) @@ -215,6 +250,9 @@ out:  	if (!IS_ERR_OR_NULL(rq))  		i915_add_request_no_flush(rq); +	else +		engine->context_unpin(engine, shadow_ctx); +  	mutex_unlock(&dev_priv->drm.struct_mutex);  	return ret;  } @@ -310,7 +348,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload)  				(u32)((workload->ctx_desc.lrca + i) <<  					GTT_PAGE_SHIFT));  		if (context_gpa == INTEL_GVT_INVALID_ADDR) { -			gvt_err("invalid guest context descriptor\n"); +			gvt_vgpu_err("invalid guest context descriptor\n");  			return;  		} @@ -359,15 +397,31 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)  	workload = scheduler->current_workload[ring_id];  	vgpu = workload->vgpu; -	if (!workload->status && !vgpu->resetting) { +	/* For the workload w/ request, needs to wait for the context +	 * switch to make sure request is completed. +	 * For the workload w/o request, directly complete the workload. +	 */ +	if (workload->req) { +		struct drm_i915_private *dev_priv = +			workload->vgpu->gvt->dev_priv; +		struct intel_engine_cs *engine = +			dev_priv->engine[workload->ring_id];  		wait_event(workload->shadow_ctx_status_wq,  			   !atomic_read(&workload->shadow_ctx_active)); -		update_guest_context(workload); +		i915_gem_request_put(fetch_and_zero(&workload->req)); + +		if (!workload->status && !vgpu->resetting) { +			update_guest_context(workload); -		for_each_set_bit(event, workload->pending_events, -				 INTEL_GVT_EVENT_MAX) -			intel_vgpu_trigger_virtual_event(vgpu, event); +			for_each_set_bit(event, workload->pending_events, +					 INTEL_GVT_EVENT_MAX) +				intel_vgpu_trigger_virtual_event(vgpu, event); +		} +		mutex_lock(&dev_priv->drm.struct_mutex); +		/* unpin shadow ctx as the shadow_ctx update is done */ +		engine->context_unpin(engine, workload->vgpu->shadow_ctx); +		mutex_unlock(&dev_priv->drm.struct_mutex);  	}  	gvt_dbg_sched("ring id %d complete workload %p status %d\n", @@ -397,7 +451,7 @@ static int workload_thread(void *priv)  	int ring_id = p->ring_id;  	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;  	struct intel_vgpu_workload *workload = NULL; -	long lret; +	struct intel_vgpu *vgpu = NULL;  	int ret;  	bool need_force_wake = IS_SKYLAKE(gvt->dev_priv);  	DEFINE_WAIT_FUNC(wait, woken_wake_function); @@ -440,29 +494,19 @@ static int workload_thread(void *priv)  		mutex_unlock(&gvt->lock);  		if (ret) { -			gvt_err("fail to dispatch workload, skip\n"); +			vgpu = workload->vgpu; +			gvt_vgpu_err("fail to dispatch workload, skip\n");  			goto complete;  		}  		gvt_dbg_sched("ring id %d wait workload %p\n",  				workload->ring_id, workload); - -		lret = i915_wait_request(workload->req, -					 0, MAX_SCHEDULE_TIMEOUT); -		if (lret < 0) { -			workload->status = lret; -			gvt_err("fail to wait workload, skip\n"); -		} else { -			workload->status = 0; -		} +		i915_wait_request(workload->req, 0, MAX_SCHEDULE_TIMEOUT);  complete:  		gvt_dbg_sched("will complete workload %p, status: %d\n",  				workload, workload->status); -		if (workload->req) -			i915_gem_request_put(fetch_and_zero(&workload->req)); -  		complete_current_workload(gvt, ring_id);  		if (need_force_wake) @@ -493,15 +537,16 @@ void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu)  void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt)  {  	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; -	int i; +	struct intel_engine_cs *engine; +	enum intel_engine_id i;  	gvt_dbg_core("clean workload scheduler\n"); -	for (i = 0; i < I915_NUM_ENGINES; i++) { -		if (scheduler->thread[i]) { -			kthread_stop(scheduler->thread[i]); -			scheduler->thread[i] = NULL; -		} +	for_each_engine(engine, gvt->dev_priv, i) { +		atomic_notifier_chain_unregister( +					&engine->context_status_notifier, +					&gvt->shadow_ctx_notifier_block[i]); +		kthread_stop(scheduler->thread[i]);  	}  } @@ -509,18 +554,15 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt)  {  	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;  	struct workload_thread_param *param = NULL; +	struct intel_engine_cs *engine; +	enum intel_engine_id i;  	int ret; -	int i;  	gvt_dbg_core("init workload scheduler\n");  	init_waitqueue_head(&scheduler->workload_complete_wq); -	for (i = 0; i < I915_NUM_ENGINES; i++) { -		/* check ring mask at init time */ -		if (!HAS_ENGINE(gvt->dev_priv, i)) -			continue; - +	for_each_engine(engine, gvt->dev_priv, i) {  		init_waitqueue_head(&scheduler->waitq[i]);  		param = kzalloc(sizeof(*param), GFP_KERNEL); @@ -539,6 +581,11 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt)  			ret = PTR_ERR(scheduler->thread[i]);  			goto err;  		} + +		gvt->shadow_ctx_notifier_block[i].notifier_call = +					shadow_context_status_change; +		atomic_notifier_chain_register(&engine->context_status_notifier, +					&gvt->shadow_ctx_notifier_block[i]);  	}  	return 0;  err: @@ -550,9 +597,6 @@ err:  void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu)  { -	atomic_notifier_chain_unregister(&vgpu->shadow_ctx->status_notifier, -			&vgpu->shadow_ctx_notifier_block); -  	i915_gem_context_put_unlocked(vgpu->shadow_ctx);  } @@ -567,10 +611,5 @@ int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu)  	vgpu->shadow_ctx->engine[RCS].initialised = true; -	vgpu->shadow_ctx_notifier_block.notifier_call = -		shadow_context_status_change; - -	atomic_notifier_chain_register(&vgpu->shadow_ctx->status_notifier, -				       &vgpu->shadow_ctx_notifier_block);  	return 0;  } diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 95a97aa0051e..649ef280cc9a 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -64,6 +64,20 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu)  	WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);  } +static struct { +	unsigned int low_mm; +	unsigned int high_mm; +	unsigned int fence; +	enum intel_vgpu_edid edid; +	char *name; +} vgpu_types[] = { +/* Fixed vGPU type table */ +	{ MB_TO_BYTES(64), MB_TO_BYTES(384), 4, GVT_EDID_1024_768, "8" }, +	{ MB_TO_BYTES(128), MB_TO_BYTES(512), 4, GVT_EDID_1920_1200, "4" }, +	{ MB_TO_BYTES(256), MB_TO_BYTES(1024), 4, GVT_EDID_1920_1200, "2" }, +	{ MB_TO_BYTES(512), MB_TO_BYTES(2048), 4, GVT_EDID_1920_1200, "1" }, +}; +  /**   * intel_gvt_init_vgpu_types - initialize vGPU type list   * @gvt : GVT device @@ -78,9 +92,8 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)  	unsigned int min_low;  	/* vGPU type name is defined as GVTg_Vx_y which contains -	 * physical GPU generation type and 'y' means maximum vGPU -	 * instances user can create on one physical GPU for this -	 * type. +	 * physical GPU generation type (e.g V4 as BDW server, V5 as +	 * SKL server).  	 *  	 * Depend on physical SKU resource, might see vGPU types like  	 * GVTg_V4_8, GVTg_V4_4, GVTg_V4_2, etc. We can create @@ -92,7 +105,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)  	 */  	low_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE;  	high_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE; -	num_types = 4; +	num_types = sizeof(vgpu_types) / sizeof(vgpu_types[0]);  	gvt->types = kzalloc(num_types * sizeof(struct intel_vgpu_type),  			     GFP_KERNEL); @@ -101,28 +114,29 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)  	min_low = MB_TO_BYTES(32);  	for (i = 0; i < num_types; ++i) { -		if (low_avail / min_low == 0) +		if (low_avail / vgpu_types[i].low_mm == 0)  			break; -		gvt->types[i].low_gm_size = min_low; -		gvt->types[i].high_gm_size = max((min_low<<3), MB_TO_BYTES(384U)); -		gvt->types[i].fence = 4; -		gvt->types[i].max_instance = min(low_avail / min_low, -						 high_avail / gvt->types[i].high_gm_size); -		gvt->types[i].avail_instance = gvt->types[i].max_instance; + +		gvt->types[i].low_gm_size = vgpu_types[i].low_mm; +		gvt->types[i].high_gm_size = vgpu_types[i].high_mm; +		gvt->types[i].fence = vgpu_types[i].fence; +		gvt->types[i].resolution = vgpu_types[i].edid; +		gvt->types[i].avail_instance = min(low_avail / vgpu_types[i].low_mm, +						   high_avail / vgpu_types[i].high_mm);  		if (IS_GEN8(gvt->dev_priv)) -			sprintf(gvt->types[i].name, "GVTg_V4_%u", -						gvt->types[i].max_instance); +			sprintf(gvt->types[i].name, "GVTg_V4_%s", +						vgpu_types[i].name);  		else if (IS_GEN9(gvt->dev_priv)) -			sprintf(gvt->types[i].name, "GVTg_V5_%u", -						gvt->types[i].max_instance); +			sprintf(gvt->types[i].name, "GVTg_V5_%s", +						vgpu_types[i].name); -		min_low <<= 1; -		gvt_dbg_core("type[%d]: %s max %u avail %u low %u high %u fence %u\n", -			     i, gvt->types[i].name, gvt->types[i].max_instance, +		gvt_dbg_core("type[%d]: %s avail %u low %u high %u fence %u res %s\n", +			     i, gvt->types[i].name,  			     gvt->types[i].avail_instance,  			     gvt->types[i].low_gm_size, -			     gvt->types[i].high_gm_size, gvt->types[i].fence); +			     gvt->types[i].high_gm_size, gvt->types[i].fence, +			     vgpu_edid_str(gvt->types[i].resolution));  	}  	gvt->num_types = i; @@ -138,7 +152,7 @@ static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)  {  	int i;  	unsigned int low_gm_avail, high_gm_avail, fence_avail; -	unsigned int low_gm_min, high_gm_min, fence_min, total_min; +	unsigned int low_gm_min, high_gm_min, fence_min;  	/* Need to depend on maxium hw resource size but keep on  	 * static config for now. @@ -154,32 +168,45 @@ static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)  		low_gm_min = low_gm_avail / gvt->types[i].low_gm_size;  		high_gm_min = high_gm_avail / gvt->types[i].high_gm_size;  		fence_min = fence_avail / gvt->types[i].fence; -		total_min = min(min(low_gm_min, high_gm_min), fence_min); -		gvt->types[i].avail_instance = min(gvt->types[i].max_instance, -						   total_min); +		gvt->types[i].avail_instance = min(min(low_gm_min, high_gm_min), +						   fence_min); -		gvt_dbg_core("update type[%d]: %s max %u avail %u low %u high %u fence %u\n", -		       i, gvt->types[i].name, gvt->types[i].max_instance, +		gvt_dbg_core("update type[%d]: %s avail %u low %u high %u fence %u\n", +		       i, gvt->types[i].name,  		       gvt->types[i].avail_instance, gvt->types[i].low_gm_size,  		       gvt->types[i].high_gm_size, gvt->types[i].fence);  	}  }  /** - * intel_gvt_destroy_vgpu - destroy a virtual GPU + * intel_gvt_active_vgpu - activate a virtual GPU   * @vgpu: virtual GPU   * - * This function is called when user wants to destroy a virtual GPU. + * This function is called when user wants to activate a virtual GPU.   *   */ -void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) +void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu) +{ +	mutex_lock(&vgpu->gvt->lock); +	vgpu->active = true; +	mutex_unlock(&vgpu->gvt->lock); +} + +/** + * intel_gvt_deactive_vgpu - deactivate a virtual GPU + * @vgpu: virtual GPU + * + * This function is called when user wants to deactivate a virtual GPU. + * All virtual GPU runtime information will be destroyed. + * + */ +void intel_gvt_deactivate_vgpu(struct intel_vgpu *vgpu)  {  	struct intel_gvt *gvt = vgpu->gvt;  	mutex_lock(&gvt->lock);  	vgpu->active = false; -	idr_remove(&gvt->vgpu_idr, vgpu->id);  	if (atomic_read(&vgpu->running_workload_num)) {  		mutex_unlock(&gvt->lock); @@ -188,6 +215,26 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)  	}  	intel_vgpu_stop_schedule(vgpu); + +	mutex_unlock(&gvt->lock); +} + +/** + * intel_gvt_destroy_vgpu - destroy a virtual GPU + * @vgpu: virtual GPU + * + * This function is called when user wants to destroy a virtual GPU. + * + */ +void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) +{ +	struct intel_gvt *gvt = vgpu->gvt; + +	mutex_lock(&gvt->lock); + +	WARN(vgpu->active, "vGPU is still active!\n"); + +	idr_remove(&gvt->vgpu_idr, vgpu->id);  	intel_vgpu_clean_sched_policy(vgpu);  	intel_vgpu_clean_gvt_context(vgpu);  	intel_vgpu_clean_execlist(vgpu); @@ -248,7 +295,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,  	if (ret)  		goto out_detach_hypervisor_vgpu; -	ret = intel_vgpu_init_display(vgpu); +	ret = intel_vgpu_init_display(vgpu, param->resolution);  	if (ret)  		goto out_clean_gtt; @@ -264,7 +311,6 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,  	if (ret)  		goto out_clean_shadow_ctx; -	vgpu->active = true;  	mutex_unlock(&gvt->lock);  	return vgpu; @@ -312,6 +358,7 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,  	param.low_gm_sz = type->low_gm_size;  	param.high_gm_sz = type->high_gm_size;  	param.fence_sz = type->fence; +	param.resolution = type->resolution;  	/* XXX current param based on MB */  	param.low_gm_sz = BYTES_TO_MB(param.low_gm_sz); @@ -387,8 +434,12 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,  		populate_pvinfo_page(vgpu);  		intel_vgpu_reset_display(vgpu); -		if (dmlr) +		if (dmlr) {  			intel_vgpu_reset_cfg_space(vgpu); +			/* only reset the failsafe mode when dmlr reset */ +			vgpu->failsafe = false; +			vgpu->pv_notified = false; +		}  	}  	vgpu->resetting = false; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e703556eba99..5c089b3c2a7e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -248,6 +248,7 @@ static int i915_getparam(struct drm_device *dev, void *data,  	case I915_PARAM_IRQ_ACTIVE:  	case I915_PARAM_ALLOW_BATCHBUFFER:  	case I915_PARAM_LAST_DISPATCH: +	case I915_PARAM_HAS_EXEC_CONSTANTS:  		/* Reject all old ums/dri params. */  		return -ENODEV;  	case I915_PARAM_CHIPSET_ID: @@ -274,9 +275,6 @@ static int i915_getparam(struct drm_device *dev, void *data,  	case I915_PARAM_HAS_BSD2:  		value = !!dev_priv->engine[VCS2];  		break; -	case I915_PARAM_HAS_EXEC_CONSTANTS: -		value = INTEL_GEN(dev_priv) >= 4; -		break;  	case I915_PARAM_HAS_LLC:  		value = HAS_LLC(dev_priv);  		break; @@ -1436,8 +1434,6 @@ static int i915_drm_suspend(struct drm_device *dev)  		goto out;  	} -	intel_guc_suspend(dev_priv); -  	intel_display_suspend(dev);  	intel_dp_mst_suspend(dev); @@ -1788,7 +1784,7 @@ void i915_reset(struct drm_i915_private *dev_priv)  		goto error;  	} -	i915_gem_reset_finish(dev_priv); +	i915_gem_reset(dev_priv);  	intel_overlay_reset(dev_priv);  	/* Ok, now get things going again... */ @@ -1814,6 +1810,7 @@ void i915_reset(struct drm_i915_private *dev_priv)  	i915_queue_hangcheck(dev_priv);  wakeup: +	i915_gem_reset_finish(dev_priv);  	enable_irq(dev_priv->drm.irq);  	wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS);  	return; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0a4b42d31391..46fcd8b7080a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -293,6 +293,7 @@ enum plane_id {  	PLANE_PRIMARY,  	PLANE_SPRITE0,  	PLANE_SPRITE1, +	PLANE_SPRITE2,  	PLANE_CURSOR,  	I915_MAX_PLANES,  }; @@ -805,6 +806,7 @@ struct intel_csr {  	func(has_resource_streamer); \  	func(has_runtime_pm); \  	func(has_snoop); \ +	func(unfenced_needs_alignment); \  	func(cursor_needs_physical); \  	func(hws_needs_physical); \  	func(overlay_needs_physical); \ @@ -1324,7 +1326,7 @@ struct intel_gen6_power_mgmt {  	unsigned boosts;  	/* manual wa residency calculations */ -	struct intel_rps_ei up_ei, down_ei; +	struct intel_rps_ei ei;  	/*  	 * Protects RPS/RC6 register access and PCU communication. @@ -2063,8 +2065,6 @@ struct drm_i915_private {  	const struct intel_device_info info; -	int relative_constants_mode; -  	void __iomem *regs;  	struct intel_uncore uncore; @@ -3341,6 +3341,7 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)  }  int i915_gem_reset_prepare(struct drm_i915_private *dev_priv); +void i915_gem_reset(struct drm_i915_private *dev_priv);  void i915_gem_reset_finish(struct drm_i915_private *dev_priv);  void i915_gem_set_wedged(struct drm_i915_private *dev_priv);  void i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6908123162d1..fe531f904062 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1434,6 +1434,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,  	trace_i915_gem_object_pwrite(obj, args->offset, args->size); +	ret = -ENODEV; +	if (obj->ops->pwrite) +		ret = obj->ops->pwrite(obj, args); +	if (ret != -ENODEV) +		goto err; +  	ret = i915_gem_object_wait(obj,  				   I915_WAIT_INTERRUPTIBLE |  				   I915_WAIT_ALL, @@ -2119,6 +2125,7 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)  	 */  	shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1);  	obj->mm.madv = __I915_MADV_PURGED; +	obj->mm.pages = ERR_PTR(-EFAULT);  }  /* Try to discard unwanted pages */ @@ -2218,7 +2225,9 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,  	__i915_gem_object_reset_page_iter(obj); -	obj->ops->put_pages(obj, pages); +	if (!IS_ERR(pages)) +		obj->ops->put_pages(obj, pages); +  unlock:  	mutex_unlock(&obj->mm.lock);  } @@ -2437,7 +2446,7 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj)  	if (err)  		return err; -	if (unlikely(!obj->mm.pages)) { +	if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {  		err = ____i915_gem_object_get_pages(obj);  		if (err)  			goto unlock; @@ -2515,7 +2524,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,  	pinned = true;  	if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) { -		if (unlikely(!obj->mm.pages)) { +		if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) {  			ret = ____i915_gem_object_get_pages(obj);  			if (ret)  				goto err_unlock; @@ -2563,6 +2572,75 @@ err_unlock:  	goto out_unlock;  } +static int +i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj, +			   const struct drm_i915_gem_pwrite *arg) +{ +	struct address_space *mapping = obj->base.filp->f_mapping; +	char __user *user_data = u64_to_user_ptr(arg->data_ptr); +	u64 remain, offset; +	unsigned int pg; + +	/* Before we instantiate/pin the backing store for our use, we +	 * can prepopulate the shmemfs filp efficiently using a write into +	 * the pagecache. We avoid the penalty of instantiating all the +	 * pages, important if the user is just writing to a few and never +	 * uses the object on the GPU, and using a direct write into shmemfs +	 * allows it to avoid the cost of retrieving a page (either swapin +	 * or clearing-before-use) before it is overwritten. +	 */ +	if (READ_ONCE(obj->mm.pages)) +		return -ENODEV; + +	/* Before the pages are instantiated the object is treated as being +	 * in the CPU domain. The pages will be clflushed as required before +	 * use, and we can freely write into the pages directly. If userspace +	 * races pwrite with any other operation; corruption will ensue - +	 * that is userspace's prerogative! +	 */ + +	remain = arg->size; +	offset = arg->offset; +	pg = offset_in_page(offset); + +	do { +		unsigned int len, unwritten; +		struct page *page; +		void *data, *vaddr; +		int err; + +		len = PAGE_SIZE - pg; +		if (len > remain) +			len = remain; + +		err = pagecache_write_begin(obj->base.filp, mapping, +					    offset, len, 0, +					    &page, &data); +		if (err < 0) +			return err; + +		vaddr = kmap(page); +		unwritten = copy_from_user(vaddr + pg, user_data, len); +		kunmap(page); + +		err = pagecache_write_end(obj->base.filp, mapping, +					  offset, len, len - unwritten, +					  page, data); +		if (err < 0) +			return err; + +		if (unwritten) +			return -EFAULT; + +		remain -= len; +		user_data += len; +		offset += len; +		pg = 0; +	} while (remain); + +	return 0; +} +  static bool ban_context(const struct i915_gem_context *ctx)  {  	return (i915_gem_context_is_bannable(ctx) && @@ -2641,7 +2719,16 @@ int i915_gem_reset_prepare(struct drm_i915_private *dev_priv)  	for_each_engine(engine, dev_priv, id) {  		struct drm_i915_gem_request *request; +		/* Prevent request submission to the hardware until we have +		 * completed the reset in i915_gem_reset_finish(). If a request +		 * is completed by one engine, it may then queue a request +		 * to a second via its engine->irq_tasklet *just* as we are +		 * calling engine->init_hw() and also writing the ELSP. +		 * Turning off the engine->irq_tasklet until the reset is over +		 * prevents the race. +		 */  		tasklet_kill(&engine->irq_tasklet); +		tasklet_disable(&engine->irq_tasklet);  		if (engine_stalled(engine)) {  			request = i915_gem_find_active_request(engine); @@ -2756,7 +2843,7 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine)  	engine->reset_hw(engine, request);  } -void i915_gem_reset_finish(struct drm_i915_private *dev_priv) +void i915_gem_reset(struct drm_i915_private *dev_priv)  {  	struct intel_engine_cs *engine;  	enum intel_engine_id id; @@ -2778,6 +2865,17 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv)  	}  } +void i915_gem_reset_finish(struct drm_i915_private *dev_priv) +{ +	struct intel_engine_cs *engine; +	enum intel_engine_id id; + +	lockdep_assert_held(&dev_priv->drm.struct_mutex); + +	for_each_engine(engine, dev_priv, id) +		tasklet_enable(&engine->irq_tasklet); +} +  static void nop_submit_request(struct drm_i915_gem_request *request)  {  	dma_fence_set_error(&request->fence, -EIO); @@ -3029,6 +3127,16 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)  		args->timeout_ns -= ktime_to_ns(ktime_sub(ktime_get(), start));  		if (args->timeout_ns < 0)  			args->timeout_ns = 0; + +		/* +		 * Apparently ktime isn't accurate enough and occasionally has a +		 * bit of mismatch in the jiffies<->nsecs<->ktime loop. So patch +		 * things up to make the test happy. We allow up to 1 jiffy. +		 * +		 * This is a regression from the timespec->ktime conversion. +		 */ +		if (ret == -ETIME && !nsecs_to_jiffies(args->timeout_ns)) +			args->timeout_ns = 0;  	}  	i915_gem_object_put(obj); @@ -3974,8 +4082,11 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,  static const struct drm_i915_gem_object_ops i915_gem_object_ops = {  	.flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |  		 I915_GEM_OBJECT_IS_SHRINKABLE, +  	.get_pages = i915_gem_object_get_pages_gtt,  	.put_pages = i915_gem_object_put_pages_gtt, + +	.pwrite = i915_gem_object_pwrite_gtt,  };  struct drm_i915_gem_object * @@ -4237,6 +4348,8 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv)  	i915_gem_context_lost(dev_priv);  	mutex_unlock(&dev->struct_mutex); +	intel_guc_suspend(dev_priv); +  	cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);  	cancel_delayed_work_sync(&dev_priv->gt.retire_work); @@ -4583,8 +4696,6 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)  	init_waitqueue_head(&dev_priv->gpu_error.wait_queue);  	init_waitqueue_head(&dev_priv->gpu_error.reset_queue); -	dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL; -  	init_waitqueue_head(&dev_priv->pending_flip_queue);  	dev_priv->mm.interruptible = true; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 17f90c618208..e2d83b6d376b 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -311,7 +311,6 @@ __create_hw_context(struct drm_i915_private *dev_priv,  	ctx->ring_size = 4 * PAGE_SIZE;  	ctx->desc_template = GEN8_CTX_ADDRESSING_MODE(dev_priv) <<  			     GEN8_CTX_ADDRESSING_MODE_SHIFT; -	ATOMIC_INIT_NOTIFIER_HEAD(&ctx->status_notifier);  	/* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is not  	 * present or not in use we still need a small bias as ring wraparound diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index 0ac750b90f3d..e9c008fe14b1 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -160,9 +160,6 @@ struct i915_gem_context {  	/** desc_template: invariant fields for the HW context descriptor */  	u32 desc_template; -	/** status_notifier: list of callbacks for context-switch changes */ -	struct atomic_notifier_head status_notifier; -  	/** guilty_count: How many times this context has caused a GPU hang. */  	unsigned int guilty_count;  	/** diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index c181b1bb3d2c..3be2503aa042 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -293,12 +293,12 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,  		 * those as well to make room for our guard pages.  		 */  		if (check_color) { -			if (vma->node.start + vma->node.size == node->start) { -				if (vma->node.color == node->color) +			if (node->start + node->size == target->start) { +				if (node->color == target->color)  					continue;  			} -			if (vma->node.start == node->start + node->size) { -				if (vma->node.color == node->color) +			if (node->start == target->start + target->size) { +				if (node->color == target->color)  					continue;  			}  		} diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d02cfaefe1c8..15a15d00a6bf 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -888,6 +888,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *engine,  	struct list_head ordered_vmas;  	struct list_head pinned_vmas;  	bool has_fenced_gpu_access = INTEL_GEN(engine->i915) < 4; +	bool needs_unfenced_map = INTEL_INFO(engine->i915)->unfenced_needs_alignment;  	int retry;  	vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; @@ -908,7 +909,8 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *engine,  		if (!has_fenced_gpu_access)  			entry->flags &= ~EXEC_OBJECT_NEEDS_FENCE;  		need_fence = -			entry->flags & EXEC_OBJECT_NEEDS_FENCE && +			(entry->flags & EXEC_OBJECT_NEEDS_FENCE || +			 needs_unfenced_map) &&  			i915_gem_object_is_tiled(obj);  		need_mappable = need_fence || need_reloc_mappable(vma); @@ -1408,10 +1410,7 @@ execbuf_submit(struct i915_execbuffer_params *params,  	       struct drm_i915_gem_execbuffer2 *args,  	       struct list_head *vmas)  { -	struct drm_i915_private *dev_priv = params->request->i915;  	u64 exec_start, exec_len; -	int instp_mode; -	u32 instp_mask;  	int ret;  	ret = i915_gem_execbuffer_move_to_gpu(params->request, vmas); @@ -1422,56 +1421,11 @@ execbuf_submit(struct i915_execbuffer_params *params,  	if (ret)  		return ret; -	instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK; -	instp_mask = I915_EXEC_CONSTANTS_MASK; -	switch (instp_mode) { -	case I915_EXEC_CONSTANTS_REL_GENERAL: -	case I915_EXEC_CONSTANTS_ABSOLUTE: -	case I915_EXEC_CONSTANTS_REL_SURFACE: -		if (instp_mode != 0 && params->engine->id != RCS) { -			DRM_DEBUG("non-0 rel constants mode on non-RCS\n"); -			return -EINVAL; -		} - -		if (instp_mode != dev_priv->relative_constants_mode) { -			if (INTEL_INFO(dev_priv)->gen < 4) { -				DRM_DEBUG("no rel constants on pre-gen4\n"); -				return -EINVAL; -			} - -			if (INTEL_INFO(dev_priv)->gen > 5 && -			    instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) { -				DRM_DEBUG("rel surface constants mode invalid on gen5+\n"); -				return -EINVAL; -			} - -			/* The HW changed the meaning on this bit on gen6 */ -			if (INTEL_INFO(dev_priv)->gen >= 6) -				instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE; -		} -		break; -	default: -		DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode); +	if (args->flags & I915_EXEC_CONSTANTS_MASK) { +		DRM_DEBUG("I915_EXEC_CONSTANTS_* unsupported\n");  		return -EINVAL;  	} -	if (params->engine->id == RCS && -	    instp_mode != dev_priv->relative_constants_mode) { -		struct intel_ring *ring = params->request->ring; - -		ret = intel_ring_begin(params->request, 4); -		if (ret) -			return ret; - -		intel_ring_emit(ring, MI_NOOP); -		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); -		intel_ring_emit_reg(ring, INSTPM); -		intel_ring_emit(ring, instp_mask << 16 | instp_mode); -		intel_ring_advance(ring); - -		dev_priv->relative_constants_mode = instp_mode; -	} -  	if (args->flags & I915_EXEC_GEN7_SOL_RESET) {  		ret = i915_reset_gen7_sol_offsets(params->request);  		if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2801a4d56324..96e45a4d5441 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2704,7 +2704,7 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,  	struct i915_ggtt *ggtt = &dev_priv->ggtt;  	if (unlikely(ggtt->do_idle_maps)) { -		if (i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED)) { +		if (i915_gem_wait_for_idle(dev_priv, 0)) {  			DRM_ERROR("Failed to wait for idle; VT'd may hang.\n");  			/* Wait a bit, in hopes it avoids the hang */  			udelay(10); diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h index bf90b07163d1..76b80a0be797 100644 --- a/drivers/gpu/drm/i915/i915_gem_object.h +++ b/drivers/gpu/drm/i915/i915_gem_object.h @@ -54,6 +54,9 @@ struct drm_i915_gem_object_ops {  	struct sg_table *(*get_pages)(struct drm_i915_gem_object *);  	void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *); +	int (*pwrite)(struct drm_i915_gem_object *, +		      const struct drm_i915_gem_pwrite *); +  	int (*dmabuf_export)(struct drm_i915_gem_object *);  	void (*release)(struct drm_i915_gem_object *);  }; diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index e7c3c0318ff6..da70bfe97ec5 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -37,6 +37,17 @@ static const char *i915_fence_get_driver_name(struct dma_fence *fence)  static const char *i915_fence_get_timeline_name(struct dma_fence *fence)  { +	/* The timeline struct (as part of the ppgtt underneath a context) +	 * may be freed when the request is no longer in use by the GPU. +	 * We could extend the life of a context to beyond that of all +	 * fences, possibly keeping the hw resource around indefinitely, +	 * or we just give them a false name. Since +	 * dma_fence_ops.get_timeline_name is a debug feature, the occasional +	 * lie seems justifiable. +	 */ +	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) +		return "signaled"; +  	return to_request(fence)->timeline->common->name;  } diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 401006b4c6a3..70b3832a79dd 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -53,6 +53,17 @@ static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock)  	BUG();  } +static void i915_gem_shrinker_unlock(struct drm_device *dev, bool unlock) +{ +	if (!unlock) +		return; + +	mutex_unlock(&dev->struct_mutex); + +	/* expedite the RCU grace period to free some request slabs */ +	synchronize_rcu_expedited(); +} +  static bool any_vma_pinned(struct drm_i915_gem_object *obj)  {  	struct i915_vma *vma; @@ -232,11 +243,8 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,  		intel_runtime_pm_put(dev_priv);  	i915_gem_retire_requests(dev_priv); -	if (unlock) -		mutex_unlock(&dev_priv->drm.struct_mutex); -	/* expedite the RCU grace period to free some request slabs */ -	synchronize_rcu_expedited(); +	i915_gem_shrinker_unlock(&dev_priv->drm, unlock);  	return count;  } @@ -263,7 +271,7 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv)  				I915_SHRINK_BOUND |  				I915_SHRINK_UNBOUND |  				I915_SHRINK_ACTIVE); -	rcu_barrier(); /* wait until our RCU delayed slab frees are completed */ +	synchronize_rcu(); /* wait for our earlier RCU delayed slab frees */  	return freed;  } @@ -293,8 +301,7 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)  			count += obj->base.size >> PAGE_SHIFT;  	} -	if (unlock) -		mutex_unlock(&dev->struct_mutex); +	i915_gem_shrinker_unlock(dev, unlock);  	return count;  } @@ -321,8 +328,8 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)  					 sc->nr_to_scan - freed,  					 I915_SHRINK_BOUND |  					 I915_SHRINK_UNBOUND); -	if (unlock) -		mutex_unlock(&dev->struct_mutex); + +	i915_gem_shrinker_unlock(dev, unlock);  	return freed;  } @@ -364,8 +371,7 @@ i915_gem_shrinker_unlock_uninterruptible(struct drm_i915_private *dev_priv,  					 struct shrinker_lock_uninterruptible *slu)  {  	dev_priv->mm.interruptible = slu->was_interruptible; -	if (slu->unlock) -		mutex_unlock(&dev_priv->drm.struct_mutex); +	i915_gem_shrinker_unlock(&dev_priv->drm, slu->unlock);  }  static int diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e6ffef2f707a..b6c886ac901b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1046,68 +1046,51 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv,  	ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);  } -static bool vlv_c0_above(struct drm_i915_private *dev_priv, -			 const struct intel_rps_ei *old, -			 const struct intel_rps_ei *now, -			 int threshold) -{ -	u64 time, c0; -	unsigned int mul = 100; - -	if (old->cz_clock == 0) -		return false; - -	if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) -		mul <<= 8; - -	time = now->cz_clock - old->cz_clock; -	time *= threshold * dev_priv->czclk_freq; - -	/* Workload can be split between render + media, e.g. SwapBuffers -	 * being blitted in X after being rendered in mesa. To account for -	 * this we need to combine both engines into our activity counter. -	 */ -	c0 = now->render_c0 - old->render_c0; -	c0 += now->media_c0 - old->media_c0; -	c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC; - -	return c0 >= time; -} -  void gen6_rps_reset_ei(struct drm_i915_private *dev_priv)  { -	vlv_c0_read(dev_priv, &dev_priv->rps.down_ei); -	dev_priv->rps.up_ei = dev_priv->rps.down_ei; +	memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei));  }  static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)  { +	const struct intel_rps_ei *prev = &dev_priv->rps.ei;  	struct intel_rps_ei now;  	u32 events = 0; -	if ((pm_iir & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) == 0) +	if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0)  		return 0;  	vlv_c0_read(dev_priv, &now);  	if (now.cz_clock == 0)  		return 0; -	if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) { -		if (!vlv_c0_above(dev_priv, -				  &dev_priv->rps.down_ei, &now, -				  dev_priv->rps.down_threshold)) -			events |= GEN6_PM_RP_DOWN_THRESHOLD; -		dev_priv->rps.down_ei = now; -	} +	if (prev->cz_clock) { +		u64 time, c0; +		unsigned int mul; + +		mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */ +		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) +			mul <<= 8; + +		time = now.cz_clock - prev->cz_clock; +		time *= dev_priv->czclk_freq; + +		/* Workload can be split between render + media, +		 * e.g. SwapBuffers being blitted in X after being rendered in +		 * mesa. To account for this we need to combine both engines +		 * into our activity counter. +		 */ +		c0 = now.render_c0 - prev->render_c0; +		c0 += now.media_c0 - prev->media_c0; +		c0 *= mul; -	if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) { -		if (vlv_c0_above(dev_priv, -				 &dev_priv->rps.up_ei, &now, -				 dev_priv->rps.up_threshold)) -			events |= GEN6_PM_RP_UP_THRESHOLD; -		dev_priv->rps.up_ei = now; +		if (c0 > time * dev_priv->rps.up_threshold) +			events = GEN6_PM_RP_UP_THRESHOLD; +		else if (c0 < time * dev_priv->rps.down_threshold) +			events = GEN6_PM_RP_DOWN_THRESHOLD;  	} +	dev_priv->rps.ei = now;  	return events;  } @@ -4228,7 +4211,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)  	/* Let's track the enabled rps events */  	if (IS_VALLEYVIEW(dev_priv))  		/* WaGsvRC0ResidencyMethod:vlv */ -		dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED; +		dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;  	else  		dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; @@ -4266,6 +4249,16 @@ void intel_irq_init(struct drm_i915_private *dev_priv)  	if (!IS_GEN2(dev_priv))  		dev->vblank_disable_immediate = true; +	/* Most platforms treat the display irq block as an always-on +	 * power domain. vlv/chv can disable it at runtime and need +	 * special care to avoid writing any of the display block registers +	 * outside of the power domain. We defer setting up the display irqs +	 * in this case to the runtime pm. +	 */ +	dev_priv->display_irqs_enabled = true; +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) +		dev_priv->display_irqs_enabled = false; +  	dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;  	dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index ecb487b5356f..9bbbd4e83e3c 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -60,6 +60,7 @@  	.has_overlay = 1, .overlay_needs_physical = 1, \  	.has_gmch_display = 1, \  	.hws_needs_physical = 1, \ +	.unfenced_needs_alignment = 1, \  	.ring_mask = RENDER_RING, \  	GEN_DEFAULT_PIPEOFFSETS, \  	CURSOR_OFFSETS @@ -101,6 +102,7 @@ static const struct intel_device_info intel_i915g_info = {  	.platform = INTEL_I915G, .cursor_needs_physical = 1,  	.has_overlay = 1, .overlay_needs_physical = 1,  	.hws_needs_physical = 1, +	.unfenced_needs_alignment = 1,  };  static const struct intel_device_info intel_i915gm_info = { @@ -112,6 +114,7 @@ static const struct intel_device_info intel_i915gm_info = {  	.supports_tv = 1,  	.has_fbc = 1,  	.hws_needs_physical = 1, +	.unfenced_needs_alignment = 1,  };  static const struct intel_device_info intel_i945g_info = { @@ -120,6 +123,7 @@ static const struct intel_device_info intel_i945g_info = {  	.has_hotplug = 1, .cursor_needs_physical = 1,  	.has_overlay = 1, .overlay_needs_physical = 1,  	.hws_needs_physical = 1, +	.unfenced_needs_alignment = 1,  };  static const struct intel_device_info intel_i945gm_info = { @@ -130,6 +134,7 @@ static const struct intel_device_info intel_i945gm_info = {  	.supports_tv = 1,  	.has_fbc = 1,  	.hws_needs_physical = 1, +	.unfenced_needs_alignment = 1,  };  static const struct intel_device_info intel_g33_info = { diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index a1b7eec58be2..70964ca9251e 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1705,7 +1705,7 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv,  	 */  	if (WARN_ON(stream->sample_flags != props->sample_flags)) {  		ret = -ENODEV; -		goto err_alloc; +		goto err_flags;  	}  	list_add(&stream->link, &dev_priv->perf.streams); @@ -1728,6 +1728,7 @@ i915_perf_open_ioctl_locked(struct drm_i915_private *dev_priv,  err_open:  	list_del(&stream->link); +err_flags:  	if (stream->ops->destroy)  		stream->ops->destroy(stream);  err_alloc: @@ -1793,6 +1794,11 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv,  		if (ret)  			return ret; +		if (id == 0 || id >= DRM_I915_PERF_PROP_MAX) { +			DRM_DEBUG("Unknown i915 perf property ID\n"); +			return -EINVAL; +		} +  		switch ((enum drm_i915_perf_property_id)id) {  		case DRM_I915_PERF_PROP_CTX_HANDLE:  			props->single_context = 1; @@ -1862,9 +1868,8 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv,  			props->oa_periodic = true;  			props->oa_period_exponent = value;  			break; -		default: +		case DRM_I915_PERF_PROP_MAX:  			MISSING_CASE(id); -			DRM_DEBUG("Unknown i915 perf property ID\n");  			return -EINVAL;  		} diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 155906e84812..df20e9bc1c0f 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -512,10 +512,36 @@ err_unpin:  	return ret;  } +static void +i915_vma_remove(struct i915_vma *vma) +{ +	struct drm_i915_gem_object *obj = vma->obj; + +	GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); +	GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND)); + +	drm_mm_remove_node(&vma->node); +	list_move_tail(&vma->vm_link, &vma->vm->unbound_list); + +	/* Since the unbound list is global, only move to that list if +	 * no more VMAs exist. +	 */ +	if (--obj->bind_count == 0) +		list_move_tail(&obj->global_link, +			       &to_i915(obj->base.dev)->mm.unbound_list); + +	/* And finally now the object is completely decoupled from this vma, +	 * we can drop its hold on the backing storage and allow it to be +	 * reaped by the shrinker. +	 */ +	i915_gem_object_unpin_pages(obj); +	GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count); +} +  int __i915_vma_do_pin(struct i915_vma *vma,  		      u64 size, u64 alignment, u64 flags)  { -	unsigned int bound = vma->flags; +	const unsigned int bound = vma->flags;  	int ret;  	lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); @@ -524,18 +550,18 @@ int __i915_vma_do_pin(struct i915_vma *vma,  	if (WARN_ON(bound & I915_VMA_PIN_OVERFLOW)) {  		ret = -EBUSY; -		goto err; +		goto err_unpin;  	}  	if ((bound & I915_VMA_BIND_MASK) == 0) {  		ret = i915_vma_insert(vma, size, alignment, flags);  		if (ret) -			goto err; +			goto err_unpin;  	}  	ret = i915_vma_bind(vma, vma->obj->cache_level, flags);  	if (ret) -		goto err; +		goto err_remove;  	if ((bound ^ vma->flags) & I915_VMA_GLOBAL_BIND)  		__i915_vma_set_map_and_fenceable(vma); @@ -544,7 +570,12 @@ int __i915_vma_do_pin(struct i915_vma *vma,  	GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));  	return 0; -err: +err_remove: +	if ((bound & I915_VMA_BIND_MASK) == 0) { +		GEM_BUG_ON(vma->pages); +		i915_vma_remove(vma); +	} +err_unpin:  	__i915_vma_unpin(vma);  	return ret;  } @@ -657,9 +688,6 @@ int i915_vma_unbind(struct i915_vma *vma)  	}  	vma->flags &= ~(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND); -	drm_mm_remove_node(&vma->node); -	list_move_tail(&vma->vm_link, &vma->vm->unbound_list); -  	if (vma->pages != obj->mm.pages) {  		GEM_BUG_ON(!vma->pages);  		sg_free_table(vma->pages); @@ -667,18 +695,7 @@ int i915_vma_unbind(struct i915_vma *vma)  	}  	vma->pages = NULL; -	/* Since the unbound list is global, only move to that list if -	 * no more VMAs exist. */ -	if (--obj->bind_count == 0) -		list_move_tail(&obj->global_link, -			       &to_i915(obj->base.dev)->mm.unbound_list); - -	/* And finally now the object is completely decoupled from this vma, -	 * we can drop its hold on the backing storage and allow it to be -	 * reaped by the shrinker. -	 */ -	i915_gem_object_unpin_pages(obj); -	GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count); +	i915_vma_remove(vma);  destroy:  	if (unlikely(i915_vma_is_closed(vma))) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 0085bc745f6a..de219b71fb76 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -35,7 +35,6 @@   */  #define I915_CSR_GLK "i915/glk_dmc_ver1_01.bin" -MODULE_FIRMWARE(I915_CSR_GLK);  #define GLK_CSR_VERSION_REQUIRED	CSR_VERSION(1, 1)  #define I915_CSR_KBL "i915/kbl_dmc_ver1_01.bin" diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 01341670738f..ed1f4f272b4f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3669,10 +3669,6 @@ static void intel_update_pipe_config(struct intel_crtc *crtc,  	/* drm_atomic_helper_update_legacy_modeset_state might not be called. */  	crtc->base.mode = crtc->base.state->mode; -	DRM_DEBUG_KMS("Updating pipe size %ix%i -> %ix%i\n", -		      old_crtc_state->pipe_src_w, old_crtc_state->pipe_src_h, -		      pipe_config->pipe_src_w, pipe_config->pipe_src_h); -  	/*  	 * Update pipe size and adjust fitter if needed: the reason for this is  	 * that in compute_mode_changes we check the native mode (not the pfit @@ -4796,23 +4792,17 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)  	struct intel_crtc_scaler_state *scaler_state =  		&crtc->config->scaler_state; -	DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config); -  	if (crtc->config->pch_pfit.enabled) {  		int id; -		if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) { -			DRM_ERROR("Requesting pfit without getting a scaler first\n"); +		if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))  			return; -		}  		id = scaler_state->scaler_id;  		I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |  			PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);  		I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);  		I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size); - -		DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", crtc->config, id);  	}  } @@ -14379,6 +14369,24 @@ static void skl_update_crtcs(struct drm_atomic_state *state,  	} while (progress);  } +static void intel_atomic_helper_free_state(struct drm_i915_private *dev_priv) +{ +	struct intel_atomic_state *state, *next; +	struct llist_node *freed; + +	freed = llist_del_all(&dev_priv->atomic_helper.free_list); +	llist_for_each_entry_safe(state, next, freed, freed) +		drm_atomic_state_put(&state->base); +} + +static void intel_atomic_helper_free_state_worker(struct work_struct *work) +{ +	struct drm_i915_private *dev_priv = +		container_of(work, typeof(*dev_priv), atomic_helper.free_work); + +	intel_atomic_helper_free_state(dev_priv); +} +  static void intel_atomic_commit_tail(struct drm_atomic_state *state)  {  	struct drm_device *dev = state->dev; @@ -14545,6 +14553,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)  	 * can happen also when the device is completely off.  	 */  	intel_uncore_arm_unclaimed_mmio_detection(dev_priv); + +	intel_atomic_helper_free_state(dev_priv);  }  static void intel_atomic_commit_work(struct work_struct *work) @@ -14946,17 +14956,19 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,  		to_intel_atomic_state(old_crtc_state->state);  	bool modeset = needs_modeset(crtc->state); +	if (!modeset && +	    (intel_cstate->base.color_mgmt_changed || +	     intel_cstate->update_pipe)) { +		intel_color_set_csc(crtc->state); +		intel_color_load_luts(crtc->state); +	} +  	/* Perform vblank evasion around commit operation */  	intel_pipe_update_start(intel_crtc);  	if (modeset)  		goto out; -	if (crtc->state->color_mgmt_changed || to_intel_crtc_state(crtc->state)->update_pipe) { -		intel_color_set_csc(crtc->state); -		intel_color_load_luts(crtc->state); -	} -  	if (intel_cstate->update_pipe)  		intel_update_pipe_config(intel_crtc, old_intel_cstate);  	else if (INTEL_GEN(dev_priv) >= 9) @@ -16599,18 +16611,6 @@ fail:  	drm_modeset_acquire_fini(&ctx);  } -static void intel_atomic_helper_free_state(struct work_struct *work) -{ -	struct drm_i915_private *dev_priv = -		container_of(work, typeof(*dev_priv), atomic_helper.free_work); -	struct intel_atomic_state *state, *next; -	struct llist_node *freed; - -	freed = llist_del_all(&dev_priv->atomic_helper.free_list); -	llist_for_each_entry_safe(state, next, freed, freed) -		drm_atomic_state_put(&state->base); -} -  int intel_modeset_init(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = to_i915(dev); @@ -16631,7 +16631,7 @@ int intel_modeset_init(struct drm_device *dev)  	dev->mode_config.funcs = &intel_mode_funcs;  	INIT_WORK(&dev_priv->atomic_helper.free_work, -		  intel_atomic_helper_free_state); +		  intel_atomic_helper_free_state_worker);  	intel_init_quirks(dev); @@ -16696,12 +16696,11 @@ int intel_modeset_init(struct drm_device *dev)  		}  	} -	intel_update_czclk(dev_priv); -	intel_update_cdclk(dev_priv); -	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq; -  	intel_shared_dpll_init(dev); +	intel_update_czclk(dev_priv); +	intel_modeset_init_hw(dev); +  	if (dev_priv->max_cdclk_freq == 0)  		intel_update_max_cdclk(dev_priv); @@ -17258,8 +17257,6 @@ void intel_modeset_gem_init(struct drm_device *dev)  	intel_init_gt_powersave(dev_priv); -	intel_modeset_init_hw(dev); -  	intel_setup_overlay(dev_priv);  } diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 371acf109e34..ab1be5c80ea5 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -105,6 +105,8 @@ intel_engine_setup(struct drm_i915_private *dev_priv,  	/* Nothing to do here, execute in order of dependencies */  	engine->schedule = NULL; +	ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); +  	dev_priv->engine[id] = engine;  	return 0;  } diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 1b8ba2e77539..2d449fb5d1d2 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -357,14 +357,13 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,  				    bool *enabled, int width, int height)  {  	struct drm_i915_private *dev_priv = to_i915(fb_helper->dev); -	unsigned long conn_configured, mask; +	unsigned long conn_configured, conn_seq, mask;  	unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);  	int i, j;  	bool *save_enabled;  	bool fallback = true;  	int num_connectors_enabled = 0;  	int num_connectors_detected = 0; -	int pass = 0;  	save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);  	if (!save_enabled) @@ -374,6 +373,7 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,  	mask = BIT(count) - 1;  	conn_configured = 0;  retry: +	conn_seq = conn_configured;  	for (i = 0; i < count; i++) {  		struct drm_fb_helper_connector *fb_conn;  		struct drm_connector *connector; @@ -387,7 +387,7 @@ retry:  		if (conn_configured & BIT(i))  			continue; -		if (pass == 0 && !connector->has_tile) +		if (conn_seq == 0 && !connector->has_tile)  			continue;  		if (connector->status == connector_status_connected) @@ -498,10 +498,8 @@ retry:  		conn_configured |= BIT(i);  	} -	if ((conn_configured & mask) != mask) { -		pass++; +	if ((conn_configured & mask) != mask && conn_configured != conn_seq)  		goto retry; -	}  	/*  	 * If the BIOS didn't enable everything it could, fall back to have the diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index d23c0fcff751..8c04eca84351 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -77,6 +77,11 @@ int intel_gvt_init(struct drm_i915_private *dev_priv)  		goto bail;  	} +	if (!i915.enable_execlists) { +		DRM_INFO("GPU guest virtualisation [GVT-g] disabled due to disabled execlist submission [i915.enable_execlists module parameter]\n"); +		goto bail; +	} +  	/*  	 * We're not in host or fail to find a MPT module, disable GVT-g  	 */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ebae2bd83918..24b2fa5b6282 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1298,16 +1298,34 @@ intel_hdmi_mode_valid(struct drm_connector *connector,  static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)  { -	struct drm_device *dev = crtc_state->base.crtc->dev; +	struct drm_i915_private *dev_priv = +		to_i915(crtc_state->base.crtc->dev); +	struct drm_atomic_state *state = crtc_state->base.state; +	struct drm_connector_state *connector_state; +	struct drm_connector *connector; +	int i; -	if (HAS_GMCH_DISPLAY(to_i915(dev))) +	if (HAS_GMCH_DISPLAY(dev_priv))  		return false;  	/*  	 * HDMI 12bpc affects the clocks, so it's only possible  	 * when not cloning with other encoder types.  	 */ -	return crtc_state->output_types == 1 << INTEL_OUTPUT_HDMI; +	if (crtc_state->output_types != 1 << INTEL_OUTPUT_HDMI) +		return false; + +	for_each_connector_in_state(state, connector, connector_state, i) { +		const struct drm_display_info *info = &connector->display_info; + +		if (connector_state->crtc != crtc_state->base.crtc) +			continue; + +		if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0) +			return false; +	} + +	return true;  }  bool intel_hdmi_compute_config(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index b62e3f8ad415..54208bef7a83 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -219,7 +219,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)  			}  		}  	} -	if (dev_priv->display.hpd_irq_setup) +	if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup)  		dev_priv->display.hpd_irq_setup(dev_priv);  	spin_unlock_irq(&dev_priv->irq_lock); @@ -425,7 +425,7 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,  		}  	} -	if (storm_detected) +	if (storm_detected && dev_priv->display_irqs_enabled)  		dev_priv->display.hpd_irq_setup(dev_priv);  	spin_unlock(&dev_priv->irq_lock); @@ -471,10 +471,12 @@ void intel_hpd_init(struct drm_i915_private *dev_priv)  	 * Interrupt setup is already guaranteed to be single-threaded, this is  	 * just to make the assert_spin_locked checks happy.  	 */ -	spin_lock_irq(&dev_priv->irq_lock); -	if (dev_priv->display.hpd_irq_setup) -		dev_priv->display.hpd_irq_setup(dev_priv); -	spin_unlock_irq(&dev_priv->irq_lock); +	if (dev_priv->display_irqs_enabled && dev_priv->display.hpd_irq_setup) { +		spin_lock_irq(&dev_priv->irq_lock); +		if (dev_priv->display_irqs_enabled) +			dev_priv->display.hpd_irq_setup(dev_priv); +		spin_unlock_irq(&dev_priv->irq_lock); +	}  }  static void i915_hpd_poll_init_work(struct work_struct *work) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ebf8023d21e6..47517a02f0a4 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -345,7 +345,8 @@ execlists_context_status_change(struct drm_i915_gem_request *rq,  	if (!IS_ENABLED(CONFIG_DRM_I915_GVT))  		return; -	atomic_notifier_call_chain(&rq->ctx->status_notifier, status, rq); +	atomic_notifier_call_chain(&rq->engine->context_status_notifier, +				   status, rq);  }  static void @@ -669,15 +670,14 @@ static void execlists_submit_request(struct drm_i915_gem_request *request)  static struct intel_engine_cs *  pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked)  { -	struct intel_engine_cs *engine; +	struct intel_engine_cs *engine = +		container_of(pt, struct drm_i915_gem_request, priotree)->engine; + +	GEM_BUG_ON(!locked); -	engine = container_of(pt, -			      struct drm_i915_gem_request, -			      priotree)->engine;  	if (engine != locked) { -		if (locked) -			spin_unlock_irq(&locked->timeline->lock); -		spin_lock_irq(&engine->timeline->lock); +		spin_unlock(&locked->timeline->lock); +		spin_lock(&engine->timeline->lock);  	}  	return engine; @@ -685,7 +685,7 @@ pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked)  static void execlists_schedule(struct drm_i915_gem_request *request, int prio)  { -	struct intel_engine_cs *engine = NULL; +	struct intel_engine_cs *engine;  	struct i915_dependency *dep, *p;  	struct i915_dependency stack;  	LIST_HEAD(dfs); @@ -719,26 +719,23 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio)  	list_for_each_entry_safe(dep, p, &dfs, dfs_link) {  		struct i915_priotree *pt = dep->signaler; -		list_for_each_entry(p, &pt->signalers_list, signal_link) +		/* Within an engine, there can be no cycle, but we may +		 * refer to the same dependency chain multiple times +		 * (redundant dependencies are not eliminated) and across +		 * engines. +		 */ +		list_for_each_entry(p, &pt->signalers_list, signal_link) { +			GEM_BUG_ON(p->signaler->priority < pt->priority);  			if (prio > READ_ONCE(p->signaler->priority))  				list_move_tail(&p->dfs_link, &dfs); +		}  		list_safe_reset_next(dep, p, dfs_link); -		if (!RB_EMPTY_NODE(&pt->node)) -			continue; - -		engine = pt_lock_engine(pt, engine); - -		/* If it is not already in the rbtree, we can update the -		 * priority inplace and skip over it (and its dependencies) -		 * if it is referenced *again* as we descend the dfs. -		 */ -		if (prio > pt->priority && RB_EMPTY_NODE(&pt->node)) { -			pt->priority = prio; -			list_del_init(&dep->dfs_link); -		}  	} +	engine = request->engine; +	spin_lock_irq(&engine->timeline->lock); +  	/* Fifo and depth-first replacement ensure our deps execute before us */  	list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) {  		struct i915_priotree *pt = dep->signaler; @@ -750,16 +747,15 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio)  		if (prio <= pt->priority)  			continue; -		GEM_BUG_ON(RB_EMPTY_NODE(&pt->node)); -  		pt->priority = prio; -		rb_erase(&pt->node, &engine->execlist_queue); -		if (insert_request(pt, &engine->execlist_queue)) -			engine->execlist_first = &pt->node; +		if (!RB_EMPTY_NODE(&pt->node)) { +			rb_erase(&pt->node, &engine->execlist_queue); +			if (insert_request(pt, &engine->execlist_queue)) +				engine->execlist_first = &pt->node; +		}  	} -	if (engine) -		spin_unlock_irq(&engine->timeline->lock); +	spin_unlock_irq(&engine->timeline->lock);  	/* XXX Do we need to preempt to make room for us and our deps? */  } @@ -1439,7 +1435,9 @@ static void reset_common_ring(struct intel_engine_cs *engine,  	GEM_BUG_ON(request->ctx != port[0].request->ctx);  	/* Reset WaIdleLiteRestore:bdw,skl as well */ -	request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32); +	request->tail = +		intel_ring_wrap(request->ring, +				request->wa_tail - WA_TAIL_DWORDS*sizeof(u32));  }  static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 249623d45be0..6a29784d2b41 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4891,6 +4891,12 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)  		break;  	} +	/* When byt can survive without system hang with dynamic +	 * sw freq adjustments, this restriction can be lifted. +	 */ +	if (IS_VALLEYVIEW(dev_priv)) +		goto skip_hw_write; +  	I915_WRITE(GEN6_RP_UP_EI,  		   GT_INTERVAL_FROM_US(dev_priv, ei_up));  	I915_WRITE(GEN6_RP_UP_THRESHOLD, @@ -4911,6 +4917,7 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val)  		   GEN6_RP_UP_BUSY_AVG |  		   GEN6_RP_DOWN_IDLE_AVG); +skip_hw_write:  	dev_priv->rps.power = new_power;  	dev_priv->rps.up_threshold = threshold_up;  	dev_priv->rps.down_threshold = threshold_down; @@ -4921,8 +4928,9 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val)  {  	u32 mask = 0; +	/* We use UP_EI_EXPIRED interupts for both up/down in manual mode */  	if (val > dev_priv->rps.min_freq_softlimit) -		mask |= GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT; +		mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT;  	if (val < dev_priv->rps.max_freq_softlimit)  		mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD; @@ -5032,7 +5040,7 @@ void gen6_rps_busy(struct drm_i915_private *dev_priv)  {  	mutex_lock(&dev_priv->rps.hw_lock);  	if (dev_priv->rps.enabled) { -		if (dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) +		if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED)  			gen6_rps_reset_ei(dev_priv);  		I915_WRITE(GEN6_PMINTRMSK,  			   gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq)); @@ -7916,10 +7924,10 @@ static bool skl_pcode_try_request(struct drm_i915_private *dev_priv, u32 mbox,   * @timeout_base_ms: timeout for polling with preemption enabled   *   * Keep resending the @request to @mbox until PCODE acknowledges it, PCODE - * reports an error or an overall timeout of @timeout_base_ms+10 ms expires. + * reports an error or an overall timeout of @timeout_base_ms+50 ms expires.   * The request is acknowledged once the PCODE reply dword equals @reply after   * applying @reply_mask. Polling is first attempted with preemption enabled - * for @timeout_base_ms and if this times out for another 10 ms with + * for @timeout_base_ms and if this times out for another 50 ms with   * preemption disabled.   *   * Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some @@ -7955,14 +7963,15 @@ int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,  	 * worst case) _and_ PCODE was busy for some reason even after a  	 * (queued) request and @timeout_base_ms delay. As a workaround retry  	 * the poll with preemption disabled to maximize the number of -	 * requests. Increase the timeout from @timeout_base_ms to 10ms to +	 * requests. Increase the timeout from @timeout_base_ms to 50ms to  	 * account for interrupts that could reduce the number of these -	 * requests. +	 * requests, and for any quirks of the PCODE firmware that delays +	 * the request completion.  	 */  	DRM_DEBUG_KMS("PCODE timeout, retrying with preemption disabled\n");  	WARN_ON_ONCE(timeout_base_ms > 3);  	preempt_disable(); -	ret = wait_for_atomic(COND, 10); +	ret = wait_for_atomic(COND, 50);  	preempt_enable();  out: diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 91bc4abf5d3e..6c5f9958197d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2024,6 +2024,8 @@ static int intel_ring_context_pin(struct intel_engine_cs *engine,  		ret = context_pin(ctx, flags);  		if (ret)  			goto error; + +		ce->state->obj->mm.dirty = true;  	}  	/* The kernel context is only used as a placeholder for flushing the diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 79c2b8d72322..8cb2078c5bfc 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -403,6 +403,9 @@ struct intel_engine_cs {  	 */  	struct i915_gem_context *legacy_active_context; +	/* status_notifier: list of callbacks for context-switch changes */ +	struct atomic_notifier_head context_status_notifier; +  	struct intel_engine_hangcheck hangcheck;  	bool needs_cmd_parser; @@ -518,11 +521,17 @@ static inline void intel_ring_advance(struct intel_ring *ring)  	 */  } +static inline u32 +intel_ring_wrap(const struct intel_ring *ring, u32 pos) +{ +	return pos & (ring->size - 1); +} +  static inline u32 intel_ring_offset(struct intel_ring *ring, void *addr)  {  	/* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */  	u32 offset = addr - ring->vaddr; -	return offset & (ring->size - 1); +	return intel_ring_wrap(ring, offset);  }  int __intel_ring_space(int head, int tail, int size); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 9ef54688872a..9481ca9a3ae7 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -254,9 +254,6 @@ skl_update_plane(struct drm_plane *drm_plane,  		int scaler_id = plane_state->scaler_id;  		const struct intel_scaler *scaler; -		DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", -			      plane_id, PS_PLANE_SEL(plane_id)); -  		scaler = &crtc_state->scaler_state.scalers[scaler_id];  		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index abe08885a5ba..b7ff592b14f5 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -119,6 +119,8 @@ fw_domains_get(struct drm_i915_private *dev_priv, enum forcewake_domains fw_doma  	for_each_fw_domain_masked(d, fw_domains, dev_priv)  		fw_domain_wait_ack(d); + +	dev_priv->uncore.fw_domains_active |= fw_domains;  }  static void @@ -130,6 +132,8 @@ fw_domains_put(struct drm_i915_private *dev_priv, enum forcewake_domains fw_doma  		fw_domain_put(d);  		fw_domain_posting_read(d);  	} + +	dev_priv->uncore.fw_domains_active &= ~fw_domains;  }  static void @@ -240,10 +244,8 @@ intel_uncore_fw_release_timer(struct hrtimer *timer)  	if (WARN_ON(domain->wake_count == 0))  		domain->wake_count++; -	if (--domain->wake_count == 0) { +	if (--domain->wake_count == 0)  		dev_priv->uncore.funcs.force_wake_put(dev_priv, domain->mask); -		dev_priv->uncore.fw_domains_active &= ~domain->mask; -	}  	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); @@ -454,10 +456,8 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv,  			fw_domains &= ~domain->mask;  	} -	if (fw_domains) { +	if (fw_domains)  		dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); -		dev_priv->uncore.fw_domains_active |= fw_domains; -	}  }  /** @@ -968,7 +968,6 @@ static noinline void ___force_wake_auto(struct drm_i915_private *dev_priv,  		fw_domain_arm_timer(domain);  	dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); -	dev_priv->uncore.fw_domains_active |= fw_domains;  }  static inline void __force_wake_auto(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 4414cf73735d..36602ac7e248 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License version 2 and @@ -534,7 +534,7 @@ static void a5xx_destroy(struct msm_gpu *gpu)  	}  	if (a5xx_gpu->gpmu_bo) { -		if (a5xx_gpu->gpmu_bo) +		if (a5xx_gpu->gpmu_iova)  			msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->id);  		drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);  	} @@ -860,7 +860,9 @@ static const struct adreno_gpu_funcs funcs = {  		.idle = a5xx_idle,  		.irq = a5xx_irq,  		.destroy = a5xx_destroy, +#ifdef CONFIG_DEBUG_FS  		.show = a5xx_show, +#endif  	},  	.get_timestamp = a5xx_get_timestamp,  }; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index c9bd1e6225f4..5ae65426b4e5 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -418,18 +418,27 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,  	return 0;  } -void adreno_gpu_cleanup(struct adreno_gpu *gpu) +void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)  { -	if (gpu->memptrs_bo) { -		if (gpu->memptrs) -			msm_gem_put_vaddr(gpu->memptrs_bo); +	struct msm_gpu *gpu = &adreno_gpu->base; + +	if (adreno_gpu->memptrs_bo) { +		if (adreno_gpu->memptrs) +			msm_gem_put_vaddr(adreno_gpu->memptrs_bo); + +		if (adreno_gpu->memptrs_iova) +			msm_gem_put_iova(adreno_gpu->memptrs_bo, gpu->id); + +		drm_gem_object_unreference_unlocked(adreno_gpu->memptrs_bo); +	} +	release_firmware(adreno_gpu->pm4); +	release_firmware(adreno_gpu->pfp); -		if (gpu->memptrs_iova) -			msm_gem_put_iova(gpu->memptrs_bo, gpu->base.id); +	msm_gpu_cleanup(gpu); -		drm_gem_object_unreference_unlocked(gpu->memptrs_bo); +	if (gpu->aspace) { +		gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu, +			iommu_ports, ARRAY_SIZE(iommu_ports)); +		msm_gem_address_space_destroy(gpu->aspace);  	} -	release_firmware(gpu->pm4); -	release_firmware(gpu->pfp); -	msm_gpu_cleanup(&gpu->base);  } diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index 921270ea6059..a879ffa534b4 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -171,7 +171,7 @@ dsi_mgr_phy_enable(int id,  			}  		}  	} else { -		msm_dsi_host_reset_phy(mdsi->host); +		msm_dsi_host_reset_phy(msm_dsi->host);  		ret = enable_phy(msm_dsi, src_pll_id, &shared_timings[id]);  		if (ret)  			return ret; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c index a54d3bb5baad..8177e8511afd 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_audio.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_audio.c @@ -18,13 +18,6 @@  #include <linux/hdmi.h>  #include "hdmi.h" - -/* Supported HDMI Audio channels */ -#define MSM_HDMI_AUDIO_CHANNEL_2		0 -#define MSM_HDMI_AUDIO_CHANNEL_4		1 -#define MSM_HDMI_AUDIO_CHANNEL_6		2 -#define MSM_HDMI_AUDIO_CHANNEL_8		3 -  /* maps MSM_HDMI_AUDIO_CHANNEL_n consts used by audio driver to # of channels: */  static int nchannels[] = { 2, 4, 6, 8 }; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h index 611da7a660c9..238901987e00 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h @@ -18,7 +18,8 @@  #ifndef __MDP5_PIPE_H__  #define __MDP5_PIPE_H__ -#define SSPP_MAX	(SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */ +/* TODO: Add SSPP_MAX in mdp5.xml.h */ +#define SSPP_MAX	(SSPP_CURSOR1 + 1)  /* represents a hw pipe, which is dynamically assigned to a plane */  struct mdp5_hw_pipe { diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 59811f29607d..68e509b3b9e4 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -812,6 +812,12 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev,  	size = PAGE_ALIGN(size); +	/* Disallow zero sized objects as they make the underlying +	 * infrastructure grumpy +	 */ +	if (size == 0) +		return ERR_PTR(-EINVAL); +  	ret = msm_gem_new_impl(dev, size, flags, NULL, &obj);  	if (ret)  		goto fail; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 99e05aacbee1..af5b6ba4095b 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -706,9 +706,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)  		msm_ringbuffer_destroy(gpu->rb);  	} -	if (gpu->aspace) -		msm_gem_address_space_destroy(gpu->aspace); -  	if (gpu->fctx)  		msm_fence_context_free(gpu->fctx);  } diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index e10a4eda4078..1144e0c9e894 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -65,13 +65,11 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)  	switch (format) {  	case DRM_FORMAT_RGB565:  		dev_dbg(drm->dev, "Setting up RGB565 mode\n"); -		ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);  		ctrl |= CTRL_SET_WORD_LENGTH(0);  		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);  		break;  	case DRM_FORMAT_XRGB8888:  		dev_dbg(drm->dev, "Setting up XRGB8888 mode\n"); -		ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);  		ctrl |= CTRL_SET_WORD_LENGTH(3);  		/* Do not use packed pixels = one pixel per word instead. */  		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7); @@ -87,6 +85,36 @@ static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)  	return 0;  } +static void mxsfb_set_bus_fmt(struct mxsfb_drm_private *mxsfb) +{ +	struct drm_crtc *crtc = &mxsfb->pipe.crtc; +	struct drm_device *drm = crtc->dev; +	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; +	u32 reg; + +	reg = readl(mxsfb->base + LCDC_CTRL); + +	if (mxsfb->connector.display_info.num_bus_formats) +		bus_format = mxsfb->connector.display_info.bus_formats[0]; + +	reg &= ~CTRL_BUS_WIDTH_MASK; +	switch (bus_format) { +	case MEDIA_BUS_FMT_RGB565_1X16: +		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT); +		break; +	case MEDIA_BUS_FMT_RGB666_1X18: +		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_18BIT); +		break; +	case MEDIA_BUS_FMT_RGB888_1X24: +		reg |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT); +		break; +	default: +		dev_err(drm->dev, "Unknown media bus format %d\n", bus_format); +		break; +	} +	writel(reg, mxsfb->base + LCDC_CTRL); +} +  static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)  {  	u32 reg; @@ -168,13 +196,22 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)  		vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;  	if (m->flags & DRM_MODE_FLAG_PVSYNC)  		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH; -	if (bus_flags & DRM_BUS_FLAG_DE_HIGH) +	/* Make sure Data Enable is high active by default */ +	if (!(bus_flags & DRM_BUS_FLAG_DE_LOW))  		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH; -	if (bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE) +	/* +	 * DRM_BUS_FLAG_PIXDATA_ defines are controller centric, +	 * controllers VDCTRL0_DOTCLK is display centric. +	 * Drive on positive edge       -> display samples on falling edge +	 * DRM_BUS_FLAG_PIXDATA_POSEDGE -> VDCTRL0_DOTCLK_ACT_FALLING +	 */ +	if (bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE)  		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;  	writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0); +	mxsfb_set_bus_fmt(mxsfb); +  	/* Frame length in lines. */  	writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1); @@ -184,8 +221,8 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)  	       VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal),  	       mxsfb->base + LCDC_VDCTRL2); -	writel(SET_HOR_WAIT_CNT(m->crtc_hblank_end - m->crtc_hsync_end) | -	       SET_VERT_WAIT_CNT(m->crtc_vblank_end - m->crtc_vsync_end), +	writel(SET_HOR_WAIT_CNT(m->crtc_htotal - m->crtc_hsync_start) | +	       SET_VERT_WAIT_CNT(m->crtc_vtotal - m->crtc_vsync_start),  	       mxsfb->base + LCDC_VDCTRL3);  	writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay), diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index cdfbe0284635..ff6d6a6f842e 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -102,14 +102,18 @@ static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,  {  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); +	drm_panel_prepare(mxsfb->panel);  	mxsfb_crtc_enable(mxsfb); +	drm_panel_enable(mxsfb->panel);  }  static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)  {  	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe); +	drm_panel_disable(mxsfb->panel);  	mxsfb_crtc_disable(mxsfb); +	drm_panel_unprepare(mxsfb->panel);  }  static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe, diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c index fa8d17399407..b8e81422d4e2 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c @@ -112,6 +112,7 @@ static int mxsfb_attach_endpoint(struct drm_device *drm,  int mxsfb_create_output(struct drm_device *drm)  { +	struct mxsfb_drm_private *mxsfb = drm->dev_private;  	struct device_node *ep_np = NULL;  	struct of_endpoint ep;  	int ret; @@ -127,5 +128,8 @@ int mxsfb_create_output(struct drm_device *drm)  		}  	} +	if (!mxsfb->panel) +		return -EPROBE_DEFER; +  	return 0;  } diff --git a/drivers/gpu/drm/mxsfb/mxsfb_regs.h b/drivers/gpu/drm/mxsfb/mxsfb_regs.h index 31d62cd0d3d7..66a6ba9ec533 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_regs.h +++ b/drivers/gpu/drm/mxsfb/mxsfb_regs.h @@ -44,6 +44,7 @@  #define CTRL_DATA_SELECT		(1 << 16)  #define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)  #define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3) +#define CTRL_BUS_WIDTH_MASK		(0x3 << 10)  #define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)  #define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)  #define CTRL_MASTER			(1 << 5) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 0b4440ffbeae..a9182d5e6011 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -995,7 +995,6 @@ nv50_wndw_atomic_destroy_state(struct drm_plane *plane,  {  	struct nv50_wndw_atom *asyw = nv50_wndw_atom(state);  	__drm_atomic_helper_plane_destroy_state(&asyw->state); -	dma_fence_put(asyw->state.fence);  	kfree(asyw);  } @@ -1007,7 +1006,6 @@ nv50_wndw_atomic_duplicate_state(struct drm_plane *plane)  	if (!(asyw = kmalloc(sizeof(*asyw), GFP_KERNEL)))  		return NULL;  	__drm_atomic_helper_plane_duplicate_state(plane, &asyw->state); -	asyw->state.fence = NULL;  	asyw->interval = 1;  	asyw->sema = armw->sema;  	asyw->ntfy = armw->ntfy; @@ -2036,6 +2034,7 @@ nv50_head_atomic_check_mode(struct nv50_head *head, struct nv50_head_atom *asyh)  	u32 vbackp  = (mode->vtotal - mode->vsync_end) * vscan / ilace;  	u32 hfrontp =  mode->hsync_start - mode->hdisplay;  	u32 vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace; +	u32 blankus;  	struct nv50_head_mode *m = &asyh->mode;  	m->h.active = mode->htotal; @@ -2049,9 +2048,10 @@ nv50_head_atomic_check_mode(struct nv50_head *head, struct nv50_head_atom *asyh)  	m->v.blanks = m->v.active - vfrontp - 1;  	/*XXX: Safe underestimate, even "0" works */ -	m->v.blankus = (m->v.active - mode->vdisplay - 2) * m->h.active; -	m->v.blankus *= 1000; -	m->v.blankus /= mode->clock; +	blankus = (m->v.active - mode->vdisplay - 2) * m->h.active; +	blankus *= 1000; +	blankus /= mode->clock; +	m->v.blankus = blankus;  	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {  		m->v.blank2e =  m->v.active + m->v.synce + vbackp; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 273562dd6bbd..3b86a7399567 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -714,7 +714,7 @@ nv4a_chipset = {  	.i2c = nv04_i2c_new,  	.imem = nv40_instmem_new,  	.mc = nv44_mc_new, -	.mmu = nv44_mmu_new, +	.mmu = nv04_mmu_new,  	.pci = nv40_pci_new,  	.therm = nv40_therm_new,  	.timer = nv41_timer_new, @@ -2271,6 +2271,35 @@ nv136_chipset = {  	.fifo = gp100_fifo_new,  }; +static const struct nvkm_device_chip +nv137_chipset = { +	.name = "GP107", +	.bar = gf100_bar_new, +	.bios = nvkm_bios_new, +	.bus = gf100_bus_new, +	.devinit = gm200_devinit_new, +	.fb = gp102_fb_new, +	.fuse = gm107_fuse_new, +	.gpio = gk104_gpio_new, +	.i2c = gm200_i2c_new, +	.ibus = gm200_ibus_new, +	.imem = nv50_instmem_new, +	.ltc = gp100_ltc_new, +	.mc = gp100_mc_new, +	.mmu = gf100_mmu_new, +	.pci = gp100_pci_new, +	.pmu = gp102_pmu_new, +	.timer = gk20a_timer_new, +	.top = gk104_top_new, +	.ce[0] = gp102_ce_new, +	.ce[1] = gp102_ce_new, +	.ce[2] = gp102_ce_new, +	.ce[3] = gp102_ce_new, +	.disp = gp102_disp_new, +	.dma = gf119_dma_new, +	.fifo = gp100_fifo_new, +}; +  static int  nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,  		       struct nvkm_notify *notify) @@ -2708,6 +2737,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,  		case 0x132: device->chip = &nv132_chipset; break;  		case 0x134: device->chip = &nv134_chipset; break;  		case 0x136: device->chip = &nv136_chipset; break; +		case 0x137: device->chip = &nv137_chipset; break;  		default:  			nvdev_error(device, "unknown chipset (%08x)\n", boot0);  			goto done; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c index 003ac915eaad..8a8895246d26 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c @@ -198,7 +198,7 @@ nv31_mpeg_intr(struct nvkm_engine *engine)  		}  		if (type == 0x00000010) { -			if (!nv31_mpeg_mthd(mpeg, mthd, data)) +			if (nv31_mpeg_mthd(mpeg, mthd, data))  				show &= ~0x01000000;  		}  	} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c index e536f37e24b0..c3cf02ed468e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c @@ -172,7 +172,7 @@ nv44_mpeg_intr(struct nvkm_engine *engine)  		}  		if (type == 0x00000010) { -			if (!nv44_mpeg_mthd(subdev->device, mthd, data)) +			if (nv44_mpeg_mthd(subdev->device, mthd, data))  				show &= ~0x01000000;  		}  	} diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index af267c35d813..ee5883f59be5 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c @@ -147,9 +147,6 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,  	struct drm_gem_object *obj = buffer->priv;  	int ret = 0; -	if (WARN_ON(!obj->filp)) -		return -EINVAL; -  	ret = drm_gem_mmap_obj(obj, omap_gem_mmap_size(obj), vma);  	if (ret < 0)  		return ret; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 684f1703aa5c..aaa3e80fecb4 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -213,8 +213,8 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo,  			rbo->placement.num_busy_placement = 0;  			for (i = 0; i < rbo->placement.num_placement; i++) {  				if (rbo->placements[i].flags & TTM_PL_FLAG_VRAM) { -					if (rbo->placements[0].fpfn < fpfn) -						rbo->placements[0].fpfn = fpfn; +					if (rbo->placements[i].fpfn < fpfn) +						rbo->placements[i].fpfn = fpfn;  				} else {  					rbo->placement.busy_placement =  						&rbo->placements[i]; diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index d12b8978142f..c7af9fdd20c7 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2984,6 +2984,16 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,  		    (rdev->pdev->device == 0x6667)) {  			max_sclk = 75000;  		} +	} else if (rdev->family == CHIP_OLAND) { +		if ((rdev->pdev->revision == 0xC7) || +		    (rdev->pdev->revision == 0x80) || +		    (rdev->pdev->revision == 0x81) || +		    (rdev->pdev->revision == 0x83) || +		    (rdev->pdev->revision == 0x87) || +		    (rdev->pdev->device == 0x6604) || +		    (rdev->pdev->device == 0x6605)) { +			max_sclk = 75000; +		}  	}  	if (rps->vce_active) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index b5bfbe50bd87..b0ff304ce3dc 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -32,6 +32,10 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)  {  	const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;  	struct rcar_du_device *rcdu = crtc->group->dev; +	struct vsp1_du_lif_config cfg = { +		.width = mode->hdisplay, +		.height = mode->vdisplay, +	};  	struct rcar_du_plane_state state = {  		.state = {  			.crtc = &crtc->crtc, @@ -66,12 +70,12 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)  	 */  	crtc->group->need_restart = true; -	vsp1_du_setup_lif(crtc->vsp->vsp, mode->hdisplay, mode->vdisplay); +	vsp1_du_setup_lif(crtc->vsp->vsp, &cfg);  }  void rcar_du_vsp_disable(struct rcar_du_crtc *crtc)  { -	vsp1_du_setup_lif(crtc->vsp->vsp, 0, 0); +	vsp1_du_setup_lif(crtc->vsp->vsp, NULL);  }  void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index f80bf9385e41..d745e8b50fb8 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -464,6 +464,7 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc)  {  	struct drm_device *dev = crtc->dev;  	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); +	unsigned long flags;  	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));  	mutex_lock(&tilcdc_crtc->enable_lock); @@ -484,7 +485,17 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc)  	tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG,  			  LCDC_PALETTE_LOAD_MODE(DATA_ONLY),  			  LCDC_PALETTE_LOAD_MODE_MASK); + +	/* There is no real chance for a race here as the time stamp +	 * is taken before the raster DMA is started. The spin-lock is +	 * taken to have a memory barrier after taking the time-stamp +	 * and to avoid a context switch between taking the stamp and +	 * enabling the raster. +	 */ +	spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); +	tilcdc_crtc->last_vblank = ktime_get();  	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); +	spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);  	drm_crtc_vblank_on(crtc); @@ -539,7 +550,6 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown)  	}  	drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq); -	tilcdc_crtc->last_vblank = 0;  	tilcdc_crtc->enabled = false;  	mutex_unlock(&tilcdc_crtc->enable_lock); @@ -602,7 +612,6 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,  {  	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);  	struct drm_device *dev = crtc->dev; -	unsigned long flags;  	WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); @@ -614,28 +623,30 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,  	drm_framebuffer_reference(fb);  	crtc->primary->fb = fb; +	tilcdc_crtc->event = event; -	spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); +	mutex_lock(&tilcdc_crtc->enable_lock); -	if (crtc->hwmode.vrefresh && ktime_to_ns(tilcdc_crtc->last_vblank)) { +	if (tilcdc_crtc->enabled) { +		unsigned long flags;  		ktime_t next_vblank;  		s64 tdiff; -		next_vblank = ktime_add_us(tilcdc_crtc->last_vblank, -			1000000 / crtc->hwmode.vrefresh); +		spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); +		next_vblank = ktime_add_us(tilcdc_crtc->last_vblank, +					   1000000 / crtc->hwmode.vrefresh);  		tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));  		if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US)  			tilcdc_crtc->next_fb = fb; -	} - -	if (tilcdc_crtc->next_fb != fb) -		set_scanout(crtc, fb); +		else +			set_scanout(crtc, fb); -	tilcdc_crtc->event = event; +		spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags); +	} -	spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags); +	mutex_unlock(&tilcdc_crtc->enable_lock);  	return 0;  } @@ -1036,5 +1047,5 @@ int tilcdc_crtc_create(struct drm_device *dev)  fail:  	tilcdc_crtc_destroy(crtc); -	return -ENOMEM; +	return ret;  } diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c index fdb451e3ec01..26a7ad0f4789 100644 --- a/drivers/gpu/drm/ttm/ttm_object.c +++ b/drivers/gpu/drm/ttm/ttm_object.c @@ -179,7 +179,7 @@ int ttm_base_object_init(struct ttm_object_file *tfile,  	if (unlikely(ret != 0))  		goto out_err0; -	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); +	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);  	if (unlikely(ret != 0))  		goto out_err1; @@ -318,7 +318,8 @@ EXPORT_SYMBOL(ttm_ref_object_exists);  int ttm_ref_object_add(struct ttm_object_file *tfile,  		       struct ttm_base_object *base, -		       enum ttm_ref_type ref_type, bool *existed) +		       enum ttm_ref_type ref_type, bool *existed, +		       bool require_existed)  {  	struct drm_open_hash *ht = &tfile->ref_hash[ref_type];  	struct ttm_ref_object *ref; @@ -345,6 +346,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,  		}  		rcu_read_unlock(); +		if (require_existed) +			return -EPERM; +  		ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),  					   false, false);  		if (unlikely(ret != 0)) @@ -449,10 +453,10 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)  		ttm_ref_object_release(&ref->kref);  	} +	spin_unlock(&tfile->lock);  	for (i = 0; i < TTM_REF_NUM; ++i)  		drm_ht_remove(&tfile->ref_hash[i]); -	spin_unlock(&tfile->lock);  	ttm_object_file_unref(&tfile);  }  EXPORT_SYMBOL(ttm_object_file_release); @@ -529,9 +533,7 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev)  	*p_tdev = NULL; -	spin_lock(&tdev->object_lock);  	drm_ht_remove(&tdev->object_hash); -	spin_unlock(&tdev->object_lock);  	kfree(tdev);  } @@ -635,7 +637,7 @@ int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,  	prime = (struct ttm_prime_object *) dma_buf->priv;  	base = &prime->base;  	*handle = base->hash.key; -	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); +	ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);  	dma_buf_put(dma_buf); diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index 917dcb978c2c..0c87b1ac6b68 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -14,6 +14,7 @@  #include <linux/slab.h>  #include <linux/fb.h>  #include <linux/prefetch.h> +#include <asm/unaligned.h>  #include <drm/drmP.h>  #include "udl_drv.h" @@ -163,7 +164,7 @@ static void udl_compress_hline16(  			const u8 *const start = pixel;  			const uint16_t repeating_pixel_val16 = pixel_val16; -			*(uint16_t *)cmd = cpu_to_be16(pixel_val16); +			put_unaligned_be16(pixel_val16, cmd);  			cmd += 2;  			pixel += bpp; diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 0c06844af445..9fcf05ca492b 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -846,6 +846,17 @@ static void vc4_crtc_destroy_state(struct drm_crtc *crtc,  	drm_atomic_helper_crtc_destroy_state(crtc, state);  } +static void +vc4_crtc_reset(struct drm_crtc *crtc) +{ +	if (crtc->state) +		__drm_atomic_helper_crtc_destroy_state(crtc->state); + +	crtc->state = kzalloc(sizeof(struct vc4_crtc_state), GFP_KERNEL); +	if (crtc->state) +		crtc->state->crtc = crtc; +} +  static const struct drm_crtc_funcs vc4_crtc_funcs = {  	.set_config = drm_atomic_helper_set_config,  	.destroy = vc4_crtc_destroy, @@ -853,7 +864,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {  	.set_property = NULL,  	.cursor_set = NULL, /* handled by drm_mode_cursor_universal */  	.cursor_move = NULL, /* handled by drm_mode_cursor_universal */ -	.reset = drm_atomic_helper_crtc_reset, +	.reset = vc4_crtc_reset,  	.atomic_duplicate_state = vc4_crtc_duplicate_state,  	.atomic_destroy_state = vc4_crtc_destroy_state,  	.gamma_set = vc4_crtc_gamma_set, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 6541dd8b82dc..6b2708b4eafe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -538,7 +538,7 @@ int vmw_fence_create(struct vmw_fence_manager *fman,  		     struct vmw_fence_obj **p_fence)  {  	struct vmw_fence_obj *fence; -	int ret; + 	int ret;  	fence = kzalloc(sizeof(*fence), GFP_KERNEL);  	if (unlikely(fence == NULL)) @@ -701,6 +701,41 @@ void vmw_fence_fifo_up(struct vmw_fence_manager *fman)  } +/** + * vmw_fence_obj_lookup - Look up a user-space fence object + * + * @tfile: A struct ttm_object_file identifying the caller. + * @handle: A handle identifying the fence object. + * @return: A struct vmw_user_fence base ttm object on success or + * an error pointer on failure. + * + * The fence object is looked up and type-checked. The caller needs + * to have opened the fence object first, but since that happens on + * creation and fence objects aren't shareable, that's not an + * issue currently. + */ +static struct ttm_base_object * +vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle) +{ +	struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle); + +	if (!base) { +		pr_err("Invalid fence object handle 0x%08lx.\n", +		       (unsigned long)handle); +		return ERR_PTR(-EINVAL); +	} + +	if (base->refcount_release != vmw_user_fence_base_release) { +		pr_err("Invalid fence object handle 0x%08lx.\n", +		       (unsigned long)handle); +		ttm_base_object_unref(&base); +		return ERR_PTR(-EINVAL); +	} + +	return base; +} + +  int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,  			     struct drm_file *file_priv)  { @@ -726,13 +761,9 @@ int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,  		arg->kernel_cookie = jiffies + wait_timeout;  	} -	base = ttm_base_object_lookup(tfile, arg->handle); -	if (unlikely(base == NULL)) { -		printk(KERN_ERR "Wait invalid fence object handle " -		       "0x%08lx.\n", -		       (unsigned long)arg->handle); -		return -EINVAL; -	} +	base = vmw_fence_obj_lookup(tfile, arg->handle); +	if (IS_ERR(base)) +		return PTR_ERR(base);  	fence = &(container_of(base, struct vmw_user_fence, base)->fence); @@ -771,13 +802,9 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,  	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;  	struct vmw_private *dev_priv = vmw_priv(dev); -	base = ttm_base_object_lookup(tfile, arg->handle); -	if (unlikely(base == NULL)) { -		printk(KERN_ERR "Fence signaled invalid fence object handle " -		       "0x%08lx.\n", -		       (unsigned long)arg->handle); -		return -EINVAL; -	} +	base = vmw_fence_obj_lookup(tfile, arg->handle); +	if (IS_ERR(base)) +		return PTR_ERR(base);  	fence = &(container_of(base, struct vmw_user_fence, base)->fence);  	fman = fman_from_fence(fence); @@ -1024,6 +1051,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,  		(struct drm_vmw_fence_event_arg *) data;  	struct vmw_fence_obj *fence = NULL;  	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); +	struct ttm_object_file *tfile = vmw_fp->tfile;  	struct drm_vmw_fence_rep __user *user_fence_rep =  		(struct drm_vmw_fence_rep __user *)(unsigned long)  		arg->fence_rep; @@ -1037,24 +1065,18 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,  	 */  	if (arg->handle) {  		struct ttm_base_object *base = -			ttm_base_object_lookup_for_ref(dev_priv->tdev, -						       arg->handle); +			vmw_fence_obj_lookup(tfile, arg->handle); + +		if (IS_ERR(base)) +			return PTR_ERR(base); -		if (unlikely(base == NULL)) { -			DRM_ERROR("Fence event invalid fence object handle " -				  "0x%08lx.\n", -				  (unsigned long)arg->handle); -			return -EINVAL; -		}  		fence = &(container_of(base, struct vmw_user_fence,  				       base)->fence);  		(void) vmw_fence_obj_reference(fence);  		if (user_fence_rep != NULL) { -			bool existed; -  			ret = ttm_ref_object_add(vmw_fp->tfile, base, -						 TTM_REF_USAGE, &existed); +						 TTM_REF_USAGE, NULL, false);  			if (unlikely(ret != 0)) {  				DRM_ERROR("Failed to reference a fence "  					  "object.\n"); @@ -1097,8 +1119,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,  	return 0;  out_no_create:  	if (user_fence_rep != NULL) -		ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, -					  handle, TTM_REF_USAGE); +		ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);  out_no_ref_obj:  	vmw_fence_obj_unreference(&fence);  	return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index b8c6a03c8c54..5ec24fd801cd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -114,8 +114,6 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,  		param->value = dev_priv->has_dx;  		break;  	default: -		DRM_ERROR("Illegal vmwgfx get param request: %d\n", -			  param->param);  		return -EINVAL;  	} @@ -186,7 +184,7 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,  	bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);  	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); -	if (unlikely(arg->pad64 != 0)) { +	if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {  		DRM_ERROR("Illegal GET_3D_CAP argument.\n");  		return -EINVAL;  	} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 65b3f0369636..bf23153d4f55 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -589,7 +589,7 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo,  		return ret;  	ret = ttm_ref_object_add(tfile, &user_bo->prime.base, -				 TTM_REF_SYNCCPU_WRITE, &existed); +				 TTM_REF_SYNCCPU_WRITE, &existed, false);  	if (ret != 0 || existed)  		ttm_bo_synccpu_write_release(&user_bo->dma.base); @@ -773,7 +773,7 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,  	*handle = user_bo->prime.base.hash.key;  	return ttm_ref_object_add(tfile, &user_bo->prime.base, -				  TTM_REF_USAGE, NULL); +				  TTM_REF_USAGE, NULL, false);  }  /* diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index b445ce9b9757..05fa092c942b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -713,11 +713,14 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,  			128;  	num_sizes = 0; -	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) +	for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { +		if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS) +			return -EINVAL;  		num_sizes += req->mip_levels[i]; +	} -	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * -	    DRM_VMW_MAX_MIP_LEVELS) +	if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS || +	    num_sizes == 0)  		return -EINVAL;  	size = vmw_user_surface_size + 128 + @@ -891,17 +894,16 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,  	uint32_t handle;  	struct ttm_base_object *base;  	int ret; +	bool require_exist = false;  	if (handle_type == DRM_VMW_HANDLE_PRIME) {  		ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);  		if (unlikely(ret != 0))  			return ret;  	} else { -		if (unlikely(drm_is_render_client(file_priv))) { -			DRM_ERROR("Render client refused legacy " -				  "surface reference.\n"); -			return -EACCES; -		} +		if (unlikely(drm_is_render_client(file_priv))) +			require_exist = true; +  		if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) {  			DRM_ERROR("Locked master refused legacy "  				  "surface reference.\n"); @@ -929,17 +931,14 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,  		/*  		 * Make sure the surface creator has the same -		 * authenticating master. +		 * authenticating master, or is already registered with us.  		 */  		if (drm_is_primary_client(file_priv) && -		    user_srf->master != file_priv->master) { -			DRM_ERROR("Trying to reference surface outside of" -				  " master domain.\n"); -			ret = -EACCES; -			goto out_bad_resource; -		} +		    user_srf->master != file_priv->master) +			require_exist = true; -		ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); +		ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, +					 require_exist);  		if (unlikely(ret != 0)) {  			DRM_ERROR("Could not add a reference to a surface.\n");  			goto out_bad_resource;  | 
