Commit 69d5c4b5 authored by Jani Nikula's avatar Jani Nikula
Browse files

Merge tag 'gvt-next-2020-11-23' of https://github.com/intel/gvt-linux into drm-intel-next-queued



gvt-next-2020-11-23

- Fix host suspend/resume with vGPU (Colin)
- optimize idr init (Varma)
- Change intel_gvt_mpt as const (Julian)
- One comment error fix (Yan)

Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
From: Zhenyu Wang <zhenyuw@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201123090517.GC16939@zhen-hp.sh.intel.com
parents f287c536 9a3a238b
Loading
Loading
Loading
Loading
+179 −0
Original line number Diff line number Diff line
@@ -173,22 +173,162 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
	int pipe;

	if (IS_BROXTON(dev_priv)) {
		enum transcoder trans;
		enum port port;

		/* Clear PIPE, DDI, PHY, HPD before setting new */
		vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
			~(GEN8_DE_PORT_HOTPLUG(HPD_PORT_A) |
			  GEN8_DE_PORT_HOTPLUG(HPD_PORT_B) |
			  GEN8_DE_PORT_HOTPLUG(HPD_PORT_C));

		for_each_pipe(dev_priv, pipe) {
			vgpu_vreg_t(vgpu, PIPECONF(pipe)) &=
				~(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE);
			vgpu_vreg_t(vgpu, DSPCNTR(pipe)) &= ~DISPLAY_PLANE_ENABLE;
			vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE;
			vgpu_vreg_t(vgpu, CURCNTR(pipe)) &= ~MCURSOR_MODE;
			vgpu_vreg_t(vgpu, CURCNTR(pipe)) |= MCURSOR_MODE_DISABLE;
		}

		for (trans = TRANSCODER_A; trans <= TRANSCODER_EDP; trans++) {
			vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(trans)) &=
				~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
				  TRANS_DDI_PORT_MASK | TRANS_DDI_FUNC_ENABLE);
		}
		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
			~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
			  TRANS_DDI_PORT_MASK);

		for (port = PORT_A; port <= PORT_C; port++) {
			vgpu_vreg_t(vgpu, BXT_PHY_CTL(port)) &=
				~BXT_PHY_LANE_ENABLED;
			vgpu_vreg_t(vgpu, BXT_PHY_CTL(port)) |=
				(BXT_PHY_CMNLANE_POWERDOWN_ACK |
				 BXT_PHY_LANE_POWERDOWN_ACK);

			vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(port)) &=
				~(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
				  PORT_PLL_REF_SEL | PORT_PLL_LOCK |
				  PORT_PLL_ENABLE);

			vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) &=
				~(DDI_INIT_DISPLAY_DETECTED |
				  DDI_BUF_CTL_ENABLE);
			vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) |= DDI_BUF_IS_IDLE;
		}

		vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) &= ~(BIT(0) | BIT(1));
		vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) &=
			~PHY_POWER_GOOD;
		vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) &=
			~PHY_POWER_GOOD;
		vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) &= ~BIT(30);
		vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) &= ~BIT(30);

		vgpu_vreg_t(vgpu, SFUSE_STRAP) &= ~SFUSE_STRAP_DDIB_DETECTED;
		vgpu_vreg_t(vgpu, SFUSE_STRAP) &= ~SFUSE_STRAP_DDIC_DETECTED;

		/*
		 * Only 1 PIPE enabled in current vGPU display and PIPE_A is
		 *  tied to TRANSCODER_A in HW, so it's safe to assume PIPE_A,
		 *   TRANSCODER_A can be enabled. PORT_x depends on the input of
		 *   setup_virtual_dp_monitor.
		 */
		vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= PIPECONF_ENABLE;
		vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= I965_PIPECONF_ACTIVE;

		/*
		 * Golden M/N are calculated based on:
		 *   24 bpp, 4 lanes, 154000 pixel clk (from virtual EDID),
		 *   DP link clk 1620 MHz and non-constant_n.
		 * TODO: calculate DP link symbol clk and stream clk m/n.
		 */
		vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) = 63 << TU_SIZE_SHIFT;
		vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) |= 0x5b425e;
		vgpu_vreg_t(vgpu, PIPE_DATA_N1(TRANSCODER_A)) = 0x800000;
		vgpu_vreg_t(vgpu, PIPE_LINK_M1(TRANSCODER_A)) = 0x3cd6e;
		vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A)) = 0x80000;

		/* Enable per-DDI/PORT vreg */
		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
			vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(1);
			vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) |=
				PHY_POWER_GOOD;
			vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) |=
				BIT(30);
			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) |=
				BXT_PHY_LANE_ENABLED;
			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) &=
				~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
				  BXT_PHY_LANE_POWERDOWN_ACK);
			vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_A)) |=
				(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
				 PORT_PLL_REF_SEL | PORT_PLL_LOCK |
				 PORT_PLL_ENABLE);
			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) |=
				(DDI_BUF_CTL_ENABLE | DDI_INIT_DISPLAY_DETECTED);
			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) &=
				~DDI_BUF_IS_IDLE;
			vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)) |=
				(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
				 TRANS_DDI_FUNC_ENABLE);
			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
				GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
		}

		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
			vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED;
			vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(0);
			vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) |=
				PHY_POWER_GOOD;
			vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) |=
				BIT(30);
			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) |=
				BXT_PHY_LANE_ENABLED;
			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) &=
				~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
				  BXT_PHY_LANE_POWERDOWN_ACK);
			vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_B)) |=
				(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
				 PORT_PLL_REF_SEL | PORT_PLL_LOCK |
				 PORT_PLL_ENABLE);
			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) |=
				DDI_BUF_CTL_ENABLE;
			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) &=
				~DDI_BUF_IS_IDLE;
			vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
				(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
				 (PORT_B << TRANS_DDI_PORT_SHIFT) |
				 TRANS_DDI_FUNC_ENABLE);
			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
				GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
		}

		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
			vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIC_DETECTED;
			vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(0);
			vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) |=
				PHY_POWER_GOOD;
			vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) |=
				BIT(30);
			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) |=
				BXT_PHY_LANE_ENABLED;
			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) &=
				~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
				  BXT_PHY_LANE_POWERDOWN_ACK);
			vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_C)) |=
				(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
				 PORT_PLL_REF_SEL | PORT_PLL_LOCK |
				 PORT_PLL_ENABLE);
			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) |=
				DDI_BUF_CTL_ENABLE;
			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) &=
				~DDI_BUF_IS_IDLE;
			vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
				(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
				 (PORT_B << TRANS_DDI_PORT_SHIFT) |
				 TRANS_DDI_FUNC_ENABLE);
			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
				GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
		}
@@ -520,6 +660,45 @@ void intel_vgpu_emulate_hotplug(struct intel_vgpu *vgpu, bool connected)
		vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
				PORTD_HOTPLUG_STATUS_MASK;
		intel_vgpu_trigger_virtual_event(vgpu, DP_D_HOTPLUG);
	} else if (IS_BROXTON(i915)) {
		if (connected) {
			if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
					GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
			}
			if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
				vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
					SFUSE_STRAP_DDIB_DETECTED;
				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
					GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
			}
			if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
				vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
					SFUSE_STRAP_DDIC_DETECTED;
				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
					GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
			}
		} else {
			if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
					~GEN8_DE_PORT_HOTPLUG(HPD_PORT_A);
			}
			if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
				vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
					~SFUSE_STRAP_DDIB_DETECTED;
				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
					~GEN8_DE_PORT_HOTPLUG(HPD_PORT_B);
			}
			if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
				vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
					~SFUSE_STRAP_DDIC_DETECTED;
				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
					~GEN8_DE_PORT_HOTPLUG(HPD_PORT_C);
			}
		}
		vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
			PORTB_HOTPLUG_STATUS_MASK;
		intel_vgpu_trigger_virtual_event(vgpu, DP_B_HOTPLUG);
	}
}

+64 −0
Original line number Diff line number Diff line
@@ -636,9 +636,18 @@ static void ggtt_set_host_entry(struct intel_vgpu_mm *mm,
		struct intel_gvt_gtt_entry *entry, unsigned long index)
{
	struct intel_gvt_gtt_pte_ops *pte_ops = mm->vgpu->gvt->gtt.pte_ops;
	unsigned long offset = index;

	GEM_BUG_ON(mm->type != INTEL_GVT_MM_GGTT);

	if (vgpu_gmadr_is_aperture(mm->vgpu, index << I915_GTT_PAGE_SHIFT)) {
		offset -= (vgpu_aperture_gmadr_base(mm->vgpu) >> PAGE_SHIFT);
		mm->ggtt_mm.host_ggtt_aperture[offset] = entry->val64;
	} else if (vgpu_gmadr_is_hidden(mm->vgpu, index << I915_GTT_PAGE_SHIFT)) {
		offset -= (vgpu_hidden_gmadr_base(mm->vgpu) >> PAGE_SHIFT);
		mm->ggtt_mm.host_ggtt_hidden[offset] = entry->val64;
	}

	pte_ops->set_entry(NULL, entry, index, false, 0, mm->vgpu);
}

@@ -1944,6 +1953,21 @@ static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu)
		return ERR_PTR(-ENOMEM);
	}

	mm->ggtt_mm.host_ggtt_aperture = vzalloc((vgpu_aperture_sz(vgpu) >> PAGE_SHIFT) * sizeof(u64));
	if (!mm->ggtt_mm.host_ggtt_aperture) {
		vfree(mm->ggtt_mm.virtual_ggtt);
		vgpu_free_mm(mm);
		return ERR_PTR(-ENOMEM);
	}

	mm->ggtt_mm.host_ggtt_hidden = vzalloc((vgpu_hidden_sz(vgpu) >> PAGE_SHIFT) * sizeof(u64));
	if (!mm->ggtt_mm.host_ggtt_hidden) {
		vfree(mm->ggtt_mm.host_ggtt_aperture);
		vfree(mm->ggtt_mm.virtual_ggtt);
		vgpu_free_mm(mm);
		return ERR_PTR(-ENOMEM);
	}

	return mm;
}

@@ -1971,6 +1995,8 @@ void _intel_vgpu_mm_release(struct kref *mm_ref)
		invalidate_ppgtt_mm(mm);
	} else {
		vfree(mm->ggtt_mm.virtual_ggtt);
		vfree(mm->ggtt_mm.host_ggtt_aperture);
		vfree(mm->ggtt_mm.host_ggtt_hidden);
	}

	vgpu_free_mm(mm);
@@ -2852,3 +2878,41 @@ void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu)
	intel_vgpu_destroy_all_ppgtt_mm(vgpu);
	intel_vgpu_reset_ggtt(vgpu, true);
}

/**
 * intel_gvt_restore_ggtt - restore all vGPU's ggtt entries
 * @gvt: intel gvt device
 *
 * This function is called at driver resume stage to restore
 * GGTT entries of every vGPU.
 *
 */
void intel_gvt_restore_ggtt(struct intel_gvt *gvt)
{
	struct intel_vgpu *vgpu;
	struct intel_vgpu_mm *mm;
	int id;
	gen8_pte_t pte;
	u32 idx, num_low, num_hi, offset;

	/* Restore dirty host ggtt for all vGPUs */
	idr_for_each_entry(&(gvt)->vgpu_idr, vgpu, id) {
		mm = vgpu->gtt.ggtt_mm;

		num_low = vgpu_aperture_sz(vgpu) >> PAGE_SHIFT;
		offset = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT;
		for (idx = 0; idx < num_low; idx++) {
			pte = mm->ggtt_mm.host_ggtt_aperture[idx];
			if (pte & _PAGE_PRESENT)
				write_pte64(vgpu->gvt->gt->ggtt, offset + idx, pte);
		}

		num_hi = vgpu_hidden_sz(vgpu) >> PAGE_SHIFT;
		offset = vgpu_hidden_gmadr_base(vgpu) >> PAGE_SHIFT;
		for (idx = 0; idx < num_hi; idx++) {
			pte = mm->ggtt_mm.host_ggtt_hidden[idx];
			if (pte & _PAGE_PRESENT)
				write_pte64(vgpu->gvt->gt->ggtt, offset + idx, pte);
		}
	}
}
+4 −0
Original line number Diff line number Diff line
@@ -164,6 +164,9 @@ struct intel_vgpu_mm {
		} ppgtt_mm;
		struct {
			void *virtual_ggtt;
			/* Save/restore for PM */
			u64 *host_ggtt_aperture;
			u64 *host_ggtt_hidden;
			struct list_head partial_pte_list;
		} ggtt_mm;
	};
@@ -280,5 +283,6 @@ int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu,
	unsigned int off, void *p_data, unsigned int bytes);

void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu);
void intel_gvt_restore_ggtt(struct intel_gvt *gvt);

#endif /* _GVT_GTT_H_ */
+11 −2
Original line number Diff line number Diff line
@@ -312,7 +312,7 @@ int intel_gvt_init_device(struct drm_i915_private *i915)

	gvt_dbg_core("init gvt device\n");

	idr_init(&gvt->vgpu_idr);
	idr_init_base(&gvt->vgpu_idr, 1);
	spin_lock_init(&gvt->scheduler.mmio_context_lock);
	mutex_init(&gvt->lock);
	mutex_init(&gvt->sched_lock);
@@ -406,7 +406,16 @@ out_clean_idr:
}

int
intel_gvt_register_hypervisor(struct intel_gvt_mpt *m)
intel_gvt_pm_resume(struct intel_gvt *gvt)
{
	intel_gvt_restore_fence(gvt);
	intel_gvt_restore_mmio(gvt);
	intel_gvt_restore_ggtt(gvt);
	return 0;
}

int
intel_gvt_register_hypervisor(const struct intel_gvt_mpt *m)
{
	int ret;
	void *gvt;
+5 −2
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ struct intel_gvt_host {
	struct device *dev;
	bool initialized;
	int hypervisor_type;
	struct intel_gvt_mpt *mpt;
	const struct intel_gvt_mpt *mpt;
};

extern struct intel_gvt_host intel_gvt_host;
@@ -255,7 +255,9 @@ struct intel_gvt_mmio {
#define F_CMD_ACCESS	(1 << 3)
/* This reg has been accessed by a VM */
#define F_ACCESSED	(1 << 4)
/* This reg has been accessed through GPU commands */
/* This reg requires save & restore during host PM suspend/resume */
#define F_PM_SAVE	(1 << 5)
/* This reg could be accessed by unaligned address */
#define F_UNALIGN	(1 << 6)
/* This reg is in GVT's mmio save-restor list and in hardware
 * logical context image
@@ -685,6 +687,7 @@ void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu);
void intel_gvt_debugfs_init(struct intel_gvt *gvt);
void intel_gvt_debugfs_clean(struct intel_gvt *gvt);

int intel_gvt_pm_resume(struct intel_gvt *gvt);

#include "trace.h"
#include "mpt.h"
Loading