Merge tag 'gvt-fixes-2018-11-07' of https://github.com/intel/gvt-linux into drm-intel...
authorJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Wed, 7 Nov 2018 13:34:09 +0000 (15:34 +0200)
committerJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Wed, 7 Nov 2018 13:34:10 +0000 (15:34 +0200)
gvt-fixes-2018-11-07

- Fix invalidate of old ggtt entry (Hang)
- Fix partial ggtt entry update in any order (Hang)
- Fix one mask setting for chicken reg (Xinyun)
- Fix eDP warning in guest (Longhe)

Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
From: Zhenyu Wang <zhenyuw@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181107023137.GO25194@zhen-hp.sh.intel.com
1  2 
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/gtt.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/mmio_context.c

@@@ -1113,10 -1113,6 +1113,10 @@@ static inline void ppgtt_generate_shado
  }
  
  /**
 + * Check if can do 2M page
 + * @vgpu: target vgpu
 + * @entry: target pfn's gtt entry
 + *
   * Return 1 if 2MB huge gtt shadowing is possilbe, 0 if miscondition,
   * negtive if found err.
   */
@@@ -1905,7 -1901,6 +1905,6 @@@ static struct intel_vgpu_mm *intel_vgpu
                vgpu_free_mm(mm);
                return ERR_PTR(-ENOMEM);
        }
-       mm->ggtt_mm.last_partial_off = -1UL;
  
        return mm;
  }
@@@ -1930,7 -1925,6 +1929,6 @@@ void _intel_vgpu_mm_release(struct kre
                invalidate_ppgtt_mm(mm);
        } else {
                vfree(mm->ggtt_mm.virtual_ggtt);
-               mm->ggtt_mm.last_partial_off = -1UL;
        }
  
        vgpu_free_mm(mm);
@@@ -1949,7 -1943,7 +1947,7 @@@ void intel_vgpu_unpin_mm(struct intel_v
  
  /**
   * intel_vgpu_pin_mm - increase the pin count of a vGPU mm object
 - * @vgpu: a vGPU
 + * @mm: target vgpu mm
   *
   * This function is called when user wants to use a vGPU mm object. If this
   * mm object hasn't been shadowed yet, the shadow will be populated at this
@@@ -2168,6 -2162,8 +2166,8 @@@ static int emulate_ggtt_mmio_write(stru
        struct intel_gvt_gtt_entry e, m;
        dma_addr_t dma_addr;
        int ret;
+       struct intel_gvt_partial_pte *partial_pte, *pos, *n;
+       bool partial_update = false;
  
        if (bytes != 4 && bytes != 8)
                return -EINVAL;
        if (!vgpu_gmadr_is_valid(vgpu, gma))
                return 0;
  
-       ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index);
+       e.type = GTT_TYPE_GGTT_PTE;
        memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
                        bytes);
  
        /* If ggtt entry size is 8 bytes, and it's split into two 4 bytes
-        * write, we assume the two 4 bytes writes are consecutive.
-        * Otherwise, we abort and report error
+        * write, save the first 4 bytes in a list and update virtual
+        * PTE. Only update shadow PTE when the second 4 bytes comes.
         */
        if (bytes < info->gtt_entry_size) {
-               if (ggtt_mm->ggtt_mm.last_partial_off == -1UL) {
-                       /* the first partial part*/
-                       ggtt_mm->ggtt_mm.last_partial_off = off;
-                       ggtt_mm->ggtt_mm.last_partial_data = e.val64;
-                       return 0;
-               } else if ((g_gtt_index ==
-                               (ggtt_mm->ggtt_mm.last_partial_off >>
-                               info->gtt_entry_size_shift)) &&
-                       (off != ggtt_mm->ggtt_mm.last_partial_off)) {
-                       /* the second partial part */
-                       int last_off = ggtt_mm->ggtt_mm.last_partial_off &
-                               (info->gtt_entry_size - 1);
-                       memcpy((void *)&e.val64 + last_off,
-                               (void *)&ggtt_mm->ggtt_mm.last_partial_data +
-                               last_off, bytes);
-                       ggtt_mm->ggtt_mm.last_partial_off = -1UL;
-               } else {
-                       int last_offset;
-                       gvt_vgpu_err("failed to populate guest ggtt entry: abnormal ggtt entry write sequence, last_partial_off=%lx, offset=%x, bytes=%d, ggtt entry size=%d\n",
-                                       ggtt_mm->ggtt_mm.last_partial_off, off,
-                                       bytes, info->gtt_entry_size);
-                       /* set host ggtt entry to scratch page and clear
-                        * virtual ggtt entry as not present for last
-                        * partially write offset
-                        */
-                       last_offset = ggtt_mm->ggtt_mm.last_partial_off &
-                                       (~(info->gtt_entry_size - 1));
-                       ggtt_get_host_entry(ggtt_mm, &m, last_offset);
-                       ggtt_invalidate_pte(vgpu, &m);
-                       ops->set_pfn(&m, gvt->gtt.scratch_mfn);
-                       ops->clear_present(&m);
-                       ggtt_set_host_entry(ggtt_mm, &m, last_offset);
-                       ggtt_invalidate(gvt->dev_priv);
-                       ggtt_get_guest_entry(ggtt_mm, &e, last_offset);
-                       ops->clear_present(&e);
-                       ggtt_set_guest_entry(ggtt_mm, &e, last_offset);
-                       ggtt_mm->ggtt_mm.last_partial_off = off;
-                       ggtt_mm->ggtt_mm.last_partial_data = e.val64;
+               bool found = false;
+               list_for_each_entry_safe(pos, n,
+                               &ggtt_mm->ggtt_mm.partial_pte_list, list) {
+                       if (g_gtt_index == pos->offset >>
+                                       info->gtt_entry_size_shift) {
+                               if (off != pos->offset) {
+                                       /* the second partial part*/
+                                       int last_off = pos->offset &
+                                               (info->gtt_entry_size - 1);
+                                       memcpy((void *)&e.val64 + last_off,
+                                               (void *)&pos->data + last_off,
+                                               bytes);
+                                       list_del(&pos->list);
+                                       kfree(pos);
+                                       found = true;
+                                       break;
+                               }
+                               /* update of the first partial part */
+                               pos->data = e.val64;
+                               ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index);
+                               return 0;
+                       }
+               }
  
-                       return 0;
+               if (!found) {
+                       /* the first partial part */
+                       partial_pte = kzalloc(sizeof(*partial_pte), GFP_KERNEL);
+                       if (!partial_pte)
+                               return -ENOMEM;
+                       partial_pte->offset = off;
+                       partial_pte->data = e.val64;
+                       list_add_tail(&partial_pte->list,
+                               &ggtt_mm->ggtt_mm.partial_pte_list);
+                       partial_update = true;
                }
        }
  
-       if (ops->test_present(&e)) {
+       if (!partial_update && (ops->test_present(&e))) {
                gfn = ops->get_pfn(&e);
                m = e;
  
                } else
                        ops->set_pfn(&m, dma_addr >> PAGE_SHIFT);
        } else {
-               ggtt_get_host_entry(ggtt_mm, &m, g_gtt_index);
-               ggtt_invalidate_pte(vgpu, &m);
                ops->set_pfn(&m, gvt->gtt.scratch_mfn);
                ops->clear_present(&m);
        }
  
  out:
+       ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index);
+       ggtt_get_host_entry(ggtt_mm, &e, g_gtt_index);
+       ggtt_invalidate_pte(vgpu, &e);
        ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index);
        ggtt_invalidate(gvt->dev_priv);
-       ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index);
        return 0;
  }
  
@@@ -2430,6 -2417,8 +2421,8 @@@ int intel_vgpu_init_gtt(struct intel_vg
  
        intel_vgpu_reset_ggtt(vgpu, false);
  
+       INIT_LIST_HEAD(&gtt->ggtt_mm->ggtt_mm.partial_pte_list);
        return create_scratch_page_tree(vgpu);
  }
  
@@@ -2454,6 -2443,14 +2447,14 @@@ static void intel_vgpu_destroy_all_ppgt
  
  static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu)
  {
+       struct intel_gvt_partial_pte *pos;
+       list_for_each_entry(pos,
+                       &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list, list) {
+               gvt_dbg_mm("partial PTE update on hold 0x%lx : 0x%llx\n",
+                       pos->offset, pos->data);
+               kfree(pos);
+       }
        intel_vgpu_destroy_mm(vgpu->gtt.ggtt_mm);
        vgpu->gtt.ggtt_mm = NULL;
  }
@@@ -2525,7 -2522,8 +2526,7 @@@ fail
  /**
   * intel_vgpu_find_ppgtt_mm - find a PPGTT mm object
   * @vgpu: a vGPU
 - * @page_table_level: PPGTT page table level
 - * @root_entry: PPGTT page table root pointers
 + * @pdps: pdp root array
   *
   * This function is used to find a PPGTT mm object from mm object pool
   *
@@@ -35,6 -35,7 +35,6 @@@
  #define _GVT_GTT_H_
  
  #define I915_GTT_PAGE_SHIFT         12
 -#define I915_GTT_PAGE_MASK            (~(I915_GTT_PAGE_SIZE - 1))
  
  struct intel_vgpu_mm;
  
@@@ -132,6 -133,12 +132,12 @@@ enum intel_gvt_mm_type 
  
  #define GVT_RING_CTX_NR_PDPS  GEN8_3LVL_PDPES
  
+ struct intel_gvt_partial_pte {
+       unsigned long offset;
+       u64 data;
+       struct list_head list;
+ };
  struct intel_vgpu_mm {
        enum intel_gvt_mm_type type;
        struct intel_vgpu *vgpu;
                } ppgtt_mm;
                struct {
                        void *virtual_ggtt;
-                       unsigned long last_partial_off;
-                       u64 last_partial_data;
+                       struct list_head partial_pte_list;
                } ggtt_mm;
        };
  };
@@@ -1287,13 -1287,12 +1287,13 @@@ static int power_well_ctl_mmio_write(st
  {
        write_vreg(vgpu, offset, p_data, bytes);
  
 -      if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_CTL_REQ(HSW_DISP_PW_GLOBAL))
 +      if (vgpu_vreg(vgpu, offset) &
 +          HSW_PWR_WELL_CTL_REQ(HSW_PW_CTL_IDX_GLOBAL))
                vgpu_vreg(vgpu, offset) |=
 -                      HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL);
 +                      HSW_PWR_WELL_CTL_STATE(HSW_PW_CTL_IDX_GLOBAL);
        else
                vgpu_vreg(vgpu, offset) &=
 -                      ~HSW_PWR_WELL_CTL_STATE(HSW_DISP_PW_GLOBAL);
 +                      ~HSW_PWR_WELL_CTL_STATE(HSW_PW_CTL_IDX_GLOBAL);
        return 0;
  }
  
@@@ -1609,7 -1608,7 +1609,7 @@@ static int bxt_gt_disp_pwron_write(stru
        return 0;
  }
  
- static int bxt_edp_psr_imr_iir_write(struct intel_vgpu *vgpu,
+ static int edp_psr_imr_iir_write(struct intel_vgpu *vgpu,
                unsigned int offset, void *p_data, unsigned int bytes)
  {
        vgpu_vreg(vgpu, offset) = 0;
@@@ -2138,7 -2137,7 +2138,7 @@@ static int init_generic_mmio_info(struc
  
        MMIO_F(PCH_GMBUS0, 4 * 4, 0, 0, 0, D_ALL, gmbus_mmio_read,
                gmbus_mmio_write);
 -      MMIO_F(PCH_GPIOA, 6 * 4, F_UNALIGN, 0, 0, D_ALL, NULL, NULL);
 +      MMIO_F(PCH_GPIO_BASE, 6 * 4, F_UNALIGN, 0, 0, D_ALL, NULL, NULL);
        MMIO_F(_MMIO(0xe4f00), 0x28, 0, 0, 0, D_ALL, NULL, NULL);
  
        MMIO_F(_MMIO(_PCH_DPB_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_PRE_SKL, NULL,
        MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL);
        MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL);
        MMIO_D(GEN6_PMINTRMSK, D_ALL);
 -      /*
 -       * Use an arbitrary power well controlled by the PWR_WELL_CTL
 -       * register.
 -       */
 -      MMIO_DH(HSW_PWR_WELL_CTL_BIOS(HSW_DISP_PW_GLOBAL), D_BDW, NULL,
 -              power_well_ctl_mmio_write);
 -      MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(HSW_DISP_PW_GLOBAL), D_BDW, NULL,
 -              power_well_ctl_mmio_write);
 -      MMIO_DH(HSW_PWR_WELL_CTL_KVMR, D_BDW, NULL, power_well_ctl_mmio_write);
 -      MMIO_DH(HSW_PWR_WELL_CTL_DEBUG(HSW_DISP_PW_GLOBAL), D_BDW, NULL,
 -              power_well_ctl_mmio_write);
 +      MMIO_DH(HSW_PWR_WELL_CTL1, D_BDW, NULL, power_well_ctl_mmio_write);
 +      MMIO_DH(HSW_PWR_WELL_CTL2, D_BDW, NULL, power_well_ctl_mmio_write);
 +      MMIO_DH(HSW_PWR_WELL_CTL3, D_BDW, NULL, power_well_ctl_mmio_write);
 +      MMIO_DH(HSW_PWR_WELL_CTL4, D_BDW, NULL, power_well_ctl_mmio_write);
        MMIO_DH(HSW_PWR_WELL_CTL5, D_BDW, NULL, power_well_ctl_mmio_write);
        MMIO_DH(HSW_PWR_WELL_CTL6, D_BDW, NULL, power_well_ctl_mmio_write);
  
        MMIO_DFH(_MMIO(0x1a178), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0x1a17c), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0x2217c), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+       MMIO_DH(EDP_PSR_IMR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write);
+       MMIO_DH(EDP_PSR_IIR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write);
        return 0;
  }
  
@@@ -2817,8 -2826,13 +2820,8 @@@ static int init_skl_mmio_info(struct in
        MMIO_F(_MMIO(_DPD_AUX_CH_CTL), 6 * 4, 0, 0, 0, D_SKL_PLUS, NULL,
                                                dp_aux_ch_ctl_mmio_write);
  
 -      /*
 -       * Use an arbitrary power well controlled by the PWR_WELL_CTL
 -       * register.
 -       */
 -      MMIO_D(HSW_PWR_WELL_CTL_BIOS(SKL_DISP_PW_MISC_IO), D_SKL_PLUS);
 -      MMIO_DH(HSW_PWR_WELL_CTL_DRIVER(SKL_DISP_PW_MISC_IO), D_SKL_PLUS, NULL,
 -              skl_power_well_ctl_write);
 +      MMIO_D(HSW_PWR_WELL_CTL1, D_SKL_PLUS);
 +      MMIO_DH(HSW_PWR_WELL_CTL2, D_SKL_PLUS, NULL, skl_power_well_ctl_write);
  
        MMIO_DH(DBUF_CTL, D_SKL_PLUS, NULL, gen9_dbuf_ctl_mmio_write);
  
@@@ -3205,9 -3219,6 +3208,6 @@@ static int init_bxt_mmio_info(struct in
        MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_B), D_BXT);
        MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_C), D_BXT);
  
-       MMIO_DH(EDP_PSR_IMR, D_BXT, NULL, bxt_edp_psr_imr_iir_write);
-       MMIO_DH(EDP_PSR_IIR, D_BXT, NULL, bxt_edp_psr_imr_iir_write);
        MMIO_D(RC6_CTX_BASE, D_BXT);
  
        MMIO_D(GEN8_PUSHBUS_CONTROL, D_BXT);
@@@ -3445,7 -3456,6 +3445,7 @@@ bool intel_gvt_in_force_nonpriv_whiteli
   * @offset: register offset
   * @pdata: data buffer
   * @bytes: data length
 + * @is_read: read or write
   *
   * Returns:
   * Zero on success, negative error code if failed.
  #include "gvt.h"
  #include "trace.h"
  
 -/**
 - * Defined in Intel Open Source PRM.
 - * Ref: https://01.org/linuxgraphics/documentation/hardware-specification-prms
 - */
 -#define TRVATTL3PTRDW(i)      _MMIO(0x4de0 + (i)*4)
 -#define TRNULLDETCT           _MMIO(0x4de8)
 -#define TRINVTILEDETCT                _MMIO(0x4dec)
 -#define TRVADR                        _MMIO(0x4df0)
 -#define TRTTE                 _MMIO(0x4df4)
 -#define RING_EXCC(base)               _MMIO((base) + 0x28)
 -#define RING_GFX_MODE(base)   _MMIO((base) + 0x29c)
 -#define VF_GUARDBAND          _MMIO(0x83a4)
 -
  #define GEN9_MOCS_SIZE                64
  
  /* Raw offset is appened to each line for convenience. */
@@@ -131,7 -144,7 +131,7 @@@ static struct engine_mmio gen9_engine_m
        {RCS, GAMT_CHKN_BIT_REG, 0x0, false}, /* 0x4ab8 */
  
        {RCS, GEN9_GAMT_ECO_REG_RW_IA, 0x0, false}, /* 0x4ab0 */
-       {RCS, GEN9_CSFE_CHICKEN1_RCS, 0x0, false}, /* 0x20d4 */
+       {RCS, GEN9_CSFE_CHICKEN1_RCS, 0xffff, false}, /* 0x20d4 */
  
        {RCS, GEN8_GARBCNTL, 0x0, false}, /* 0xb004 */
        {RCS, GEN7_FF_THREAD_MODE, 0x0, false}, /* 0x20a0 */