summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/gvt/gvt.c
diff options
context:
space:
mode:
authorZhi Wang <zhi.a.wang@intel.com>2016-04-26 01:28:56 +0300
committerZhenyu Wang <zhenyuw@linux.intel.com>2016-10-14 13:13:06 +0300
commit04d348ae3f0aea6523bc3b0688b5fc90c1c60d0e (patch)
tree1eadc499b3da6b57f1bebed7b81f77a79b9a8144 /drivers/gpu/drm/i915/gvt/gvt.c
parente39c5add322184de3be052d438dfd24375bfeaea (diff)
downloadlinux-04d348ae3f0aea6523bc3b0688b5fc90c1c60d0e.tar.xz
drm/i915/gvt: vGPU display virtualization
This patch introduces the GVT-g display virtualization. It consists a collection of display MMIO handlers, like power well register handler, pipe register handler, plane register handler, which will emulate all display MMIOs behavior to support virtual mode setting sequence for guest. Signed-off-by: Bing Niu <bing.niu@intel.com> Signed-off-by: Zhi Wang <zhi.a.wang@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/gvt/gvt.c')
-rw-r--r--drivers/gpu/drm/i915/gvt/gvt.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c
index 6b5061bfebb0..27e1dd9a2570 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.c
+++ b/drivers/gpu/drm/i915/gvt/gvt.c
@@ -32,6 +32,7 @@
#include <linux/types.h>
#include <xen/xen.h>
+#include <linux/kthread.h>
#include "i915_drv.h"
@@ -114,6 +115,52 @@ static void init_device_info(struct intel_gvt *gvt)
}
}
+static int gvt_service_thread(void *data)
+{
+ struct intel_gvt *gvt = (struct intel_gvt *)data;
+ int ret;
+
+ gvt_dbg_core("service thread start\n");
+
+ while (!kthread_should_stop()) {
+ ret = wait_event_interruptible(gvt->service_thread_wq,
+ kthread_should_stop() || gvt->service_request);
+
+ if (kthread_should_stop())
+ break;
+
+ if (WARN_ONCE(ret, "service thread is waken up by signal.\n"))
+ continue;
+
+ if (test_and_clear_bit(INTEL_GVT_REQUEST_EMULATE_VBLANK,
+ (void *)&gvt->service_request)) {
+ mutex_lock(&gvt->lock);
+ intel_gvt_emulate_vblank(gvt);
+ mutex_unlock(&gvt->lock);
+ }
+ }
+
+ return 0;
+}
+
+static void clean_service_thread(struct intel_gvt *gvt)
+{
+ kthread_stop(gvt->service_thread);
+}
+
+static int init_service_thread(struct intel_gvt *gvt)
+{
+ init_waitqueue_head(&gvt->service_thread_wq);
+
+ gvt->service_thread = kthread_run(gvt_service_thread,
+ gvt, "gvt_service_thread");
+ if (IS_ERR(gvt->service_thread)) {
+ gvt_err("fail to start service thread.\n");
+ return PTR_ERR(gvt->service_thread);
+ }
+ return 0;
+}
+
/**
* intel_gvt_clean_device - clean a GVT device
* @gvt: intel gvt device
@@ -129,6 +176,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
if (WARN_ON(!gvt->initialized))
return;
+ clean_service_thread(gvt);
intel_gvt_clean_opregion(gvt);
intel_gvt_clean_gtt(gvt);
intel_gvt_clean_irq(gvt);
@@ -191,10 +239,16 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
if (ret)
goto out_clean_gtt;
+ ret = init_service_thread(gvt);
+ if (ret)
+ goto out_clean_opregion;
+
gvt_dbg_core("gvt device creation is done\n");
gvt->initialized = true;
return 0;
+out_clean_opregion:
+ intel_gvt_clean_opregion(gvt);
out_clean_gtt:
intel_gvt_clean_gtt(gvt);
out_clean_irq: