]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/blobdiff - drivers/gpu/drm/i915/gvt/handlers.c
Merge tag 'gvt-next-2016-10-27' of https://github.com/01org/gvt-linux into drm-intel...
[mirror_ubuntu-disco-kernel.git] / drivers / gpu / drm / i915 / gvt / handlers.c
index 194778b374fff789b1ab1df64bec615848296c82..9ab1f95dddc5dd73eb272d9f5806955841d6b1e9 100644 (file)
@@ -37,6 +37,8 @@
  */
 
 #include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
 
 /* XXX FIXME i915 has changed PP_XXX definition */
 #define PCH_PP_STATUS  _MMIO(0xc7200)
@@ -128,6 +130,19 @@ static int new_mmio_info(struct intel_gvt *gvt,
        return 0;
 }
 
+static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg)
+{
+       enum intel_engine_id id;
+       struct intel_engine_cs *engine;
+
+       reg &= ~GENMASK(11, 0);
+       for_each_engine(engine, gvt->dev_priv, id) {
+               if (engine->mmio_base == reg)
+                       return id;
+       }
+       return -1;
+}
+
 #define offset_to_fence_num(offset) \
        ((offset - i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) >> 3)
 
@@ -215,12 +230,49 @@ static int mul_force_wake_write(struct intel_vgpu *vgpu,
        return 0;
 }
 
+static int handle_device_reset(struct intel_vgpu *vgpu, unsigned int offset,
+               void *p_data, unsigned int bytes, unsigned long bitmap)
+{
+       struct intel_gvt_workload_scheduler *scheduler =
+               &vgpu->gvt->scheduler;
+
+       vgpu->resetting = true;
+
+       intel_vgpu_stop_schedule(vgpu);
+       /*
+        * The current_vgpu will set to NULL after stopping the
+        * scheduler when the reset is triggered by current vgpu.
+        */
+       if (scheduler->current_vgpu == NULL) {
+               mutex_unlock(&vgpu->gvt->lock);
+               intel_gvt_wait_vgpu_idle(vgpu);
+               mutex_lock(&vgpu->gvt->lock);
+       }
+
+       intel_vgpu_reset_execlist(vgpu, bitmap);
+
+       /* full GPU reset */
+       if (bitmap == 0xff) {
+               mutex_unlock(&vgpu->gvt->lock);
+               intel_vgpu_clean_gtt(vgpu);
+               mutex_lock(&vgpu->gvt->lock);
+               setup_vgpu_mmio(vgpu);
+               populate_pvinfo_page(vgpu);
+               intel_vgpu_init_gtt(vgpu);
+       }
+
+       vgpu->resetting = false;
+
+       return 0;
+}
+
 static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                void *p_data, unsigned int bytes)
 {
        u32 data;
-       u32 bitmap = 0;
+       u64 bitmap = 0;
 
+       write_vreg(vgpu, offset, p_data, bytes);
        data = vgpu_vreg(vgpu, offset);
 
        if (data & GEN6_GRDOM_FULL) {
@@ -248,7 +300,7 @@ static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                if (HAS_BSD2(vgpu->gvt->dev_priv))
                        bitmap |= (1 << VCS2);
        }
-       return 0;
+       return handle_device_reset(vgpu, offset, p_data, bytes, bitmap);
 }
 
 static int gmbus_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
@@ -1262,6 +1314,84 @@ static int ring_timestamp_mmio_read(struct intel_vgpu *vgpu,
        return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
 }
 
+static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+               void *p_data, unsigned int bytes)
+{
+       int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset);
+       struct intel_vgpu_execlist *execlist;
+       u32 data = *(u32 *)p_data;
+       int ret = 0;
+
+       if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1))
+               return -EINVAL;
+
+       execlist = &vgpu->execlist[ring_id];
+
+       execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data;
+       if (execlist->elsp_dwords.index == 3) {
+               ret = intel_vgpu_submit_execlist(vgpu, ring_id);
+               if(ret)
+                       gvt_err("fail submit workload on ring %d\n", ring_id);
+       }
+
+       ++execlist->elsp_dwords.index;
+       execlist->elsp_dwords.index &= 0x3;
+       return ret;
+}
+
+static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+               void *p_data, unsigned int bytes)
+{
+       u32 data = *(u32 *)p_data;
+       int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset);
+       bool enable_execlist;
+
+       write_vreg(vgpu, offset, p_data, bytes);
+       if ((data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE))
+                       || (data & _MASKED_BIT_DISABLE(GFX_RUN_LIST_ENABLE))) {
+               enable_execlist = !!(data & GFX_RUN_LIST_ENABLE);
+
+               gvt_dbg_core("EXECLIST %s on ring %d\n",
+                               (enable_execlist ? "enabling" : "disabling"),
+                               ring_id);
+
+               if (enable_execlist)
+                       intel_vgpu_start_schedule(vgpu);
+       }
+       return 0;
+}
+
+static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu,
+               unsigned int offset, void *p_data, unsigned int bytes)
+{
+       int rc = 0;
+       unsigned int id = 0;
+
+       switch (offset) {
+       case 0x4260:
+               id = RCS;
+               break;
+       case 0x4264:
+               id = VCS;
+               break;
+       case 0x4268:
+               id = VCS2;
+               break;
+       case 0x426c:
+               id = BCS;
+               break;
+       case 0x4270:
+               id = VECS;
+               break;
+       default:
+               rc = -EINVAL;
+               break;
+       }
+       set_bit(id, (void *)vgpu->tlb_handle_pending);
+
+       return rc;
+}
+
 #define MMIO_F(reg, s, f, am, rm, d, r, w) do { \
        ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \
                f, s, am, rm, d, r, w); \
@@ -1343,7 +1473,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
 
        /* RING MODE */
 #define RING_REG(base) (base + 0x29c)
-       MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, NULL);
+       MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, ring_mode_mmio_write);
 #undef RING_REG
 
        MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK, NULL, NULL);
@@ -2069,11 +2199,11 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_F(CL_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
        MMIO_F(PS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
        MMIO_F(PS_DEPTH_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
-       MMIO_DH(0x4260, D_BDW_PLUS, NULL, NULL);
-       MMIO_DH(0x4264, D_BDW_PLUS, NULL, NULL);
-       MMIO_DH(0x4268, D_BDW_PLUS, NULL, NULL);
-       MMIO_DH(0x426c, D_BDW_PLUS, NULL, NULL);
-       MMIO_DH(0x4270, D_BDW_PLUS, NULL, NULL);
+       MMIO_DH(0x4260, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+       MMIO_DH(0x4264, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+       MMIO_DH(0x4268, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+       MMIO_DH(0x426c, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+       MMIO_DH(0x4270, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
        MMIO_DFH(0x4094, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
 
        return 0;
@@ -2158,7 +2288,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
        MMIO_D(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
        MMIO_D(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
        MMIO_D(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
-       MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
+       MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, ring_mode_mmio_write);
        MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK,
                        NULL, NULL);
        MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK,
@@ -2169,8 +2299,8 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
        MMIO_RING_D(RING_ACTHD_UDW, D_BDW_PLUS);
 
 #define RING_REG(base) (base + 0x230)
-       MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, NULL);
-       MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL);
+       MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, elsp_mmio_write);
+       MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, elsp_mmio_write);
 #undef RING_REG
 
 #define RING_REG(base) (base + 0x234)