clear-pkgs-linux-iot-lts2018/1104-Change-the-priority-of...

236 lines
7.8 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Zhao Yakui <yakui.zhao@intel.com>
Date: Fri, 17 May 2019 09:22:17 +0800
Subject: [PATCH] Change the priority of acrngt_emulation_thread on demand when
injecting VBLANK interrupt
When pipe vblank interrupt is injected, the priority of
acrngt_emulation_thread will be increased so that it can handle the
emulated i915 trap in time. It will be restored after 750us, which is
handled in one higher priority RT thread.(It needs to wait for the timer
and then change the priority of acrngt_emulation_thread to normal).
The RT is used when injecting the Vblank interrupt.
V1-V2: Preempt is disabled when changing the priority and starting timer
in function of injecting vblank interrupt for UOS
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Liu Shuo <shuo.liu@intel.com>
---
drivers/gpu/drm/i915/gvt/acrngt.c | 69 +++++++++++++++++++++++++++-
drivers/gpu/drm/i915/gvt/acrngt.h | 10 ++--
drivers/gpu/drm/i915/gvt/gvt.h | 1 +
drivers/gpu/drm/i915/gvt/interrupt.c | 23 +++++++++-
4 files changed, 96 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/i915/gvt/acrngt.c b/drivers/gpu/drm/i915/gvt/acrngt.c
index e27b53b165aa..ff48b15ae9d4 100644
--- a/drivers/gpu/drm/i915/gvt/acrngt.c
+++ b/drivers/gpu/drm/i915/gvt/acrngt.c
@@ -33,6 +33,8 @@
#include <linux/freezer.h>
#include <linux/wait.h>
#include <linux/sched.h>
+#include <linux/hrtimer.h>
+#include <uapi/linux/sched/types.h>
#include <linux/vhm/acrn_hv_defs.h>
#include <linux/vhm/acrn_common.h>
@@ -56,6 +58,7 @@ do { if (x) break; \
__FILE__, __func__, __LINE__, #x); dump_stack(); BUG(); \
} while (0)
+#define ACRNGT_TIMER_ISR 1
struct kobject *acrn_gvt_ctrl_kobj;
static struct kset *acrn_gvt_kset;
@@ -64,6 +67,56 @@ static DEFINE_MUTEX(acrn_gvt_sysfs_lock);
struct gvt_acrngt acrngt_priv;
const struct intel_gvt_ops *intel_gvt_ops;
+static ssize_t acrngt_sysfs_instance_manage(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count);
+static ssize_t acrngt_sysfs_vgpu_id(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf);
+
+static int acrngt_emulation_timer_thread(void *data)
+{
+ struct acrngt_hvm_dev *info = data;
+ struct sched_param param = { .sched_priority = 2 };
+
+ sched_setscheduler_nocheck(current, SCHED_FIFO, &param);
+
+ param.sched_priority = 0;
+ while (!kthread_should_stop()) {
+
+ wait_event_interruptible(info->timer_thread_wq,
+ kthread_should_stop() ||
+ test_bit(ACRNGT_TIMER_ISR, &info->thread_flags));
+
+ if (kthread_should_stop())
+ break;
+
+ if (!test_bit(ACRNGT_TIMER_ISR, &info->thread_flags))
+ continue;
+
+ if (info->emulation_thread) {
+ /* Restore the priority to NORMAL */
+ sched_setscheduler_nocheck(info->emulation_thread,
+ SCHED_NORMAL, &param);
+ }
+ clear_bit(ACRNGT_TIMER_ISR, &info->thread_flags);
+ trace_printk("ACRN thread work is fired. Policy %d, Prio is %d\n",
+ info->emulation_thread->policy,
+ task_nice(info->emulation_thread));
+ }
+
+ return 0;
+}
+
+static enum hrtimer_restart acrn_thread_timer(struct hrtimer *hrtimer)
+{
+ struct acrngt_hvm_dev *info =
+ container_of(hrtimer, struct acrngt_hvm_dev, thread_timer);
+
+ set_bit(ACRNGT_TIMER_ISR, &info->thread_flags);
+ wake_up(&info->timer_thread_wq);
+
+ return HRTIMER_NORESTART;
+}
+
static void disable_domu_plane(int pipe, int plane)
{
struct drm_i915_private *dev_priv = acrngt_priv.gvt->dev_priv;
@@ -83,8 +136,12 @@ void acrngt_instance_destroy(struct intel_vgpu *vgpu)
if (vgpu) {
info = (struct acrngt_hvm_dev *)vgpu->handle;
- if (info && info->emulation_thread != NULL)
+ if (info && info->emulation_thread != NULL) {
kthread_stop(info->emulation_thread);
+ info->emulation_thread = NULL;
+ }
+ if (info && info->timer_thread != NULL)
+ kthread_stop(info->timer_thread);
for_each_pipe(gvt->dev_priv, pipe) {
for_each_universal_plane(gvt->dev_priv, pipe, plane) {
@@ -103,6 +160,8 @@ void acrngt_instance_destroy(struct intel_vgpu *vgpu)
gvt_dbg_core("destroy vgpu instance, vm id: %d, client %d",
info->vm_id, info->client);
+ hrtimer_cancel(&info->thread_timer);
+
if (info->client != 0)
acrn_ioreq_destroy_client(info->client);
@@ -234,6 +293,7 @@ static int acrngt_emulation_thread(void *priv)
gvt_dbg_core("start kthread for VM%d\n", info->vm_id);
ASSERT(info->nr_vcpu <= MAX_HVM_VCPUS_SUPPORTED);
+ set_user_nice(current, -10);
set_freezable();
while (1) {
@@ -359,6 +419,13 @@ struct intel_vgpu *acrngt_instance_create(domid_t vm_id,
goto err;
}
info->emulation_thread = thread;
+ hrtimer_init(&info->thread_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ info->thread_timer.function = acrn_thread_timer;
+ vgpu->vgpu_priv = info;
+
+ init_waitqueue_head(&info->timer_thread_wq);
+ info->timer_thread = kthread_run(acrngt_emulation_timer_thread, info,
+ "acrngt_work:%d", vm_id);
gvt_dbg_core("create vgpu instance success, vm_id %d, client %d,"
" nr_vcpu %d\n", info->vm_id,info->client, info->nr_vcpu);
diff --git a/drivers/gpu/drm/i915/gvt/acrngt.h b/drivers/gpu/drm/i915/gvt/acrngt.h
index 0799df2ec557..ea8e411134e1 100644
--- a/drivers/gpu/drm/i915/gvt/acrngt.h
+++ b/drivers/gpu/drm/i915/gvt/acrngt.h
@@ -50,6 +50,11 @@ struct acrngt_hvm_dev {
int client;
struct vhm_request *req_buf;
struct vhm_vm *vm;
+ struct hrtimer thread_timer;
+ struct work_struct thread_work;
+ long thread_flags;
+ struct task_struct *timer_thread;
+ wait_queue_head_t timer_thread_wq;
};
struct acrngt_hvm_params {
@@ -69,11 +74,6 @@ struct gvt_acrngt {
struct intel_vgpu *vgpus[GVT_MAX_VGPU_INSTANCE];
};
-static ssize_t acrngt_sysfs_instance_manage(struct kobject *kobj,
- struct kobj_attribute *attr, const char *buf, size_t count);
-static ssize_t acrngt_sysfs_vgpu_id(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf);
-
struct intel_vgpu *acrngt_instance_create(domid_t vm_id,
struct intel_vgpu_type *type);
void acrngt_instance_destroy(struct intel_vgpu *vgpu);
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index b0073edbe4a4..089406ebc2f1 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -241,6 +241,7 @@ struct intel_vgpu {
bool ge_cache_enable;
bool entire_nonctxmmio_checked;
ktime_t vgpu_msi_time;
+ void *vgpu_priv;
};
/* validating GM healthy status*/
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c
index 06ce906b6673..7bb9be5ae9fd 100644
--- a/drivers/gpu/drm/i915/gvt/interrupt.c
+++ b/drivers/gpu/drm/i915/gvt/interrupt.c
@@ -28,10 +28,13 @@
* Min he <min.he@intel.com>
*
*/
-
+#include <linux/hrtimer.h>
+#include <linux/sched.h>
+#include <uapi/linux/sched/types.h>
#include "i915_drv.h"
#include "gvt.h"
#include "trace.h"
+#include "acrngt.h"
/* common offset among interrupt control registers */
#define regbase_to_isr(base) (base)
@@ -642,6 +645,24 @@ void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu,
handler(irq, event, vgpu);
ops->check_pending_irq(vgpu);
+ if (((event == PIPE_B_VBLANK) ||
+ (event == PIPE_C_VBLANK)) && (vgpu->vgpu_priv)) {
+ struct acrngt_hvm_dev *vhm_dev = vgpu->vgpu_priv;
+ struct sched_param param = { .sched_priority = 1 };
+
+ if (hrtimer_active(&vhm_dev->thread_timer))
+ hrtimer_cancel(&vhm_dev->thread_timer);
+
+ preempt_disable();
+ trace_printk("ACRN thread timer is started. Policy is %d\n",
+ vhm_dev->emulation_thread->policy);
+ /* 750*1000 ns */
+ hrtimer_set_expires(&vhm_dev->thread_timer, 750000);
+ hrtimer_start_expires(&vhm_dev->thread_timer, HRTIMER_MODE_REL);
+ sched_setscheduler_nocheck(vhm_dev->emulation_thread,
+ SCHED_FIFO, &param);
+ preempt_enable();
+ }
}
static void init_events(
--
https://clearlinux.org