aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/gvt/sched_policy.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c
index 5aa7a2539e4d..dd5b38c3e4ed 100644
--- a/drivers/gpu/drm/i915/gvt/sched_policy.c
+++ b/drivers/gpu/drm/i915/gvt/sched_policy.c
@@ -67,6 +67,60 @@ struct gvt_sched_data {
67 struct list_head lru_runq_head; 67 struct list_head lru_runq_head;
68}; 68};
69 69
70static void vgpu_update_timeslice(struct intel_vgpu *pre_vgpu)
71{
72 ktime_t delta_ts;
73 struct vgpu_sched_data *vgpu_data = pre_vgpu->sched_data;
74
75 delta_ts = vgpu_data->sched_out_time - vgpu_data->sched_in_time;
76
77 vgpu_data->sched_time += delta_ts;
78 vgpu_data->left_ts -= delta_ts;
79}
80
81#define GVT_TS_BALANCE_PERIOD_MS 100
82#define GVT_TS_BALANCE_STAGE_NUM 10
83
84static void gvt_balance_timeslice(struct gvt_sched_data *sched_data)
85{
86 struct vgpu_sched_data *vgpu_data;
87 struct list_head *pos;
88 static uint64_t stage_check;
89 int stage = stage_check++ % GVT_TS_BALANCE_STAGE_NUM;
90
91 /* The timeslice accumulation reset at stage 0, which is
92 * allocated again without adding previous debt.
93 */
94 if (stage == 0) {
95 int total_weight = 0;
96 ktime_t fair_timeslice;
97
98 list_for_each(pos, &sched_data->lru_runq_head) {
99 vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list);
100 total_weight += vgpu_data->sched_ctl.weight;
101 }
102
103 list_for_each(pos, &sched_data->lru_runq_head) {
104 vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list);
105 fair_timeslice = ms_to_ktime(GVT_TS_BALANCE_PERIOD_MS) *
106 vgpu_data->sched_ctl.weight /
107 total_weight;
108
109 vgpu_data->allocated_ts = fair_timeslice;
110 vgpu_data->left_ts = vgpu_data->allocated_ts;
111 }
112 } else {
113 list_for_each(pos, &sched_data->lru_runq_head) {
114 vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list);
115
116 /* timeslice for next 100ms should add the left/debt
117 * slice of previous stages.
118 */
119 vgpu_data->left_ts += vgpu_data->allocated_ts;
120 }
121 }
122}
123
70static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) 124static void try_to_schedule_next_vgpu(struct intel_gvt *gvt)
71{ 125{
72 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; 126 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
@@ -103,6 +157,7 @@ static void try_to_schedule_next_vgpu(struct intel_gvt *gvt)
103 if (scheduler->current_vgpu) { 157 if (scheduler->current_vgpu) {
104 vgpu_data = scheduler->current_vgpu->sched_data; 158 vgpu_data = scheduler->current_vgpu->sched_data;
105 vgpu_data->sched_out_time = cur_time; 159 vgpu_data->sched_out_time = cur_time;
160 vgpu_update_timeslice(scheduler->current_vgpu);
106 } 161 }
107 vgpu_data = scheduler->next_vgpu->sched_data; 162 vgpu_data = scheduler->next_vgpu->sched_data;
108 vgpu_data->sched_in_time = cur_time; 163 vgpu_data->sched_in_time = cur_time;
@@ -148,6 +203,10 @@ static void tbs_sched_func(struct gvt_sched_data *sched_data)
148 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; 203 struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
149 struct vgpu_sched_data *vgpu_data; 204 struct vgpu_sched_data *vgpu_data;
150 struct intel_vgpu *vgpu = NULL; 205 struct intel_vgpu *vgpu = NULL;
206 static uint64_t timer_check;
207
208 if (!(timer_check++ % GVT_TS_BALANCE_PERIOD_MS))
209 gvt_balance_timeslice(sched_data);
151 210
152 /* no active vgpu or has already had a target */ 211 /* no active vgpu or has already had a target */
153 if (list_empty(&sched_data->lru_runq_head) || scheduler->next_vgpu) 212 if (list_empty(&sched_data->lru_runq_head) || scheduler->next_vgpu)