Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next-queued
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 2 Jun 2016 07:54:12 +0000 (09:54 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 2 Jun 2016 07:54:12 +0000 (09:54 +0200)
Git got absolutely destroyed with all our cherry-picking from
drm-intel-next-queued to various branches. It ended up inserting
intel_crtc_page_flip 2x even in intel_display.c.

Backmerge to get back to sanity.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
40 files changed:
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_guc_submission.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/i915_params.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_sysfs.c
drivers/gpu/drm/i915/i915_trace.h
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_dpll_mgr.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_fbdev.c
drivers/gpu/drm/i915/intel_guc.h
drivers/gpu/drm/i915/intel_guc_fwif.h
drivers/gpu/drm/i915/intel_guc_loader.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_lrc.h
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_opregion.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/i915/intel_uncore.c

index 0a4bedb..e4f2c55 100644 (file)
@@ -199,13 +199,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
                seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits);
 }
 
-static void describe_ctx(struct seq_file *m, struct intel_context *ctx)
-{
-       seq_putc(m, ctx->legacy_hw_ctx.initialized ? 'I' : 'i');
-       seq_putc(m, ctx->remap_slice ? 'R' : 'r');
-       seq_putc(m, ' ');
-}
-
 static int i915_gem_object_list_info(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = m->private;
@@ -424,6 +417,42 @@ static void print_batch_pool_stats(struct seq_file *m,
        print_file_stats(m, "[k]batch pool", stats);
 }
 
+static int per_file_ctx_stats(int id, void *ptr, void *data)
+{
+       struct i915_gem_context *ctx = ptr;
+       int n;
+
+       for (n = 0; n < ARRAY_SIZE(ctx->engine); n++) {
+               if (ctx->engine[n].state)
+                       per_file_stats(0, ctx->engine[n].state, data);
+               if (ctx->engine[n].ringbuf)
+                       per_file_stats(0, ctx->engine[n].ringbuf->obj, data);
+       }
+
+       return 0;
+}
+
+static void print_context_stats(struct seq_file *m,
+                               struct drm_i915_private *dev_priv)
+{
+       struct file_stats stats;
+       struct drm_file *file;
+
+       memset(&stats, 0, sizeof(stats));
+
+       mutex_lock(&dev_priv->dev->struct_mutex);
+       if (dev_priv->kernel_context)
+               per_file_ctx_stats(0, dev_priv->kernel_context, &stats);
+
+       list_for_each_entry(file, &dev_priv->dev->filelist, lhead) {
+               struct drm_i915_file_private *fpriv = file->driver_priv;
+               idr_for_each(&fpriv->context_idr, per_file_ctx_stats, &stats);
+       }
+       mutex_unlock(&dev_priv->dev->struct_mutex);
+
+       print_file_stats(m, "[k]contexts", stats);
+}
+
 #define count_vmas(list, member) do { \
        list_for_each_entry(vma, list, member) { \
                size += i915_gem_obj_total_ggtt_size(vma->obj); \
@@ -528,10 +557,10 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 
        seq_putc(m, '\n');
        print_batch_pool_stats(m, dev_priv);
-
        mutex_unlock(&dev->struct_mutex);
 
        mutex_lock(&dev->filelist_mutex);
+       print_context_stats(m, dev_priv);
        list_for_each_entry_reverse(file, &dev->filelist, lhead) {
                struct file_stats stats;
                struct task_struct *task;
@@ -1279,6 +1308,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
                }
                seq_printf(m, "PM IER=0x%08x IMR=0x%08x ISR=0x%08x IIR=0x%08x, MASK=0x%08x\n",
                           pm_ier, pm_imr, pm_isr, pm_iir, pm_mask);
+               seq_printf(m, "pm_intr_keep: 0x%08x\n", dev_priv->rps.pm_intr_keep);
                seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
                seq_printf(m, "Render p-state ratio: %d\n",
                           (gt_perf_status & (IS_GEN9(dev) ? 0x1ff00 : 0xff00)) >> 8);
@@ -1989,8 +2019,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *engine;
-       struct intel_context *ctx;
-       enum intel_engine_id id;
+       struct i915_gem_context *ctx;
        int ret;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1998,32 +2027,36 @@ static int i915_context_status(struct seq_file *m, void *unused)
                return ret;
 
        list_for_each_entry(ctx, &dev_priv->context_list, link) {
-               if (!i915.enable_execlists &&
-                   ctx->legacy_hw_ctx.rcs_state == NULL)
-                       continue;
-
                seq_printf(m, "HW context %u ", ctx->hw_id);
-               describe_ctx(m, ctx);
-               if (ctx == dev_priv->kernel_context)
-                       seq_printf(m, "(kernel context) ");
+               if (IS_ERR(ctx->file_priv)) {
+                       seq_puts(m, "(deleted) ");
+               } else if (ctx->file_priv) {
+                       struct pid *pid = ctx->file_priv->file->pid;
+                       struct task_struct *task;
 
-               if (i915.enable_execlists) {
-                       seq_putc(m, '\n');
-                       for_each_engine_id(engine, dev_priv, id) {
-                               struct drm_i915_gem_object *ctx_obj =
-                                       ctx->engine[id].state;
-                               struct intel_ringbuffer *ringbuf =
-                                       ctx->engine[id].ringbuf;
-
-                               seq_printf(m, "%s: ", engine->name);
-                               if (ctx_obj)
-                                       describe_obj(m, ctx_obj);
-                               if (ringbuf)
-                                       describe_ctx_ringbuf(m, ringbuf);
-                               seq_putc(m, '\n');
+                       task = get_pid_task(pid, PIDTYPE_PID);
+                       if (task) {
+                               seq_printf(m, "(%s [%d]) ",
+                                          task->comm, task->pid);
+                               put_task_struct(task);
                        }
                } else {
-                       describe_obj(m, ctx->legacy_hw_ctx.rcs_state);
+                       seq_puts(m, "(kernel) ");
+               }
+
+               seq_putc(m, ctx->remap_slice ? 'R' : 'r');
+               seq_putc(m, '\n');
+
+               for_each_engine(engine, dev_priv) {
+                       struct intel_context *ce = &ctx->engine[engine->id];
+
+                       seq_printf(m, "%s: ", engine->name);
+                       seq_putc(m, ce->initialised ? 'I' : 'i');
+                       if (ce->state)
+                               describe_obj(m, ce->state);
+                       if (ce->ringbuf)
+                               describe_ctx_ringbuf(m, ce->ringbuf);
+                       seq_putc(m, '\n');
                }
 
                seq_putc(m, '\n');
@@ -2035,13 +2068,13 @@ static int i915_context_status(struct seq_file *m, void *unused)
 }
 
 static void i915_dump_lrc_obj(struct seq_file *m,
-                             struct intel_context *ctx,
+                             struct i915_gem_context *ctx,
                              struct intel_engine_cs *engine)
 {
+       struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
        struct page *page;
        uint32_t *reg_state;
        int j;
-       struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
        unsigned long ggtt_offset = 0;
 
        seq_printf(m, "CONTEXT: %s %u\n", engine->name, ctx->hw_id);
@@ -2083,7 +2116,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *engine;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        int ret;
 
        if (!i915.enable_execlists) {
@@ -2263,7 +2296,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 
 static int per_file_ctx(int id, void *ptr, void *data)
 {
-       struct intel_context *ctx = ptr;
+       struct i915_gem_context *ctx = ptr;
        struct seq_file *m = data;
        struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
 
@@ -2504,6 +2537,7 @@ static void i915_guc_client_info(struct seq_file *m,
        seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n",
                client->wq_size, client->wq_offset, client->wq_tail);
 
+       seq_printf(m, "\tWork queue full: %u\n", client->no_wq_space);
        seq_printf(m, "\tFailed to queue: %u\n", client->q_fail);
        seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
        seq_printf(m, "\tLast submission result: %d\n", client->retcode);
index fd06bff..07edaed 100644 (file)
@@ -507,7 +507,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
         * working irqs for e.g. gmbus and dp aux transfers. */
        intel_modeset_init(dev);
 
-       intel_guc_ucode_init(dev);
+       intel_guc_init(dev);
 
        ret = i915_gem_init(dev);
        if (ret)
@@ -544,7 +544,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
 cleanup_gem:
        i915_gem_fini(dev);
 cleanup_irq:
-       intel_guc_ucode_fini(dev);
+       intel_guc_fini(dev);
        drm_irq_uninstall(dev);
        intel_teardown_gmbus(dev);
 cleanup_csr:
@@ -1307,7 +1307,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
 
        intel_uncore_sanitize(dev_priv);
 
-       intel_opregion_setup(dev);
+       intel_opregion_setup(dev_priv);
 
        i915_gem_load_init_fences(dev_priv);
 
@@ -1376,7 +1376,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
 
        if (INTEL_INFO(dev_priv)->num_pipes) {
                /* Must be done after probing outputs */
-               intel_opregion_init(dev);
+               intel_opregion_register(dev_priv);
                acpi_video_register();
        }
 
@@ -1395,7 +1395,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
        i915_audio_component_cleanup(dev_priv);
        intel_gpu_ips_teardown();
        acpi_video_unregister();
-       intel_opregion_fini(dev_priv->dev);
+       intel_opregion_unregister(dev_priv);
        i915_teardown_sysfs(dev_priv->dev);
        i915_gem_shrinker_cleanup(dev_priv);
 }
@@ -1527,7 +1527,7 @@ int i915_driver_unload(struct drm_device *dev)
        /* Flush any outstanding unpin_work. */
        flush_workqueue(dev_priv->wq);
 
-       intel_guc_ucode_fini(dev);
+       intel_guc_fini(dev);
        i915_gem_fini(dev);
        intel_fbc_cleanup_cfb(dev_priv);
 
index 61bf5a9..872c606 100644 (file)
@@ -626,10 +626,10 @@ static int i915_drm_suspend(struct drm_device *dev)
        i915_save_state(dev);
 
        opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
-       intel_opregion_notify_adapter(dev, opregion_target_state);
+       intel_opregion_notify_adapter(dev_priv, opregion_target_state);
 
        intel_uncore_forcewake_reset(dev_priv, false);
-       intel_opregion_fini(dev);
+       intel_opregion_unregister(dev_priv);
 
        intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
 
@@ -747,7 +747,7 @@ static int i915_drm_resume(struct drm_device *dev)
        mutex_unlock(&dev->struct_mutex);
 
        i915_restore_state(dev);
-       intel_opregion_setup(dev);
+       intel_opregion_setup(dev_priv);
 
        intel_init_pch_refclk(dev);
        drm_mode_config_reset(dev);
@@ -792,7 +792,7 @@ static int i915_drm_resume(struct drm_device *dev)
        /* Config may have changed between suspend and resume */
        drm_helper_hpd_irq_event(dev);
 
-       intel_opregion_init(dev);
+       intel_opregion_register(dev_priv);
 
        intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
 
@@ -800,7 +800,7 @@ static int i915_drm_resume(struct drm_device *dev)
        dev_priv->modeset_restore = MODESET_DONE;
        mutex_unlock(&dev_priv->modeset_restore_lock);
 
-       intel_opregion_notify_adapter(dev, PCI_D0);
+       intel_opregion_notify_adapter(dev_priv, PCI_D0);
 
        drm_kms_helper_poll_enable(dev);
 
@@ -1588,14 +1588,14 @@ static int intel_runtime_suspend(struct device *device)
         * FIXME: We really should find a document that references the arguments
         * used below!
         */
-       if (IS_BROADWELL(dev)) {
+       if (IS_BROADWELL(dev_priv)) {
                /*
                 * On Broadwell, if we use PCI_D1 the PCH DDI ports will stop
                 * being detected, and the call we do at intel_runtime_resume()
                 * won't be able to restore them. Since PCI_D3hot matches the
                 * actual specification and appears to be working, use it.
                 */
-               intel_opregion_notify_adapter(dev, PCI_D3hot);
+               intel_opregion_notify_adapter(dev_priv, PCI_D3hot);
        } else {
                /*
                 * current versions of firmware which depend on this opregion
@@ -1604,7 +1604,7 @@ static int intel_runtime_suspend(struct device *device)
                 * to distinguish it from notifications that might be sent via
                 * the suspend path.
                 */
-               intel_opregion_notify_adapter(dev, PCI_D1);
+               intel_opregion_notify_adapter(dev_priv, PCI_D1);
        }
 
        assert_forcewakes_inactive(dev_priv);
@@ -1628,7 +1628,7 @@ static int intel_runtime_resume(struct device *device)
        WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
        disable_rpm_wakeref_asserts(dev_priv);
 
-       intel_opregion_notify_adapter(dev, PCI_D0);
+       intel_opregion_notify_adapter(dev_priv, PCI_D0);
        dev_priv->pm.suspended = false;
        if (intel_uncore_unclaimed_mmio(dev_priv))
                DRM_DEBUG_DRIVER("Unclaimed access during suspend, bios?\n");
index b4ea941..96d5034 100644 (file)
@@ -834,9 +834,8 @@ struct i915_ctx_hang_stats {
 /* This must match up with the value previously used for execbuf2.rsvd1. */
 #define DEFAULT_CONTEXT_HANDLE 0
 
-#define CONTEXT_NO_ZEROMAP (1<<0)
 /**
- * struct intel_context - as the name implies, represents a context.
+ * struct i915_gem_context - as the name implies, represents a context.
  * @ref: reference count.
  * @user_handle: userspace tracking identity for this context.
  * @remap_slice: l3 row remapping information.
@@ -854,37 +853,33 @@ struct i915_ctx_hang_stats {
  * Contexts are memory images used by the hardware to store copies of their
  * internal state.
  */
-struct intel_context {
+struct i915_gem_context {
        struct kref ref;
-       int user_handle;
-       uint8_t remap_slice;
        struct drm_i915_private *i915;
-       int flags;
        struct drm_i915_file_private *file_priv;
-       struct i915_ctx_hang_stats hang_stats;
        struct i915_hw_ppgtt *ppgtt;
 
+       struct i915_ctx_hang_stats hang_stats;
+
        /* Unique identifier for this context, used by the hw for tracking */
+       unsigned long flags;
        unsigned hw_id;
+       u32 user_handle;
+#define CONTEXT_NO_ZEROMAP             (1<<0)
 
-       /* Legacy ring buffer submission */
-       struct {
-               struct drm_i915_gem_object *rcs_state;
-               bool initialized;
-       } legacy_hw_ctx;
-
-       /* Execlists */
-       struct {
+       struct intel_context {
                struct drm_i915_gem_object *state;
                struct intel_ringbuffer *ringbuf;
-               int pin_count;
                struct i915_vma *lrc_vma;
-               u64 lrc_desc;
                uint32_t *lrc_reg_state;
+               u64 lrc_desc;
+               int pin_count;
                bool initialised;
        } engine[I915_NUM_ENGINES];
 
        struct list_head link;
+
+       u8 remap_slice;
 };
 
 enum fb_op_origin {
@@ -1132,6 +1127,8 @@ struct intel_gen6_power_mgmt {
        bool interrupts_enabled;
        u32 pm_iir;
 
+       u32 pm_intr_keep;
+
        /* Frequencies are stored in potentially platform dependent multiples.
         * In other words, *_freq needs to be multiplied by X to be interesting.
         * Soft limits are those which are used for the dynamic reclocking done
@@ -1715,7 +1712,7 @@ struct i915_execbuffer_params {
        uint64_t                        batch_obj_vm_offset;
        struct intel_engine_cs *engine;
        struct drm_i915_gem_object      *batch_obj;
-       struct intel_context            *ctx;
+       struct i915_gem_context            *ctx;
        struct drm_i915_gem_request     *request;
 };
 
@@ -1765,6 +1762,7 @@ struct drm_i915_private {
        wait_queue_head_t gmbus_wait_queue;
 
        struct pci_dev *bridge_dev;
+       struct i915_gem_context *kernel_context;
        struct intel_engine_cs engine[I915_NUM_ENGINES];
        struct drm_i915_gem_object *semaphore_obj;
        uint32_t last_seqno, next_seqno;
@@ -1820,13 +1818,17 @@ struct drm_i915_private {
        int num_fence_regs; /* 8 on pre-965, 16 otherwise */
 
        unsigned int fsb_freq, mem_freq, is_ddr3;
-       unsigned int skl_boot_cdclk;
+       unsigned int skl_preferred_vco_freq;
        unsigned int cdclk_freq, max_cdclk_freq, atomic_cdclk_freq;
        unsigned int max_dotclk_freq;
        unsigned int rawclk_freq;
        unsigned int hpll_freq;
        unsigned int czclk_freq;
 
+       struct {
+               unsigned int vco, ref;
+       } cdclk_pll;
+
        /**
         * wq - Driver workqueue for GEM.
         *
@@ -2018,8 +2020,6 @@ struct drm_i915_private {
                void (*stop_engine)(struct intel_engine_cs *engine);
        } gt;
 
-       struct intel_context *kernel_context;
-
        /* perform PHY state sanity checks? */
        bool chv_phy_assert[2];
 
@@ -2386,7 +2386,7 @@ struct drm_i915_gem_request {
         * i915_gem_request_free() will then decrement the refcount on the
         * context.
         */
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        struct intel_ringbuffer *ringbuf;
 
        /**
@@ -2398,7 +2398,7 @@ struct drm_i915_gem_request {
         * we keep the previous context pinned until the following (this)
         * request is retired.
         */
-       struct intel_context *previous_context;
+       struct i915_gem_context *previous_context;
 
        /** Batch buffer related to this request if any (used for
            error state dump only) */
@@ -2442,7 +2442,7 @@ struct drm_i915_gem_request {
 
 struct drm_i915_gem_request * __must_check
 i915_gem_request_alloc(struct intel_engine_cs *engine,
-                      struct intel_context *ctx);
+                      struct i915_gem_context *ctx);
 void i915_gem_request_free(struct kref *req_ref);
 int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
                                   struct drm_file *file);
@@ -2807,8 +2807,14 @@ struct drm_i915_cmd_table {
 
 #define HAS_CSR(dev)   (IS_GEN9(dev))
 
-#define HAS_GUC_UCODE(dev)     (IS_GEN9(dev) && !IS_KABYLAKE(dev))
-#define HAS_GUC_SCHED(dev)     (IS_GEN9(dev) && !IS_KABYLAKE(dev))
+/*
+ * For now, anything with a GuC requires uCode loading, and then supports
+ * command submission once loaded. But these are logically independent
+ * properties, so we have separate macros to test them.
+ */
+#define HAS_GUC(dev)           (IS_GEN9(dev) && !IS_KABYLAKE(dev))
+#define HAS_GUC_UCODE(dev)     (HAS_GUC(dev))
+#define HAS_GUC_SCHED(dev)     (HAS_GUC(dev))
 
 #define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
                                    INTEL_INFO(dev)->gen >= 8)
@@ -3422,22 +3428,36 @@ void i915_gem_context_reset(struct drm_device *dev);
 int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
 int i915_switch_context(struct drm_i915_gem_request *req);
-struct intel_context *
-i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
 void i915_gem_context_free(struct kref *ctx_ref);
 struct drm_i915_gem_object *
 i915_gem_alloc_context_obj(struct drm_device *dev, size_t size);
-static inline void i915_gem_context_reference(struct intel_context *ctx)
+
+static inline struct i915_gem_context *
+i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
+{
+       struct i915_gem_context *ctx;
+
+       lockdep_assert_held(&file_priv->dev_priv->dev->struct_mutex);
+
+       ctx = idr_find(&file_priv->context_idr, id);
+       if (!ctx)
+               return ERR_PTR(-ENOENT);
+
+       return ctx;
+}
+
+static inline void i915_gem_context_reference(struct i915_gem_context *ctx)
 {
        kref_get(&ctx->ref);
 }
 
-static inline void i915_gem_context_unreference(struct intel_context *ctx)
+static inline void i915_gem_context_unreference(struct i915_gem_context *ctx)
 {
+       lockdep_assert_held(&ctx->i915->dev->struct_mutex);
        kref_put(&ctx->ref, i915_gem_context_free);
 }
 
-static inline bool i915_gem_context_is_default(const struct intel_context *c)
+static inline bool i915_gem_context_is_default(const struct i915_gem_context *c)
 {
        return c->user_handle == DEFAULT_CONTEXT_HANDLE;
 }
@@ -3607,19 +3627,19 @@ bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
 
 /* intel_opregion.c */
 #ifdef CONFIG_ACPI
-extern int intel_opregion_setup(struct drm_device *dev);
-extern void intel_opregion_init(struct drm_device *dev);
-extern void intel_opregion_fini(struct drm_device *dev);
+extern int intel_opregion_setup(struct drm_i915_private *dev_priv);
+extern void intel_opregion_register(struct drm_i915_private *dev_priv);
+extern void intel_opregion_unregister(struct drm_i915_private *dev_priv);
 extern void intel_opregion_asle_intr(struct drm_i915_private *dev_priv);
 extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
                                         bool enable);
-extern int intel_opregion_notify_adapter(struct drm_device *dev,
+extern int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
                                         pci_power_t state);
-extern int intel_opregion_get_panel_type(struct drm_device *dev);
+extern int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv);
 #else
-static inline int intel_opregion_setup(struct drm_device *dev) { return 0; }
-static inline void intel_opregion_init(struct drm_device *dev) { return; }
-static inline void intel_opregion_fini(struct drm_device *dev) { return; }
+static inline int intel_opregion_setup(struct drm_i915_private *dev) { return 0; }
+static inline void intel_opregion_init(struct drm_i915_private *dev) { }
+static inline void intel_opregion_fini(struct drm_i915_private *dev) { }
 static inline void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
 {
 }
@@ -3629,11 +3649,11 @@ intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, bool enable)
        return 0;
 }
 static inline int
-intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
+intel_opregion_notify_adapter(struct drm_i915_private *dev, pci_power_t state)
 {
        return 0;
 }
-static inline int intel_opregion_get_panel_type(struct drm_device *dev)
+static inline int intel_opregion_get_panel_type(struct drm_i915_private *dev)
 {
        return -ENODEV;
 }
index 12407bc..343d881 100644 (file)
@@ -2692,7 +2692,7 @@ void __i915_add_request(struct drm_i915_gem_request *request,
 }
 
 static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
-                                  const struct intel_context *ctx)
+                                  const struct i915_gem_context *ctx)
 {
        unsigned long elapsed;
 
@@ -2717,7 +2717,7 @@ static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
 }
 
 static void i915_set_reset_status(struct drm_i915_private *dev_priv,
-                                 struct intel_context *ctx,
+                                 struct i915_gem_context *ctx,
                                  const bool guilty)
 {
        struct i915_ctx_hang_stats *hs;
@@ -2745,7 +2745,7 @@ void i915_gem_request_free(struct kref *req_ref)
 
 static inline int
 __i915_gem_request_alloc(struct intel_engine_cs *engine,
-                        struct intel_context *ctx,
+                        struct i915_gem_context *ctx,
                         struct drm_i915_gem_request **req_out)
 {
        struct drm_i915_private *dev_priv = engine->i915;
@@ -2821,7 +2821,7 @@ err:
  */
 struct drm_i915_gem_request *
 i915_gem_request_alloc(struct intel_engine_cs *engine,
-                      struct intel_context *ctx)
+                      struct i915_gem_context *ctx)
 {
        struct drm_i915_gem_request *req;
        int err;
@@ -4886,13 +4886,10 @@ i915_gem_init_hw(struct drm_device *dev)
        intel_mocs_init_l3cc_table(dev);
 
        /* We can't enable contexts until all firmware is loaded */
-       if (HAS_GUC_UCODE(dev)) {
-               ret = intel_guc_ucode_load(dev);
-               if (ret) {
-                       DRM_ERROR("Failed to initialize GuC, error %d\n", ret);
-                       ret = -EIO;
+       if (HAS_GUC(dev)) {
+               ret = intel_guc_setup(dev);
+               if (ret)
                        goto out;
-               }
        }
 
        /*
index 2aedd18..a3b11aa 100644 (file)
@@ -134,7 +134,7 @@ static int get_context_size(struct drm_i915_private *dev_priv)
        return ret;
 }
 
-static void i915_gem_context_clean(struct intel_context *ctx)
+static void i915_gem_context_clean(struct i915_gem_context *ctx)
 {
        struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
        struct i915_vma *vma, *next;
@@ -151,13 +151,12 @@ static void i915_gem_context_clean(struct intel_context *ctx)
 
 void i915_gem_context_free(struct kref *ctx_ref)
 {
-       struct intel_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
+       struct i915_gem_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
+       int i;
 
+       lockdep_assert_held(&ctx->i915->dev->struct_mutex);
        trace_i915_context_free(ctx);
 
-       if (i915.enable_execlists)
-               intel_lr_context_free(ctx);
-
        /*
         * This context is going away and we need to remove all VMAs still
         * around. This is to handle imported shared objects for which
@@ -167,8 +166,19 @@ void i915_gem_context_free(struct kref *ctx_ref)
 
        i915_ppgtt_put(ctx->ppgtt);
 
-       if (ctx->legacy_hw_ctx.rcs_state)
-               drm_gem_object_unreference(&ctx->legacy_hw_ctx.rcs_state->base);
+       for (i = 0; i < I915_NUM_ENGINES; i++) {
+               struct intel_context *ce = &ctx->engine[i];
+
+               if (!ce->state)
+                       continue;
+
+               WARN_ON(ce->pin_count);
+               if (ce->ringbuf)
+                       intel_ringbuffer_free(ce->ringbuf);
+
+               drm_gem_object_unreference(&ce->state->base);
+       }
+
        list_del(&ctx->link);
 
        ida_simple_remove(&ctx->i915->context_hw_ida, ctx->hw_id);
@@ -181,6 +191,8 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
        struct drm_i915_gem_object *obj;
        int ret;
 
+       lockdep_assert_held(&dev->struct_mutex);
+
        obj = i915_gem_object_create(dev, size);
        if (IS_ERR(obj))
                return obj;
@@ -234,12 +246,12 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out)
        return 0;
 }
 
-static struct intel_context *
+static struct i915_gem_context *
 __create_hw_context(struct drm_device *dev,
                    struct drm_i915_file_private *file_priv)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        int ret;
 
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -263,7 +275,7 @@ __create_hw_context(struct drm_device *dev,
                        ret = PTR_ERR(obj);
                        goto err_out;
                }
-               ctx->legacy_hw_ctx.rcs_state = obj;
+               ctx->engine[RCS].state = obj;
        }
 
        /* Default context will never have a file_priv */
@@ -296,44 +308,27 @@ err_out:
  * context state of the GPU for applications that don't utilize HW contexts, as
  * well as an idle case.
  */
-static struct intel_context *
+static struct i915_gem_context *
 i915_gem_create_context(struct drm_device *dev,
                        struct drm_i915_file_private *file_priv)
 {
-       const bool is_global_default_ctx = file_priv == NULL;
-       struct intel_context *ctx;
-       int ret = 0;
+       struct i915_gem_context *ctx;
 
-       BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+       lockdep_assert_held(&dev->struct_mutex);
 
        ctx = __create_hw_context(dev, file_priv);
        if (IS_ERR(ctx))
                return ctx;
 
-       if (is_global_default_ctx && ctx->legacy_hw_ctx.rcs_state) {
-               /* We may need to do things with the shrinker which
-                * require us to immediately switch back to the default
-                * context. This can cause a problem as pinning the
-                * default context also requires GTT space which may not
-                * be available. To avoid this we always pin the default
-                * context.
-                */
-               ret = i915_gem_obj_ggtt_pin(ctx->legacy_hw_ctx.rcs_state,
-                                           get_context_alignment(to_i915(dev)), 0);
-               if (ret) {
-                       DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
-                       goto err_destroy;
-               }
-       }
-
        if (USES_FULL_PPGTT(dev)) {
                struct i915_hw_ppgtt *ppgtt = i915_ppgtt_create(dev, file_priv);
 
-               if (IS_ERR_OR_NULL(ppgtt)) {
+               if (IS_ERR(ppgtt)) {
                        DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
                                         PTR_ERR(ppgtt));
-                       ret = PTR_ERR(ppgtt);
-                       goto err_unpin;
+                       idr_remove(&file_priv->context_idr, ctx->user_handle);
+                       i915_gem_context_unreference(ctx);
+                       return ERR_CAST(ppgtt);
                }
 
                ctx->ppgtt = ppgtt;
@@ -342,24 +337,19 @@ i915_gem_create_context(struct drm_device *dev,
        trace_i915_context_create(ctx);
 
        return ctx;
-
-err_unpin:
-       if (is_global_default_ctx && ctx->legacy_hw_ctx.rcs_state)
-               i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state);
-err_destroy:
-       idr_remove(&file_priv->context_idr, ctx->user_handle);
-       i915_gem_context_unreference(ctx);
-       return ERR_PTR(ret);
 }
 
-static void i915_gem_context_unpin(struct intel_context *ctx,
+static void i915_gem_context_unpin(struct i915_gem_context *ctx,
                                   struct intel_engine_cs *engine)
 {
        if (i915.enable_execlists) {
                intel_lr_context_unpin(ctx, engine);
        } else {
-               if (engine->id == RCS && ctx->legacy_hw_ctx.rcs_state)
-                       i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state);
+               struct intel_context *ce = &ctx->engine[engine->id];
+
+               if (ce->state)
+                       i915_gem_object_ggtt_unpin(ce->state);
+
                i915_gem_context_unreference(ctx);
        }
 }
@@ -368,8 +358,10 @@ void i915_gem_context_reset(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       lockdep_assert_held(&dev->struct_mutex);
+
        if (i915.enable_execlists) {
-               struct intel_context *ctx;
+               struct i915_gem_context *ctx;
 
                list_for_each_entry(ctx, &dev_priv->context_list, link)
                        intel_lr_context_reset(dev_priv, ctx);
@@ -381,7 +373,7 @@ void i915_gem_context_reset(struct drm_device *dev)
 int i915_gem_context_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
 
        /* Init should only be called once per module load. Eventually the
         * restriction on the context_disabled check can be loosened. */
@@ -421,6 +413,26 @@ int i915_gem_context_init(struct drm_device *dev)
                return PTR_ERR(ctx);
        }
 
+       if (!i915.enable_execlists && ctx->engine[RCS].state) {
+               int ret;
+
+               /* We may need to do things with the shrinker which
+                * require us to immediately switch back to the default
+                * context. This can cause a problem as pinning the
+                * default context also requires GTT space which may not
+                * be available. To avoid this we always pin the default
+                * context.
+                */
+               ret = i915_gem_obj_ggtt_pin(ctx->engine[RCS].state,
+                                           get_context_alignment(dev_priv), 0);
+               if (ret) {
+                       DRM_ERROR("Failed to pinned default global context (error %d)\n",
+                                 ret);
+                       i915_gem_context_unreference(ctx);
+                       return ret;
+               }
+       }
+
        dev_priv->kernel_context = ctx;
 
        DRM_DEBUG_DRIVER("%s context support initialized\n",
@@ -433,26 +445,32 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv)
 {
        struct intel_engine_cs *engine;
 
+       lockdep_assert_held(&dev_priv->dev->struct_mutex);
+
        for_each_engine(engine, dev_priv) {
-               if (engine->last_context == NULL)
-                       continue;
+               if (engine->last_context) {
+                       i915_gem_context_unpin(engine->last_context, engine);
+                       engine->last_context = NULL;
+               }
 
-               i915_gem_context_unpin(engine->last_context, engine);
-               engine->last_context = NULL;
+               /* Force the GPU state to be reinitialised on enabling */
+               dev_priv->kernel_context->engine[engine->id].initialised =
+                       engine->init_context == NULL;
        }
 
        /* Force the GPU state to be reinitialised on enabling */
-       dev_priv->kernel_context->legacy_hw_ctx.initialized = false;
        dev_priv->kernel_context->remap_slice = ALL_L3_SLICES(dev_priv);
 }
 
 void i915_gem_context_fini(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_context *dctx = dev_priv->kernel_context;
+       struct i915_gem_context *dctx = dev_priv->kernel_context;
+
+       lockdep_assert_held(&dev->struct_mutex);
 
-       if (dctx->legacy_hw_ctx.rcs_state)
-               i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state);
+       if (!i915.enable_execlists && dctx->engine[RCS].state)
+               i915_gem_object_ggtt_unpin(dctx->engine[RCS].state);
 
        i915_gem_context_unreference(dctx);
        dev_priv->kernel_context = NULL;
@@ -462,8 +480,9 @@ void i915_gem_context_fini(struct drm_device *dev)
 
 static int context_idr_cleanup(int id, void *p, void *data)
 {
-       struct intel_context *ctx = p;
+       struct i915_gem_context *ctx = p;
 
+       ctx->file_priv = ERR_PTR(-EBADF);
        i915_gem_context_unreference(ctx);
        return 0;
 }
@@ -471,7 +490,7 @@ static int context_idr_cleanup(int id, void *p, void *data)
 int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
 
        idr_init(&file_priv->context_idr);
 
@@ -491,22 +510,12 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
 
+       lockdep_assert_held(&dev->struct_mutex);
+
        idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
        idr_destroy(&file_priv->context_idr);
 }
 
-struct intel_context *
-i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
-{
-       struct intel_context *ctx;
-
-       ctx = (struct intel_context *)idr_find(&file_priv->context_idr, id);
-       if (!ctx)
-               return ERR_PTR(-ENOENT);
-
-       return ctx;
-}
-
 static inline int
 mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
 {
@@ -569,7 +578,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
        intel_ring_emit(engine, MI_NOOP);
        intel_ring_emit(engine, MI_SET_CONTEXT);
        intel_ring_emit(engine,
-                       i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) |
+                       i915_gem_obj_ggtt_offset(req->ctx->engine[RCS].state) |
                        flags);
        /*
         * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
@@ -641,12 +650,12 @@ static int remap_l3(struct drm_i915_gem_request *req, int slice)
 
 static inline bool skip_rcs_switch(struct i915_hw_ppgtt *ppgtt,
                                   struct intel_engine_cs *engine,
-                                  struct intel_context *to)
+                                  struct i915_gem_context *to)
 {
        if (to->remap_slice)
                return false;
 
-       if (!to->legacy_hw_ctx.initialized)
+       if (!to->engine[RCS].initialised)
                return false;
 
        if (ppgtt && (intel_engine_flag(engine) & ppgtt->pd_dirty_rings))
@@ -658,7 +667,7 @@ static inline bool skip_rcs_switch(struct i915_hw_ppgtt *ppgtt,
 static bool
 needs_pd_load_pre(struct i915_hw_ppgtt *ppgtt,
                  struct intel_engine_cs *engine,
-                 struct intel_context *to)
+                 struct i915_gem_context *to)
 {
        if (!ppgtt)
                return false;
@@ -683,7 +692,7 @@ needs_pd_load_pre(struct i915_hw_ppgtt *ppgtt,
 
 static bool
 needs_pd_load_post(struct i915_hw_ppgtt *ppgtt,
-                  struct intel_context *to,
+                  struct i915_gem_context *to,
                   u32 hw_flags)
 {
        if (!ppgtt)
@@ -700,10 +709,10 @@ needs_pd_load_post(struct i915_hw_ppgtt *ppgtt,
 
 static int do_rcs_switch(struct drm_i915_gem_request *req)
 {
-       struct intel_context *to = req->ctx;
+       struct i915_gem_context *to = req->ctx;
        struct intel_engine_cs *engine = req->engine;
        struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt;
-       struct intel_context *from;
+       struct i915_gem_context *from;
        u32 hw_flags;
        int ret, i;
 
@@ -711,7 +720,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
                return 0;
 
        /* Trying to pin first makes error handling easier. */
-       ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
+       ret = i915_gem_obj_ggtt_pin(to->engine[RCS].state,
                                    get_context_alignment(engine->i915),
                                    0);
        if (ret)
@@ -734,7 +743,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
         *
         * XXX: We need a real interface to do this instead of trickery.
         */
-       ret = i915_gem_object_set_to_gtt_domain(to->legacy_hw_ctx.rcs_state, false);
+       ret = i915_gem_object_set_to_gtt_domain(to->engine[RCS].state, false);
        if (ret)
                goto unpin_out;
 
@@ -749,7 +758,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
                        goto unpin_out;
        }
 
-       if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
+       if (!to->engine[RCS].initialised || i915_gem_context_is_default(to))
                /* NB: If we inhibit the restore, the context is not allowed to
                 * die because future work may end up depending on valid address
                 * space. This means we must enforce that a page table load
@@ -773,8 +782,8 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
         * MI_SET_CONTEXT instead of when the next seqno has completed.
         */
        if (from != NULL) {
-               from->legacy_hw_ctx.rcs_state->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
-               i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->legacy_hw_ctx.rcs_state), req);
+               from->engine[RCS].state->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
+               i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->engine[RCS].state), req);
                /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
                 * whole damn pipeline, we don't need to explicitly mark the
                 * object dirty. The only exception is that the context must be
@@ -782,10 +791,10 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
                 * able to defer doing this until we know the object would be
                 * swapped, but there is no way to do that yet.
                 */
-               from->legacy_hw_ctx.rcs_state->dirty = 1;
+               from->engine[RCS].state->dirty = 1;
 
                /* obj is kept alive until the next request by its active ref */
-               i915_gem_object_ggtt_unpin(from->legacy_hw_ctx.rcs_state);
+               i915_gem_object_ggtt_unpin(from->engine[RCS].state);
                i915_gem_context_unreference(from);
        }
        i915_gem_context_reference(to);
@@ -820,19 +829,19 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
                to->remap_slice &= ~(1<<i);
        }
 
-       if (!to->legacy_hw_ctx.initialized) {
+       if (!to->engine[RCS].initialised) {
                if (engine->init_context) {
                        ret = engine->init_context(req);
                        if (ret)
                                return ret;
                }
-               to->legacy_hw_ctx.initialized = true;
+               to->engine[RCS].initialised = true;
        }
 
        return 0;
 
 unpin_out:
-       i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state);
+       i915_gem_object_ggtt_unpin(to->engine[RCS].state);
        return ret;
 }
 
@@ -852,14 +861,12 @@ unpin_out:
 int i915_switch_context(struct drm_i915_gem_request *req)
 {
        struct intel_engine_cs *engine = req->engine;
-       struct drm_i915_private *dev_priv = req->i915;
 
        WARN_ON(i915.enable_execlists);
-       WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+       lockdep_assert_held(&req->i915->dev->struct_mutex);
 
-       if (engine->id != RCS ||
-           req->ctx->legacy_hw_ctx.rcs_state == NULL) {
-               struct intel_context *to = req->ctx;
+       if (!req->ctx->engine[engine->id].state) {
+               struct i915_gem_context *to = req->ctx;
                struct i915_hw_ppgtt *ppgtt =
                        to->ppgtt ?: req->i915->mm.aliasing_ppgtt;
 
@@ -897,7 +904,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 {
        struct drm_i915_gem_context_create *args = data;
        struct drm_i915_file_private *file_priv = file->driver_priv;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        int ret;
 
        if (!contexts_enabled(dev))
@@ -926,7 +933,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
 {
        struct drm_i915_gem_context_destroy *args = data;
        struct drm_i915_file_private *file_priv = file->driver_priv;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        int ret;
 
        if (args->pad != 0)
@@ -939,13 +946,13 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
        if (ret)
                return ret;
 
-       ctx = i915_gem_context_get(file_priv, args->ctx_id);
+       ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
        if (IS_ERR(ctx)) {
                mutex_unlock(&dev->struct_mutex);
                return PTR_ERR(ctx);
        }
 
-       idr_remove(&ctx->file_priv->context_idr, ctx->user_handle);
+       idr_remove(&file_priv->context_idr, ctx->user_handle);
        i915_gem_context_unreference(ctx);
        mutex_unlock(&dev->struct_mutex);
 
@@ -958,14 +965,14 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
        struct drm_i915_gem_context_param *args = data;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        int ret;
 
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                return ret;
 
-       ctx = i915_gem_context_get(file_priv, args->ctx_id);
+       ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
        if (IS_ERR(ctx)) {
                mutex_unlock(&dev->struct_mutex);
                return PTR_ERR(ctx);
@@ -1001,14 +1008,14 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
 {
        struct drm_i915_file_private *file_priv = file->driver_priv;
        struct drm_i915_gem_context_param *args = data;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        int ret;
 
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                return ret;
 
-       ctx = i915_gem_context_get(file_priv, args->ctx_id);
+       ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
        if (IS_ERR(ctx)) {
                mutex_unlock(&dev->struct_mutex);
                return PTR_ERR(ctx);
@@ -1047,7 +1054,7 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_reset_stats *args = data;
        struct i915_ctx_hang_stats *hs;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        int ret;
 
        if (args->flags || args->pad)
@@ -1060,7 +1067,7 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
        if (ret)
                return ret;
 
-       ctx = i915_gem_context_get(file->driver_priv, args->ctx_id);
+       ctx = i915_gem_context_lookup(file->driver_priv, args->ctx_id);
        if (IS_ERR(ctx)) {
                mutex_unlock(&dev->struct_mutex);
                return PTR_ERR(ctx);
index f315e78..8097698 100644 (file)
@@ -714,7 +714,7 @@ eb_vma_misplaced(struct i915_vma *vma)
 static int
 i915_gem_execbuffer_reserve(struct intel_engine_cs *engine,
                            struct list_head *vmas,
-                           struct intel_context *ctx,
+                           struct i915_gem_context *ctx,
                            bool *need_relocs)
 {
        struct drm_i915_gem_object *obj;
@@ -826,7 +826,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
                                  struct intel_engine_cs *engine,
                                  struct eb_vmas *eb,
                                  struct drm_i915_gem_exec_object2 *exec,
-                                 struct intel_context *ctx)
+                                 struct i915_gem_context *ctx)
 {
        struct drm_i915_gem_relocation_entry *reloc;
        struct i915_address_space *vm;
@@ -1063,17 +1063,17 @@ validate_exec_list(struct drm_device *dev,
        return 0;
 }
 
-static struct intel_context *
+static struct i915_gem_context *
 i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
                          struct intel_engine_cs *engine, const u32 ctx_id)
 {
-       struct intel_context *ctx = NULL;
+       struct i915_gem_context *ctx = NULL;
        struct i915_ctx_hang_stats *hs;
 
        if (engine->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE)
                return ERR_PTR(-EINVAL);
 
-       ctx = i915_gem_context_get(file->driver_priv, ctx_id);
+       ctx = i915_gem_context_lookup(file->driver_priv, ctx_id);
        if (IS_ERR(ctx))
                return ctx;
 
@@ -1428,7 +1428,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        struct drm_i915_gem_object *batch_obj;
        struct drm_i915_gem_exec_object2 shadow_exec_entry;
        struct intel_engine_cs *engine;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        struct i915_address_space *vm;
        struct i915_execbuffer_params params_master; /* XXX: will be removed later */
        struct i915_execbuffer_params *params = &params_master;
index 169242a..ac72451 100644 (file)
@@ -360,10 +360,9 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
        struct drm_i915_gem_object *client_obj = client->client_obj;
        struct drm_i915_private *dev_priv = guc_to_i915(guc);
        struct intel_engine_cs *engine;
-       struct intel_context *ctx = client->owner;
+       struct i915_gem_context *ctx = client->owner;
        struct guc_context_desc desc;
        struct sg_table *sg;
-       enum intel_engine_id id;
        u32 gfx_addr;
 
        memset(&desc, 0, sizeof(desc));
@@ -373,10 +372,10 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
        desc.priority = client->priority;
        desc.db_id = client->doorbell_id;
 
-       for_each_engine_id(engine, dev_priv, id) {
+       for_each_engine(engine, dev_priv) {
+               struct intel_context *ce = &ctx->engine[engine->id];
                struct guc_execlist_context *lrc = &desc.lrc[engine->guc_id];
                struct drm_i915_gem_object *obj;
-               uint64_t ctx_desc;
 
                /* TODO: We have a design issue to be solved here. Only when we
                 * receive the first batch, we know which engine is used by the
@@ -385,20 +384,18 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
                 * for now who owns a GuC client. But for future owner of GuC
                 * client, need to make sure lrc is pinned prior to enter here.
                 */
-               obj = ctx->engine[id].state;
-               if (!obj)
+               if (!ce->state)
                        break;  /* XXX: continue? */
 
-               ctx_desc = intel_lr_context_descriptor(ctx, engine);
-               lrc->context_desc = (u32)ctx_desc;
+               lrc->context_desc = lower_32_bits(ce->lrc_desc);
 
                /* The state page is after PPHWSP */
-               gfx_addr = i915_gem_obj_ggtt_offset(obj);
+               gfx_addr = i915_gem_obj_ggtt_offset(ce->state);
                lrc->ring_lcra = gfx_addr + LRC_STATE_PN * PAGE_SIZE;
                lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
                                (engine->guc_id << GUC_ELC_ENGINE_OFFSET);
 
-               obj = ctx->engine[id].ringbuf->obj;
+               obj = ce->ringbuf->obj;
                gfx_addr = i915_gem_obj_ggtt_offset(obj);
 
                lrc->ring_begin = gfx_addr;
@@ -426,7 +423,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
        desc.wq_size = client->wq_size;
 
        /*
-        * XXX: Take LRCs from an existing intel_context if this is not an
+        * XXX: Take LRCs from an existing context if this is not an
         * IsKMDCreatedContext client
         */
        desc.desc_private = (uintptr_t)client;
@@ -450,47 +447,64 @@ static void guc_fini_ctx_desc(struct intel_guc *guc,
                             sizeof(desc) * client->ctx_index);
 }
 
-int i915_guc_wq_check_space(struct i915_guc_client *gc)
+/**
+ * i915_guc_wq_check_space() - check that the GuC can accept a request
+ * @request:   request associated with the commands
+ *
+ * Return:     0 if space is available
+ *             -EAGAIN if space is not currently available
+ *
+ * This function must be called (and must return 0) before a request
+ * is submitted to the GuC via i915_guc_submit() below. Once a result
+ * of 0 has been returned, it remains valid until (but only until)
+ * the next call to submit().
+ *
+ * This precheck allows the caller to determine in advance that space
+ * will be available for the next submission before committing resources
+ * to it, and helps avoid late failures with complicated recovery paths.
+ */
+int i915_guc_wq_check_space(struct drm_i915_gem_request *request)
 {
+       const size_t wqi_size = sizeof(struct guc_wq_item);
+       struct i915_guc_client *gc = request->i915->guc.execbuf_client;
        struct guc_process_desc *desc;
-       u32 size = sizeof(struct guc_wq_item);
-       int ret = -ETIMEDOUT, timeout_counter = 200;
+       u32 freespace;
 
-       if (!gc)
-               return 0;
+       GEM_BUG_ON(gc == NULL);
 
        desc = gc->client_base + gc->proc_desc_offset;
 
-       while (timeout_counter-- > 0) {
-               if (CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size) >= size) {
-                       ret = 0;
-                       break;
-               }
+       freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
+       if (likely(freespace >= wqi_size))
+               return 0;
 
-               if (timeout_counter)
-                       usleep_range(1000, 2000);
-       };
+       gc->no_wq_space += 1;
 
-       return ret;
+       return -EAGAIN;
 }
 
-static int guc_add_workqueue_item(struct i915_guc_client *gc,
-                                 struct drm_i915_gem_request *rq)
+static void guc_add_workqueue_item(struct i915_guc_client *gc,
+                                  struct drm_i915_gem_request *rq)
 {
+       /* wqi_len is in DWords, and does not include the one-word header */
+       const size_t wqi_size = sizeof(struct guc_wq_item);
+       const u32 wqi_len = wqi_size/sizeof(u32) - 1;
        struct guc_process_desc *desc;
        struct guc_wq_item *wqi;
        void *base;
-       u32 tail, wq_len, wq_off, space;
+       u32 freespace, tail, wq_off, wq_page;
 
        desc = gc->client_base + gc->proc_desc_offset;
-       space = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
-       if (WARN_ON(space < sizeof(struct guc_wq_item)))
-               return -ENOSPC; /* shouldn't happen */
 
-       /* postincrement WQ tail for next time */
-       wq_off = gc->wq_tail;
-       gc->wq_tail += sizeof(struct guc_wq_item);
-       gc->wq_tail &= gc->wq_size - 1;
+       /* Free space is guaranteed, see i915_guc_wq_check_space() above */
+       freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
+       GEM_BUG_ON(freespace < wqi_size);
+
+       /* The GuC firmware wants the tail index in QWords, not bytes */
+       tail = rq->tail;
+       GEM_BUG_ON(tail & 7);
+       tail >>= 3;
+       GEM_BUG_ON(tail > WQ_RING_TAIL_MAX);
 
        /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we
         * should not have the case where structure wqi is across page, neither
@@ -499,19 +513,23 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc,
         * XXX: if not the case, we need save data to a temp wqi and copy it to
         * workqueue buffer dw by dw.
         */
-       WARN_ON(sizeof(struct guc_wq_item) != 16);
-       WARN_ON(wq_off & 3);
+       BUILD_BUG_ON(wqi_size != 16);
+
+       /* postincrement WQ tail for next time */
+       wq_off = gc->wq_tail;
+       gc->wq_tail += wqi_size;
+       gc->wq_tail &= gc->wq_size - 1;
+       GEM_BUG_ON(wq_off & (wqi_size - 1));
 
-       /* wq starts from the page after doorbell / process_desc */
-       base = kmap_atomic(i915_gem_object_get_page(gc->client_obj,
-                       (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT));
+       /* WQ starts from the page after doorbell / process_desc */
+       wq_page = (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT;
        wq_off &= PAGE_SIZE - 1;
+       base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, wq_page));
        wqi = (struct guc_wq_item *)((char *)base + wq_off);
 
-       /* len does not include the header */
-       wq_len = sizeof(struct guc_wq_item) / sizeof(u32) - 1;
+       /* Now fill in the 4-word work queue item */
        wqi->header = WQ_TYPE_INORDER |
-                       (wq_len << WQ_LEN_SHIFT) |
+                       (wqi_len << WQ_LEN_SHIFT) |
                        (rq->engine->guc_id << WQ_TARGET_SHIFT) |
                        WQ_NO_WCFLUSH_WAIT;
 
@@ -519,48 +537,50 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc,
        wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx,
                                                             rq->engine);
 
-       /* The GuC firmware wants the tail index in QWords, not bytes */
-       tail = rq->ringbuf->tail >> 3;
        wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT;
-       wqi->fence_id = 0; /*XXX: what fence to be here */
+       wqi->fence_id = rq->seqno;
 
        kunmap_atomic(base);
-
-       return 0;
 }
 
 /**
  * i915_guc_submit() - Submit commands through GuC
- * @client:    the guc client where commands will go through
  * @rq:                request associated with the commands
  *
- * Return:     0 if succeed
+ * Return:     0 on success, otherwise an errno.
+ *             (Note: nonzero really shouldn't happen!)
+ *
+ * The caller must have already called i915_guc_wq_check_space() above
+ * with a result of 0 (success) since the last request submission. This
+ * guarantees that there is space in the work queue for the new request,
+ * so enqueuing the item cannot fail.
+ *
+ * Bad Things Will Happen if the caller violates this protocol e.g. calls
+ * submit() when check() says there's no space, or calls submit() multiple
+ * times with no intervening check().
+ *
+ * The only error here arises if the doorbell hardware isn't functioning
+ * as expected, which really shouln't happen.
  */
-int i915_guc_submit(struct i915_guc_client *client,
-                   struct drm_i915_gem_request *rq)
+int i915_guc_submit(struct drm_i915_gem_request *rq)
 {
-       struct intel_guc *guc = client->guc;
        unsigned int engine_id = rq->engine->guc_id;
-       int q_ret, b_ret;
+       struct intel_guc *guc = &rq->i915->guc;
+       struct i915_guc_client *client = guc->execbuf_client;
+       int b_ret;
 
-       q_ret = guc_add_workqueue_item(client, rq);
-       if (q_ret == 0)
-               b_ret = guc_ring_doorbell(client);
+       guc_add_workqueue_item(client, rq);
+       b_ret = guc_ring_doorbell(client);
 
        client->submissions[engine_id] += 1;
-       if (q_ret) {
-               client->q_fail += 1;
-               client->retcode = q_ret;
-       } else if (b_ret) {
+       client->retcode = b_ret;
+       if (b_ret)
                client->b_fail += 1;
-               client->retcode = q_ret = b_ret;
-       } else {
-               client->retcode = 0;
-       }
+
        guc->submissions[engine_id] += 1;
        guc->last_seqno[engine_id] = rq->seqno;
 
-       return q_ret;
+       return b_ret;
 }
 
 /*
@@ -677,7 +697,7 @@ static void guc_client_free(struct drm_device *dev,
  */
 static struct i915_guc_client *guc_client_alloc(struct drm_device *dev,
                                                uint32_t priority,
-                                               struct intel_context *ctx)
+                                               struct i915_gem_context *ctx)
 {
        struct i915_guc_client *client;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -915,11 +935,12 @@ int i915_guc_submission_enable(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_guc *guc = &dev_priv->guc;
-       struct intel_context *ctx = dev_priv->kernel_context;
        struct i915_guc_client *client;
 
        /* client for execbuf submission */
-       client = guc_client_alloc(dev, GUC_CTX_PRIORITY_KMD_NORMAL, ctx);
+       client = guc_client_alloc(dev,
+                                 GUC_CTX_PRIORITY_KMD_NORMAL,
+                                 dev_priv->kernel_context);
        if (!client) {
                DRM_ERROR("Failed to create execbuf guc_client\n");
                return -ENOMEM;
@@ -966,10 +987,10 @@ int intel_guc_suspend(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_guc *guc = &dev_priv->guc;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        u32 data[3];
 
-       if (!i915.enable_guc_submission)
+       if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
                return 0;
 
        ctx = dev_priv->kernel_context;
@@ -992,10 +1013,10 @@ int intel_guc_resume(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_guc *guc = &dev_priv->guc;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        u32 data[3];
 
-       if (!i915.enable_guc_submission)
+       if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
                return 0;
 
        ctx = dev_priv->kernel_context;
index 3242a37..5c73783 100644 (file)
@@ -364,19 +364,7 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv)
 
 u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask)
 {
-       /*
-        * SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer
-        * if GEN6_PM_UP_EI_EXPIRED is masked.
-        *
-        * TODO: verify if this can be reproduced on VLV,CHV.
-        */
-       if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv))
-               mask &= ~GEN6_PM_RP_UP_EI_EXPIRED;
-
-       if (INTEL_INFO(dev_priv)->gen >= 8)
-               mask &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP;
-
-       return mask;
+       return (mask & ~dev_priv->rps.pm_intr_keep);
 }
 
 void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv)
@@ -3797,6 +3785,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
        uint32_t de_pipe_enables;
        u32 de_port_masked = GEN8_AUX_CHANNEL_A;
        u32 de_port_enables;
+       u32 de_misc_masked = GEN8_DE_MISC_GSE;
        enum pipe pipe;
 
        if (INTEL_INFO(dev_priv)->gen >= 9) {
@@ -3832,6 +3821,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
                                          de_pipe_enables);
 
        GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
+       GEN5_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
 }
 
 static int gen8_irq_postinstall(struct drm_device *dev)
@@ -4576,6 +4566,20 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
        else
                dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
 
+       dev_priv->rps.pm_intr_keep = 0;
+
+       /*
+        * SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer
+        * if GEN6_PM_UP_EI_EXPIRED is masked.
+        *
+        * TODO: verify if this can be reproduced on VLV,CHV.
+        */
+       if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv))
+               dev_priv->rps.pm_intr_keep |= GEN6_PM_RP_UP_EI_EXPIRED;
+
+       if (INTEL_INFO(dev_priv)->gen >= 8)
+               dev_priv->rps.pm_intr_keep |= GEN8_PMINTR_REDIRECT_TO_NON_DISP;
+
        INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work,
                          i915_hangcheck_elapsed);
 
index 383c076..5e18cf9 100644 (file)
@@ -54,7 +54,8 @@ struct i915_params i915 __read_mostly = {
        .verbose_state_checks = 1,
        .nuclear_pageflip = 0,
        .edp_vswing = 0,
-       .enable_guc_submission = false,
+       .enable_guc_loading = 0,
+       .enable_guc_submission = 0,
        .guc_log_level = -1,
        .enable_dp_mst = true,
        .inject_load_failure = 0,
@@ -198,8 +199,15 @@ MODULE_PARM_DESC(edp_vswing,
                 "(0=use value from vbt [default], 1=low power swing(200mV),"
                 "2=default swing(400mV))");
 
-module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, bool, 0400);
-MODULE_PARM_DESC(enable_guc_submission, "Enable GuC submission (default:false)");
+module_param_named_unsafe(enable_guc_loading, i915.enable_guc_loading, int, 0400);
+MODULE_PARM_DESC(enable_guc_loading,
+               "Enable GuC firmware loading "
+               "(-1=auto, 0=never [default], 1=if available, 2=required)");
+
+module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, int, 0400);
+MODULE_PARM_DESC(enable_guc_submission,
+               "Enable GuC submission "
+               "(-1=auto, 0=never [default], 1=if available, 2=required)");
 
 module_param_named(guc_log_level, i915.guc_log_level, int, 0400);
 MODULE_PARM_DESC(guc_log_level,
index 65e73dd..1323261 100644 (file)
@@ -45,6 +45,8 @@ struct i915_params {
        int enable_ips;
        int invert_brightness;
        int enable_cmd_parser;
+       int enable_guc_loading;
+       int enable_guc_submission;
        int guc_log_level;
        int use_mmio_flip;
        int mmio_debug;
@@ -57,7 +59,6 @@ struct i915_params {
        bool load_detect_test;
        bool reset;
        bool disable_display;
-       bool enable_guc_submission;
        bool verbose_state_checks;
        bool nuclear_pageflip;
        bool enable_dp_mst;
index e307725..0845059 100644 (file)
@@ -7031,7 +7031,7 @@ enum skl_disp_power_wells {
 #define VLV_RCEDATA                            _MMIO(0xA0BC)
 #define GEN6_RC6pp_THRESHOLD                   _MMIO(0xA0C0)
 #define GEN6_PMINTRMSK                         _MMIO(0xA168)
-#define GEN8_PMINTR_REDIRECT_TO_NON_DISP       (1<<31)
+#define   GEN8_PMINTR_REDIRECT_TO_NON_DISP     (1<<31)
 #define VLV_PWRDWNUPCTL                                _MMIO(0xA294)
 #define GEN9_MEDIA_PG_IDLE_HYSTERESIS          _MMIO(0xA0C4)
 #define GEN9_RENDER_PG_IDLE_HYSTERESIS         _MMIO(0xA0C8)
index 37b6444..02507bf 100644 (file)
@@ -203,7 +203,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
        struct drm_minor *dminor = dev_to_drm_minor(dev);
        struct drm_device *drm_dev = dminor->dev;
        struct drm_i915_private *dev_priv = drm_dev->dev_private;
-       struct intel_context *ctx;
+       struct i915_gem_context *ctx;
        u32 *temp = NULL; /* Just here to make handling failures easy */
        int slice = (int)(uintptr_t)attr->private;
        int ret;
index 20b2e40..6768db0 100644 (file)
@@ -734,12 +734,12 @@ DEFINE_EVENT(i915_ppgtt, i915_ppgtt_release,
  * the context.
  */
 DECLARE_EVENT_CLASS(i915_context,
-       TP_PROTO(struct intel_context *ctx),
+       TP_PROTO(struct i915_gem_context *ctx),
        TP_ARGS(ctx),
 
        TP_STRUCT__entry(
                        __field(u32, dev)
-                       __field(struct intel_context *, ctx)
+                       __field(struct i915_gem_context *, ctx)
                        __field(struct i915_address_space *, vm)
        ),
 
@@ -754,12 +754,12 @@ DECLARE_EVENT_CLASS(i915_context,
 )
 
 DEFINE_EVENT(i915_context, i915_context_create,
-       TP_PROTO(struct intel_context *ctx),
+       TP_PROTO(struct i915_gem_context *ctx),
        TP_ARGS(ctx)
 );
 
 DEFINE_EVENT(i915_context, i915_context_free,
-       TP_PROTO(struct intel_context *ctx),
+       TP_PROTO(struct i915_gem_context *ctx),
        TP_ARGS(ctx)
 );
 
@@ -771,13 +771,13 @@ DEFINE_EVENT(i915_context, i915_context_free,
  * called only if full ppgtt is enabled.
  */
 TRACE_EVENT(switch_mm,
-       TP_PROTO(struct intel_engine_cs *engine, struct intel_context *to),
+       TP_PROTO(struct intel_engine_cs *engine, struct i915_gem_context *to),
 
        TP_ARGS(engine, to),
 
        TP_STRUCT__entry(
                        __field(u32, ring)
-                       __field(struct intel_context *, to)
+                       __field(struct i915_gem_context *, to)
                        __field(struct i915_address_space *, vm)
                        __field(u32, dev)
        ),
index 8b68c48..624e755 100644 (file)
@@ -213,7 +213,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 
        dev_priv->vbt.lvds_dither = lvds_options->pixel_dither;
 
-       ret = intel_opregion_get_panel_type(dev_priv->dev);
+       ret = intel_opregion_get_panel_type(dev_priv);
        if (ret >= 0) {
                WARN_ON(ret > 0xf);
                panel_type = ret;
index 3fbb6fc..6229681 100644 (file)
@@ -839,7 +839,7 @@ void intel_crt_init(struct drm_device *dev)
                           &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
 
        drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs,
-                        DRM_MODE_ENCODER_DAC, NULL);
+                        DRM_MODE_ENCODER_DAC, "CRT");
 
        intel_connector_attach_encoder(intel_connector, &crt->base);
 
index c454744..022b41d 100644 (file)
@@ -2347,7 +2347,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
        encoder = &intel_encoder->base;
 
        drm_encoder_init(dev, encoder, &intel_ddi_funcs,
-                        DRM_MODE_ENCODER_TMDS, NULL);
+                        DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port));
 
        intel_encoder->compute_config = intel_ddi_compute_config;
        intel_encoder->enable = intel_enable_ddi;
index 3f8987b..60cba19 100644 (file)
@@ -123,6 +123,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
 static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
 static int ilk_max_pixel_rate(struct drm_atomic_state *state);
+static int broxton_calc_cdclk(int max_pixclk);
 
 struct intel_limit {
        struct {
@@ -4277,8 +4278,9 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)
        struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
        const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
 
-       DRM_DEBUG_KMS("Updating scaler for [CRTC:%i] scaler_user index %u.%u\n",
-                     intel_crtc->base.base.id, intel_crtc->pipe, SKL_CRTC_INDEX);
+       DRM_DEBUG_KMS("Updating scaler for [CRTC:%d:%s] scaler_user index %u.%u\n",
+                     intel_crtc->base.base.id, intel_crtc->base.name,
+                     intel_crtc->pipe, SKL_CRTC_INDEX);
 
        return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
                &state->scaler_state.scaler_id, BIT(DRM_ROTATE_0),
@@ -4308,9 +4310,9 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
 
        bool force_detach = !fb || !plane_state->visible;
 
-       DRM_DEBUG_KMS("Updating scaler for [PLANE:%d] scaler_user index %u.%u\n",
-                     intel_plane->base.base.id, intel_crtc->pipe,
-                     drm_plane_index(&intel_plane->base));
+       DRM_DEBUG_KMS("Updating scaler for [PLANE:%d:%s] scaler_user index %u.%u\n",
+                     intel_plane->base.base.id, intel_plane->base.name,
+                     intel_crtc->pipe, drm_plane_index(&intel_plane->base));
 
        ret = skl_update_scaler(crtc_state, force_detach,
                                drm_plane_index(&intel_plane->base),
@@ -4326,8 +4328,9 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
 
        /* check colorkey */
        if (plane_state->ckey.flags != I915_SET_COLORKEY_NONE) {
-               DRM_DEBUG_KMS("[PLANE:%d] scaling with color key not allowed",
-                             intel_plane->base.base.id);
+               DRM_DEBUG_KMS("[PLANE:%d:%s] scaling with color key not allowed",
+                             intel_plane->base.base.id,
+                             intel_plane->base.name);
                return -EINVAL;
        }
 
@@ -4346,8 +4349,9 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
        case DRM_FORMAT_VYUY:
                break;
        default:
-               DRM_DEBUG_KMS("[PLANE:%d] FB:%d unsupported scaling format 0x%x\n",
-                       intel_plane->base.base.id, fb->base.id, fb->pixel_format);
+               DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n",
+                             intel_plane->base.base.id, intel_plane->base.name,
+                             fb->base.id, fb->pixel_format);
                return -EINVAL;
        }
 
@@ -5265,21 +5269,34 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)
                return max_cdclk_freq*90/100;
 }
 
+static int skl_calc_cdclk(int max_pixclk, int vco);
+
 static void intel_update_max_cdclk(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
                u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
+               int max_cdclk, vco;
+
+               vco = dev_priv->skl_preferred_vco_freq;
+               WARN_ON(vco != 8100000 && vco != 8640000);
 
+               /*
+                * Use the lower (vco 8640) cdclk values as a
+                * first guess. skl_calc_cdclk() will correct it
+                * if the preferred vco is 8100 instead.
+                */
                if (limit == SKL_DFSM_CDCLK_LIMIT_675)
-                       dev_priv->max_cdclk_freq = 675000;
+                       max_cdclk = 617143;
                else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
-                       dev_priv->max_cdclk_freq = 540000;
+                       max_cdclk = 540000;
                else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
-                       dev_priv->max_cdclk_freq = 450000;
+                       max_cdclk = 432000;
                else
-                       dev_priv->max_cdclk_freq = 337500;
+                       max_cdclk = 308571;
+
+               dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
        } else if (IS_BROXTON(dev)) {
                dev_priv->max_cdclk_freq = 624000;
        } else if (IS_BROADWELL(dev))  {
@@ -5320,8 +5337,14 @@ static void intel_update_cdclk(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
-       DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
-                        dev_priv->cdclk_freq);
+
+       if (INTEL_GEN(dev_priv) >= 9)
+               DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
+                                dev_priv->cdclk_freq, dev_priv->cdclk_pll.vco,
+                                dev_priv->cdclk_pll.ref);
+       else
+               DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz\n",
+                                dev_priv->cdclk_freq);
 
        /*
         * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
@@ -5331,9 +5354,6 @@ static void intel_update_cdclk(struct drm_device *dev)
         */
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                I915_WRITE(GMBUSFREQ_VLV, DIV_ROUND_UP(dev_priv->cdclk_freq, 1000));
-
-       if (dev_priv->max_cdclk_freq == 0)
-               intel_update_max_cdclk(dev);
 }
 
 /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
@@ -5342,51 +5362,93 @@ static int skl_cdclk_decimal(int cdclk)
        return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
 }
 
-static void broxton_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
+static int bxt_de_pll_vco(struct drm_i915_private *dev_priv, int cdclk)
 {
-       uint32_t divider;
-       uint32_t ratio;
-       uint32_t current_cdclk;
-       int ret;
+       int ratio;
+
+       if (cdclk == dev_priv->cdclk_pll.ref)
+               return 0;
 
-       /* frequency = 19.2MHz * ratio / 2 / div{1,1.5,2,4} */
        switch (cdclk) {
+       default:
+               MISSING_CASE(cdclk);
        case 144000:
+       case 288000:
+       case 384000:
+       case 576000:
+               ratio = 60;
+               break;
+       case 624000:
+               ratio = 65;
+               break;
+       }
+
+       return dev_priv->cdclk_pll.ref * ratio;
+}
+
+static void bxt_de_pll_disable(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE(BXT_DE_PLL_ENABLE, 0);
+
+       /* Timeout 200us */
+       if (wait_for((I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK) == 0, 1))
+               DRM_ERROR("timeout waiting for DE PLL unlock\n");
+
+       dev_priv->cdclk_pll.vco = 0;
+}
+
+static void bxt_de_pll_enable(struct drm_i915_private *dev_priv, int vco)
+{
+       int ratio = DIV_ROUND_CLOSEST(vco, dev_priv->cdclk_pll.ref);
+       u32 val;
+
+       val = I915_READ(BXT_DE_PLL_CTL);
+       val &= ~BXT_DE_PLL_RATIO_MASK;
+       val |= BXT_DE_PLL_RATIO(ratio);
+       I915_WRITE(BXT_DE_PLL_CTL, val);
+
+       I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
+
+       /* Timeout 200us */
+       if (wait_for((I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK) != 0, 1))
+               DRM_ERROR("timeout waiting for DE PLL lock\n");
+
+       dev_priv->cdclk_pll.vco = vco;
+}
+
+static void broxton_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
+{
+       u32 val, divider;
+       int vco, ret;
+
+       vco = bxt_de_pll_vco(dev_priv, cdclk);
+
+       DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk, vco);
+
+       /* cdclk = vco / 2 / div{1,1.5,2,4} */
+       switch (DIV_ROUND_CLOSEST(vco, cdclk)) {
+       case 8:
                divider = BXT_CDCLK_CD2X_DIV_SEL_4;
-               ratio = BXT_DE_PLL_RATIO(60);
                break;
-       case 288000:
+       case 4:
                divider = BXT_CDCLK_CD2X_DIV_SEL_2;
-               ratio = BXT_DE_PLL_RATIO(60);
                break;
-       case 384000:
+       case 3:
                divider = BXT_CDCLK_CD2X_DIV_SEL_1_5;
-               ratio = BXT_DE_PLL_RATIO(60);
                break;
-       case 576000:
-               divider = BXT_CDCLK_CD2X_DIV_SEL_1;
-               ratio = BXT_DE_PLL_RATIO(60);
-               break;
-       case 624000:
+       case 2:
                divider = BXT_CDCLK_CD2X_DIV_SEL_1;
-               ratio = BXT_DE_PLL_RATIO(65);
-               break;
-       case 19200:
-               /*
-                * Bypass frequency with DE PLL disabled. Init ratio, divider
-                * to suppress GCC warning.
-                */
-               ratio = 0;
-               divider = 0;
                break;
        default:
-               DRM_ERROR("unsupported CDCLK freq %d", cdclk);
+               WARN_ON(cdclk != dev_priv->cdclk_pll.ref);
+               WARN_ON(vco != 0);
 
-               return;
+               divider = BXT_CDCLK_CD2X_DIV_SEL_1;
+               break;
        }
 
-       mutex_lock(&dev_priv->rps.hw_lock);
        /* Inform power controller of upcoming frequency change */
+       mutex_lock(&dev_priv->rps.hw_lock);
        ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
                                      0x80000000);
        mutex_unlock(&dev_priv->rps.hw_lock);
@@ -5397,52 +5459,26 @@ static void broxton_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
                return;
        }
 
-       current_cdclk = I915_READ(CDCLK_CTL) & CDCLK_FREQ_DECIMAL_MASK;
-       /* convert from .1 fixpoint MHz with -1MHz offset to kHz */
-       current_cdclk = current_cdclk * 500 + 1000;
+       if (dev_priv->cdclk_pll.vco != 0 &&
+           dev_priv->cdclk_pll.vco != vco)
+               bxt_de_pll_disable(dev_priv);
 
+       if (dev_priv->cdclk_pll.vco != vco)
+               bxt_de_pll_enable(dev_priv, vco);
+
+       val = divider | skl_cdclk_decimal(cdclk);
        /*
-        * DE PLL has to be disabled when
-        * - setting to 19.2MHz (bypass, PLL isn't used)
-        * - before setting to 624MHz (PLL needs toggling)
-        * - before setting to any frequency from 624MHz (PLL needs toggling)
-        */
-       if (cdclk == 19200 || cdclk == 624000 ||
-           current_cdclk == 624000) {
-               I915_WRITE(BXT_DE_PLL_ENABLE, ~BXT_DE_PLL_PLL_ENABLE);
-               /* Timeout 200us */
-               if (wait_for(!(I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK),
-                            1))
-                       DRM_ERROR("timout waiting for DE PLL unlock\n");
-       }
-
-       if (cdclk != 19200) {
-               uint32_t val;
-
-               val = I915_READ(BXT_DE_PLL_CTL);
-               val &= ~BXT_DE_PLL_RATIO_MASK;
-               val |= ratio;
-               I915_WRITE(BXT_DE_PLL_CTL, val);
-
-               I915_WRITE(BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
-               /* Timeout 200us */
-               if (wait_for(I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_LOCK, 1))
-                       DRM_ERROR("timeout waiting for DE PLL lock\n");
-
-               val = divider | skl_cdclk_decimal(cdclk);
-               /*
-                * FIXME if only the cd2x divider needs changing, it could be done
-                * without shutting off the pipe (if only one pipe is active).
-                */
-               val |= BXT_CDCLK_CD2X_PIPE_NONE;
-               /*
-                * Disable SSA Precharge when CD clock frequency < 500 MHz,
-                * enable otherwise.
-                */
-               if (cdclk >= 500000)
-                       val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
-               I915_WRITE(CDCLK_CTL, val);
-       }
+        * FIXME if only the cd2x divider needs changing, it could be done
+        * without shutting off the pipe (if only one pipe is active).
+        */
+       val |= BXT_CDCLK_CD2X_PIPE_NONE;
+       /*
+        * Disable SSA Precharge when CD clock frequency < 500 MHz,
+        * enable otherwise.
+        */
+       if (cdclk >= 500000)
+               val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
+       I915_WRITE(CDCLK_CTL, val);
 
        mutex_lock(&dev_priv->rps.hw_lock);
        ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
@@ -5458,114 +5494,155 @@ static void broxton_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
        intel_update_cdclk(dev_priv->dev);
 }
 
-static bool broxton_cdclk_is_enabled(struct drm_i915_private *dev_priv)
+static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 {
-       if (!(I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_PLL_ENABLE))
-               return false;
+       u32 cdctl, expected;
 
-       /* TODO: Check for a valid CDCLK rate */
+       intel_update_cdclk(dev_priv->dev);
 
-       if (!(I915_READ(DBUF_CTL) & DBUF_POWER_REQUEST)) {
-               DRM_DEBUG_DRIVER("CDCLK enabled, but DBUF power not requested\n");
+       if (dev_priv->cdclk_pll.vco == 0 ||
+           dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
+               goto sanitize;
 
-               return false;
-       }
+       /* DPLL okay; verify the cdclock
+        *
+        * Some BIOS versions leave an incorrect decimal frequency value and
+        * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
+        * so sanitize this register.
+        */
+       cdctl = I915_READ(CDCLK_CTL);
+       /*
+        * Let's ignore the pipe field, since BIOS could have configured the
+        * dividers both synching to an active pipe, or asynchronously
+        * (PIPE_NONE).
+        */
+       cdctl &= ~BXT_CDCLK_CD2X_PIPE_NONE;
 
-       if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE)) {
-               DRM_DEBUG_DRIVER("CDCLK enabled, but DBUF power hasn't settled\n");
+       expected = (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) |
+                  skl_cdclk_decimal(dev_priv->cdclk_freq);
+       /*
+        * Disable SSA Precharge when CD clock frequency < 500 MHz,
+        * enable otherwise.
+        */
+       if (dev_priv->cdclk_freq >= 500000)
+               expected |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
 
-               return false;
-       }
+       if (cdctl == expected)
+               /* All well; nothing to sanitize */
+               return;
 
-       return true;
-}
+sanitize:
+       DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
 
-bool broxton_cdclk_verify_state(struct drm_i915_private *dev_priv)
-{
-       return broxton_cdclk_is_enabled(dev_priv);
+       /* force cdclk programming */
+       dev_priv->cdclk_freq = 0;
+
+       /* force full PLL disable + enable */
+       dev_priv->cdclk_pll.vco = -1;
 }
 
 void broxton_init_cdclk(struct drm_i915_private *dev_priv)
 {
-       /* check if cd clock is enabled */
-       if (broxton_cdclk_is_enabled(dev_priv)) {
-               DRM_DEBUG_KMS("CDCLK already enabled, won't reprogram it\n");
-               return;
-       }
+       bxt_sanitize_cdclk(dev_priv);
 
-       DRM_DEBUG_KMS("CDCLK not enabled, enabling it\n");
+       if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0)
+               return;
 
        /*
         * FIXME:
         * - The initial CDCLK needs to be read from VBT.
         *   Need to make this change after VBT has changes for BXT.
-        * - check if setting the max (or any) cdclk freq is really necessary
-        *   here, it belongs to modeset time
         */
-       broxton_set_cdclk(dev_priv, 624000);
-
-       I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST);
-       POSTING_READ(DBUF_CTL);
-
-       udelay(10);
-
-       if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE))
-               DRM_ERROR("DBuf power enable timeout!\n");
+       broxton_set_cdclk(dev_priv, broxton_calc_cdclk(0));
 }
 
 void broxton_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
-       I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST);
-       POSTING_READ(DBUF_CTL);
+       broxton_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref);
+}
 
-       udelay(10);
+static int skl_calc_cdclk(int max_pixclk, int vco)
+{
+       if (vco == 8640000) {
+               if (max_pixclk > 540000)
+                       return 617143;
+               else if (max_pixclk > 432000)
+                       return 540000;
+               else if (max_pixclk > 308571)
+                       return 432000;
+               else
+                       return 308571;
+       } else {
+               if (max_pixclk > 540000)
+                       return 675000;
+               else if (max_pixclk > 450000)
+                       return 540000;
+               else if (max_pixclk > 337500)
+                       return 450000;
+               else
+                       return 337500;
+       }
+}
 
-       if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
-               DRM_ERROR("DBuf power disable timeout!\n");
+static void
+skl_dpll0_update(struct drm_i915_private *dev_priv)
+{
+       u32 val;
 
-       /* Set minimum (bypass) frequency, in effect turning off the DE PLL */
-       broxton_set_cdclk(dev_priv, 19200);
-}
+       dev_priv->cdclk_pll.ref = 24000;
+       dev_priv->cdclk_pll.vco = 0;
 
-static const struct skl_cdclk_entry {
-       unsigned int freq;
-       unsigned int vco;
-} skl_cdclk_frequencies[] = {
-       { .freq = 308570, .vco = 8640 },
-       { .freq = 337500, .vco = 8100 },
-       { .freq = 432000, .vco = 8640 },
-       { .freq = 450000, .vco = 8100 },
-       { .freq = 540000, .vco = 8100 },
-       { .freq = 617140, .vco = 8640 },
-       { .freq = 675000, .vco = 8100 },
-};
+       val = I915_READ(LCPLL1_CTL);
+       if ((val & LCPLL_PLL_ENABLE) == 0)
+               return;
 
-static unsigned int skl_cdclk_get_vco(unsigned int freq)
-{
-       unsigned int i;
+       if (WARN_ON((val & LCPLL_PLL_LOCK) == 0))
+               return;
+
+       val = I915_READ(DPLL_CTRL1);
 
-       for (i = 0; i < ARRAY_SIZE(skl_cdclk_frequencies); i++) {
-               const struct skl_cdclk_entry *e = &skl_cdclk_frequencies[i];
+       if (WARN_ON((val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
+                           DPLL_CTRL1_SSC(SKL_DPLL0) |
+                           DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
+                   DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
+               return;
 
-               if (e->freq == freq)
-                       return e->vco;
+       switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
+       case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
+       case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
+       case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
+       case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
+               dev_priv->cdclk_pll.vco = 8100000;
+               break;
+       case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
+       case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
+               dev_priv->cdclk_pll.vco = 8640000;
+               break;
+       default:
+               MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
+               break;
        }
+}
+
+void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco)
+{
+       bool changed = dev_priv->skl_preferred_vco_freq != vco;
 
-       return 8100;
+       dev_priv->skl_preferred_vco_freq = vco;
+
+       if (changed)
+               intel_update_max_cdclk(dev_priv->dev);
 }
 
 static void
 skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
 {
-       int min_cdclk;
+       int min_cdclk = skl_calc_cdclk(0, vco);
        u32 val;
 
-       /* select the minimum CDCLK before enabling DPLL 0 */
-       if (vco == 8640)
-               min_cdclk = 308570;
-       else
-               min_cdclk = 337500;
+       WARN_ON(vco != 8100000 && vco != 8640000);
 
+       /* select the minimum CDCLK before enabling DPLL 0 */
        val = CDCLK_FREQ_337_308 | skl_cdclk_decimal(min_cdclk);
        I915_WRITE(CDCLK_CTL, val);
        POSTING_READ(CDCLK_CTL);
@@ -5577,14 +5654,14 @@ skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
         * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
         * The modeset code is responsible for the selection of the exact link
         * rate later on, with the constraint of choosing a frequency that
-        * works with required_vco.
+        * works with vco.
         */
        val = I915_READ(DPLL_CTRL1);
 
        val &= ~(DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) | DPLL_CTRL1_SSC(SKL_DPLL0) |
                 DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
        val |= DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
-       if (vco == 8640)
+       if (vco == 8640000)
                val |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
                                            SKL_DPLL0);
        else
@@ -5598,6 +5675,11 @@ skl_dpll0_enable(struct drm_i915_private *dev_priv, int vco)
 
        if (wait_for(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK, 5))
                DRM_ERROR("DPLL0 not locked\n");
+
+       dev_priv->cdclk_pll.vco = vco;
+
+       /* We'll want to keep using the current vco from now on. */
+       skl_set_preferred_cdclk_vco(dev_priv, vco);
 }
 
 static void
@@ -5606,6 +5688,8 @@ skl_dpll0_disable(struct drm_i915_private *dev_priv)
        I915_WRITE(LCPLL1_CTL, I915_READ(LCPLL1_CTL) & ~LCPLL_PLL_ENABLE);
        if (wait_for(!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_LOCK), 1))
                DRM_ERROR("Couldn't disable DPLL0\n");
+
+       dev_priv->cdclk_pll.vco = 0;
 }
 
 static bool skl_cdclk_pcu_ready(struct drm_i915_private *dev_priv)
@@ -5635,12 +5719,14 @@ static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv)
        return false;
 }
 
-static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
+static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
 {
        struct drm_device *dev = dev_priv->dev;
        u32 freq_select, pcu_ack;
 
-       DRM_DEBUG_DRIVER("Changing CDCLK to %dKHz\n", cdclk);
+       WARN_ON((cdclk == 24000) != (vco == 0));
+
+       DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk, vco);
 
        if (!skl_cdclk_wait_for_pcu_ready(dev_priv)) {
                DRM_ERROR("failed to inform PCU about cdclk change\n");
@@ -5658,19 +5744,26 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
                freq_select = CDCLK_FREQ_540;
                pcu_ack = 2;
                break;
-       case 308570:
+       case 308571:
        case 337500:
        default:
                freq_select = CDCLK_FREQ_337_308;
                pcu_ack = 0;
                break;
-       case 617140:
+       case 617143:
        case 675000:
                freq_select = CDCLK_FREQ_675_617;
                pcu_ack = 3;
                break;
        }
 
+       if (dev_priv->cdclk_pll.vco != 0 &&
+           dev_priv->cdclk_pll.vco != vco)
+               skl_dpll0_disable(dev_priv);
+
+       if (dev_priv->cdclk_pll.vco != vco)
+               skl_dpll0_enable(dev_priv, vco);
+
        I915_WRITE(CDCLK_CTL, freq_select | skl_cdclk_decimal(cdclk));
        POSTING_READ(CDCLK_CTL);
 
@@ -5682,49 +5775,41 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk)
        intel_update_cdclk(dev);
 }
 
+static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
+
 void skl_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
-       /* disable DBUF power */
-       I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST);
-       POSTING_READ(DBUF_CTL);
-
-       udelay(10);
-
-       if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
-               DRM_ERROR("DBuf power disable timeout\n");
-
-       skl_dpll0_disable(dev_priv);
+       skl_set_cdclk(dev_priv, dev_priv->cdclk_pll.ref, 0);
 }
 
 void skl_init_cdclk(struct drm_i915_private *dev_priv)
 {
-       unsigned int vco;
+       int cdclk, vco;
 
-       /* DPLL0 not enabled (happens on early BIOS versions) */
-       if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) {
-               /* enable DPLL0 */
-               vco = skl_cdclk_get_vco(dev_priv->skl_boot_cdclk);
-               skl_dpll0_enable(dev_priv, vco);
-       }
+       skl_sanitize_cdclk(dev_priv);
 
-       /* set CDCLK to the frequency the BIOS chose */
-       skl_set_cdclk(dev_priv, dev_priv->skl_boot_cdclk);
-
-       /* enable DBUF power */
-       I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST);
-       POSTING_READ(DBUF_CTL);
+       if (dev_priv->cdclk_freq != 0 && dev_priv->cdclk_pll.vco != 0) {
+               /*
+                * Use the current vco as our initial
+                * guess as to what the preferred vco is.
+                */
+               if (dev_priv->skl_preferred_vco_freq == 0)
+                       skl_set_preferred_cdclk_vco(dev_priv,
+                                                   dev_priv->cdclk_pll.vco);
+               return;
+       }
 
-       udelay(10);
+       vco = dev_priv->skl_preferred_vco_freq;
+       if (vco == 0)
+               vco = 8100000;
+       cdclk = skl_calc_cdclk(0, vco);
 
-       if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE))
-               DRM_ERROR("DBuf power enable timeout\n");
+       skl_set_cdclk(dev_priv, cdclk, vco);
 }
 
-int skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
+static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
 {
-       uint32_t lcpll1 = I915_READ(LCPLL1_CTL);
-       uint32_t cdctl = I915_READ(CDCLK_CTL);
-       int freq = dev_priv->skl_boot_cdclk;
+       uint32_t cdctl, expected;
 
        /*
         * check if the pre-os intialized the display
@@ -5734,8 +5819,10 @@ int skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
        if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
                goto sanitize;
 
+       intel_update_cdclk(dev_priv->dev);
        /* Is PLL enabled and locked ? */
-       if (!((lcpll1 & LCPLL_PLL_ENABLE) && (lcpll1 & LCPLL_PLL_LOCK)))
+       if (dev_priv->cdclk_pll.vco == 0 ||
+           dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
                goto sanitize;
 
        /* DPLL okay; verify the cdclock
@@ -5744,19 +5831,20 @@ int skl_sanitize_cdclk(struct drm_i915_private *dev_priv)
         * decimal part is programmed wrong from BIOS where pre-os does not
         * enable display. Verify the same as well.
         */
-       if (cdctl == ((cdctl & CDCLK_FREQ_SEL_MASK) | skl_cdclk_decimal(freq)))
+       cdctl = I915_READ(CDCLK_CTL);
+       expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
+               skl_cdclk_decimal(dev_priv->cdclk_freq);
+       if (cdctl == expected)
                /* All well; nothing to sanitize */
-               return false;
+               return;
+
 sanitize:
-       /*
-        * As of now initialize with max cdclk till
-        * we get dynamic cdclk support
-        * */
-       dev_priv->skl_boot_cdclk = dev_priv->max_cdclk_freq;
-       skl_init_cdclk(dev_priv);
+       DRM_DEBUG_KMS("Sanitizing cdclk programmed by pre-os\n");
 
-       /* we did have to sanitize */
-       return true;
+       /* force cdclk programming */
+       dev_priv->cdclk_freq = 0;
+       /* force full PLL disable + enable */
+       dev_priv->cdclk_pll.vco = -1;
 }
 
 /* Adjust CDclk dividers to allow high res or save power if possible */
@@ -5898,10 +5986,6 @@ static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
 
 static int broxton_calc_cdclk(int max_pixclk)
 {
-       /*
-        * FIXME:
-        * - set 19.2MHz bypass frequency if there are no active pipes
-        */
        if (max_pixclk > 576000)
                return 624000;
        else if (max_pixclk > 384000)
@@ -6242,8 +6326,8 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
 
        dev_priv->display.crtc_disable(crtc);
 
-       DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was enabled, now disabled\n",
-                     crtc->base.id);
+       DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
+                     crtc->base.id, crtc->name);
 
        WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0);
        crtc->state->active = false;
@@ -6543,10 +6627,10 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+       int clock_limit = dev_priv->max_dotclk_freq;
 
-       /* FIXME should check pixel clock limits on all platforms */
        if (INTEL_INFO(dev)->gen < 4) {
-               int clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
+               clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
 
                /*
                 * Enable double wide mode when the dot clock
@@ -6554,16 +6638,16 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
                 */
                if (intel_crtc_supports_double_wide(crtc) &&
                    adjusted_mode->crtc_clock > clock_limit) {
-                       clock_limit *= 2;
+                       clock_limit = dev_priv->max_dotclk_freq;
                        pipe_config->double_wide = true;
                }
+       }
 
-               if (adjusted_mode->crtc_clock > clock_limit) {
-                       DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
-                                     adjusted_mode->crtc_clock, clock_limit,
-                                     yesno(pipe_config->double_wide));
-                       return -EINVAL;
-               }
+       if (adjusted_mode->crtc_clock > clock_limit) {
+               DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
+                             adjusted_mode->crtc_clock, clock_limit,
+                             yesno(pipe_config->double_wide));
+               return -EINVAL;
        }
 
        /*
@@ -6595,76 +6679,98 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 static int skylake_get_display_clock_speed(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       uint32_t lcpll1 = I915_READ(LCPLL1_CTL);
-       uint32_t cdctl = I915_READ(CDCLK_CTL);
-       uint32_t linkrate;
+       uint32_t cdctl;
 
-       if (!(lcpll1 & LCPLL_PLL_ENABLE))
-               return 24000; /* 24MHz is the cd freq with NSSC ref */
+       skl_dpll0_update(dev_priv);
 
-       if ((cdctl & CDCLK_FREQ_SEL_MASK) == CDCLK_FREQ_540)
-               return 540000;
+       if (dev_priv->cdclk_pll.vco == 0)
+               return dev_priv->cdclk_pll.ref;
 
-       linkrate = (I915_READ(DPLL_CTRL1) &
-                   DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) >> 1;
+       cdctl = I915_READ(CDCLK_CTL);
 
-       if (linkrate == DPLL_CTRL1_LINK_RATE_2160 ||
-           linkrate == DPLL_CTRL1_LINK_RATE_1080) {
-               /* vco 8640 */
+       if (dev_priv->cdclk_pll.vco == 8640000) {
                switch (cdctl & CDCLK_FREQ_SEL_MASK) {
                case CDCLK_FREQ_450_432:
                        return 432000;
                case CDCLK_FREQ_337_308:
-                       return 308570;
+                       return 308571;
+               case CDCLK_FREQ_540:
+                       return 540000;
                case CDCLK_FREQ_675_617:
-                       return 617140;
+                       return 617143;
                default:
-                       WARN(1, "Unknown cd freq selection\n");
+                       MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
                }
        } else {
-               /* vco 8100 */
                switch (cdctl & CDCLK_FREQ_SEL_MASK) {
                case CDCLK_FREQ_450_432:
                        return 450000;
                case CDCLK_FREQ_337_308:
                        return 337500;
+               case CDCLK_FREQ_540:
+                       return 540000;
                case CDCLK_FREQ_675_617:
                        return 675000;
                default:
-                       WARN(1, "Unknown cd freq selection\n");
+                       MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
                }
        }
 
-       /* error case, do as if DPLL0 isn't enabled */
-       return 24000;
+       return dev_priv->cdclk_pll.ref;
+}
+
+static void bxt_de_pll_update(struct drm_i915_private *dev_priv)
+{
+       u32 val;
+
+       dev_priv->cdclk_pll.ref = 19200;
+       dev_priv->cdclk_pll.vco = 0;
+
+       val = I915_READ(BXT_DE_PLL_ENABLE);
+       if ((val & BXT_DE_PLL_PLL_ENABLE) == 0)
+               return;
+
+       if (WARN_ON((val & BXT_DE_PLL_LOCK) == 0))
+               return;
+
+       val = I915_READ(BXT_DE_PLL_CTL);
+       dev_priv->cdclk_pll.vco = (val & BXT_DE_PLL_RATIO_MASK) *
+               dev_priv->cdclk_pll.ref;
 }
 
 static int broxton_get_display_clock_speed(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
-       uint32_t cdctl = I915_READ(CDCLK_CTL);
-       uint32_t pll_ratio = I915_READ(BXT_DE_PLL_CTL) & BXT_DE_PLL_RATIO_MASK;
-       uint32_t pll_enab = I915_READ(BXT_DE_PLL_ENABLE);
-       int cdclk;
+       u32 divider;
+       int div, vco;
+
+       bxt_de_pll_update(dev_priv);
 
-       if (!(pll_enab & BXT_DE_PLL_PLL_ENABLE))
-               return 19200;
+       vco = dev_priv->cdclk_pll.vco;
+       if (vco == 0)
+               return dev_priv->cdclk_pll.ref;
 
-       cdclk = 19200 * pll_ratio / 2;
+       divider = I915_READ(CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
 
-       switch (cdctl & BXT_CDCLK_CD2X_DIV_SEL_MASK) {
+       switch (divider) {
        case BXT_CDCLK_CD2X_DIV_SEL_1:
-               return cdclk;  /* 576MHz or 624MHz */
+               div = 2;
+               break;
        case BXT_CDCLK_CD2X_DIV_SEL_1_5:
-               return cdclk * 2 / 3; /* 384MHz */
+               div = 3;
+               break;
        case BXT_CDCLK_CD2X_DIV_SEL_2:
-               return cdclk / 2; /* 288MHz */
+               div = 4;
+               break;
        case BXT_CDCLK_CD2X_DIV_SEL_4:
-               return cdclk / 4; /* 144MHz */
+               div = 8;
+               break;
+       default:
+               MISSING_CASE(divider);
+               return dev_priv->cdclk_pll.ref;
        }
 
-       /* error case, do as if DE PLL isn't enabled */
-       return 19200;
+       return DIV_ROUND_CLOSEST(vco, div);
 }
 
 static int broadwell_get_display_clock_speed(struct drm_device *dev)
@@ -8255,12 +8361,14 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
+       int i;
        u32 val, final;
        bool has_lvds = false;
        bool has_cpu_edp = false;
        bool has_panel = false;
        bool has_ck505 = false;
        bool can_ssc = false;
+       bool using_ssc_source = false;
 
        /* We need to take the global config into account */
        for_each_intel_encoder(dev, encoder) {
@@ -8287,8 +8395,22 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
                can_ssc = true;
        }
 
-       DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
-                     has_panel, has_lvds, has_ck505);
+       /* Check if any DPLLs are using the SSC source */
+       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+               u32 temp = I915_READ(PCH_DPLL(i));
+
+               if (!(temp & DPLL_VCO_ENABLE))
+                       continue;
+
+               if ((temp & PLL_REF_INPUT_MASK) ==
+                   PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+                       using_ssc_source = true;
+                       break;
+               }
+       }
+
+       DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
+                     has_panel, has_lvds, has_ck505, using_ssc_source);
 
        /* Ironlake: try to setup display ref clock before DPLL
         * enabling. This is only under driver's control after
@@ -8308,9 +8430,12 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
        else
                final |= DREF_NONSPREAD_SOURCE_ENABLE;
 
-       final &= ~DREF_SSC_SOURCE_MASK;
        final &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-       final &= ~DREF_SSC1_ENABLE;
+
+       if (!using_ssc_source) {
+               final &= ~DREF_SSC_SOURCE_MASK;
+               final &= ~DREF_SSC1_ENABLE;
+       }
 
        if (has_panel) {
                final |= DREF_SSC_SOURCE_ENABLE;
@@ -8373,7 +8498,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
                POSTING_READ(PCH_DREF_CONTROL);
                udelay(200);
        } else {
-               DRM_DEBUG_KMS("Disabling SSC entirely\n");
+               DRM_DEBUG_KMS("Disabling CPU source output\n");
 
                val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
@@ -8384,16 +8509,20 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
                POSTING_READ(PCH_DREF_CONTROL);
                udelay(200);
 
-               /* Turn off the SSC source */
-               val &= ~DREF_SSC_SOURCE_MASK;
-               val |= DREF_SSC_SOURCE_DISABLE;
+               if (!using_ssc_source) {
+                       DRM_DEBUG_KMS("Disabling SSC source\n");
 
-               /* Turn off SSC1 */
-               val &= ~DREF_SSC1_ENABLE;
+                       /* Turn off the SSC source */
+                       val &= ~DREF_SSC_SOURCE_MASK;
+                       val |= DREF_SSC_SOURCE_DISABLE;
 
-               I915_WRITE(PCH_DREF_CONTROL, val);
-               POSTING_READ(PCH_DREF_CONTROL);
-               udelay(200);
+                       /* Turn off SSC1 */
+                       val &= ~DREF_SSC1_ENABLE;
+
+                       I915_WRITE(PCH_DREF_CONTROL, val);
+                       POSTING_READ(PCH_DREF_CONTROL);
+                       udelay(200);
+               }
        }
 
        BUG_ON(val != final);
@@ -9719,6 +9848,47 @@ static void broadwell_modeset_commit_cdclk(struct drm_atomic_state *old_state)
        broadwell_set_cdclk(dev, req_cdclk);
 }
 
+static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
+{
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
+       struct drm_i915_private *dev_priv = to_i915(state->dev);
+       const int max_pixclk = ilk_max_pixel_rate(state);
+       int vco = intel_state->cdclk_pll_vco;
+       int cdclk;
+
+       /*
+        * FIXME should also account for plane ratio
+        * once 64bpp pixel formats are supported.
+        */
+       cdclk = skl_calc_cdclk(max_pixclk, vco);
+
+       /*
+        * FIXME move the cdclk caclulation to
+        * compute_config() so we can fail gracegully.
+        */
+       if (cdclk > dev_priv->max_cdclk_freq) {
+               DRM_ERROR("requested cdclk (%d kHz) exceeds max (%d kHz)\n",
+                         cdclk, dev_priv->max_cdclk_freq);
+               cdclk = dev_priv->max_cdclk_freq;
+       }
+
+       intel_state->cdclk = intel_state->dev_cdclk = cdclk;
+       if (!intel_state->active_crtcs)
+               intel_state->dev_cdclk = skl_calc_cdclk(0, vco);
+
+       return 0;
+}
+
+static void skl_modeset_commit_cdclk(struct drm_atomic_state *old_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(old_state->dev);
+       struct intel_atomic_state *intel_state = to_intel_atomic_state(old_state);
+       unsigned int req_cdclk = intel_state->dev_cdclk;
+       unsigned int req_vco = intel_state->cdclk_pll_vco;
+
+       skl_set_cdclk(dev_priv, req_cdclk, req_vco);
+}
+
 static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
                                      struct intel_crtc_state *crtc_state)
 {
@@ -11765,12 +11935,12 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_plane_state *old_plane_state =
                to_intel_plane_state(plane->state);
-       int idx = intel_crtc->base.base.id, ret;
        bool mode_changed = needs_modeset(crtc_state);
        bool was_crtc_enabled = crtc->state->active;
        bool is_crtc_enabled = crtc_state->active;
        bool turn_off, turn_on, visible, was_visible;
        struct drm_framebuffer *fb = plane_state->fb;
+       int ret;
 
        if (crtc_state && INTEL_INFO(dev)->gen >= 9 &&
            plane->type != DRM_PLANE_TYPE_CURSOR) {
@@ -11809,11 +11979,15 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        turn_off = was_visible && (!visible || mode_changed);
        turn_on = visible && (!was_visible || mode_changed);
 
-       DRM_DEBUG_ATOMIC("[CRTC:%i] has [PLANE:%i] with fb %i\n", idx,
-                        plane->base.id, fb ? fb->base.id : -1);
+       DRM_DEBUG_ATOMIC("[CRTC:%d:%s] has [PLANE:%d:%s] with fb %i\n",
+                        intel_crtc->base.base.id,
+                        intel_crtc->base.name,
+                        plane->base.id, plane->name,
+                        fb ? fb->base.id : -1);
 
-       DRM_DEBUG_ATOMIC("[PLANE:%i] visible %i -> %i, off %i, on %i, ms %i\n",
-                        plane->base.id, was_visible, visible,
+       DRM_DEBUG_ATOMIC("[PLANE:%d:%s] visible %i -> %i, off %i, on %i, ms %i\n",
+                        plane->base.id, plane->name,
+                        was_visible, visible,
                         turn_off, turn_on, mode_changed);
 
        if (turn_on) {
@@ -12104,7 +12278,8 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
        struct intel_plane_state *state;
        struct drm_framebuffer *fb;
 
-       DRM_DEBUG_KMS("[CRTC:%d]%s config %p for pipe %c\n", crtc->base.base.id,
+       DRM_DEBUG_KMS("[CRTC:%d:%s]%s config %p for pipe %c\n",
+                     crtc->base.base.id, crtc->base.name,
                      context, pipe_config, pipe_name(crtc->pipe));
 
        DRM_DEBUG_KMS("cpu_transcoder: %s\n", transcoder_name(pipe_config->cpu_transcoder));
@@ -12205,29 +12380,24 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
                state = to_intel_plane_state(plane->state);
                fb = state->base.fb;
                if (!fb) {
-                       DRM_DEBUG_KMS("%s PLANE:%d plane: %u.%u idx: %d "
-                               "disabled, scaler_id = %d\n",
-                               plane->type == DRM_PLANE_TYPE_CURSOR ? "CURSOR" : "STANDARD",
-                               plane->base.id, intel_plane->pipe,
-                               (crtc->base.primary == plane) ? 0 : intel_plane->plane + 1,
-                               drm_plane_index(plane), state->scaler_id);
+                       DRM_DEBUG_KMS("[PLANE:%d:%s] disabled, scaler_id = %d\n",
+                                     plane->base.id, plane->name, state->scaler_id);
                        continue;
                }
 
-               DRM_DEBUG_KMS("%s PLANE:%d plane: %u.%u idx: %d enabled",
-                       plane->type == DRM_PLANE_TYPE_CURSOR ? "CURSOR" : "STANDARD",
-                       plane->base.id, intel_plane->pipe,
-                       crtc->base.primary == plane ? 0 : intel_plane->plane + 1,
-                       drm_plane_index(plane));
-               DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = 0x%x",
-                       fb->base.id, fb->width, fb->height, fb->pixel_format);
-               DRM_DEBUG_KMS("\tscaler:%d src (%u, %u) %ux%u dst (%u, %u) %ux%u\n",
-                       state->scaler_id,
-                       state->src.x1 >> 16, state->src.y1 >> 16,
-                       drm_rect_width(&state->src) >> 16,
-                       drm_rect_height(&state->src) >> 16,
-                       state->dst.x1, state->dst.y1,
-                       drm_rect_width(&state->dst), drm_rect_height(&state->dst));
+               DRM_DEBUG_KMS("[PLANE:%d:%s] enabled",
+                             plane->base.id, plane->name);
+               DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = %s",
+                             fb->base.id, fb->width, fb->height,
+                             drm_get_format_name(fb->pixel_format));
+               DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n",
+                             state->scaler_id,
+                             state->src.x1 >> 16, state->src.y1 >> 16,
+                             drm_rect_width(&state->src) >> 16,
+                             drm_rect_height(&state->src) >> 16,
+                             state->dst.x1, state->dst.y1,
+                             drm_rect_width(&state->dst),
+                             drm_rect_height(&state->dst));
        }
 }
 
@@ -12894,7 +13064,7 @@ verify_crtc_state(struct drm_crtc *crtc,
        pipe_config->base.crtc = crtc;
        pipe_config->base.state = old_state;
 
-       DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
+       DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
 
        active = dev_priv->display.get_pipe_config(intel_crtc, pipe_config);
 
@@ -13255,9 +13425,17 @@ static int intel_modeset_checks(struct drm_atomic_state *state)
         * adjusted_mode bits in the crtc directly.
         */
        if (dev_priv->display.modeset_calc_cdclk) {
+               if (!intel_state->cdclk_pll_vco)
+                       intel_state->cdclk_pll_vco = dev_priv->cdclk_pll.vco;
+               if (!intel_state->cdclk_pll_vco)
+                       intel_state->cdclk_pll_vco = dev_priv->skl_preferred_vco_freq;
+
                ret = dev_priv->display.modeset_calc_cdclk(state);
+               if (ret < 0)
+                       return ret;
 
-               if (!ret && intel_state->dev_cdclk != dev_priv->cdclk_freq)
+               if (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
+                   intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco)
                        ret = intel_modeset_all_pipes(state);
 
                if (ret < 0)
@@ -13606,7 +13784,8 @@ static int intel_atomic_commit(struct drm_device *dev,
                drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 
                if (dev_priv->display.modeset_commit_cdclk &&
-                   intel_state->dev_cdclk != dev_priv->cdclk_freq)
+                   (intel_state->dev_cdclk != dev_priv->cdclk_freq ||
+                    intel_state->cdclk_pll_vco != dev_priv->cdclk_pll.vco))
                        dev_priv->display.modeset_commit_cdclk(state);
 
                intel_modeset_verify_disabled(dev);
@@ -13702,8 +13881,8 @@ void intel_crtc_restore_mode(struct drm_crtc *crtc)
 
        state = drm_atomic_state_alloc(dev);
        if (!state) {
-               DRM_DEBUG_KMS("[CRTC:%d] crtc restore failed, out of memory",
-                             crtc->base.id);
+               DRM_DEBUG_KMS("[CRTC:%d:%s] crtc restore failed, out of memory",
+                             crtc->base.id, crtc->name);
                return;
        }
 
@@ -13971,9 +14150,11 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
  */
 void intel_plane_destroy(struct drm_plane *plane)
 {
-       struct intel_plane *intel_plane = to_intel_plane(plane);
+       if (!plane)
+               return;
+
        drm_plane_cleanup(plane);
-       kfree(intel_plane);
+       kfree(to_intel_plane(plane));
 }
 
 const struct drm_plane_funcs intel_plane_funcs = {
@@ -14045,10 +14226,24 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
                primary->disable_plane = i9xx_disable_primary_plane;
        }
 
-       ret = drm_universal_plane_init(dev, &primary->base, 0,
-                                      &intel_plane_funcs,
-                                      intel_primary_formats, num_formats,
-                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (INTEL_INFO(dev)->gen >= 9)
+               ret = drm_universal_plane_init(dev, &primary->base, 0,
+                                              &intel_plane_funcs,
+                                              intel_primary_formats, num_formats,
+                                              DRM_PLANE_TYPE_PRIMARY,
+                                              "plane 1%c", pipe_name(pipe));
+       else if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
+               ret = drm_universal_plane_init(dev, &primary->base, 0,
+                                              &intel_plane_funcs,
+                                              intel_primary_formats, num_formats,
+                                              DRM_PLANE_TYPE_PRIMARY,
+                                              "primary %c", pipe_name(pipe));
+       else
+               ret = drm_universal_plane_init(dev, &primary->base, 0,
+                                              &intel_plane_funcs,
+                                              intel_primary_formats, num_formats,
+                                              DRM_PLANE_TYPE_PRIMARY,
+                                              "plane %c", plane_name(primary->plane));
        if (ret)
                goto fail;
 
@@ -14206,7 +14401,8 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
                                       &intel_plane_funcs,
                                       intel_cursor_formats,
                                       ARRAY_SIZE(intel_cursor_formats),
-                                      DRM_PLANE_TYPE_CURSOR, NULL);
+                                      DRM_PLANE_TYPE_CURSOR,
+                                      "cursor %c", pipe_name(pipe));
        if (ret)
                goto fail;
 
@@ -14291,7 +14487,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
                goto fail;
 
        ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
-                                       cursor, &intel_crtc_funcs, NULL);
+                                       cursor, &intel_crtc_funcs,
+                                       "pipe %c", pipe_name(pipe));
        if (ret)
                goto fail;
 
@@ -14325,10 +14522,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
        return;
 
 fail:
-       if (primary)
-               drm_plane_cleanup(primary);
-       if (cursor)
-               drm_plane_cleanup(cursor);
+       intel_plane_destroy(primary);
+       intel_plane_destroy(cursor);
        kfree(crtc_state);
        kfree(intel_crtc);
 }
@@ -14507,6 +14702,8 @@ static void intel_setup_outputs(struct drm_device *dev)
                if (I915_READ(PCH_DP_D) & DP_DETECTED)
                        intel_dp_init(dev, PCH_DP_D, PORT_D);
        } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+               bool has_edp;
+
                /*
                 * The DP_DETECTED bit is the latched state of the DDC
                 * SDA pin at boot. However since eDP doesn't require DDC
@@ -14516,19 +14713,17 @@ static void intel_setup_outputs(struct drm_device *dev)
                 * eDP ports. Consult the VBT as well as DP_DETECTED to
                 * detect eDP ports.
                 */
-               if (I915_READ(VLV_HDMIB) & SDVO_DETECTED &&
-                   !intel_dp_is_edp(dev, PORT_B))
+               has_edp = intel_dp_is_edp(dev, PORT_B);
+               if (I915_READ(VLV_DP_B) & DP_DETECTED || has_edp)
+                       has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B);
+               if (I915_READ(VLV_HDMIB) & SDVO_DETECTED && !has_edp)
                        intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
-               if (I915_READ(VLV_DP_B) & DP_DETECTED ||
-                   intel_dp_is_edp(dev, PORT_B))
-                       intel_dp_init(dev, VLV_DP_B, PORT_B);
 
-               if (I915_READ(VLV_HDMIC) & SDVO_DETECTED &&
-                   !intel_dp_is_edp(dev, PORT_C))
+               has_edp = intel_dp_is_edp(dev, PORT_C);
+               if (I915_READ(VLV_DP_C) & DP_DETECTED || has_edp)
+                       has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C);
+               if (I915_READ(VLV_HDMIC) & SDVO_DETECTED && !has_edp)
                        intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
-               if (I915_READ(VLV_DP_C) & DP_DETECTED ||
-                   intel_dp_is_edp(dev, PORT_C))
-                       intel_dp_init(dev, VLV_DP_C, PORT_C);
 
                if (IS_CHERRYVIEW(dev)) {
                        /* eDP not supported on port D, so don't check VBT */
@@ -15020,6 +15215,11 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
                        broxton_modeset_commit_cdclk;
                dev_priv->display.modeset_calc_cdclk =
                        broxton_modeset_calc_cdclk;
+       } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+               dev_priv->display.modeset_commit_cdclk =
+                       skl_modeset_commit_cdclk;
+               dev_priv->display.modeset_calc_cdclk =
+                       skl_modeset_calc_cdclk;
        }
 
        switch (INTEL_INFO(dev_priv)->gen) {
@@ -15418,6 +15618,9 @@ void intel_modeset_init(struct drm_device *dev)
 
        intel_shared_dpll_init(dev);
 
+       if (dev_priv->max_cdclk_freq == 0)
+               intel_update_max_cdclk(dev);
+
        /* Just disable it once at startup */
        i915_disable_vga(dev);
        intel_setup_outputs(dev);
@@ -15558,8 +15761,8 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
        if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
                bool plane;
 
-               DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
-                             crtc->base.base.id);
+               DRM_DEBUG_KMS("[CRTC:%d:%s] wrong plane connection detected!\n",
+                             crtc->base.base.id, crtc->base.name);
 
                /* Pipe has the wrong plane attached and the plane is active.
                 * Temporarily change the plane mapping and disable everything
@@ -15727,26 +15930,24 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                if (crtc_state->base.active) {
                        dev_priv->active_crtcs |= 1 << crtc->pipe;
 
-                       if (IS_BROADWELL(dev_priv)) {
+                       if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
                                pixclk = ilk_pipe_pixel_rate(crtc_state);
-
-                               /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
-                               if (crtc_state->ips_enabled)
-                                       pixclk = DIV_ROUND_UP(pixclk * 100, 95);
-                       } else if (IS_VALLEYVIEW(dev_priv) ||
-                                  IS_CHERRYVIEW(dev_priv) ||
-                                  IS_BROXTON(dev_priv))
+                       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                                pixclk = crtc_state->base.adjusted_mode.crtc_clock;
                        else
                                WARN_ON(dev_priv->display.modeset_calc_cdclk);
+
+                       /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
+                       if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
+                               pixclk = DIV_ROUND_UP(pixclk * 100, 95);
                }
 
                dev_priv->min_pixclk[crtc->pipe] = pixclk;
 
                readout_plane_state(crtc);
 
-               DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
-                             crtc->base.base.id,
+               DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n",
+                             crtc->base.base.id, crtc->base.name,
                              crtc->active ? "enabled" : "disabled");
        }
 
index cccf9bc..7dfff87 100644 (file)
@@ -1578,6 +1578,27 @@ found:
                                &pipe_config->dp_m2_n2);
        }
 
+       /*
+        * DPLL0 VCO may need to be adjusted to get the correct
+        * clock for eDP. This will affect cdclk as well.
+        */
+       if (is_edp(intel_dp) &&
+           (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))) {
+               int vco;
+
+               switch (pipe_config->port_clock / 2) {
+               case 108000:
+               case 216000:
+                       vco = 8640000;
+                       break;
+               default:
+                       vco = 8100000;
+                       break;
+               }
+
+               to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco;
+       }
+
        if (!HAS_DDI(dev))
                intel_dp_set_clock(encoder, pipe_config);
 
@@ -5547,9 +5568,9 @@ fail:
        return false;
 }
 
-void
-intel_dp_init(struct drm_device *dev,
-             i915_reg_t output_reg, enum port port)
+bool intel_dp_init(struct drm_device *dev,
+                  i915_reg_t output_reg,
+                  enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_digital_port *intel_dig_port;
@@ -5559,7 +5580,7 @@ intel_dp_init(struct drm_device *dev,
 
        intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
        if (!intel_dig_port)
-               return;
+               return false;
 
        intel_connector = intel_connector_alloc();
        if (!intel_connector)
@@ -5569,7 +5590,7 @@ intel_dp_init(struct drm_device *dev,
        encoder = &intel_encoder->base;
 
        if (drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
-                            DRM_MODE_ENCODER_TMDS, NULL))
+                            DRM_MODE_ENCODER_TMDS, "DP %c", port_name(port)))
                goto err_encoder_init;
 
        intel_encoder->compute_config = intel_dp_compute_config;
@@ -5616,7 +5637,7 @@ intel_dp_init(struct drm_device *dev,
        if (!intel_dp_init_connector(intel_dig_port, intel_connector))
                goto err_init_connector;
 
-       return;
+       return true;
 
 err_init_connector:
        drm_encoder_cleanup(encoder);
@@ -5624,8 +5645,7 @@ err_encoder_init:
        kfree(intel_connector);
 err_connector_alloc:
        kfree(intel_dig_port);
-
-       return;
+       return false;
 }
 
 void intel_dp_mst_suspend(struct drm_device *dev)
index 7a34090..f62ca9a 100644 (file)
@@ -534,7 +534,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum
        intel_mst->primary = intel_dig_port;
 
        drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs,
-                        DRM_MODE_ENCODER_DPMST, NULL);
+                        DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe));
 
        intel_encoder->type = INTEL_OUTPUT_DP_MST;
        intel_encoder->crtc_mask = 0x7;
index c283ba4..c0eff15 100644 (file)
@@ -208,8 +208,8 @@ intel_find_shared_dpll(struct intel_crtc *crtc,
                if (memcmp(&crtc_state->dpll_hw_state,
                           &shared_dpll[i].hw_state,
                           sizeof(crtc_state->dpll_hw_state)) == 0) {
-                       DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, active %x)\n",
-                                     crtc->base.base.id, pll->name,
+                       DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
+                                     crtc->base.base.id, crtc->base.name, pll->name,
                                      shared_dpll[i].crtc_mask,
                                      pll->active_mask);
                        return pll;
@@ -220,8 +220,8 @@ intel_find_shared_dpll(struct intel_crtc *crtc,
        for (i = range_min; i <= range_max; i++) {
                pll = &dev_priv->shared_dplls[i];
                if (shared_dpll[i].crtc_mask == 0) {
-                       DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
-                                     crtc->base.base.id, pll->name);
+                       DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
+                                     crtc->base.base.id, crtc->base.name, pll->name);
                        return pll;
                }
        }
@@ -358,14 +358,17 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
                i = (enum intel_dpll_id) crtc->pipe;
                pll = &dev_priv->shared_dplls[i];
 
-               DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
-                             crtc->base.base.id, pll->name);
+               DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
+                             crtc->base.base.id, crtc->base.name, pll->name);
        } else {
                pll = intel_find_shared_dpll(crtc, crtc_state,
                                             DPLL_ID_PCH_PLL_A,
                                             DPLL_ID_PCH_PLL_B);
        }
 
+       if (!pll)
+               return NULL;
+
        /* reference the pll */
        intel_reference_shared_dpll(pll, crtc_state);
 
@@ -1236,9 +1239,6 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
                case 162000:
                        ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
                        break;
-               /* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
-               results in CDCLK change. Need to handle the change of CDCLK by
-               disabling pipes and re-enabling them */
                case 108000:
                        ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
                        break;
@@ -1613,8 +1613,8 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
        i = (enum intel_dpll_id) intel_dig_port->port;
        pll = intel_get_shared_dpll_by_id(dev_priv, i);
 
-       DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
-               crtc->base.base.id, pll->name);
+       DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
+                     crtc->base.base.id, crtc->base.name, pll->name);
 
        intel_reference_shared_dpll(pll, crtc_state);
 
@@ -1633,18 +1633,10 @@ static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
 static void intel_ddi_pll_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t val = I915_READ(LCPLL_CTL);
-
-       if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
-               int cdclk_freq;
-
-               cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
-               dev_priv->skl_boot_cdclk = cdclk_freq;
-               if (skl_sanitize_cdclk(dev_priv))
-                       DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
-               if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
-                       DRM_ERROR("LCPLL1 is disabled\n");
-       } else if (!IS_BROXTON(dev_priv)) {
+
+       if (INTEL_GEN(dev_priv) < 9) {
+               uint32_t val = I915_READ(LCPLL_CTL);
+
                /*
                 * The LCPLL register should be turned on by the BIOS. For now
                 * let's just check its state and print errors in case
index 97de5e0..ebe7b34 100644 (file)
@@ -304,6 +304,9 @@ struct intel_atomic_state {
        unsigned int active_crtcs;
        unsigned int min_pixclk[I915_MAX_PIPES];
 
+       /* SKL/KBL Only */
+       unsigned int cdclk_pll_vco;
+
        struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
 
        /*
@@ -1133,6 +1136,7 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv);
 void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
+void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco);
 void intel_update_rawclk(struct drm_i915_private *dev_priv);
 int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
                      const char *name, u32 reg, int ref_freq);
@@ -1259,7 +1263,6 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv);
 void hsw_disable_pc8(struct drm_i915_private *dev_priv);
 void broxton_init_cdclk(struct drm_i915_private *dev_priv);
 void broxton_uninit_cdclk(struct drm_i915_private *dev_priv);
-bool broxton_cdclk_verify_state(struct drm_i915_private *dev_priv);
 void broxton_ddi_phy_init(struct drm_i915_private *dev_priv);
 void broxton_ddi_phy_uninit(struct drm_i915_private *dev_priv);
 void broxton_ddi_phy_verify_state(struct drm_i915_private *dev_priv);
@@ -1268,8 +1271,8 @@ void bxt_enable_dc9(struct drm_i915_private *dev_priv);
 void bxt_disable_dc9(struct drm_i915_private *dev_priv);
 void gen9_enable_dc5(struct drm_i915_private *dev_priv);
 void skl_init_cdclk(struct drm_i915_private *dev_priv);
-int skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
 void skl_uninit_cdclk(struct drm_i915_private *dev_priv);
+unsigned int skl_cdclk_get_vco(unsigned int freq);
 void skl_enable_dc6(struct drm_i915_private *dev_priv);
 void skl_disable_dc6(struct drm_i915_private *dev_priv);
 void intel_dp_get_m_n(struct intel_crtc *crtc,
@@ -1309,7 +1312,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private *);
 void intel_csr_ucode_resume(struct drm_i915_private *);
 
 /* intel_dp.c */
-void intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
+bool intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                             struct intel_connector *intel_connector);
 void intel_dp_set_link_params(struct intel_dp *intel_dp,
index 4009618..cbe2537 100644 (file)
@@ -1450,7 +1450,7 @@ void intel_dsi_init(struct drm_device *dev)
        connector = &intel_connector->base;
 
        drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI,
-                        NULL);
+                        "DSI %c", port_name(port));
 
        intel_encoder->compute_config = intel_dsi_compute_config;
        intel_encoder->pre_enable = intel_dsi_pre_enable;
index 286baec..a456f2e 100644 (file)
@@ -406,6 +406,18 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
        return mode;
 }
 
+static char intel_dvo_port_name(i915_reg_t dvo_reg)
+{
+       if (i915_mmio_reg_equal(dvo_reg, DVOA))
+               return 'A';
+       else if (i915_mmio_reg_equal(dvo_reg, DVOB))
+               return 'B';
+       else if (i915_mmio_reg_equal(dvo_reg, DVOC))
+               return 'C';
+       else
+               return '?';
+}
+
 void intel_dvo_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -428,8 +440,6 @@ void intel_dvo_init(struct drm_device *dev)
        intel_dvo->attached_connector = intel_connector;
 
        intel_encoder = &intel_dvo->base;
-       drm_encoder_init(dev, &intel_encoder->base,
-                        &intel_dvo_enc_funcs, encoder_type, NULL);
 
        intel_encoder->disable = intel_disable_dvo;
        intel_encoder->enable = intel_enable_dvo;
@@ -496,6 +506,10 @@ void intel_dvo_init(struct drm_device *dev)
                if (!dvoinit)
                        continue;
 
+               drm_encoder_init(dev, &intel_encoder->base,
+                                &intel_dvo_enc_funcs, encoder_type,
+                                "DVO %c", intel_dvo_port_name(dvo->dvo_reg));
+
                intel_encoder->type = INTEL_OUTPUT_DVO;
                intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
                switch (dvo->type) {
index 99e2753..ef8e676 100644 (file)
@@ -490,10 +490,10 @@ retry:
                }
                crtcs[i] = new_crtc;
 
-               DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
+               DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n",
                              connector->name,
-                             pipe_name(to_intel_crtc(connector->state->crtc)->pipe),
                              connector->state->crtc->base.id,
+                             connector->state->crtc->name,
                              modes[i]->hdisplay, modes[i]->vdisplay,
                              modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");
 
index 9d79c4c..41601c7 100644 (file)
@@ -48,14 +48,23 @@ struct drm_i915_gem_request;
  * queue (a circular array of work items), again described in the process
  * descriptor. Work queue pages are mapped momentarily as required.
  *
- * Finally, we also keep a few statistics here, including the number of
- * submissions to each engine, and a record of the last submission failure
- * (if any).
+ * We also keep a few statistics on failures. Ideally, these should all
+ * be zero!
+ *   no_wq_space: times that the submission pre-check found no space was
+ *                available in the work queue (note, the queue is shared,
+ *                not per-engine). It is OK for this to be nonzero, but
+ *                it should not be huge!
+ *   q_fail: failed to enqueue a work item. This should never happen,
+ *           because we check for space beforehand.
+ *   b_fail: failed to ring the doorbell. This should never happen, unless
+ *           somehow the hardware misbehaves, or maybe if the GuC firmware
+ *           crashes? We probably need to reset the GPU to recover.
+ *   retcode: errno from last guc_submit()
  */
 struct i915_guc_client {
        struct drm_i915_gem_object *client_obj;
        void *client_base;              /* first page (only) of above   */
-       struct intel_context *owner;
+       struct i915_gem_context *owner;
        struct intel_guc *guc;
        uint32_t priority;
        uint32_t ctx_index;
@@ -71,12 +80,13 @@ struct i915_guc_client {
        uint32_t wq_tail;
        uint32_t unused;                /* Was 'wq_head'                */
 
-       /* GuC submission statistics & status */
-       uint64_t submissions[GUC_MAX_ENGINES_NUM];
-       uint32_t q_fail;
+       uint32_t no_wq_space;
+       uint32_t q_fail;                /* No longer used               */
        uint32_t b_fail;
        int retcode;
-       int spare;                      /* pad to 32 DWords             */
+
+       /* Per-engine counts of GuC submissions */
+       uint64_t submissions[GUC_MAX_ENGINES_NUM];
 };
 
 enum intel_guc_fw_status {
@@ -138,9 +148,9 @@ struct intel_guc {
 };
 
 /* intel_guc_loader.c */
-extern void intel_guc_ucode_init(struct drm_device *dev);
-extern int intel_guc_ucode_load(struct drm_device *dev);
-extern void intel_guc_ucode_fini(struct drm_device *dev);
+extern void intel_guc_init(struct drm_device *dev);
+extern int intel_guc_setup(struct drm_device *dev);
+extern void intel_guc_fini(struct drm_device *dev);
 extern const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status);
 extern int intel_guc_suspend(struct drm_device *dev);
 extern int intel_guc_resume(struct drm_device *dev);
@@ -148,10 +158,9 @@ extern int intel_guc_resume(struct drm_device *dev);
 /* i915_guc_submission.c */
 int i915_guc_submission_init(struct drm_device *dev);
 int i915_guc_submission_enable(struct drm_device *dev);
-int i915_guc_submit(struct i915_guc_client *client,
-                   struct drm_i915_gem_request *rq);
+int i915_guc_wq_check_space(struct drm_i915_gem_request *rq);
+int i915_guc_submit(struct drm_i915_gem_request *rq);
 void i915_guc_submission_disable(struct drm_device *dev);
 void i915_guc_submission_fini(struct drm_device *dev);
-int i915_guc_wq_check_space(struct i915_guc_client *client);
 
 #endif
index 2de57ff..944786d 100644 (file)
@@ -71,7 +71,8 @@
 #define   WQ_WORKLOAD_TOUCH            (2 << WQ_WORKLOAD_SHIFT)
 
 #define WQ_RING_TAIL_SHIFT             20
-#define WQ_RING_TAIL_MASK              (0x7FF << WQ_RING_TAIL_SHIFT)
+#define WQ_RING_TAIL_MAX               0x7FF   /* 2^11 QWords */
+#define WQ_RING_TAIL_MASK              (WQ_RING_TAIL_MAX << WQ_RING_TAIL_SHIFT)
 
 #define GUC_DOORBELL_ENABLED           1
 #define GUC_DOORBELL_DISABLED          0
index 34405de..f2b88c7 100644 (file)
@@ -103,6 +103,7 @@ static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv)
 {
        struct intel_engine_cs *engine;
        int irqs;
+       u32 tmp;
 
        /* tell all command streamers to forward interrupts and vblank to GuC */
        irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS);
@@ -117,6 +118,16 @@ static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv)
        I915_WRITE(GUC_BCS_RCS_IER, ~irqs);
        I915_WRITE(GUC_VCS2_VCS1_IER, ~irqs);
        I915_WRITE(GUC_WD_VECS_IER, ~irqs);
+
+       /*
+        * If GuC has routed PM interrupts to itself, don't keep it.
+        * and keep other interrupts those are unmasked by GuC.
+       */
+       tmp = I915_READ(GEN6_PMINTRMSK);
+       if (tmp & GEN8_PMINTR_REDIRECT_TO_NON_DISP) {
+               dev_priv->rps.pm_intr_keep |= ~(tmp & ~GEN8_PMINTR_REDIRECT_TO_NON_DISP);
+               dev_priv->rps.pm_intr_keep &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP;
+       }
 }
 
 static u32 get_gttype(struct drm_i915_private *dev_priv)
@@ -386,65 +397,58 @@ static int i915_reset_guc(struct drm_i915_private *dev_priv)
 }
 
 /**
- * intel_guc_ucode_load() - load GuC uCode into the device
+ * intel_guc_setup() - finish preparing the GuC for activity
  * @dev:       drm device
  *
  * Called from gem_init_hw() during driver loading and also after a GPU reset.
  *
+ * The main action required here it to load the GuC uCode into the device.
  * The firmware image should have already been fetched into memory by the
- * earlier call to intel_guc_ucode_init(), so here we need only check that
- * is succeeded, and then transfer the image to the h/w.
+ * earlier call to intel_guc_init(), so here we need only check that worked,
+ * and then transfer the image to the h/w.
  *
  * Return:     non-zero code on error
  */
-int intel_guc_ucode_load(struct drm_device *dev)
+int intel_guc_setup(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
-       int retries, err = 0;
+       const char *fw_path = guc_fw->guc_fw_path;
+       int retries, ret, err;
 
-       if (!i915.enable_guc_submission)
-               return 0;
-
-       DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
+       DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n",
+               fw_path,
                intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
                intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
 
-       direct_interrupts_to_host(dev_priv);
-
-       if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_NONE)
-               return 0;
-
-       if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_SUCCESS &&
-           guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL)
-               return -ENOEXEC;
-
-       guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
-
-       DRM_DEBUG_DRIVER("GuC fw fetch status %s\n",
-               intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
+       /* Loading forbidden, or no firmware to load? */
+       if (!i915.enable_guc_loading) {
+               err = 0;
+               goto fail;
+       } else if (fw_path == NULL || *fw_path == '\0') {
+               if (*fw_path == '\0')
+                       DRM_INFO("No GuC firmware known for this platform\n");
+               err = -ENODEV;
+               goto fail;
+       }
 
-       switch (guc_fw->guc_fw_fetch_status) {
-       case GUC_FIRMWARE_FAIL:
-               /* something went wrong :( */
+       /* Fetch failed, or already fetched but failed to load? */
+       if (guc_fw->guc_fw_fetch_status != GUC_FIRMWARE_SUCCESS) {
                err = -EIO;
                goto fail;
-
-       case GUC_FIRMWARE_NONE:
-       case GUC_FIRMWARE_PENDING:
-       default:
-               /* "can't happen" */
-               WARN_ONCE(1, "GuC fw %s invalid guc_fw_fetch_status %s [%d]\n",
-                       guc_fw->guc_fw_path,
-                       intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
-                       guc_fw->guc_fw_fetch_status);
-               err = -ENXIO;
+       } else if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL) {
+               err = -ENOEXEC;
                goto fail;
-
-       case GUC_FIRMWARE_SUCCESS:
-               break;
        }
 
+       direct_interrupts_to_host(dev_priv);
+
+       guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
+
+       DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
+               intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
+               intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+
        err = i915_guc_submission_init(dev);
        if (err)
                goto fail;
@@ -462,7 +466,7 @@ int intel_guc_ucode_load(struct drm_device *dev)
                 */
                err = i915_reset_guc(dev_priv);
                if (err) {
-                       DRM_ERROR("GuC reset failed, err %d\n", err);
+                       DRM_ERROR("GuC reset failed: %d\n", err);
                        goto fail;
                }
 
@@ -473,8 +477,8 @@ int intel_guc_ucode_load(struct drm_device *dev)
                if (--retries == 0)
                        goto fail;
 
-               DRM_INFO("GuC fw load failed, err %d; will reset and "
-                       "retry %d more time(s)\n", err, retries);
+               DRM_INFO("GuC fw load failed: %d; will reset and "
+                        "retry %d more time(s)\n", err, retries);
        }
 
        guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS;
@@ -496,7 +500,6 @@ int intel_guc_ucode_load(struct drm_device *dev)
        return 0;
 
 fail:
-       DRM_ERROR("GuC firmware load failed, err %d\n", err);
        if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING)
                guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL;
 
@@ -504,7 +507,41 @@ fail:
        i915_guc_submission_disable(dev);
        i915_guc_submission_fini(dev);
 
-       return err;
+       /*
+        * We've failed to load the firmware :(
+        *
+        * Decide whether to disable GuC submission and fall back to
+        * execlist mode, and whether to hide the error by returning
+        * zero or to return -EIO, which the caller will treat as a
+        * nonfatal error (i.e. it doesn't prevent driver load, but
+        * marks the GPU as wedged until reset).
+        */
+       if (i915.enable_guc_loading > 1) {
+               ret = -EIO;
+       } else if (i915.enable_guc_submission > 1) {
+               ret = -EIO;
+       } else {
+               ret = 0;
+       }
+
+       if (err == 0)
+               DRM_INFO("GuC firmware load skipped\n");
+       else if (ret == -EIO)
+               DRM_ERROR("GuC firmware load failed: %d\n", err);
+       else
+               DRM_INFO("GuC firmware load failed: %d\n", err);
+
+       if (i915.enable_guc_submission) {
+               if (fw_path == NULL)
+                       DRM_INFO("GuC submission without firmware not supported\n");
+               if (ret == 0)
+                       DRM_INFO("Falling back to execlist mode\n");
+               else
+                       DRM_ERROR("GuC init failed: %d\n", ret);
+       }
+       i915.enable_guc_submission = 0;
+
+       return ret;
 }
 
 static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
@@ -629,22 +666,25 @@ fail:
 }
 
 /**
- * intel_guc_ucode_init() - define parameters and fetch firmware
+ * intel_guc_init() - define parameters and fetch firmware
  * @dev:       drm device
  *
  * Called early during driver load, but after GEM is initialised.
  *
  * The firmware will be transferred to the GuC's memory later,
- * when intel_guc_ucode_load() is called.
+ * when intel_guc_setup() is called.
  */
-void intel_guc_ucode_init(struct drm_device *dev)
+void intel_guc_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
        const char *fw_path;
 
-       if (!HAS_GUC_SCHED(dev))
-               i915.enable_guc_submission = false;
+       /* A negative value means "use platform default" */
+       if (i915.enable_guc_loading < 0)
+               i915.enable_guc_loading = HAS_GUC_UCODE(dev);
+       if (i915.enable_guc_submission < 0)
+               i915.enable_guc_submission = HAS_GUC_SCHED(dev);
 
        if (!HAS_GUC_UCODE(dev)) {
                fw_path = NULL;
@@ -657,26 +697,21 @@ void intel_guc_ucode_init(struct drm_device *dev)
                guc_fw->guc_fw_major_wanted = 8;
                guc_fw->guc_fw_minor_wanted = 7;
        } else {
-               i915.enable_guc_submission = false;
                fw_path = "";   /* unknown device */
        }
 
-       if (!i915.enable_guc_submission)
-               return;
-
        guc_fw->guc_dev = dev;
        guc_fw->guc_fw_path = fw_path;
        guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
        guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE;
 
+       /* Early (and silent) return if GuC loading is disabled */
+       if (!i915.enable_guc_loading)
+               return;
        if (fw_path == NULL)
                return;
-
-       if (*fw_path == '\0') {
-               DRM_ERROR("No GuC firmware known for this platform\n");
-               guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL;
+       if (*fw_path == '\0')
                return;
-       }
 
        guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING;
        DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path);
@@ -685,10 +720,10 @@ void intel_guc_ucode_init(struct drm_device *dev)
 }
 
 /**
- * intel_guc_ucode_fini() - clean up all allocated resources
+ * intel_guc_fini() - clean up all allocated resources
  * @dev:       drm device
  */
-void intel_guc_ucode_fini(struct drm_device *dev)
+void intel_guc_fini(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
index 6b52c6a..eb455ea 100644 (file)
@@ -1945,7 +1945,7 @@ void intel_hdmi_init(struct drm_device *dev,
        intel_encoder = &intel_dig_port->base;
 
        drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
-                        DRM_MODE_ENCODER_TMDS, NULL);
+                        DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port));
 
        intel_encoder->compute_config = intel_hdmi_compute_config;
        if (HAS_PCH_SPLIT(dev)) {
index db10c96..5c191a1 100644 (file)
@@ -231,9 +231,9 @@ enum {
 /* Typical size of the average request (2 pipecontrols and a MI_BB) */
 #define EXECLISTS_REQUEST_SIZE 64 /* bytes */
 
-static int execlists_context_deferred_alloc(struct intel_context *ctx,
+static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
                                            struct intel_engine_cs *engine);
-static int intel_lr_context_pin(struct intel_context *ctx,
+static int intel_lr_context_pin(struct i915_gem_context *ctx,
                                struct intel_engine_cs *engine);
 
 /**
@@ -302,7 +302,7 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine)
  *                                       descriptor for a pinned context
  *
  * @ctx: Context to work on
- * @ring: Engine the descriptor will be used with
+ * @engine: Engine the descriptor will be used with
  *
  * The context descriptor encodes various attributes of a context,
  * including its GTT address and some flags. Because it's fairly
@@ -317,22 +317,23 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine)
  *    bits 55-63:    group ID, currently unused and set to 0
  */
 static void
-intel_lr_context_descriptor_update(struct intel_context *ctx,
+intel_lr_context_descriptor_update(struct i915_gem_context *ctx,
                                   struct intel_engine_cs *engine)
 {
+       struct intel_context *ce = &ctx->engine[engine->id];
        u64 desc;
 
        BUILD_BUG_ON(MAX_CONTEXT_HW_ID > (1<<GEN8_CTX_ID_WIDTH));
 
        desc = engine->ctx_desc_template;                       /* bits  0-11 */
-       desc |= ctx->engine[engine->id].lrc_vma->node.start +   /* bits 12-31 */
-              LRC_PPHWSP_PN * PAGE_SIZE;
+       desc |= ce->lrc_vma->node.start + LRC_PPHWSP_PN * PAGE_SIZE;
+                                                               /* bits 12-31 */
        desc |= (u64)ctx->hw_id << GEN8_CTX_ID_SHIFT;           /* bits 32-52 */
 
-       ctx->engine[engine->id].lrc_desc = desc;
+       ce->lrc_desc = desc;
 }
 
-uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
+uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx,
                                     struct intel_engine_cs *engine)
 {
        return ctx->engine[engine->id].lrc_desc;
@@ -676,6 +677,7 @@ static int execlists_move_to_gpu(struct drm_i915_gem_request *req,
 int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request)
 {
        struct intel_engine_cs *engine = request->engine;
+       struct intel_context *ce = &request->ctx->engine[engine->id];
        int ret;
 
        /* Flush enough space to reduce the likelihood of waiting after
@@ -684,13 +686,13 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
         */
        request->reserved_space += EXECLISTS_REQUEST_SIZE;
 
-       if (request->ctx->engine[engine->id].state == NULL) {
+       if (!ce->state) {
                ret = execlists_context_deferred_alloc(request->ctx, engine);
                if (ret)
                        return ret;
        }
 
-       request->ringbuf = request->ctx->engine[engine->id].ringbuf;
+       request->ringbuf = ce->ringbuf;
 
        if (i915.enable_guc_submission) {
                /*
@@ -698,9 +700,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
                 * going any further, as the i915_add_request() call
                 * later on mustn't fail ...
                 */
-               struct intel_guc *guc = &request->i915->guc;
-
-               ret = i915_guc_wq_check_space(guc->execbuf_client);
+               ret = i915_guc_wq_check_space(request);
                if (ret)
                        return ret;
        }
@@ -713,12 +713,12 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
        if (ret)
                goto err_unpin;
 
-       if (!request->ctx->engine[engine->id].initialised) {
+       if (!ce->initialised) {
                ret = engine->init_context(request);
                if (ret)
                        goto err_unpin;
 
-               request->ctx->engine[engine->id].initialised = true;
+               ce->initialised = true;
        }
 
        /* Note that after this point, we have committed to using
@@ -749,7 +749,6 @@ static int
 intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
 {
        struct intel_ringbuffer *ringbuf = request->ringbuf;
-       struct drm_i915_private *dev_priv = request->i915;
        struct intel_engine_cs *engine = request->engine;
 
        intel_logical_ring_advance(ringbuf);
@@ -777,8 +776,8 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
        request->previous_context = engine->last_context;
        engine->last_context = request->ctx;
 
-       if (dev_priv->guc.execbuf_client)
-               i915_guc_submit(dev_priv->guc.execbuf_client, request);
+       if (i915.enable_guc_submission)
+               i915_guc_submit(request);
        else
                execlists_context_queue(request);
 
@@ -934,28 +933,26 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req)
        return 0;
 }
 
-static int intel_lr_context_pin(struct intel_context *ctx,
+static int intel_lr_context_pin(struct i915_gem_context *ctx,
                                struct intel_engine_cs *engine)
 {
        struct drm_i915_private *dev_priv = ctx->i915;
-       struct drm_i915_gem_object *ctx_obj;
-       struct intel_ringbuffer *ringbuf;
+       struct intel_context *ce = &ctx->engine[engine->id];
        void *vaddr;
        u32 *lrc_reg_state;
        int ret;
 
        lockdep_assert_held(&ctx->i915->dev->struct_mutex);
 
-       if (ctx->engine[engine->id].pin_count++)
+       if (ce->pin_count++)
                return 0;
 
-       ctx_obj = ctx->engine[engine->id].state;
-       ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN,
-                       PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
+       ret = i915_gem_obj_ggtt_pin(ce->state, GEN8_LR_CONTEXT_ALIGN,
+                                   PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
        if (ret)
                goto err;
 
-       vaddr = i915_gem_object_pin_map(ctx_obj);
+       vaddr = i915_gem_object_pin_map(ce->state);
        if (IS_ERR(vaddr)) {
                ret = PTR_ERR(vaddr);
                goto unpin_ctx_obj;
@@ -963,17 +960,17 @@ static int intel_lr_context_pin(struct intel_context *ctx,
 
        lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
 
-       ringbuf = ctx->engine[engine->id].ringbuf;
-       ret = intel_pin_and_map_ringbuffer_obj(dev_priv, ringbuf);
+       ret = intel_pin_and_map_ringbuffer_obj(dev_priv, ce->ringbuf);
        if (ret)
                goto unpin_map;
 
        i915_gem_context_reference(ctx);
-       ctx->engine[engine->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj);
+       ce->lrc_vma = i915_gem_obj_to_ggtt(ce->state);
        intel_lr_context_descriptor_update(ctx, engine);
-       lrc_reg_state[CTX_RING_BUFFER_START+1] = ringbuf->vma->node.start;
-       ctx->engine[engine->id].lrc_reg_state = lrc_reg_state;
-       ctx_obj->dirty = true;
+
+       lrc_reg_state[CTX_RING_BUFFER_START+1] = ce->ringbuf->vma->node.start;
+       ce->lrc_reg_state = lrc_reg_state;
+       ce->state->dirty = true;
 
        /* Invalidate GuC TLB. */
        if (i915.enable_guc_submission)
@@ -982,34 +979,33 @@ static int intel_lr_context_pin(struct intel_context *ctx,
        return 0;
 
 unpin_map:
-       i915_gem_object_unpin_map(ctx_obj);
+       i915_gem_object_unpin_map(ce->state);
 unpin_ctx_obj:
-       i915_gem_object_ggtt_unpin(ctx_obj);
+       i915_gem_object_ggtt_unpin(ce->state);
 err:
-       ctx->engine[engine->id].pin_count = 0;
+       ce->pin_count = 0;
        return ret;
 }
 
-void intel_lr_context_unpin(struct intel_context *ctx,
+void intel_lr_context_unpin(struct i915_gem_context *ctx,
                            struct intel_engine_cs *engine)
 {
-       struct drm_i915_gem_object *ctx_obj;
+       struct intel_context *ce = &ctx->engine[engine->id];
 
        lockdep_assert_held(&ctx->i915->dev->struct_mutex);
-       GEM_BUG_ON(ctx->engine[engine->id].pin_count == 0);
+       GEM_BUG_ON(ce->pin_count == 0);
 
-       if (--ctx->engine[engine->id].pin_count)
+       if (--ce->pin_count)
                return;
 
-       intel_unpin_ringbuffer_obj(ctx->engine[engine->id].ringbuf);
+       intel_unpin_ringbuffer_obj(ce->ringbuf);
 
-       ctx_obj = ctx->engine[engine->id].state;
-       i915_gem_object_unpin_map(ctx_obj);
-       i915_gem_object_ggtt_unpin(ctx_obj);
+       i915_gem_object_unpin_map(ce->state);
+       i915_gem_object_ggtt_unpin(ce->state);
 
-       ctx->engine[engine->id].lrc_vma = NULL;
-       ctx->engine[engine->id].lrc_desc = 0;
-       ctx->engine[engine->id].lrc_reg_state = NULL;
+       ce->lrc_vma = NULL;
+       ce->lrc_desc = 0;
+       ce->lrc_reg_state = NULL;
 
        i915_gem_context_unreference(ctx);
 }
@@ -2051,7 +2047,7 @@ logical_ring_setup(struct drm_device *dev, enum intel_engine_id id)
 static int
 logical_ring_init(struct intel_engine_cs *engine)
 {
-       struct intel_context *dctx = engine->i915->kernel_context;
+       struct i915_gem_context *dctx = engine->i915->kernel_context;
        int ret;
 
        ret = i915_cmd_parser_init_ring(engine);
@@ -2275,7 +2271,7 @@ static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *engine)
 }
 
 static int
-populate_lr_context(struct intel_context *ctx,
+populate_lr_context(struct i915_gem_context *ctx,
                    struct drm_i915_gem_object *ctx_obj,
                    struct intel_engine_cs *engine,
                    struct intel_ringbuffer *ringbuf)
@@ -2415,31 +2411,6 @@ populate_lr_context(struct intel_context *ctx,
        return 0;
 }
 
-/**
- * intel_lr_context_free() - free the LRC specific bits of a context
- * @ctx: the LR context to free.
- *
- * The real context freeing is done in i915_gem_context_free: this only
- * takes care of the bits that are LRC related: the per-engine backing
- * objects and the logical ringbuffer.
- */
-void intel_lr_context_free(struct intel_context *ctx)
-{
-       int i;
-
-       for (i = I915_NUM_ENGINES; --i >= 0; ) {
-               struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
-               struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state;
-
-               if (!ctx_obj)
-                       continue;
-
-               WARN_ON(ctx->engine[i].pin_count);
-               intel_ringbuffer_free(ringbuf);
-               drm_gem_object_unreference(&ctx_obj->base);
-       }
-}
-
 /**
  * intel_lr_context_size() - return the size of the context for an engine
  * @ring: which engine to find the context size for
@@ -2491,16 +2462,16 @@ uint32_t intel_lr_context_size(struct intel_engine_cs *engine)
  *
  * Return: non-zero on error.
  */
-static int execlists_context_deferred_alloc(struct intel_context *ctx,
+static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
                                            struct intel_engine_cs *engine)
 {
        struct drm_i915_gem_object *ctx_obj;
+       struct intel_context *ce = &ctx->engine[engine->id];
        uint32_t context_size;
        struct intel_ringbuffer *ringbuf;
        int ret;
 
-       WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL);
-       WARN_ON(ctx->engine[engine->id].state);
+       WARN_ON(ce->state);
 
        context_size = round_up(intel_lr_context_size(engine), 4096);
 
@@ -2525,9 +2496,9 @@ static int execlists_context_deferred_alloc(struct intel_context *ctx,
                goto error_ringbuf;
        }
 
-       ctx->engine[engine->id].ringbuf = ringbuf;
-       ctx->engine[engine->id].state = ctx_obj;
-       ctx->engine[engine->id].initialised = engine->init_context == NULL;
+       ce->ringbuf = ringbuf;
+       ce->state = ctx_obj;
+       ce->initialised = engine->init_context == NULL;
 
        return 0;
 
@@ -2535,21 +2506,19 @@ error_ringbuf:
        intel_ringbuffer_free(ringbuf);
 error_deref_obj:
        drm_gem_object_unreference(&ctx_obj->base);
-       ctx->engine[engine->id].ringbuf = NULL;
-       ctx->engine[engine->id].state = NULL;
+       ce->ringbuf = NULL;
+       ce->state = NULL;
        return ret;
 }
 
 void intel_lr_context_reset(struct drm_i915_private *dev_priv,
-                           struct intel_context *ctx)
+                           struct i915_gem_context *ctx)
 {
        struct intel_engine_cs *engine;
 
        for_each_engine(engine, dev_priv) {
-               struct drm_i915_gem_object *ctx_obj =
-                               ctx->engine[engine->id].state;
-               struct intel_ringbuffer *ringbuf =
-                               ctx->engine[engine->id].ringbuf;
+               struct intel_context *ce = &ctx->engine[engine->id];
+               struct drm_i915_gem_object *ctx_obj = ce->state;
                void *vaddr;
                uint32_t *reg_state;
 
@@ -2568,7 +2537,7 @@ void intel_lr_context_reset(struct drm_i915_private *dev_priv,
 
                i915_gem_object_unpin_map(ctx_obj);
 
-               ringbuf->head = 0;
-               ringbuf->tail = 0;
+               ce->ringbuf->head = 0;
+               ce->ringbuf->tail = 0;
        }
 }
index 1afba03..a8db42a 100644 (file)
@@ -99,16 +99,17 @@ static inline void intel_logical_ring_emit_reg(struct intel_ringbuffer *ringbuf,
 #define LRC_PPHWSP_PN  (LRC_GUCSHR_PN + 1)
 #define LRC_STATE_PN   (LRC_PPHWSP_PN + 1)
 
-void intel_lr_context_free(struct intel_context *ctx);
+struct i915_gem_context;
+
 uint32_t intel_lr_context_size(struct intel_engine_cs *engine);
-void intel_lr_context_unpin(struct intel_context *ctx,
+void intel_lr_context_unpin(struct i915_gem_context *ctx,
                            struct intel_engine_cs *engine);
 
 struct drm_i915_private;
 
 void intel_lr_context_reset(struct drm_i915_private *dev_priv,
-                           struct intel_context *ctx);
-uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
+                           struct i915_gem_context *ctx);
+uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx,
                                     struct intel_engine_cs *engine);
 
 /* Execlists */
index d65fd94..56eb3bd 100644 (file)
@@ -978,7 +978,7 @@ void intel_lvds_init(struct drm_device *dev)
                           DRM_MODE_CONNECTOR_LVDS);
 
        drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
-                        DRM_MODE_ENCODER_LVDS, NULL);
+                        DRM_MODE_ENCODER_LVDS, "LVDS");
 
        intel_encoder->enable = intel_enable_lvds;
        intel_encoder->pre_enable = intel_pre_enable_lvds;
index 8347fd8..f6d8a21 100644 (file)
@@ -240,10 +240,11 @@ struct opregion_asle_ext {
 
 #define MAX_DSLP       1500
 
-static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
+static int swsci(struct drm_i915_private *dev_priv,
+                u32 function, u32 parm, u32 *parm_out)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct opregion_swsci *swsci = dev_priv->opregion.swsci;
+       struct pci_dev *pdev = dev_priv->dev->pdev;
        u32 main_function, sub_function, scic;
        u16 swsci_val;
        u32 dslp;
@@ -293,16 +294,16 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
        swsci->scic = scic;
 
        /* Ensure SCI event is selected and event trigger is cleared. */
-       pci_read_config_word(dev->pdev, SWSCI, &swsci_val);
+       pci_read_config_word(pdev, SWSCI, &swsci_val);
        if (!(swsci_val & SWSCI_SCISEL) || (swsci_val & SWSCI_GSSCIE)) {
                swsci_val |= SWSCI_SCISEL;
                swsci_val &= ~SWSCI_GSSCIE;
-               pci_write_config_word(dev->pdev, SWSCI, swsci_val);
+               pci_write_config_word(pdev, SWSCI, swsci_val);
        }
 
        /* Use event trigger to tell bios to check the mail. */
        swsci_val |= SWSCI_GSSCIE;
-       pci_write_config_word(dev->pdev, SWSCI, swsci_val);
+       pci_write_config_word(pdev, SWSCI, swsci_val);
 
        /* Poll for the result. */
 #define C (((scic = swsci->scic) & SWSCI_SCIC_INDICATOR) == 0)
@@ -336,13 +337,13 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
 int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
                                  bool enable)
 {
-       struct drm_device *dev = intel_encoder->base.dev;
+       struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
        u32 parm = 0;
        u32 type = 0;
        u32 port;
 
        /* don't care about old stuff for now */
-       if (!HAS_DDI(dev))
+       if (!HAS_DDI(dev_priv))
                return 0;
 
        if (intel_encoder->type == INTEL_OUTPUT_DSI)
@@ -382,7 +383,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
 
        parm |= type << (16 + port * 3);
 
-       return swsci(dev, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
+       return swsci(dev_priv, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
 }
 
 static const struct {
@@ -396,27 +397,28 @@ static const struct {
        { PCI_D3cold,   0x04 },
 };
 
-int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
+int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
+                                 pci_power_t state)
 {
        int i;
 
-       if (!HAS_DDI(dev))
+       if (!HAS_DDI(dev_priv))
                return 0;
 
        for (i = 0; i < ARRAY_SIZE(power_state_map); i++) {
                if (state == power_state_map[i].pci_power_state)
-                       return swsci(dev, SWSCI_SBCB_ADAPTER_POWER_STATE,
+                       return swsci(dev_priv, SWSCI_SBCB_ADAPTER_POWER_STATE,
                                     power_state_map[i].parm, NULL);
        }
 
        return -EINVAL;
 }
 
-static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
+static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_connector *connector;
        struct opregion_asle *asle = dev_priv->opregion.asle;
+       struct drm_device *dev = dev_priv->dev;
 
        DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
 
@@ -449,7 +451,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
        return 0;
 }
 
-static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
+static u32 asle_set_als_illum(struct drm_i915_private *dev_priv, u32 alsi)
 {
        /* alsi is the current ALS reading in lux. 0 indicates below sensor
           range, 0xffff indicates above sensor range. 1-0xfffe are valid */
@@ -457,13 +459,13 @@ static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
        return ASLC_ALS_ILLUM_FAILED;
 }
 
-static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
+static u32 asle_set_pwm_freq(struct drm_i915_private *dev_priv, u32 pfmb)
 {
        DRM_DEBUG_DRIVER("PWM freq is not supported\n");
        return ASLC_PWM_FREQ_FAILED;
 }
 
-static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
+static u32 asle_set_pfit(struct drm_i915_private *dev_priv, u32 pfit)
 {
        /* Panel fitting is currently controlled by the X code, so this is a
           noop until modesetting support works fully */
@@ -471,13 +473,13 @@ static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
        return ASLC_PFIT_FAILED;
 }
 
-static u32 asle_set_supported_rotation_angles(struct drm_device *dev, u32 srot)
+static u32 asle_set_supported_rotation_angles(struct drm_i915_private *dev_priv, u32 srot)
 {
        DRM_DEBUG_DRIVER("SROT is not supported\n");
        return ASLC_ROTATION_ANGLES_FAILED;
 }
 
-static u32 asle_set_button_array(struct drm_device *dev, u32 iuer)
+static u32 asle_set_button_array(struct drm_i915_private *dev_priv, u32 iuer)
 {
        if (!iuer)
                DRM_DEBUG_DRIVER("Button array event is not supported (nothing)\n");
@@ -495,7 +497,7 @@ static u32 asle_set_button_array(struct drm_device *dev, u32 iuer)
        return ASLC_BUTTON_ARRAY_FAILED;
 }
 
-static u32 asle_set_convertible(struct drm_device *dev, u32 iuer)
+static u32 asle_set_convertible(struct drm_i915_private *dev_priv, u32 iuer)
 {
        if (iuer & ASLE_IUER_CONVERTIBLE)
                DRM_DEBUG_DRIVER("Convertible is not supported (clamshell)\n");
@@ -505,7 +507,7 @@ static u32 asle_set_convertible(struct drm_device *dev, u32 iuer)
        return ASLC_CONVERTIBLE_FAILED;
 }
 
-static u32 asle_set_docking(struct drm_device *dev, u32 iuer)
+static u32 asle_set_docking(struct drm_i915_private *dev_priv, u32 iuer)
 {
        if (iuer & ASLE_IUER_DOCKING)
                DRM_DEBUG_DRIVER("Docking is not supported (docked)\n");
@@ -515,7 +517,7 @@ static u32 asle_set_docking(struct drm_device *dev, u32 iuer)
        return ASLC_DOCKING_FAILED;
 }
 
-static u32 asle_isct_state(struct drm_device *dev)
+static u32 asle_isct_state(struct drm_i915_private *dev_priv)
 {
        DRM_DEBUG_DRIVER("ISCT is not supported\n");
        return ASLC_ISCT_STATE_FAILED;
@@ -527,7 +529,6 @@ static void asle_work(struct work_struct *work)
                container_of(work, struct intel_opregion, asle_work);
        struct drm_i915_private *dev_priv =
                container_of(opregion, struct drm_i915_private, opregion);
-       struct drm_device *dev = dev_priv->dev;
        struct opregion_asle *asle = dev_priv->opregion.asle;
        u32 aslc_stat = 0;
        u32 aslc_req;
@@ -544,32 +545,32 @@ static void asle_work(struct work_struct *work)
        }
 
        if (aslc_req & ASLC_SET_ALS_ILLUM)
-               aslc_stat |= asle_set_als_illum(dev, asle->alsi);
+               aslc_stat |= asle_set_als_illum(dev_priv, asle->alsi);
 
        if (aslc_req & ASLC_SET_BACKLIGHT)
-               aslc_stat |= asle_set_backlight(dev, asle->bclp);
+               aslc_stat |= asle_set_backlight(dev_priv, asle->bclp);
 
        if (aslc_req & ASLC_SET_PFIT)
-               aslc_stat |= asle_set_pfit(dev, asle->pfit);
+               aslc_stat |= asle_set_pfit(dev_priv, asle->pfit);
 
        if (aslc_req & ASLC_SET_PWM_FREQ)
-               aslc_stat |= asle_set_pwm_freq(dev, asle->pfmb);
+               aslc_stat |= asle_set_pwm_freq(dev_priv, asle->pfmb);
 
        if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
-               aslc_stat |= asle_set_supported_rotation_angles(dev,
+               aslc_stat |= asle_set_supported_rotation_angles(dev_priv,
                                                        asle->srot);
 
        if (aslc_req & ASLC_BUTTON_ARRAY)
-               aslc_stat |= asle_set_button_array(dev, asle->iuer);
+               aslc_stat |= asle_set_button_array(dev_priv, asle->iuer);
 
        if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
-               aslc_stat |= asle_set_convertible(dev, asle->iuer);
+               aslc_stat |= asle_set_convertible(dev_priv, asle->iuer);
 
        if (aslc_req & ASLC_DOCKING_INDICATOR)
-               aslc_stat |= asle_set_docking(dev, asle->iuer);
+               aslc_stat |= asle_set_docking(dev_priv, asle->iuer);
 
        if (aslc_req & ASLC_ISCT_STATE_CHANGE)
-               aslc_stat |= asle_isct_state(dev);
+               aslc_stat |= asle_isct_state(dev_priv);
 
        asle->aslc = aslc_stat;
 }
@@ -656,10 +657,10 @@ static void set_did(struct intel_opregion *opregion, int i, u32 val)
        }
 }
 
-static void intel_didl_outputs(struct drm_device *dev)
+static void intel_didl_outputs(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_opregion *opregion = &dev_priv->opregion;
+       struct pci_dev *pdev = dev_priv->dev->pdev;
        struct drm_connector *connector;
        acpi_handle handle;
        struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
@@ -668,7 +669,7 @@ static void intel_didl_outputs(struct drm_device *dev)
        u32 temp, max_outputs;
        int i = 0;
 
-       handle = ACPI_HANDLE(&dev->pdev->dev);
+       handle = ACPI_HANDLE(&pdev->dev);
        if (!handle || acpi_bus_get_device(handle, &acpi_dev))
                return;
 
@@ -723,7 +724,7 @@ end:
 
 blind_set:
        i = 0;
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+       list_for_each_entry(connector, &dev_priv->dev->mode_config.connector_list, head) {
                int output_type = ACPI_OTHER_OUTPUT;
                if (i >= max_outputs) {
                        DRM_DEBUG_KMS("More than %u outputs in connector list\n",
@@ -759,9 +760,8 @@ blind_set:
        goto end;
 }
 
-static void intel_setup_cadls(struct drm_device *dev)
+static void intel_setup_cadls(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_opregion *opregion = &dev_priv->opregion;
        int i = 0;
        u32 disp_id;
@@ -778,17 +778,16 @@ static void intel_setup_cadls(struct drm_device *dev)
        } while (++i < 8 && disp_id != 0);
 }
 
-void intel_opregion_init(struct drm_device *dev)
+void intel_opregion_register(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_opregion *opregion = &dev_priv->opregion;
 
        if (!opregion->header)
                return;
 
        if (opregion->acpi) {
-               intel_didl_outputs(dev);
-               intel_setup_cadls(dev);
+               intel_didl_outputs(dev_priv);
+               intel_setup_cadls(dev_priv);
 
                /* Notify BIOS we are ready to handle ACPI video ext notifs.
                 * Right now, all the events are handled by the ACPI video module.
@@ -806,9 +805,8 @@ void intel_opregion_init(struct drm_device *dev)
        }
 }
 
-void intel_opregion_fini(struct drm_device *dev)
+void intel_opregion_unregister(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_opregion *opregion = &dev_priv->opregion;
 
        if (!opregion->header)
@@ -840,9 +838,8 @@ void intel_opregion_fini(struct drm_device *dev)
        opregion->lid_state = NULL;
 }
 
-static void swsci_setup(struct drm_device *dev)
+static void swsci_setup(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_opregion *opregion = &dev_priv->opregion;
        bool requested_callbacks = false;
        u32 tmp;
@@ -852,7 +849,7 @@ static void swsci_setup(struct drm_device *dev)
        opregion->swsci_sbcb_sub_functions = 1;
 
        /* We use GBDA to ask for supported GBDA calls. */
-       if (swsci(dev, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
+       if (swsci(dev_priv, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
                /* make the bits match the sub-function codes */
                tmp <<= 1;
                opregion->swsci_gbda_sub_functions |= tmp;
@@ -863,7 +860,7 @@ static void swsci_setup(struct drm_device *dev)
         * must not call interfaces that are not specifically requested by the
         * bios.
         */
-       if (swsci(dev, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
+       if (swsci(dev_priv, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
                /* here, the bits already match sub-function codes */
                opregion->swsci_sbcb_sub_functions |= tmp;
                requested_callbacks = true;
@@ -874,7 +871,7 @@ static void swsci_setup(struct drm_device *dev)
         * the callback is _requested_. But we still can't call interfaces that
         * are not requested.
         */
-       if (swsci(dev, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
+       if (swsci(dev_priv, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
                /* make the bits match the sub-function codes */
                u32 low = tmp & 0x7ff;
                u32 high = tmp & ~0xfff; /* bit 11 is reserved */
@@ -916,10 +913,10 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = {
        { }
 };
 
-int intel_opregion_setup(struct drm_device *dev)
+int intel_opregion_setup(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_opregion *opregion = &dev_priv->opregion;
+       struct pci_dev *pdev = dev_priv->dev->pdev;
        u32 asls, mboxes;
        char buf[sizeof(OPREGION_SIGNATURE)];
        int err = 0;
@@ -931,7 +928,7 @@ int intel_opregion_setup(struct drm_device *dev)
        BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
        BUILD_BUG_ON(sizeof(struct opregion_asle_ext) != 0x400);
 
-       pci_read_config_dword(dev->pdev, ASLS, &asls);
+       pci_read_config_dword(pdev, ASLS, &asls);
        DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
        if (asls == 0) {
                DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
@@ -963,7 +960,7 @@ int intel_opregion_setup(struct drm_device *dev)
        if (mboxes & MBOX_SWSCI) {
                DRM_DEBUG_DRIVER("SWSCI supported\n");
                opregion->swsci = base + OPREGION_SWSCI_OFFSET;
-               swsci_setup(dev);
+               swsci_setup(dev_priv);
        }
 
        if (mboxes & MBOX_ASLE) {
@@ -1012,12 +1009,12 @@ err_out:
 }
 
 int
-intel_opregion_get_panel_type(struct drm_device *dev)
+intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
 {
        u32 panel_details;
        int ret;
 
-       ret = swsci(dev, SWSCI_GBDA_PANEL_DETAILS, 0x0, &panel_details);
+       ret = swsci(dev_priv, SWSCI_GBDA_PANEL_DETAILS, 0x0, &panel_details);
        if (ret) {
                DRM_DEBUG_KMS("Failed to get panel details from OpRegion (%d)\n",
                              ret);
index 29bdd79..0827459 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <linux/cpufreq.h>
+#include <drm/drm_plane_helper.h>
 #include "i915_drv.h"
 #include "intel_drv.h"
 #include "../../../platform/x86/intel_ips.h"
@@ -2949,6 +2950,46 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
        }
 }
 
+/*
+ * Determines the downscale amount of a plane for the purposes of watermark calculations.
+ * The bspec defines downscale amount as:
+ *
+ * """
+ * Horizontal down scale amount = maximum[1, Horizontal source size /
+ *                                           Horizontal destination size]
+ * Vertical down scale amount = maximum[1, Vertical source size /
+ *                                         Vertical destination size]
+ * Total down scale amount = Horizontal down scale amount *
+ *                           Vertical down scale amount
+ * """
+ *
+ * Return value is provided in 16.16 fixed point form to retain fractional part.
+ * Caller should take care of dividing & rounding off the value.
+ */
+static uint32_t
+skl_plane_downscale_amount(const struct intel_plane_state *pstate)
+{
+       uint32_t downscale_h, downscale_w;
+       uint32_t src_w, src_h, dst_w, dst_h;
+
+       if (WARN_ON(!pstate->visible))
+               return DRM_PLANE_HELPER_NO_SCALING;
+
+       /* n.b., src is 16.16 fixed point, dst is whole integer */
+       src_w = drm_rect_width(&pstate->src);
+       src_h = drm_rect_height(&pstate->src);
+       dst_w = drm_rect_width(&pstate->dst);
+       dst_h = drm_rect_height(&pstate->dst);
+       if (intel_rotation_90_or_270(pstate->base.rotation))
+               swap(dst_w, dst_h);
+
+       downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
+       downscale_w = max(src_w / dst_w, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
+
+       /* Provide result in 16.16 fixed point */
+       return (uint64_t)downscale_w * downscale_h >> 16;
+}
+
 static unsigned int
 skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
                             const struct drm_plane_state *pstate,
@@ -2956,6 +2997,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
 {
        struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
        struct drm_framebuffer *fb = pstate->fb;
+       uint32_t down_scale_amount, data_rate;
        uint32_t width = 0, height = 0;
        unsigned format = fb ? fb->pixel_format : DRM_FORMAT_XRGB8888;
 
@@ -2975,15 +3017,19 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
        /* for planar format */
        if (format == DRM_FORMAT_NV12) {
                if (y)  /* y-plane data rate */
-                       return width * height *
+                       data_rate = width * height *
                                drm_format_plane_cpp(format, 0);
                else    /* uv-plane data rate */
-                       return (width / 2) * (height / 2) *
+                       data_rate = (width / 2) * (height / 2) *
                                drm_format_plane_cpp(format, 1);
+       } else {
+               /* for packed formats */
+               data_rate = width * height * drm_format_plane_cpp(format, 0);
        }
 
-       /* for packed formats */
-       return width * height * drm_format_plane_cpp(format, 0);
+       down_scale_amount = skl_plane_downscale_amount(intel_pstate);
+
+       return (uint64_t)data_rate * down_scale_amount >> 16;
 }
 
 /*
@@ -3042,6 +3088,69 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
        return total_data_rate;
 }
 
+static uint16_t
+skl_ddb_min_alloc(const struct drm_plane_state *pstate,
+                 const int y)
+{
+       struct drm_framebuffer *fb = pstate->fb;
+       struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
+       uint32_t src_w, src_h;
+       uint32_t min_scanlines = 8;
+       uint8_t plane_bpp;
+
+       if (WARN_ON(!fb))
+               return 0;
+
+       /* For packed formats, no y-plane, return 0 */
+       if (y && fb->pixel_format != DRM_FORMAT_NV12)
+               return 0;
+
+       /* For Non Y-tile return 8-blocks */
+       if (fb->modifier[0] != I915_FORMAT_MOD_Y_TILED &&
+           fb->modifier[0] != I915_FORMAT_MOD_Yf_TILED)
+               return 8;
+
+       src_w = drm_rect_width(&intel_pstate->src) >> 16;
+       src_h = drm_rect_height(&intel_pstate->src) >> 16;
+
+       if (intel_rotation_90_or_270(pstate->rotation))
+               swap(src_w, src_h);
+
+       /* Halve UV plane width and height for NV12 */
+       if (fb->pixel_format == DRM_FORMAT_NV12 && !y) {
+               src_w /= 2;
+               src_h /= 2;
+       }
+
+       if (fb->pixel_format == DRM_FORMAT_NV12 && !y)
+               plane_bpp = drm_format_plane_cpp(fb->pixel_format, 1);
+       else
+               plane_bpp = drm_format_plane_cpp(fb->pixel_format, 0);
+
+       if (intel_rotation_90_or_270(pstate->rotation)) {
+               switch (plane_bpp) {
+               case 1:
+                       min_scanlines = 32;
+                       break;
+               case 2:
+                       min_scanlines = 16;
+                       break;
+               case 4:
+                       min_scanlines = 8;
+                       break;
+               case 8:
+                       min_scanlines = 4;
+                       break;
+               default:
+                       WARN(1, "Unsupported pixel depth %u for rotation",
+                            plane_bpp);
+                       min_scanlines = 32;
+               }
+       }
+
+       return DIV_ROUND_UP((4 * src_w * plane_bpp), 512) * min_scanlines/4 + 3;
+}
+
 static int
 skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
                      struct skl_ddb_allocation *ddb /* out */)
@@ -3104,11 +3213,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
                        continue;
                }
 
-               minimum[id] = 8;
-               if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
-                       y_minimum[id] = 8;
-               else
-                       y_minimum[id] = 0;
+               minimum[id] = skl_ddb_min_alloc(pstate, 0);
+               y_minimum[id] = skl_ddb_min_alloc(pstate, 1);
        }
 
        for (i = 0; i < PLANE_CURSOR; i++) {
@@ -3225,6 +3331,30 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
        return ret;
 }
 
+static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cstate,
+                                             struct intel_plane_state *pstate)
+{
+       uint64_t adjusted_pixel_rate;
+       uint64_t downscale_amount;
+       uint64_t pixel_rate;
+
+       /* Shouldn't reach here on disabled planes... */
+       if (WARN_ON(!pstate->visible))
+               return 0;
+
+       /*
+        * Adjusted plane pixel rate is just the pipe's adjusted pixel rate
+        * with additional adjustments for plane-specific scaling.
+        */
+       adjusted_pixel_rate = skl_pipe_pixel_rate(cstate);
+       downscale_amount = skl_plane_downscale_amount(pstate);
+
+       pixel_rate = adjusted_pixel_rate * downscale_amount >> 16;
+       WARN_ON(pixel_rate != clamp_t(uint32_t, pixel_rate, 0, ~0));
+
+       return pixel_rate;
+}
+
 static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
                                struct intel_crtc_state *cstate,
                                struct intel_plane_state *intel_pstate,
@@ -3243,6 +3373,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
        uint32_t selected_result;
        uint8_t cpp;
        uint32_t width = 0, height = 0;
+       uint32_t plane_pixel_rate;
 
        if (latency == 0 || !cstate->base.active || !intel_pstate->visible) {
                *enabled = false;
@@ -3256,9 +3387,10 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
                swap(width, height);
 
        cpp = drm_format_plane_cpp(fb->pixel_format, 0);
-       method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
-                                cpp, latency);
-       method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
+       plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate);
+
+       method1 = skl_wm_method1(plane_pixel_rate, cpp, latency);
+       method2 = skl_wm_method2(plane_pixel_rate,
                                 cstate->base.adjusted_mode.crtc_htotal,
                                 width,
                                 cpp,
@@ -4046,7 +4178,6 @@ void skl_wm_get_hw_state(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
        struct drm_crtc *crtc;
-       struct intel_crtc *intel_crtc;
 
        skl_ddb_get_hw_state(dev_priv, ddb);
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
@@ -4059,23 +4190,6 @@ void skl_wm_get_hw_state(struct drm_device *dev)
                /* Easy/common case; just sanitize DDB now if everything off */
                memset(ddb, 0, sizeof(*ddb));
        }
-
-       /* Calculate plane data rates */
-       for_each_intel_crtc(dev, intel_crtc) {
-               struct intel_crtc_state *cstate = intel_crtc->config;
-               struct intel_plane *intel_plane;
-
-               for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
-                       const struct drm_plane_state *pstate =
-                               intel_plane->base.state;
-                       int id = skl_wm_plane_id(intel_plane);
-
-                       cstate->wm.skl.plane_data_rate[id] =
-                               skl_plane_relative_data_rate(cstate, pstate, 0);
-                       cstate->wm.skl.plane_y_data_rate[id] =
-                               skl_plane_relative_data_rate(cstate, pstate, 1);
-               }
-       }
 }
 
 static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
@@ -5039,7 +5153,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv)
        for_each_engine(engine, dev_priv)
                I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
-       if (HAS_GUC_UCODE(dev_priv))
+       if (HAS_GUC(dev_priv))
                I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA);
 
        I915_WRITE(GEN6_RC_SLEEP, 0);
index 929e7b4..b33c876 100644 (file)
@@ -119,7 +119,7 @@ struct intel_ringbuffer {
        u32 last_retired_head;
 };
 
-struct intel_context;
+struct i915_gem_context;
 struct drm_i915_reg_table;
 
 /*
@@ -310,7 +310,7 @@ struct intel_engine_cs {
 
        wait_queue_head_t irq_queue;
 
-       struct intel_context *last_context;
+       struct i915_gem_context *last_context;
 
        struct intel_ring_hangcheck hangcheck;
 
index b69b935..fe8faf3 100644 (file)
@@ -806,15 +806,27 @@ static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
        return (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0;
 }
 
+static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
+{
+       u32 tmp = I915_READ(DBUF_CTL);
+
+       WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
+            (DBUF_POWER_STATE | DBUF_POWER_REQUEST),
+            "Unexpected DBuf power power state (0x%08x)\n", tmp);
+}
+
 static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
                                          struct i915_power_well *power_well)
 {
        gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 
-       if (IS_BROXTON(dev_priv)) {
-               broxton_cdclk_verify_state(dev_priv);
+       WARN_ON(dev_priv->cdclk_freq !=
+               dev_priv->display.get_display_clock_speed(dev_priv->dev));
+
+       gen9_assert_dbuf_enabled(dev_priv);
+
+       if (IS_BROXTON(dev_priv))
                broxton_ddi_phy_verify_state(dev_priv);
-       }
 }
 
 static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
@@ -2176,6 +2188,28 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
        mutex_unlock(&power_domains->lock);
 }
 
+static void gen9_dbuf_enable(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST);
+       POSTING_READ(DBUF_CTL);
+
+       udelay(10);
+
+       if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE))
+               DRM_ERROR("DBuf power enable timeout\n");
+}
+
+static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
+{
+       I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST);
+       POSTING_READ(DBUF_CTL);
+
+       udelay(10);
+
+       if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
+               DRM_ERROR("DBuf power disable timeout!\n");
+}
+
 static void skl_display_core_init(struct drm_i915_private *dev_priv,
                                   bool resume)
 {
@@ -2200,12 +2234,11 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv,
 
        mutex_unlock(&power_domains->lock);
 
-       if (!resume)
-               return;
-
        skl_init_cdclk(dev_priv);
 
-       if (dev_priv->csr.dmc_payload)
+       gen9_dbuf_enable(dev_priv);
+
+       if (resume && dev_priv->csr.dmc_payload)
                intel_csr_load_program(dev_priv);
 }
 
@@ -2216,6 +2249,8 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
 
        gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 
+       gen9_dbuf_disable(dev_priv);
+
        skl_uninit_cdclk(dev_priv);
 
        /* The spec doesn't call for removing the reset handshake flag */
@@ -2260,9 +2295,11 @@ void bxt_display_core_init(struct drm_i915_private *dev_priv,
        mutex_unlock(&power_domains->lock);
 
        broxton_init_cdclk(dev_priv);
+
+       gen9_dbuf_enable(dev_priv);
+
        broxton_ddi_phy_init(dev_priv);
 
-       broxton_cdclk_verify_state(dev_priv);
        broxton_ddi_phy_verify_state(dev_priv);
 
        if (resume && dev_priv->csr.dmc_payload)
@@ -2277,6 +2314,9 @@ void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
        gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 
        broxton_ddi_phy_uninit(dev_priv);
+
+       gen9_dbuf_disable(dev_priv);
+
        broxton_uninit_cdclk(dev_priv);
 
        /* The spec doesn't call for removing the reset handshake flag */
index 2128fae..1a71456 100644 (file)
@@ -2981,7 +2981,7 @@ bool intel_sdvo_init(struct drm_device *dev,
        intel_encoder = &intel_sdvo->base;
        intel_encoder->type = INTEL_OUTPUT_SDVO;
        drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0,
-                        NULL);
+                        "SDVO %c", port_name(port));
 
        /* Read the regs to test if we can talk to the device */
        for (i = 0; i < 0x40; i++) {
index 97b1a54..324ccb0 100644 (file)
@@ -1114,10 +1114,18 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
 
        possible_crtcs = (1 << pipe);
 
-       ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
-                                      &intel_plane_funcs,
-                                      plane_formats, num_plane_formats,
-                                      DRM_PLANE_TYPE_OVERLAY, NULL);
+       if (INTEL_INFO(dev)->gen >= 9)
+               ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
+                                              &intel_plane_funcs,
+                                              plane_formats, num_plane_formats,
+                                              DRM_PLANE_TYPE_OVERLAY,
+                                              "plane %d%c", plane + 2, pipe_name(pipe));
+       else
+               ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
+                                              &intel_plane_funcs,
+                                              plane_formats, num_plane_formats,
+                                              DRM_PLANE_TYPE_OVERLAY,
+                                              "sprite %c", sprite_name(pipe, plane));
        if (ret)
                goto fail;
 
index 223129d..1f3a0e1 100644 (file)
@@ -1591,7 +1591,7 @@ intel_tv_init(struct drm_device *dev)
                           DRM_MODE_CONNECTOR_SVIDEO);
 
        drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
-                        DRM_MODE_ENCODER_TVDAC, NULL);
+                        DRM_MODE_ENCODER_TVDAC, "TV");
 
        intel_encoder->compute_config = intel_tv_compute_config;
        intel_encoder->get_config = intel_tv_get_config;
index 385114b..c1ca458 100644 (file)
@@ -1715,7 +1715,7 @@ int intel_guc_reset(struct drm_i915_private *dev_priv)
        int ret;
        unsigned long irqflags;
 
-       if (!i915.enable_guc_submission)
+       if (!HAS_GUC(dev_priv))
                return -EINVAL;
 
        intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);