drm/i915: Use HWS for seqno tracking everywhere
[cascardo/linux.git] / drivers / gpu / drm / i915 / i915_drv.h
index 0349c5f..5a1e8e0 100644 (file)
@@ -47,6 +47,7 @@
 #include <drm/intel-gtt.h>
 #include <drm/drm_legacy.h> /* for struct drm_dma_handle */
 #include <drm/drm_gem.h>
+#include <drm/drm_auth.h>
 
 #include "i915_params.h"
 #include "i915_reg.h"
 #include "i915_gem_gtt.h"
 #include "i915_gem_render_state.h"
 
+#include "intel_gvt.h"
+
 /* General customization:
  */
 
 #define DRIVER_NAME            "i915"
 #define DRIVER_DESC            "Intel Graphics"
-#define DRIVER_DATE            "20160606"
+#define DRIVER_DATE            "20160620"
 
 #undef WARN_ON
 /* Many gcc seem to no see through this and fall over :( */
@@ -503,6 +506,7 @@ struct drm_i915_error_state {
                bool valid;
                /* Software tracked state */
                bool waiting;
+               int num_waiters;
                int hangcheck_score;
                enum intel_ring_hangcheck_action hangcheck_action;
                int num_requests;
@@ -548,6 +552,12 @@ struct drm_i915_error_state {
                        u32 tail;
                } *requests;
 
+               struct drm_i915_error_waiter {
+                       char comm[TASK_COMM_LEN];
+                       pid_t pid;
+                       u32 seqno;
+               } *waiters;
+
                struct {
                        u32 gfx_mode;
                        union {
@@ -761,7 +771,8 @@ struct intel_csr {
        func(has_llc) sep \
        func(has_snoop) sep \
        func(has_ddi) sep \
-       func(has_fpga_dbg)
+       func(has_fpga_dbg) sep \
+       func(has_pooled_eu)
 
 #define DEFINE_FLAG(name) u8 name:1
 #define SEP_SEMICOLON ;
@@ -787,6 +798,7 @@ struct intel_device_info {
        u8 subslice_per_slice;
        u8 eu_total;
        u8 eu_per_subslice;
+       u8 min_eu_in_pool;
        /* For each slice, which subslice(s) has(have) 7 EUs (bitfield)? */
        u8 subslice_7eu[3];
        u8 has_slice_pg:1;
@@ -867,6 +879,8 @@ struct i915_gem_context {
        u32 user_handle;
 #define CONTEXT_NO_ZEROMAP             (1<<0)
 
+       u32 ggtt_alignment;
+
        struct intel_context {
                struct drm_i915_gem_object *state;
                struct intel_ringbuffer *ringbuf;
@@ -876,6 +890,10 @@ struct i915_gem_context {
                int pin_count;
                bool initialised;
        } engine[I915_NUM_ENGINES];
+       u32 ring_size;
+       u32 desc_template;
+       struct atomic_notifier_head status_notifier;
+       bool execlists_force_single_submission;
 
        struct list_head link;
 
@@ -1363,7 +1381,6 @@ struct i915_gpu_error {
        /* Hang gpu twice in this window and your context gets banned */
 #define DRM_I915_CTX_BAN_PERIOD DIV_ROUND_UP(8*DRM_I915_HANGCHECK_PERIOD, 1000)
 
-       struct workqueue_struct *hangcheck_wq;
        struct delayed_work hangcheck_work;
 
        /* For reset and error_state handling. */
@@ -1399,6 +1416,12 @@ struct i915_gpu_error {
 #define I915_RESET_IN_PROGRESS_FLAG    1
 #define I915_WEDGED                    (1 << 31)
 
+       /**
+        * Waitqueue to signal when a hang is detected. Used to for waiters
+        * to release the struct_mutex for the reset to procede.
+        */
+       wait_queue_head_t wait_queue;
+
        /**
         * Waitqueue to signal when the reset has completed. Used by clients
         * that wait for dev_priv->mm.wedged to settle.
@@ -1413,7 +1436,7 @@ struct i915_gpu_error {
 #define I915_STOP_RING_ALLOW_WARN      (1 << 30)
 
        /* For missed irq/seqno simulation. */
-       unsigned int test_irq_rings;
+       unsigned long test_irq_rings;
 };
 
 enum modeset_restore {
@@ -1724,6 +1747,8 @@ struct intel_wm_config {
 };
 
 struct drm_i915_private {
+       struct drm_device drm;
+
        struct drm_device *dev;
        struct kmem_cache *objects;
        struct kmem_cache *vmas;
@@ -1739,6 +1764,8 @@ struct drm_i915_private {
 
        struct i915_virtual_gpu vgpu;
 
+       struct intel_gvt gvt;
+
        struct intel_guc guc;
 
        struct intel_csr csr;
@@ -2033,7 +2060,7 @@ struct drm_i915_private {
 
 static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
 {
-       return dev->dev_private;
+       return container_of(dev, struct drm_i915_private, drm);
 }
 
 static inline struct drm_i915_private *dev_to_i915(struct device *dev)
@@ -2204,6 +2231,7 @@ struct drm_i915_gem_object {
 
        unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS;
 
+       unsigned int has_wc_mmap;
        unsigned int pin_display;
 
        struct sg_table *pages;
@@ -2256,6 +2284,12 @@ struct drm_i915_gem_object {
 };
 #define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
 
+static inline bool
+i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
+{
+       return obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE;
+}
+
 /*
  * Optimised SGL iterator for GEM objects
  */
@@ -2346,7 +2380,6 @@ struct drm_i915_gem_request {
        /** On Which ring this request was generated */
        struct drm_i915_private *i915;
        struct intel_engine_cs *engine;
-       unsigned reset_counter;
 
         /** GEM sequence number associated with the previous request,
          * when the HWS breadcrumb is equal to this the GPU is processing
@@ -2602,7 +2635,7 @@ struct drm_i915_cmd_table {
 #define INTEL_DEVID(p) (INTEL_INFO(p)->device_id)
 
 #define REVID_FOREVER          0xff
-#define INTEL_REVID(p) (__I915__(p)->dev->pdev->revision)
+#define INTEL_REVID(p) (__I915__(p)->drm.pdev->revision)
 
 #define GEN_FOREVER (0)
 /*
@@ -2741,17 +2774,22 @@ struct drm_i915_cmd_table {
 #define IS_GEN8(dev)   (INTEL_INFO(dev)->gen_mask & BIT(7))
 #define IS_GEN9(dev)   (INTEL_INFO(dev)->gen_mask & BIT(8))
 
-#define RENDER_RING            (1<<RCS)
-#define BSD_RING               (1<<VCS)
-#define BLT_RING               (1<<BCS)
-#define VEBOX_RING             (1<<VECS)
-#define BSD2_RING              (1<<VCS2)
-#define ALL_ENGINES            (~0)
-
-#define HAS_BSD(dev)           (INTEL_INFO(dev)->ring_mask & BSD_RING)
-#define HAS_BSD2(dev)          (INTEL_INFO(dev)->ring_mask & BSD2_RING)
-#define HAS_BLT(dev)           (INTEL_INFO(dev)->ring_mask & BLT_RING)
-#define HAS_VEBOX(dev)         (INTEL_INFO(dev)->ring_mask & VEBOX_RING)
+#define ENGINE_MASK(id)        BIT(id)
+#define RENDER_RING    ENGINE_MASK(RCS)
+#define BSD_RING       ENGINE_MASK(VCS)
+#define BLT_RING       ENGINE_MASK(BCS)
+#define VEBOX_RING     ENGINE_MASK(VECS)
+#define BSD2_RING      ENGINE_MASK(VCS2)
+#define ALL_ENGINES    (~0)
+
+#define HAS_ENGINE(dev_priv, id) \
+       (INTEL_INFO(dev_priv)->ring_mask & ENGINE_MASK(id))
+
+#define HAS_BSD(dev_priv)      HAS_ENGINE(dev_priv, VCS)
+#define HAS_BSD2(dev_priv)     HAS_ENGINE(dev_priv, VCS2)
+#define HAS_BLT(dev_priv)      HAS_ENGINE(dev_priv, BCS)
+#define HAS_VEBOX(dev_priv)    HAS_ENGINE(dev_priv, VECS)
+
 #define HAS_LLC(dev)           (INTEL_INFO(dev)->has_llc)
 #define HAS_SNOOP(dev)         (INTEL_INFO(dev)->has_snoop)
 #define HAS_EDRAM(dev)         (__I915__(dev)->edram_cap & EDRAM_ENABLED)
@@ -2772,9 +2810,10 @@ struct drm_i915_cmd_table {
 #define HAS_BROKEN_CS_TLB(dev)         (IS_I830(dev) || IS_845G(dev))
 
 /* WaRsDisableCoarsePowerGating:skl,bxt */
-#define NEEDS_WaRsDisableCoarsePowerGating(dev) (IS_BXT_REVID(dev, 0, BXT_REVID_A1) || \
-                                                IS_SKL_GT3(dev) || \
-                                                IS_SKL_GT4(dev))
+#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
+       (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) || \
+        IS_SKL_GT3(dev_priv) || \
+        IS_SKL_GT4(dev_priv))
 
 /*
  * dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts
@@ -2832,6 +2871,8 @@ struct drm_i915_cmd_table {
                                 !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && \
                                 !IS_BROXTON(dev))
 
+#define HAS_POOLED_EU(dev)     (INTEL_INFO(dev)->has_pooled_eu)
+
 #define INTEL_PCH_DEVICE_ID_MASK               0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE           0x3b00
 #define INTEL_PCH_CPT_DEVICE_ID_TYPE           0x1c00
@@ -2866,16 +2907,13 @@ struct drm_i915_cmd_table {
 
 #include "i915_trace.h"
 
-extern const struct drm_ioctl_desc i915_ioctls[];
-extern int i915_max_ioctl;
-
 extern int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state);
 extern int i915_resume_switcheroo(struct drm_device *dev);
 
 int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv,
                                int enable_ppgtt);
 
-/* i915_dma.c */
+/* i915_drv.c */
 void __printf(3, 4)
 __i915_printk(struct drm_i915_private *dev_priv, const char *level,
              const char *fmt, ...);
@@ -2883,14 +2921,6 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,
 #define i915_report_error(dev_priv, fmt, ...)                             \
        __i915_printk(dev_priv, KERN_ERR, fmt, ##__VA_ARGS__)
 
-extern int i915_driver_load(struct drm_device *, unsigned long flags);
-extern int i915_driver_unload(struct drm_device *);
-extern int i915_driver_open(struct drm_device *dev, struct drm_file *file);
-extern void i915_driver_lastclose(struct drm_device * dev);
-extern void i915_driver_preclose(struct drm_device *dev,
-                                struct drm_file *file);
-extern void i915_driver_postclose(struct drm_device *dev,
-                                 struct drm_file *file);
 #ifdef CONFIG_COMPAT
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
                              unsigned long arg);
@@ -2915,7 +2945,23 @@ void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
 bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port);
 
 /* i915_irq.c */
-void i915_queue_hangcheck(struct drm_i915_private *dev_priv);
+static inline void i915_queue_hangcheck(struct drm_i915_private *dev_priv)
+{
+       unsigned long delay;
+
+       if (unlikely(!i915.enable_hangcheck))
+               return;
+
+       /* Don't continually defer the hangcheck so that it is always run at
+        * least once after work has been scheduled on any ring. Otherwise,
+        * we will ignore a hung ring if a second ring is kept busy.
+        */
+
+       delay = round_jiffies_up_relative(DRM_I915_HANGCHECK_JIFFIES);
+       queue_delayed_work(system_long_wq,
+                          &dev_priv->gpu_error.hangcheck_work, delay);
+}
+
 __printf(3, 4)
 void i915_handle_error(struct drm_i915_private *dev_priv,
                       u32 engine_mask,
@@ -2949,6 +2995,23 @@ void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv,
 u64 intel_uncore_edram_size(struct drm_i915_private *dev_priv);
 
 void assert_forcewakes_inactive(struct drm_i915_private *dev_priv);
+
+int intel_wait_for_register(struct drm_i915_private *dev_priv,
+                           i915_reg_t reg,
+                           const u32 mask,
+                           const u32 value,
+                           const unsigned long timeout_ms);
+int intel_wait_for_register_fw(struct drm_i915_private *dev_priv,
+                              i915_reg_t reg,
+                              const u32 mask,
+                              const u32 value,
+                              const unsigned long timeout_ms);
+
+static inline bool intel_gvt_active(struct drm_i915_private *dev_priv)
+{
+       return dev_priv->gvt.initialized;
+}
+
 static inline bool intel_vgpu_active(struct drm_i915_private *dev_priv)
 {
        return dev_priv->vgpu.active;
@@ -3008,7 +3071,6 @@ ibx_disable_display_interrupt(struct drm_i915_private *dev_priv, uint32_t bits)
        ibx_display_interrupt_update(dev_priv, bits, 0);
 }
 
-
 /* i915_gem.c */
 int i915_gem_create_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *file_priv);
@@ -3225,24 +3287,27 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
        return (int32_t)(seq1 - seq2) >= 0;
 }
 
-static inline bool i915_gem_request_started(struct drm_i915_gem_request *req,
-                                          bool lazy_coherency)
+static inline bool i915_gem_request_started(const struct drm_i915_gem_request *req)
 {
-       if (!lazy_coherency && req->engine->irq_seqno_barrier)
-               req->engine->irq_seqno_barrier(req->engine);
-       return i915_seqno_passed(req->engine->get_seqno(req->engine),
+       return i915_seqno_passed(intel_engine_get_seqno(req->engine),
                                 req->previous_seqno);
 }
 
-static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
-                                             bool lazy_coherency)
+static inline bool i915_gem_request_completed(const struct drm_i915_gem_request *req)
 {
-       if (!lazy_coherency && req->engine->irq_seqno_barrier)
-               req->engine->irq_seqno_barrier(req->engine);
-       return i915_seqno_passed(req->engine->get_seqno(req->engine),
+       return i915_seqno_passed(intel_engine_get_seqno(req->engine),
                                 req->seqno);
 }
 
+bool __i915_spin_request(const struct drm_i915_gem_request *request,
+                        int state, unsigned long timeout_us);
+static inline bool i915_spin_request(const struct drm_i915_gem_request *request,
+                                    int state, unsigned long timeout_us)
+{
+       return (i915_gem_request_started(request) &&
+               __i915_spin_request(request, state, timeout_us));
+}
+
 int __must_check i915_gem_get_seqno(struct drm_i915_private *dev_priv, u32 *seqno);
 int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno);
 
@@ -3311,7 +3376,7 @@ int i915_gem_init_engines(struct drm_device *dev);
 int __must_check i915_gem_init_hw(struct drm_device *dev);
 void i915_gem_init_swizzling(struct drm_device *dev);
 void i915_gem_cleanup_engines(struct drm_device *dev);
-int __must_check i915_gpu_idle(struct drm_device *dev);
+int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv);
 int __must_check i915_gem_suspend(struct drm_device *dev);
 void __i915_add_request(struct drm_i915_gem_request *req,
                        struct drm_i915_gem_object *batch_obj,
@@ -3457,13 +3522,15 @@ int i915_switch_context(struct drm_i915_gem_request *req);
 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);
+struct i915_gem_context *
+i915_gem_context_create_gvt(struct drm_device *dev);
 
 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);
+       lockdep_assert_held(&file_priv->dev_priv->drm.struct_mutex);
 
        ctx = idr_find(&file_priv->context_idr, id);
        if (!ctx)
@@ -3479,7 +3546,7 @@ static inline void i915_gem_context_reference(struct i915_gem_context *ctx)
 
 static inline void i915_gem_context_unreference(struct i915_gem_context *ctx)
 {
-       lockdep_assert_held(&ctx->i915->dev->struct_mutex);
+       lockdep_assert_held(&ctx->i915->drm.struct_mutex);
        kref_put(&ctx->ref, i915_gem_context_free);
 }
 
@@ -3555,7 +3622,7 @@ void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv);
 /* i915_gem_tiling.c */
 static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
 {
-       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
 
        return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
                obj->tiling_mode != I915_TILING_NONE;
@@ -3569,12 +3636,14 @@ int i915_verify_lists(struct drm_device *dev);
 #endif
 
 /* i915_debugfs.c */
-int i915_debugfs_init(struct drm_minor *minor);
-void i915_debugfs_cleanup(struct drm_minor *minor);
 #ifdef CONFIG_DEBUG_FS
+int i915_debugfs_register(struct drm_i915_private *dev_priv);
+void i915_debugfs_unregister(struct drm_i915_private *dev_priv);
 int i915_debugfs_connector_add(struct drm_connector *connector);
 void intel_display_crc_init(struct drm_device *dev);
 #else
+static inline int i915_debugfs_register(struct drm_i915_private *) {return 0;}
+static inline void i915_debugfs_unregister(struct drm_i915_private *) {}
 static inline int i915_debugfs_connector_add(struct drm_connector *connector)
 { return 0; }
 static inline void intel_display_crc_init(struct drm_device *dev) {}
@@ -3665,8 +3734,8 @@ extern int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
 extern int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv);
 #else
 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_register(struct drm_i915_private *dev_priv) { }
+static inline void intel_opregion_unregister(struct drm_i915_private *dev_priv) { }
 static inline void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
 {
 }
@@ -3700,7 +3769,8 @@ extern void intel_modeset_init_hw(struct drm_device *dev);
 extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
-extern void intel_connector_unregister(struct intel_connector *);
+extern int intel_connector_register(struct drm_connector *);
+extern void intel_connector_unregister(struct drm_connector *);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern void intel_display_resume(struct drm_device *dev);
 extern void i915_redisable_vga(struct drm_device *dev);
@@ -3710,7 +3780,6 @@ extern void intel_init_pch_refclk(struct drm_device *dev);
 extern void intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
 extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
                                  bool enable);
-extern void intel_detect_pch(struct drm_device *dev);
 
 extern bool i915_semaphore_is_enabled(struct drm_i915_private *dev_priv);
 int i915_reg_read_ioctl(struct drm_device *dev, void *data,
@@ -3843,6 +3912,7 @@ __raw_write(64, q)
  */
 #define I915_READ_FW(reg__) __raw_i915_read32(dev_priv, (reg__))
 #define I915_WRITE_FW(reg__, val__) __raw_i915_write32(dev_priv, (reg__), (val__))
+#define I915_WRITE64_FW(reg__, val__) __raw_i915_write64(dev_priv, (reg__), (val__))
 #define POSTING_READ_FW(reg__) (void)I915_READ_FW(reg__)
 
 /* "Broadcast RGB" property */
@@ -3914,4 +3984,39 @@ static inline void i915_trace_irq_get(struct intel_engine_cs *engine,
                i915_gem_request_assign(&engine->trace_irq_req, req);
 }
 
+static inline bool __i915_request_irq_complete(struct drm_i915_gem_request *req)
+{
+       struct intel_engine_cs *engine = req->engine;
+
+       /* Ensure our read of the seqno is coherent so that we
+        * do not "miss an interrupt" (i.e. if this is the last
+        * request and the seqno write from the GPU is not visible
+        * by the time the interrupt fires, we will see that the
+        * request is incomplete and go back to sleep awaiting
+        * another interrupt that will never come.)
+        *
+        * Strictly, we only need to do this once after an interrupt,
+        * but it is easier and safer to do it every time the waiter
+        * is woken.
+        */
+       if (engine->irq_seqno_barrier)
+               engine->irq_seqno_barrier(engine);
+
+       if (i915_gem_request_completed(req))
+               return true;
+
+       /* We need to check whether any gpu reset happened in between
+        * the request being submitted and now. If a reset has occurred,
+        * the seqno will have been advance past ours and our request
+        * is complete. If we are in the process of handling a reset,
+        * the request is effectively complete as the rendering will
+        * be discarded, but we need to return in order to drop the
+        * struct_mutex.
+        */
+       if (i915_reset_in_progress(&req->i915->gpu_error))
+               return true;
+
+       return false;
+}
+
 #endif