]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'drm-intel-fixes-2017-08-09-1' of git://anongit.freedesktop.org/git/drm...
authorDave Airlie <airlied@redhat.com>
Thu, 10 Aug 2017 00:17:31 +0000 (10:17 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 10 Aug 2017 00:17:31 +0000 (10:17 +1000)
drm/i915 fixes for v4.13-rc5

* tag 'drm-intel-fixes-2017-08-09-1' of git://anongit.freedesktop.org/git/drm-intel:
  drm/i915: fix backlight invert for non-zero minimum brightness
  drm/i915/shrinker: Wrap need_resched() inside preempt-disable
  drm/i915/perf: fix flex eu registers programming
  drm/i915: Fix out-of-bounds array access in bdw_load_gamma_lut
  drm/i915/gvt: Change the max length of mmio_reg_rw from 4 to 8
  drm/i915/gvt: Initialize MMIO Block with HW state
  drm/i915/gvt: clean workload queue if error happened
  drm/i915/gvt: change resetting to resetting_eng

drivers/gpu/drm/i915/gvt/execlist.c
drivers/gpu/drm/i915/gvt/firmware.c
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/scheduler.c
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_gem_shrinker.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/intel_color.c
drivers/gpu/drm/i915/intel_panel.c

index 700050556242480e6fbf8eb4a8d97c6307e9390d..1648887d3f55248cf055524a2f0e341062f0cd8d 100644 (file)
@@ -46,6 +46,8 @@
 #define same_context(a, b) (((a)->context_id == (b)->context_id) && \
                ((a)->lrca == (b)->lrca))
 
+static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask);
+
 static int context_switch_events[] = {
        [RCS] = RCS_AS_CONTEXT_SWITCH,
        [BCS] = BCS_AS_CONTEXT_SWITCH,
@@ -499,10 +501,10 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 static int complete_execlist_workload(struct intel_vgpu_workload *workload)
 {
        struct intel_vgpu *vgpu = workload->vgpu;
-       struct intel_vgpu_execlist *execlist =
-               &vgpu->execlist[workload->ring_id];
+       int ring_id = workload->ring_id;
+       struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id];
        struct intel_vgpu_workload *next_workload;
-       struct list_head *next = workload_q_head(vgpu, workload->ring_id)->next;
+       struct list_head *next = workload_q_head(vgpu, ring_id)->next;
        bool lite_restore = false;
        int ret;
 
@@ -512,10 +514,25 @@ static int complete_execlist_workload(struct intel_vgpu_workload *workload)
        release_shadow_batch_buffer(workload);
        release_shadow_wa_ctx(&workload->wa_ctx);
 
-       if (workload->status || vgpu->resetting)
+       if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) {
+               /* if workload->status is not successful means HW GPU
+                * has occurred GPU hang or something wrong with i915/GVT,
+                * and GVT won't inject context switch interrupt to guest.
+                * So this error is a vGPU hang actually to the guest.
+                * According to this we should emunlate a vGPU hang. If
+                * there are pending workloads which are already submitted
+                * from guest, we should clean them up like HW GPU does.
+                *
+                * if it is in middle of engine resetting, the pending
+                * workloads won't be submitted to HW GPU and will be
+                * cleaned up during the resetting process later, so doing
+                * the workload clean up here doesn't have any impact.
+                **/
+               clean_workloads(vgpu, ENGINE_MASK(ring_id));
                goto out;
+       }
 
-       if (!list_empty(workload_q_head(vgpu, workload->ring_id))) {
+       if (!list_empty(workload_q_head(vgpu, ring_id))) {
                struct execlist_ctx_descriptor_format *this_desc, *next_desc;
 
                next_workload = container_of(next,
index 5dad9298b2d5dbbe7b626895806e6008047bbd6a..a26c1705430eb2134d002b68ddcb26d272684bd9 100644 (file)
@@ -72,11 +72,13 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
        struct intel_gvt_device_info *info = &gvt->device_info;
        struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
        struct intel_gvt_mmio_info *e;
+       struct gvt_mmio_block *block = gvt->mmio.mmio_block;
+       int num = gvt->mmio.num_mmio_block;
        struct gvt_firmware_header *h;
        void *firmware;
        void *p;
        unsigned long size, crc32_start;
-       int i;
+       int i, j;
        int ret;
 
        size = sizeof(*h) + info->mmio_size + info->cfg_space_size;
@@ -105,6 +107,13 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
        hash_for_each(gvt->mmio.mmio_info_table, i, e, node)
                *(u32 *)(p + e->offset) = I915_READ_NOTRACE(_MMIO(e->offset));
 
+       for (i = 0; i < num; i++, block++) {
+               for (j = 0; j < block->size; j += 4)
+                       *(u32 *)(p + INTEL_GVT_MMIO_OFFSET(block->offset) + j) =
+                               I915_READ_NOTRACE(_MMIO(INTEL_GVT_MMIO_OFFSET(
+                                                       block->offset) + j));
+       }
+
        memcpy(gvt->firmware.mmio, p, info->mmio_size);
 
        crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4;
index 3a74e79eac2f6c13fef32e1611b539db7b8f46c3..2964a4d01a66da5d2fb06d256ed35fa83fa96a38 100644 (file)
@@ -149,7 +149,7 @@ struct intel_vgpu {
        bool active;
        bool pv_notified;
        bool failsafe;
-       bool resetting;
+       unsigned int resetting_eng;
        void *sched_data;
        struct vgpu_sched_ctl sched_ctl;
 
@@ -195,6 +195,15 @@ struct intel_gvt_fence {
        unsigned long vgpu_allocated_fence_num;
 };
 
+/* Special MMIO blocks. */
+struct gvt_mmio_block {
+       unsigned int device;
+       i915_reg_t   offset;
+       unsigned int size;
+       gvt_mmio_func read;
+       gvt_mmio_func write;
+};
+
 #define INTEL_GVT_MMIO_HASH_BITS 11
 
 struct intel_gvt_mmio {
@@ -214,6 +223,9 @@ struct intel_gvt_mmio {
 /* This reg could be accessed by unaligned address */
 #define F_UNALIGN      (1 << 6)
 
+       struct gvt_mmio_block *mmio_block;
+       unsigned int num_mmio_block;
+
        DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS);
        unsigned int num_tracked_mmio;
 };
index 17febe830ff6984e06bb81cb91601a76b67d5f2a..feed9921b3b3eb05e6e8dce5e1b510f4d6fc9479 100644 (file)
@@ -2857,31 +2857,15 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
        return 0;
 }
 
-/* Special MMIO blocks. */
-static struct gvt_mmio_block {
-       unsigned int device;
-       i915_reg_t   offset;
-       unsigned int size;
-       gvt_mmio_func read;
-       gvt_mmio_func write;
-} gvt_mmio_blocks[] = {
-       {D_SKL_PLUS, _MMIO(CSR_MMIO_START_RANGE), 0x3000, NULL, NULL},
-       {D_ALL, _MMIO(MCHBAR_MIRROR_BASE_SNB), 0x40000, NULL, NULL},
-       {D_ALL, _MMIO(VGT_PVINFO_PAGE), VGT_PVINFO_SIZE,
-               pvinfo_mmio_read, pvinfo_mmio_write},
-       {D_ALL, LGC_PALETTE(PIPE_A, 0), 1024, NULL, NULL},
-       {D_ALL, LGC_PALETTE(PIPE_B, 0), 1024, NULL, NULL},
-       {D_ALL, LGC_PALETTE(PIPE_C, 0), 1024, NULL, NULL},
-};
-
 static struct gvt_mmio_block *find_mmio_block(struct intel_gvt *gvt,
                                              unsigned int offset)
 {
        unsigned long device = intel_gvt_get_device_type(gvt);
-       struct gvt_mmio_block *block = gvt_mmio_blocks;
+       struct gvt_mmio_block *block = gvt->mmio.mmio_block;
+       int num = gvt->mmio.num_mmio_block;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(gvt_mmio_blocks); i++, block++) {
+       for (i = 0; i < num; i++, block++) {
                if (!(device & block->device))
                        continue;
                if (offset >= INTEL_GVT_MMIO_OFFSET(block->offset) &&
@@ -2912,6 +2896,17 @@ void intel_gvt_clean_mmio_info(struct intel_gvt *gvt)
        gvt->mmio.mmio_attribute = NULL;
 }
 
+/* Special MMIO blocks. */
+static struct gvt_mmio_block mmio_blocks[] = {
+       {D_SKL_PLUS, _MMIO(CSR_MMIO_START_RANGE), 0x3000, NULL, NULL},
+       {D_ALL, _MMIO(MCHBAR_MIRROR_BASE_SNB), 0x40000, NULL, NULL},
+       {D_ALL, _MMIO(VGT_PVINFO_PAGE), VGT_PVINFO_SIZE,
+               pvinfo_mmio_read, pvinfo_mmio_write},
+       {D_ALL, LGC_PALETTE(PIPE_A, 0), 1024, NULL, NULL},
+       {D_ALL, LGC_PALETTE(PIPE_B, 0), 1024, NULL, NULL},
+       {D_ALL, LGC_PALETTE(PIPE_C, 0), 1024, NULL, NULL},
+};
+
 /**
  * intel_gvt_setup_mmio_info - setup MMIO information table for GVT device
  * @gvt: GVT device
@@ -2951,6 +2946,9 @@ int intel_gvt_setup_mmio_info(struct intel_gvt *gvt)
                        goto err;
        }
 
+       gvt->mmio.mmio_block = mmio_blocks;
+       gvt->mmio.num_mmio_block = ARRAY_SIZE(mmio_blocks);
+
        gvt_dbg_mmio("traced %u virtual mmio registers\n",
                     gvt->mmio.num_tracked_mmio);
        return 0;
@@ -3030,7 +3028,7 @@ int intel_vgpu_mmio_reg_rw(struct intel_vgpu *vgpu, unsigned int offset,
        gvt_mmio_func func;
        int ret;
 
-       if (WARN_ON(bytes > 4))
+       if (WARN_ON(bytes > 8))
                return -EINVAL;
 
        /*
index 4f7057d62d88b393ce77670f9100bc2d3b246014..22e08eb2d0b7c66faf01741656fb33d1535925f3 100644 (file)
@@ -432,7 +432,8 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
 
                i915_gem_request_put(fetch_and_zero(&workload->req));
 
-               if (!workload->status && !vgpu->resetting) {
+               if (!workload->status && !(vgpu->resetting_eng &
+                                          ENGINE_MASK(ring_id))) {
                        update_guest_context(workload);
 
                        for_each_set_bit(event, workload->pending_events,
index 90c14e6e3ea06b8de36d90284132659eb80f72c6..3deadcbd5a245c039169f1a10c6c91cc791d3a66 100644 (file)
@@ -480,11 +480,13 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
 {
        struct intel_gvt *gvt = vgpu->gvt;
        struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+       unsigned int resetting_eng = dmlr ? ALL_ENGINES : engine_mask;
 
        gvt_dbg_core("------------------------------------------\n");
        gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n",
                     vgpu->id, dmlr, engine_mask);
-       vgpu->resetting = true;
+
+       vgpu->resetting_eng = resetting_eng;
 
        intel_vgpu_stop_schedule(vgpu);
        /*
@@ -497,7 +499,7 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
                mutex_lock(&gvt->lock);
        }
 
-       intel_vgpu_reset_execlist(vgpu, dmlr ? ALL_ENGINES : engine_mask);
+       intel_vgpu_reset_execlist(vgpu, resetting_eng);
 
        /* full GPU reset or device model level reset */
        if (engine_mask == ALL_ENGINES || dmlr) {
@@ -520,7 +522,7 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
                }
        }
 
-       vgpu->resetting = false;
+       vgpu->resetting_eng = 0;
        gvt_dbg_core("reset vgpu%d done\n", vgpu->id);
        gvt_dbg_core("------------------------------------------\n");
 }
index 1032f98add112a66a19fb186a2b28de773caadf8..77fb3980813143d2d9e3432c0ebb994a4bcad032 100644 (file)
@@ -43,16 +43,21 @@ static bool shrinker_lock(struct drm_i915_private *dev_priv, bool *unlock)
                return true;
 
        case MUTEX_TRYLOCK_FAILED:
+               *unlock = false;
+               preempt_disable();
                do {
                        cpu_relax();
                        if (mutex_trylock(&dev_priv->drm.struct_mutex)) {
-       case MUTEX_TRYLOCK_SUCCESS:
                                *unlock = true;
-                               return true;
+                               break;
                        }
                } while (!need_resched());
+               preempt_enable();
+               return *unlock;
 
-               return false;
+       case MUTEX_TRYLOCK_SUCCESS:
+               *unlock = true;
+               return true;
        }
 
        BUG();
index 9cd22f83b0cfaee680ed06c5bde67db6fc89d0fa..f33d90226704108e71ee5662e01977e32b627fcb 100644 (file)
@@ -1601,11 +1601,11 @@ static int gen8_emit_oa_config(struct drm_i915_gem_request *req)
        u32 *cs;
        int i;
 
-       cs = intel_ring_begin(req, n_flex_regs * 2 + 4);
+       cs = intel_ring_begin(req, ARRAY_SIZE(flex_mmio) * 2 + 4);
        if (IS_ERR(cs))
                return PTR_ERR(cs);
 
-       *cs++ = MI_LOAD_REGISTER_IMM(n_flex_regs + 1);
+       *cs++ = MI_LOAD_REGISTER_IMM(ARRAY_SIZE(flex_mmio) + 1);
 
        *cs++ = i915_mmio_reg_offset(GEN8_OACTXCONTROL);
        *cs++ = (dev_priv->perf.oa.period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
index 306c6b06b330bfc57f75a992c60468cb9d88e81c..17c4ae7e4e7c51e85de97cb8c803b280115de8cf 100644 (file)
@@ -398,6 +398,7 @@ static void bdw_load_gamma_lut(struct drm_crtc_state *state, u32 offset)
                }
 
                /* Program the max register to clamp values > 1.0. */
+               i = lut_size - 1;
                I915_WRITE(PREC_PAL_GC_MAX(pipe, 0),
                           drm_color_lut_extract(lut[i].red, 16));
                I915_WRITE(PREC_PAL_GC_MAX(pipe, 1),
index 96c2cbd81869e7e55dedc8ce09f53938466bee70..593349be8b9dfce328d20ea3ca5d1b22e41da320 100644 (file)
@@ -469,7 +469,7 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector,
 
        if (i915.invert_brightness > 0 ||
            dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
-               return panel->backlight.max - val;
+               return panel->backlight.max - val + panel->backlight.min;
        }
 
        return val;