]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'gvt-fixes-2017-05-11' of https://github.com/01org/gvt-linux into drm-intel...
authorJani Nikula <jani.nikula@intel.com>
Mon, 15 May 2017 10:03:30 +0000 (13:03 +0300)
committerJani Nikula <jani.nikula@intel.com>
Mon, 15 May 2017 10:03:31 +0000 (13:03 +0300)
gvt-fixes-2017-05-11

- vGPU scheduler performance regression fix (Ping)
- bypass in-context mmio restore (Chuanxiao)
- one typo fix (Colin)

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170511054736.swpcmnzdoqi75cnl@zhen-hp.sh.intel.com
1  2 
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/render.c
drivers/gpu/drm/i915/gvt/sched_policy.c

index 0ad1a508e2af478dc9fb91df18bdc95304efad44,31624f1df893bf1c37766125081efc5f7af31e5b..c995e540ff96e1f8a18a9232de2b26794fa03aa2
@@@ -68,8 -68,6 +68,8 @@@ unsigned long intel_gvt_get_device_type
                return D_BDW;
        else if (IS_SKYLAKE(gvt->dev_priv))
                return D_SKL;
 +      else if (IS_KABYLAKE(gvt->dev_priv))
 +              return D_KBL;
  
        return 0;
  }
@@@ -236,8 -234,7 +236,8 @@@ static int mul_force_wake_write(struct 
        old = vgpu_vreg(vgpu, offset);
        new = CALC_MODE_MASK_REG(old, *(u32 *)p_data);
  
 -      if (IS_SKYLAKE(vgpu->gvt->dev_priv)) {
 +      if (IS_SKYLAKE(vgpu->gvt->dev_priv)
 +              || IS_KABYLAKE(vgpu->gvt->dev_priv)) {
                switch (offset) {
                case FORCEWAKE_RENDER_GEN9_REG:
                        ack_reg_offset = FORCEWAKE_ACK_RENDER_GEN9_REG;
@@@ -826,9 -823,8 +826,9 @@@ static int dp_aux_ch_ctl_mmio_write(str
        write_vreg(vgpu, offset, p_data, bytes);
        data = vgpu_vreg(vgpu, offset);
  
 -      if (IS_SKYLAKE(vgpu->gvt->dev_priv) &&
 -          offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) {
 +      if ((IS_SKYLAKE(vgpu->gvt->dev_priv)
 +              || IS_KABYLAKE(vgpu->gvt->dev_priv))
 +              && offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) {
                /* SKL DPB/C/D aux ctl register changed */
                return 0;
        } else if (IS_BROADWELL(vgpu->gvt->dev_priv) &&
@@@ -1244,7 -1240,7 +1244,7 @@@ static int dma_ctrl_write(struct intel_
        mode = vgpu_vreg(vgpu, offset);
  
        if (GFX_MODE_BIT_SET_IN_MASK(mode, START_DMA)) {
-               WARN_ONCE(1, "VM(%d): iGVT-g doesn't supporte GuC\n",
+               WARN_ONCE(1, "VM(%d): iGVT-g doesn't support GuC\n",
                                vgpu->id);
                return 0;
        }
@@@ -1315,8 -1311,7 +1315,8 @@@ static int mailbox_write(struct intel_v
  
        switch (cmd) {
        case GEN9_PCODE_READ_MEM_LATENCY:
 -              if (IS_SKYLAKE(vgpu->gvt->dev_priv)) {
 +              if (IS_SKYLAKE(vgpu->gvt->dev_priv)
 +                       || IS_KABYLAKE(vgpu->gvt->dev_priv)) {
                        /**
                         * "Read memory latency" command on gen9.
                         * Below memory latency values are read
                }
                break;
        case SKL_PCODE_CDCLK_CONTROL:
 -              if (IS_SKYLAKE(vgpu->gvt->dev_priv))
 +              if (IS_SKYLAKE(vgpu->gvt->dev_priv)
 +                       || IS_KABYLAKE(vgpu->gvt->dev_priv))
                        *data0 = SKL_CDCLK_READY_FOR_CHANGE;
                break;
        case GEN6_PCODE_READ_RC6VIDS:
@@@ -1424,7 -1418,6 +1424,7 @@@ static int elsp_mmio_write(struct intel
  
        execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data;
        if (execlist->elsp_dwords.index == 3) {
 +              vgpu->last_ctx_submit_time = ktime_get();
                ret = intel_vgpu_submit_execlist(vgpu, ring_id);
                if(ret)
                        gvt_vgpu_err("fail submit workload on ring %d\n",
@@@ -2599,232 -2592,219 +2599,232 @@@ static int init_skl_mmio_info(struct in
        MMIO_DH(FORCEWAKE_MEDIA_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write);
        MMIO_DH(FORCEWAKE_ACK_MEDIA_GEN9, D_SKL_PLUS, NULL, NULL);
  
 -      MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
 -      MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
 -      MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
 +      MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL,
 +                                              dp_aux_ch_ctl_mmio_write);
 +      MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL,
 +                                              dp_aux_ch_ctl_mmio_write);
 +      MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL,
 +                                              dp_aux_ch_ctl_mmio_write);
  
 -      MMIO_D(HSW_PWR_WELL_BIOS, D_SKL);
 -      MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, skl_power_well_ctl_write);
 +      MMIO_D(HSW_PWR_WELL_BIOS, D_SKL_PLUS);
 +      MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL_PLUS, NULL,
 +                                              skl_power_well_ctl_write);
 +      MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL_PLUS, 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);
        MMIO_DFH(GEN9_GAMT_ECO_REG_RW_IA, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
 -      MMIO_DH(0x4ddc, D_SKL, NULL, skl_misc_ctl_write);
 -      MMIO_DH(0x42080, D_SKL, NULL, skl_misc_ctl_write);
 -      MMIO_D(0x45504, D_SKL);
 -      MMIO_D(0x45520, D_SKL);
 -      MMIO_D(0x46000, D_SKL);
 -      MMIO_DH(0x46010, D_SKL, NULL, skl_lcpll_write);
 -      MMIO_DH(0x46014, D_SKL, NULL, skl_lcpll_write);
 -      MMIO_D(0x6C040, D_SKL);
 -      MMIO_D(0x6C048, D_SKL);
 -      MMIO_D(0x6C050, D_SKL);
 -      MMIO_D(0x6C044, D_SKL);
 -      MMIO_D(0x6C04C, D_SKL);
 -      MMIO_D(0x6C054, D_SKL);
 -      MMIO_D(0x6c058, D_SKL);
 -      MMIO_D(0x6c05c, D_SKL);
 -      MMIO_DH(0X6c060, D_SKL, dpll_status_read, NULL);
 -
 -      MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL, NULL, pf_write);
 -
 -      MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL, NULL, pf_write);
 -
 -      MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL, NULL, pf_write);
 -      MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL, NULL, pf_write);
 -
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(CUR_BUF_CFG(PIPE_A), D_SKL, NULL, NULL);
 -      MMIO_DH(CUR_BUF_CFG(PIPE_B), D_SKL, NULL, NULL);
 -      MMIO_DH(CUR_BUF_CFG(PIPE_C), D_SKL, NULL, NULL);
 -
 -      MMIO_F(PLANE_WM(PIPE_A, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(PLANE_WM(PIPE_A, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(PLANE_WM(PIPE_A, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -
 -      MMIO_F(PLANE_WM(PIPE_B, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(PLANE_WM(PIPE_B, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(PLANE_WM(PIPE_B, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -
 -      MMIO_F(PLANE_WM(PIPE_C, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(PLANE_WM(PIPE_C, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(PLANE_WM(PIPE_C, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -
 -      MMIO_F(CUR_WM(PIPE_A, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(CUR_WM(PIPE_B, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(CUR_WM(PIPE_C, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
 -
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_A, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_A, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_A, 2), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_B, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_B, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_B, 2), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_C, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_C, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_WM_TRANS(PIPE_C, 2), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(CUR_WM_TRANS(PIPE_A), D_SKL, NULL, NULL);
 -      MMIO_DH(CUR_WM_TRANS(PIPE_B), D_SKL, NULL, NULL);
 -      MMIO_DH(CUR_WM_TRANS(PIPE_C), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(_REG_701C0(PIPE_A, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_A, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_A, 3), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_A, 4), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(_REG_701C0(PIPE_B, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_B, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_B, 3), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_B, 4), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(_REG_701C0(PIPE_C, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_C, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_C, 3), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C0(PIPE_C, 4), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(_REG_701C4(PIPE_A, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_A, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_A, 3), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_A, 4), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(_REG_701C4(PIPE_B, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_B, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_B, 3), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_B, 4), D_SKL, NULL, NULL);
 -
 -      MMIO_DH(_REG_701C4(PIPE_C, 1), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_C, 2), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_C, 3), D_SKL, NULL, NULL);
 -      MMIO_DH(_REG_701C4(PIPE_C, 4), D_SKL, NULL, NULL);
 -
 -      MMIO_D(0x70380, D_SKL);
 -      MMIO_D(0x71380, D_SKL);
 -      MMIO_D(0x72380, D_SKL);
 -      MMIO_D(0x7039c, D_SKL);
 -
 -      MMIO_F(0x80000, 0x3000, 0, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_D(0x8f074, D_SKL);
 -      MMIO_D(0x8f004, D_SKL);
 -      MMIO_D(0x8f034, D_SKL);
 -
 -      MMIO_D(0xb11c, D_SKL);
 -
 -      MMIO_D(0x51000, D_SKL);
 -      MMIO_D(0x6c00c, D_SKL);
 -
 -      MMIO_F(0xc800, 0x7f8, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL);
 -      MMIO_F(0xb020, 0x80, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL);
 -
 -      MMIO_D(0xd08, 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);
 +      MMIO_DH(0x4ddc, D_SKL_PLUS, NULL, skl_misc_ctl_write);
 +      MMIO_DH(0x42080, D_SKL_PLUS, NULL, skl_misc_ctl_write);
 +      MMIO_D(0x45504, D_SKL_PLUS);
 +      MMIO_D(0x45520, D_SKL_PLUS);
 +      MMIO_D(0x46000, D_SKL_PLUS);
 +      MMIO_DH(0x46010, D_SKL | D_KBL, NULL, skl_lcpll_write);
 +      MMIO_DH(0x46014, D_SKL | D_KBL, NULL, skl_lcpll_write);
 +      MMIO_D(0x6C040, D_SKL | D_KBL);
 +      MMIO_D(0x6C048, D_SKL | D_KBL);
 +      MMIO_D(0x6C050, D_SKL | D_KBL);
 +      MMIO_D(0x6C044, D_SKL | D_KBL);
 +      MMIO_D(0x6C04C, D_SKL | D_KBL);
 +      MMIO_D(0x6C054, D_SKL | D_KBL);
 +      MMIO_D(0x6c058, D_SKL | D_KBL);
 +      MMIO_D(0x6c05c, D_SKL | D_KBL);
 +      MMIO_DH(0X6c060, D_SKL | D_KBL, dpll_status_read, NULL);
 +
 +      MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL_PLUS, NULL, pf_write);
 +
 +      MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL_PLUS, NULL, pf_write);
 +
 +      MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL_PLUS, NULL, pf_write);
 +      MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL_PLUS, NULL, pf_write);
 +
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_A, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_A, 3), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_B, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_B, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_B, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_B, 3), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_C, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_C, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_C, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_BUF_CFG(PIPE_C, 3), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(CUR_BUF_CFG(PIPE_A), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(CUR_BUF_CFG(PIPE_B), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(CUR_BUF_CFG(PIPE_C), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_F(PLANE_WM(PIPE_A, 0, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_F(PLANE_WM(PIPE_A, 1, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_F(PLANE_WM(PIPE_A, 2, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_F(PLANE_WM(PIPE_B, 0, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_F(PLANE_WM(PIPE_B, 1, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_F(PLANE_WM(PIPE_B, 2, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_F(PLANE_WM(PIPE_C, 0, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_F(PLANE_WM(PIPE_C, 1, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_F(PLANE_WM(PIPE_C, 2, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_F(CUR_WM(PIPE_A, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_F(CUR_WM(PIPE_B, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_F(CUR_WM(PIPE_C, 0), 4 * 8, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_A, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_A, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_A, 2), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_B, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_B, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_B, 2), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_C, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_C, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_WM_TRANS(PIPE_C, 2), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(CUR_WM_TRANS(PIPE_A), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(CUR_WM_TRANS(PIPE_B), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(CUR_WM_TRANS(PIPE_C), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 3), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 3), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 0), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(_REG_701C0(PIPE_A, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_A, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_A, 3), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_A, 4), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(_REG_701C0(PIPE_B, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_B, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_B, 3), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_B, 4), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(_REG_701C0(PIPE_C, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_C, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_C, 3), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C0(PIPE_C, 4), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(_REG_701C4(PIPE_A, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_A, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_A, 3), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_A, 4), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(_REG_701C4(PIPE_B, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_B, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_B, 3), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_B, 4), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_DH(_REG_701C4(PIPE_C, 1), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_C, 2), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_C, 3), D_SKL_PLUS, NULL, NULL);
 +      MMIO_DH(_REG_701C4(PIPE_C, 4), D_SKL_PLUS, NULL, NULL);
 +
 +      MMIO_D(0x70380, D_SKL_PLUS);
 +      MMIO_D(0x71380, D_SKL_PLUS);
 +      MMIO_D(0x72380, D_SKL_PLUS);
 +      MMIO_D(0x7039c, D_SKL_PLUS);
 +
 +      MMIO_F(0x80000, 0x3000, 0, 0, 0, D_SKL_PLUS, NULL, NULL);
 +      MMIO_D(0x8f074, D_SKL | D_KBL);
 +      MMIO_D(0x8f004, D_SKL | D_KBL);
 +      MMIO_D(0x8f034, D_SKL | D_KBL);
 +
 +      MMIO_D(0xb11c, D_SKL | D_KBL);
 +
 +      MMIO_D(0x51000, D_SKL | D_KBL);
 +      MMIO_D(0x6c00c, D_SKL_PLUS);
 +
 +      MMIO_F(0xc800, 0x7f8, F_CMD_ACCESS, 0, 0, D_SKL | D_KBL, NULL, NULL);
 +      MMIO_F(0xb020, 0x80, F_CMD_ACCESS, 0, 0, D_SKL | D_KBL, NULL, NULL);
 +
 +      MMIO_D(0xd08, D_SKL_PLUS);
 +      MMIO_DFH(0x20e0, D_SKL_PLUS, F_MODE_MASK, NULL, NULL);
 +      MMIO_DFH(0x20ec, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
  
        /* TRTT */
 -      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_DFH(0x4de0, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL);
 +      MMIO_DFH(0x4de4, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL);
 +      MMIO_DFH(0x4de8, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL);
 +      MMIO_DFH(0x4dec, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL);
 +      MMIO_DFH(0x4df0, D_SKL | D_KBL, F_CMD_ACCESS, NULL, NULL);
 +      MMIO_DFH(0x4df4, D_SKL | D_KBL, F_CMD_ACCESS, NULL, gen9_trtte_write);
 +      MMIO_DH(0x4dfc, D_SKL | D_KBL, NULL, gen9_trtt_chicken_write);
  
 -      MMIO_D(0x45008, D_SKL);
 +      MMIO_D(0x45008, D_SKL | D_KBL);
  
 -      MMIO_D(0x46430, D_SKL);
 +      MMIO_D(0x46430, D_SKL | D_KBL);
  
 -      MMIO_D(0x46520, D_SKL);
 +      MMIO_D(0x46520, D_SKL | D_KBL);
  
 -      MMIO_D(0xc403c, D_SKL);
 -      MMIO_D(0xb004, D_SKL);
 +      MMIO_D(0xc403c, D_SKL | D_KBL);
 +      MMIO_D(0xb004, D_SKL_PLUS);
        MMIO_DH(DMA_CTRL, D_SKL_PLUS, NULL, dma_ctrl_write);
  
 -      MMIO_D(0x65900, D_SKL);
 -      MMIO_D(0x1082c0, D_SKL);
 -      MMIO_D(0x4068, D_SKL);
 -      MMIO_D(0x67054, D_SKL);
 -      MMIO_D(0x6e560, D_SKL);
 -      MMIO_D(0x6e554, D_SKL);
 -      MMIO_D(0x2b20, D_SKL);
 -      MMIO_D(0x65f00, D_SKL);
 -      MMIO_D(0x65f08, D_SKL);
 -      MMIO_D(0x320f0, 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);
 -
 -      MMIO_D(_PLANE_KEYVAL_1(PIPE_A), D_SKL);
 -      MMIO_D(_PLANE_KEYVAL_1(PIPE_B), D_SKL);
 -      MMIO_D(_PLANE_KEYVAL_1(PIPE_C), D_SKL);
 -      MMIO_D(_PLANE_KEYMSK_1(PIPE_A), D_SKL);
 -      MMIO_D(_PLANE_KEYMSK_1(PIPE_B), D_SKL);
 -      MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL);
 -
 -      MMIO_D(0x44500, D_SKL);
 +      MMIO_D(0x65900, D_SKL_PLUS);
 +      MMIO_D(0x1082c0, D_SKL | D_KBL);
 +      MMIO_D(0x4068, D_SKL | D_KBL);
 +      MMIO_D(0x67054, D_SKL | D_KBL);
 +      MMIO_D(0x6e560, D_SKL | D_KBL);
 +      MMIO_D(0x6e554, D_SKL | D_KBL);
 +      MMIO_D(0x2b20, D_SKL | D_KBL);
 +      MMIO_D(0x65f00, D_SKL | D_KBL);
 +      MMIO_D(0x65f08, D_SKL | D_KBL);
 +      MMIO_D(0x320f0, D_SKL | D_KBL);
 +
 +      MMIO_DFH(_REG_VCS2_EXCC, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
 +      MMIO_DFH(_REG_VECS_EXCC, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
 +      MMIO_D(0x70034, D_SKL_PLUS);
 +      MMIO_D(0x71034, D_SKL_PLUS);
 +      MMIO_D(0x72034, D_SKL_PLUS);
 +
 +      MMIO_D(_PLANE_KEYVAL_1(PIPE_A), D_SKL_PLUS);
 +      MMIO_D(_PLANE_KEYVAL_1(PIPE_B), D_SKL_PLUS);
 +      MMIO_D(_PLANE_KEYVAL_1(PIPE_C), D_SKL_PLUS);
 +      MMIO_D(_PLANE_KEYMSK_1(PIPE_A), D_SKL_PLUS);
 +      MMIO_D(_PLANE_KEYMSK_1(PIPE_B), D_SKL_PLUS);
 +      MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL_PLUS);
 +
 +      MMIO_D(0x44500, D_SKL_PLUS);
        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,
 +      MMIO_DFH(GEN8_HDC_CHICKEN1, D_SKL | D_KBL, F_MODE_MASK | F_CMD_ACCESS,
                NULL, NULL);
 +
 +      MMIO_D(0x4ab8, D_KBL);
 +      MMIO_D(0x940c, D_SKL_PLUS);
 +      MMIO_D(0x2248, D_SKL_PLUS | D_KBL);
 +      MMIO_D(0x4ab0, D_SKL | D_KBL);
 +      MMIO_D(0x20d4, D_SKL | D_KBL);
 +
        return 0;
  }
  
@@@ -2901,8 -2881,7 +2901,8 @@@ int intel_gvt_setup_mmio_info(struct in
                ret = init_broadwell_mmio_info(gvt);
                if (ret)
                        goto err;
 -      } else if (IS_SKYLAKE(dev_priv)) {
 +      } else if (IS_SKYLAKE(dev_priv)
 +              || IS_KABYLAKE(dev_priv)) {
                ret = init_broadwell_mmio_info(gvt);
                if (ret)
                        goto err;
index c6e7972ac21da8eda7143619a401554e2575a160,05b75b9f852afb6ea6506ebbd55f4fde2829714b..a5e11d89df2f86d13dc546f7b3e1a9e9c8ba7d97
@@@ -44,7 -44,7 +44,7 @@@ struct render_mmio 
        u32 value;
  };
  
 -static struct render_mmio gen8_render_mmio_list[] = {
 +static struct render_mmio gen8_render_mmio_list[] __cacheline_aligned = {
        {RCS, _MMIO(0x229c), 0xffff, false},
        {RCS, _MMIO(0x2248), 0x0, false},
        {RCS, _MMIO(0x2098), 0x0, false},
@@@ -75,7 -75,7 +75,7 @@@
        {BCS, _MMIO(0x22028), 0x0, false},
  };
  
 -static struct render_mmio gen9_render_mmio_list[] = {
 +static struct render_mmio gen9_render_mmio_list[] __cacheline_aligned = {
        {RCS, _MMIO(0x229c), 0xffff, false},
        {RCS, _MMIO(0x2248), 0x0, false},
        {RCS, _MMIO(0x2098), 0x0, false},
        {VCS2, _MMIO(0x1c028), 0xffff, false},
  
        {VECS, _MMIO(0x1a028), 0xffff, false},
 +
 +      {RCS, _MMIO(0x7304), 0xffff, true},
 +      {RCS, _MMIO(0x2248), 0x0, false},
 +      {RCS, _MMIO(0x940c), 0x0, false},
 +      {RCS, _MMIO(0x4ab8), 0x0, false},
 +
 +      {RCS, _MMIO(0x4ab0), 0x0, false},
 +      {RCS, _MMIO(0x20d4), 0x0, false},
 +
 +      {RCS, _MMIO(0xb004), 0x0, false},
 +      {RCS, _MMIO(0x20a0), 0x0, false},
 +      {RCS, _MMIO(0x20e4), 0xffff, false},
  };
  
  static u32 gen9_render_mocs[I915_NUM_ENGINES][64];
@@@ -171,7 -159,7 +171,7 @@@ static void handle_tlb_pending_event(st
         */
        fw = intel_uncore_forcewake_for_reg(dev_priv, reg,
                                            FW_REG_READ | FW_REG_WRITE);
 -      if (ring_id == RCS && IS_SKYLAKE(dev_priv))
 +      if (ring_id == RCS && (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)))
                fw |= FORCEWAKE_RENDER;
  
        intel_uncore_forcewake_get(dev_priv, fw);
@@@ -204,6 -192,9 +204,6 @@@ static void load_mocs(struct intel_vgp
        if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
                return;
  
 -      if (!IS_SKYLAKE(dev_priv))
 -              return;
 -
        offset.reg = regs[ring_id];
        for (i = 0; i < 64; i++) {
                gen9_render_mocs[ring_id][i] = I915_READ(offset);
@@@ -239,6 -230,9 +239,6 @@@ static void restore_mocs(struct intel_v
        if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
                return;
  
 -      if (!IS_SKYLAKE(dev_priv))
 -              return;
 -
        offset.reg = regs[ring_id];
        for (i = 0; i < 64; i++) {
                vgpu_vreg(vgpu, offset) = I915_READ(offset);
@@@ -271,8 -265,7 +271,8 @@@ void intel_gvt_load_render_mmio(struct 
        u32 inhibit_mask =
                _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT);
  
 -      if (IS_SKYLAKE(vgpu->gvt->dev_priv)) {
 +      if (IS_SKYLAKE(vgpu->gvt->dev_priv)
 +              || IS_KABYLAKE(vgpu->gvt->dev_priv)) {
                mmio = gen9_render_mmio_list;
                array_size = ARRAY_SIZE(gen9_render_mmio_list);
                load_mocs(vgpu, ring_id);
@@@ -319,7 -312,7 +319,7 @@@ void intel_gvt_restore_render_mmio(stru
        u32 v;
        int i, array_size;
  
 -      if (IS_SKYLAKE(dev_priv)) {
 +      if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
                mmio = gen9_render_mmio_list;
                array_size = ARRAY_SIZE(gen9_render_mmio_list);
                restore_mocs(vgpu, ring_id);
                } else
                        v = mmio->value;
  
+               if (mmio->in_context)
+                       continue;
                I915_WRITE(mmio->reg, v);
                POSTING_READ(mmio->reg);
  
index 79ba4b3440aafd9537f287028d1e23a6186109a1,6ac77f8cc405d897caa373b95bd993b1ce4e3aa3..f25ff133865f1327936483ac166b97c41e0baa60
@@@ -47,92 -47,23 +47,96 @@@ static bool vgpu_has_pending_workload(s
        return false;
  }
  
 +struct vgpu_sched_data {
 +      struct list_head lru_list;
 +      struct intel_vgpu *vgpu;
 +
 +      ktime_t sched_in_time;
 +      ktime_t sched_out_time;
 +      ktime_t sched_time;
 +      ktime_t left_ts;
 +      ktime_t allocated_ts;
 +
 +      struct vgpu_sched_ctl sched_ctl;
 +};
 +
 +struct gvt_sched_data {
 +      struct intel_gvt *gvt;
 +      struct hrtimer timer;
 +      unsigned long period;
 +      struct list_head lru_runq_head;
 +};
 +
 +static void vgpu_update_timeslice(struct intel_vgpu *pre_vgpu)
 +{
 +      ktime_t delta_ts;
 +      struct vgpu_sched_data *vgpu_data = pre_vgpu->sched_data;
 +
 +      delta_ts = vgpu_data->sched_out_time - vgpu_data->sched_in_time;
 +
 +      vgpu_data->sched_time += delta_ts;
 +      vgpu_data->left_ts -= delta_ts;
 +}
 +
 +#define GVT_TS_BALANCE_PERIOD_MS 100
 +#define GVT_TS_BALANCE_STAGE_NUM 10
 +
 +static void gvt_balance_timeslice(struct gvt_sched_data *sched_data)
 +{
 +      struct vgpu_sched_data *vgpu_data;
 +      struct list_head *pos;
 +      static uint64_t stage_check;
 +      int stage = stage_check++ % GVT_TS_BALANCE_STAGE_NUM;
 +
 +      /* The timeslice accumulation reset at stage 0, which is
 +       * allocated again without adding previous debt.
 +       */
 +      if (stage == 0) {
 +              int total_weight = 0;
 +              ktime_t fair_timeslice;
 +
 +              list_for_each(pos, &sched_data->lru_runq_head) {
 +                      vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list);
 +                      total_weight += vgpu_data->sched_ctl.weight;
 +              }
 +
 +              list_for_each(pos, &sched_data->lru_runq_head) {
 +                      vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list);
 +                      fair_timeslice = ms_to_ktime(GVT_TS_BALANCE_PERIOD_MS) *
 +                                              vgpu_data->sched_ctl.weight /
 +                                              total_weight;
 +
 +                      vgpu_data->allocated_ts = fair_timeslice;
 +                      vgpu_data->left_ts = vgpu_data->allocated_ts;
 +              }
 +      } else {
 +              list_for_each(pos, &sched_data->lru_runq_head) {
 +                      vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list);
 +
 +                      /* timeslice for next 100ms should add the left/debt
 +                       * slice of previous stages.
 +                       */
 +                      vgpu_data->left_ts += vgpu_data->allocated_ts;
 +              }
 +      }
 +}
 +
  static void try_to_schedule_next_vgpu(struct intel_gvt *gvt)
  {
        struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
        enum intel_engine_id i;
        struct intel_engine_cs *engine;
 +      struct vgpu_sched_data *vgpu_data;
 +      ktime_t cur_time;
  
-       /* no target to schedule */
-       if (!scheduler->next_vgpu)
+       /* no need to schedule if next_vgpu is the same with current_vgpu,
+        * let scheduler chose next_vgpu again by setting it to NULL.
+        */
+       if (scheduler->next_vgpu == scheduler->current_vgpu) {
+               scheduler->next_vgpu = NULL;
                return;
+       }
  
 -      gvt_dbg_sched("try to schedule next vgpu %d\n",
 -                      scheduler->next_vgpu->id);
 -
        /*
         * after the flag is set, workload dispatch thread will
         * stop dispatching workload for current vgpu
  
        /* still have uncompleted workload? */
        for_each_engine(engine, gvt->dev_priv, i) {
 -              if (scheduler->current_workload[i]) {
 -                      gvt_dbg_sched("still have running workload\n");
 +              if (scheduler->current_workload[i])
                        return;
 -              }
        }
  
 -      gvt_dbg_sched("switch to next vgpu %d\n",
 -                      scheduler->next_vgpu->id);
 +      cur_time = ktime_get();
 +      if (scheduler->current_vgpu) {
 +              vgpu_data = scheduler->current_vgpu->sched_data;
 +              vgpu_data->sched_out_time = cur_time;
 +              vgpu_update_timeslice(scheduler->current_vgpu);
 +      }
 +      vgpu_data = scheduler->next_vgpu->sched_data;
 +      vgpu_data->sched_in_time = cur_time;
  
        /* switch current vgpu */
        scheduler->current_vgpu = scheduler->next_vgpu;
                wake_up(&scheduler->waitq[i]);
  }
  
 -struct tbs_vgpu_data {
 -      struct list_head list;
 -      struct intel_vgpu *vgpu;
 -      /* put some per-vgpu sched stats here */
 -};
 -
 -struct tbs_sched_data {
 -      struct intel_gvt *gvt;
 -      struct delayed_work work;
 -      unsigned long period;
 -      struct list_head runq_head;
 -};
 -
 -#define GVT_DEFAULT_TIME_SLICE (msecs_to_jiffies(1))
 -
 -static void tbs_sched_func(struct work_struct *work)
 +static struct intel_vgpu *find_busy_vgpu(struct gvt_sched_data *sched_data)
  {
 -      struct tbs_sched_data *sched_data = container_of(work,
 -                      struct tbs_sched_data, work.work);
 -      struct tbs_vgpu_data *vgpu_data;
 -
 -      struct intel_gvt *gvt = sched_data->gvt;
 -      struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
 -
 +      struct vgpu_sched_data *vgpu_data;
        struct intel_vgpu *vgpu = NULL;
 -      struct list_head *pos, *head;
 -
 -      mutex_lock(&gvt->lock);
 -
 -      /* no vgpu or has already had a target */
 -      if (list_empty(&sched_data->runq_head) || scheduler->next_vgpu)
 -              goto out;
 -
 -      if (scheduler->current_vgpu) {
 -              vgpu_data = scheduler->current_vgpu->sched_data;
 -              head = &vgpu_data->list;
 -      } else {
 -              head = &sched_data->runq_head;
 -      }
 +      struct list_head *head = &sched_data->lru_runq_head;
 +      struct list_head *pos;
  
        /* search a vgpu with pending workload */
        list_for_each(pos, head) {
 -              if (pos == &sched_data->runq_head)
 -                      continue;
  
 -              vgpu_data = container_of(pos, struct tbs_vgpu_data, list);
 +              vgpu_data = container_of(pos, struct vgpu_sched_data, lru_list);
                if (!vgpu_has_pending_workload(vgpu_data->vgpu))
                        continue;
  
 -              vgpu = vgpu_data->vgpu;
 -              break;
 +              /* Return the vGPU only if it has time slice left */
 +              if (vgpu_data->left_ts > 0) {
 +                      vgpu = vgpu_data->vgpu;
 +                      break;
 +              }
        }
  
 +      return vgpu;
 +}
 +
 +/* in nanosecond */
 +#define GVT_DEFAULT_TIME_SLICE 1000000
 +
 +static void tbs_sched_func(struct gvt_sched_data *sched_data)
 +{
 +      struct intel_gvt *gvt = sched_data->gvt;
 +      struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
 +      struct vgpu_sched_data *vgpu_data;
 +      struct intel_vgpu *vgpu = NULL;
 +      static uint64_t timer_check;
 +
 +      if (!(timer_check++ % GVT_TS_BALANCE_PERIOD_MS))
 +              gvt_balance_timeslice(sched_data);
 +
 +      /* no active vgpu or has already had a target */
 +      if (list_empty(&sched_data->lru_runq_head) || scheduler->next_vgpu)
 +              goto out;
 +
 +      vgpu = find_busy_vgpu(sched_data);
        if (vgpu) {
                scheduler->next_vgpu = vgpu;
 -              gvt_dbg_sched("pick next vgpu %d\n", vgpu->id);
 +
 +              /* Move the last used vGPU to the tail of lru_list */
 +              vgpu_data = vgpu->sched_data;
 +              list_del_init(&vgpu_data->lru_list);
 +              list_add_tail(&vgpu_data->lru_list,
 +                              &sched_data->lru_runq_head);
 +      } else {
 +              scheduler->next_vgpu = gvt->idle_vgpu;
        }
  out:
 -      if (scheduler->next_vgpu) {
 -              gvt_dbg_sched("try to schedule next vgpu %d\n",
 -                              scheduler->next_vgpu->id);
 +      if (scheduler->next_vgpu)
                try_to_schedule_next_vgpu(gvt);
 -      }
 +}
  
 -      /*
 -       * still have vgpu on runq
 -       * or last schedule haven't finished due to running workload
 -       */
 -      if (!list_empty(&sched_data->runq_head) || scheduler->next_vgpu)
 -              schedule_delayed_work(&sched_data->work, sched_data->period);
 +void intel_gvt_schedule(struct intel_gvt *gvt)
 +{
 +      struct gvt_sched_data *sched_data = gvt->scheduler.sched_data;
  
 +      mutex_lock(&gvt->lock);
 +      tbs_sched_func(sched_data);
        mutex_unlock(&gvt->lock);
  }
  
 +static enum hrtimer_restart tbs_timer_fn(struct hrtimer *timer_data)
 +{
 +      struct gvt_sched_data *data;
 +
 +      data = container_of(timer_data, struct gvt_sched_data, timer);
 +
 +      intel_gvt_request_service(data->gvt, INTEL_GVT_REQUEST_SCHED);
 +
 +      hrtimer_add_expires_ns(&data->timer, data->period);
 +
 +      return HRTIMER_RESTART;
 +}
 +
  static int tbs_sched_init(struct intel_gvt *gvt)
  {
        struct intel_gvt_workload_scheduler *scheduler =
                &gvt->scheduler;
  
 -      struct tbs_sched_data *data;
 +      struct gvt_sched_data *data;
  
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
  
 -      INIT_LIST_HEAD(&data->runq_head);
 -      INIT_DELAYED_WORK(&data->work, tbs_sched_func);
 +      INIT_LIST_HEAD(&data->lru_runq_head);
 +      hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 +      data->timer.function = tbs_timer_fn;
        data->period = GVT_DEFAULT_TIME_SLICE;
        data->gvt = gvt;
  
        scheduler->sched_data = data;
 +
        return 0;
  }
  
@@@ -272,28 -190,25 +276,28 @@@ static void tbs_sched_clean(struct inte
  {
        struct intel_gvt_workload_scheduler *scheduler =
                &gvt->scheduler;
 -      struct tbs_sched_data *data = scheduler->sched_data;
 +      struct gvt_sched_data *data = scheduler->sched_data;
 +
 +      hrtimer_cancel(&data->timer);
  
 -      cancel_delayed_work(&data->work);
        kfree(data);
        scheduler->sched_data = NULL;
  }
  
  static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu)
  {
 -      struct tbs_vgpu_data *data;
 +      struct vgpu_sched_data *data;
  
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
  
 +      data->sched_ctl.weight = vgpu->sched_ctl.weight;
        data->vgpu = vgpu;
 -      INIT_LIST_HEAD(&data->list);
 +      INIT_LIST_HEAD(&data->lru_list);
  
        vgpu->sched_data = data;
 +
        return 0;
  }
  
@@@ -305,24 -220,21 +309,24 @@@ static void tbs_sched_clean_vgpu(struc
  
  static void tbs_sched_start_schedule(struct intel_vgpu *vgpu)
  {
 -      struct tbs_sched_data *sched_data = vgpu->gvt->scheduler.sched_data;
 -      struct tbs_vgpu_data *vgpu_data = vgpu->sched_data;
 +      struct gvt_sched_data *sched_data = vgpu->gvt->scheduler.sched_data;
 +      struct vgpu_sched_data *vgpu_data = vgpu->sched_data;
  
 -      if (!list_empty(&vgpu_data->list))
 +      if (!list_empty(&vgpu_data->lru_list))
                return;
  
 -      list_add_tail(&vgpu_data->list, &sched_data->runq_head);
 -      schedule_delayed_work(&sched_data->work, 0);
 +      list_add_tail(&vgpu_data->lru_list, &sched_data->lru_runq_head);
 +
 +      if (!hrtimer_active(&sched_data->timer))
 +              hrtimer_start(&sched_data->timer, ktime_add_ns(ktime_get(),
 +                      sched_data->period), HRTIMER_MODE_ABS);
  }
  
  static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu)
  {
 -      struct tbs_vgpu_data *vgpu_data = vgpu->sched_data;
 +      struct vgpu_sched_data *vgpu_data = vgpu->sched_data;
  
 -      list_del_init(&vgpu_data->list);
 +      list_del_init(&vgpu_data->lru_list);
  }
  
  static struct intel_gvt_sched_policy_ops tbs_schedule_ops = {