]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/gpu/drm/i915/i915_drv.h
Merge airlied/drm-next into drm-misc-next
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / i915 / i915_drv.h
index 2981014fcfe2f0dce737d28de641bf05b57fc5de..7c6fab08a2e6d1d61c878affe449769608df2009 100644 (file)
@@ -80,8 +80,8 @@
 
 #define DRIVER_NAME            "i915"
 #define DRIVER_DESC            "Intel Graphics"
-#define DRIVER_DATE            "20170619"
-#define DRIVER_TIMESTAMP       1497857498
+#define DRIVER_DATE            "20170717"
+#define DRIVER_TIMESTAMP       1500275179
 
 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and
  * WARN_ON()) for hw state sanity checks to check for unexpected conditions
@@ -122,7 +122,7 @@ static inline bool is_fixed16_zero(uint_fixed_16_16_t val)
        return false;
 }
 
-static inline uint_fixed_16_16_t u32_to_fixed_16_16(uint32_t val)
+static inline uint_fixed_16_16_t u32_to_fixed16(uint32_t val)
 {
        uint_fixed_16_16_t fp;
 
@@ -132,17 +132,17 @@ static inline uint_fixed_16_16_t u32_to_fixed_16_16(uint32_t val)
        return fp;
 }
 
-static inline uint32_t fixed_16_16_to_u32_round_up(uint_fixed_16_16_t fp)
+static inline uint32_t fixed16_to_u32_round_up(uint_fixed_16_16_t fp)
 {
        return DIV_ROUND_UP(fp.val, 1 << 16);
 }
 
-static inline uint32_t fixed_16_16_to_u32(uint_fixed_16_16_t fp)
+static inline uint32_t fixed16_to_u32(uint_fixed_16_16_t fp)
 {
        return fp.val >> 16;
 }
 
-static inline uint_fixed_16_16_t min_fixed_16_16(uint_fixed_16_16_t min1,
+static inline uint_fixed_16_16_t min_fixed16(uint_fixed_16_16_t min1,
                                                 uint_fixed_16_16_t min2)
 {
        uint_fixed_16_16_t min;
@@ -151,7 +151,7 @@ static inline uint_fixed_16_16_t min_fixed_16_16(uint_fixed_16_16_t min1,
        return min;
 }
 
-static inline uint_fixed_16_16_t max_fixed_16_16(uint_fixed_16_16_t max1,
+static inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1,
                                                 uint_fixed_16_16_t max2)
 {
        uint_fixed_16_16_t max;
@@ -160,6 +160,14 @@ static inline uint_fixed_16_16_t max_fixed_16_16(uint_fixed_16_16_t max1,
        return max;
 }
 
+static inline uint_fixed_16_16_t clamp_u64_to_fixed16(uint64_t val)
+{
+       uint_fixed_16_16_t fp;
+       WARN_ON(val >> 32);
+       fp.val = clamp_t(uint32_t, val, 0, ~0);
+       return fp;
+}
+
 static inline uint32_t div_round_up_fixed16(uint_fixed_16_16_t val,
                                            uint_fixed_16_16_t d)
 {
@@ -170,48 +178,30 @@ static inline uint32_t mul_round_up_u32_fixed16(uint32_t val,
                                                uint_fixed_16_16_t mul)
 {
        uint64_t intermediate_val;
-       uint32_t result;
 
        intermediate_val = (uint64_t) val * mul.val;
        intermediate_val = DIV_ROUND_UP_ULL(intermediate_val, 1 << 16);
        WARN_ON(intermediate_val >> 32);
-       result = clamp_t(uint32_t, intermediate_val, 0, ~0);
-       return result;
+       return clamp_t(uint32_t, intermediate_val, 0, ~0);
 }
 
 static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val,
                                             uint_fixed_16_16_t mul)
 {
        uint64_t intermediate_val;
-       uint_fixed_16_16_t fp;
 
        intermediate_val = (uint64_t) val.val * mul.val;
        intermediate_val = intermediate_val >> 16;
-       WARN_ON(intermediate_val >> 32);
-       fp.val = clamp_t(uint32_t, intermediate_val, 0, ~0);
-       return fp;
+       return clamp_u64_to_fixed16(intermediate_val);
 }
 
-static inline uint_fixed_16_16_t fixed_16_16_div(uint32_t val, uint32_t d)
+static inline uint_fixed_16_16_t div_fixed16(uint32_t val, uint32_t d)
 {
-       uint_fixed_16_16_t fp, res;
-
-       fp = u32_to_fixed_16_16(val);
-       res.val = DIV_ROUND_UP(fp.val, d);
-       return res;
-}
-
-static inline uint_fixed_16_16_t fixed_16_16_div_u64(uint32_t val, uint32_t d)
-{
-       uint_fixed_16_16_t res;
        uint64_t interm_val;
 
        interm_val = (uint64_t)val << 16;
        interm_val = DIV_ROUND_UP_ULL(interm_val, d);
-       WARN_ON(interm_val >> 32);
-       res.val = (uint32_t) interm_val;
-
-       return res;
+       return clamp_u64_to_fixed16(interm_val);
 }
 
 static inline uint32_t div_round_up_u32_fixed16(uint32_t val,
@@ -225,16 +215,32 @@ static inline uint32_t div_round_up_u32_fixed16(uint32_t val,
        return clamp_t(uint32_t, interm_val, 0, ~0);
 }
 
-static inline uint_fixed_16_16_t mul_u32_fixed_16_16(uint32_t val,
+static inline uint_fixed_16_16_t mul_u32_fixed16(uint32_t val,
                                                     uint_fixed_16_16_t mul)
 {
        uint64_t intermediate_val;
-       uint_fixed_16_16_t fp;
 
        intermediate_val = (uint64_t) val * mul.val;
-       WARN_ON(intermediate_val >> 32);
-       fp.val = (uint32_t) intermediate_val;
-       return fp;
+       return clamp_u64_to_fixed16(intermediate_val);
+}
+
+static inline uint_fixed_16_16_t add_fixed16(uint_fixed_16_16_t add1,
+                                            uint_fixed_16_16_t add2)
+{
+       uint64_t interm_sum;
+
+       interm_sum = (uint64_t) add1.val + add2.val;
+       return clamp_u64_to_fixed16(interm_sum);
+}
+
+static inline uint_fixed_16_16_t add_fixed16_u32(uint_fixed_16_16_t add1,
+                                                uint32_t add2)
+{
+       uint64_t interm_sum;
+       uint_fixed_16_16_t interm_add2 = u32_to_fixed16(add2);
+
+       interm_sum = (uint64_t) add1.val + interm_add2.val;
+       return clamp_u64_to_fixed16(interm_sum);
 }
 
 static inline const char *yesno(bool v)
@@ -584,8 +590,7 @@ struct drm_i915_file_private {
        struct idr context_idr;
 
        struct intel_rps_client {
-               struct list_head link;
-               unsigned boosts;
+               atomic_t boosts;
        } rps;
 
        unsigned int bsd_engine;
@@ -753,6 +758,7 @@ struct intel_csr {
        func(has_csr); \
        func(has_ddi); \
        func(has_dp_mst); \
+       func(has_reset_engine); \
        func(has_fbc); \
        func(has_fpga_dbg); \
        func(has_full_ppgtt); \
@@ -917,6 +923,7 @@ struct i915_gpu_state {
                enum intel_engine_hangcheck_action hangcheck_action;
                struct i915_address_space *vm;
                int num_requests;
+               u32 reset_count;
 
                /* position of active request inside the ring */
                u32 rq_head, rq_post, rq_tail;
@@ -1149,8 +1156,8 @@ struct i915_psr {
 enum intel_pch {
        PCH_NONE = 0,   /* No PCH present */
        PCH_IBX,        /* Ibexpeak PCH */
-       PCH_CPT,        /* Cougarpoint PCH */
-       PCH_LPT,        /* Lynxpoint PCH */
+       PCH_CPT,        /* Cougarpoint/Pantherpoint PCH */
+       PCH_LPT,        /* Lynxpoint/Wildcatpoint PCH */
        PCH_SPT,        /* Sunrisepoint PCH */
        PCH_KBP,        /* Kabypoint PCH */
        PCH_CNP,        /* Cannonpoint PCH */
@@ -1166,6 +1173,7 @@ enum intel_sbi_destination {
 #define QUIRK_INVERT_BRIGHTNESS (1<<2)
 #define QUIRK_BACKLIGHT_PRESENT (1<<3)
 #define QUIRK_PIN_SWIZZLED_PAGES (1<<5)
+#define QUIRK_INCREASE_T12_DELAY (1<<6)
 
 struct intel_fbdev;
 struct intel_fbc_work;
@@ -1301,13 +1309,10 @@ struct intel_gen6_power_mgmt {
        int last_adj;
        enum { LOW_POWER, BETWEEN, HIGH_POWER } power;
 
-       spinlock_t client_lock;
-       struct list_head clients;
-       bool client_boost;
-
        bool enabled;
        struct delayed_work autoenable_work;
-       unsigned boosts;
+       atomic_t num_waiters;
+       atomic_t boosts;
 
        /* manual wa residency calculations */
        struct intel_rps_ei ei;
@@ -1550,6 +1555,12 @@ struct i915_gpu_error {
         * inspect the bit and do the reset directly, otherwise the worker
         * waits for the struct_mutex.
         *
+        * #I915_RESET_ENGINE[num_engines] - Since the driver doesn't need to
+        * acquire the struct_mutex to reset an engine, we need an explicit
+        * flag to prevent two concurrent reset attempts in the same engine.
+        * As the number of engines continues to grow, allocate the flags from
+        * the most significant bits.
+        *
         * #I915_WEDGED - If reset fails and we can no longer use the GPU,
         * we set the #I915_WEDGED bit. Prior to command submission, e.g.
         * i915_gem_request_alloc(), this bit is checked and the sequence
@@ -1559,6 +1570,10 @@ struct i915_gpu_error {
 #define I915_RESET_BACKOFF     0
 #define I915_RESET_HANDOFF     1
 #define I915_WEDGED            (BITS_PER_LONG - 1)
+#define I915_RESET_ENGINE      (I915_WEDGED - I915_NUM_ENGINES)
+
+       /** Number of times an engine has been reset */
+       u32 reset_engine_count[I915_NUM_ENGINES];
 
        /**
         * Waitqueue to signal when a hang is detected. Used to for waiters
@@ -2236,13 +2251,6 @@ struct drm_i915_private {
        DECLARE_HASHTABLE(mm_structs, 7);
        struct mutex mm_lock;
 
-       /* The hw wants to have a stable context identifier for the lifetime
-        * of the context (for OA, PASID, faults, etc). This is limited
-        * in execlists to 21 bits.
-        */
-       struct ida context_hw_ida;
-#define MAX_CONTEXT_HW_ID (1<<21) /* exclusive */
-
        /* Kernel Modesetting */
 
        struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
@@ -2319,7 +2327,18 @@ struct drm_i915_private {
         */
        struct mutex av_mutex;
 
-       struct list_head context_list;
+       struct {
+               struct list_head list;
+               struct llist_head free_list;
+               struct work_struct free_work;
+
+               /* The hw wants to have a stable context identifier for the
+                * lifetime of the context (for OA, PASID, faults, etc).
+                * This is limited in execlists to 21 bits.
+                */
+               struct ida hw_ida;
+#define MAX_CONTEXT_HW_ID (1<<21) /* exclusive */
+       } contexts;
 
        u32 fdi_rx_config;
 
@@ -2994,16 +3013,17 @@ intel_info(const struct drm_i915_private *dev_priv)
 
 #define HAS_POOLED_EU(dev_priv)        ((dev_priv)->info.has_pooled_eu)
 
-#define INTEL_PCH_DEVICE_ID_MASK               0xff00
-#define INTEL_PCH_DEVICE_ID_MASK_EXT           0xff80
+#define INTEL_PCH_DEVICE_ID_MASK               0xff80
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE           0x3b00
 #define INTEL_PCH_CPT_DEVICE_ID_TYPE           0x1c00
 #define INTEL_PCH_PPT_DEVICE_ID_TYPE           0x1e00
 #define INTEL_PCH_LPT_DEVICE_ID_TYPE           0x8c00
 #define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE                0x9c00
+#define INTEL_PCH_WPT_DEVICE_ID_TYPE           0x8c80
+#define INTEL_PCH_WPT_LP_DEVICE_ID_TYPE                0x9c80
 #define INTEL_PCH_SPT_DEVICE_ID_TYPE           0xA100
 #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE                0x9D00
-#define INTEL_PCH_KBP_DEVICE_ID_TYPE           0xA200
+#define INTEL_PCH_KBP_DEVICE_ID_TYPE           0xA280
 #define INTEL_PCH_CNP_DEVICE_ID_TYPE           0xA300
 #define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE                0x9D80
 #define INTEL_PCH_P2X_DEVICE_ID_TYPE           0x7100
@@ -3018,9 +3038,11 @@ intel_info(const struct drm_i915_private *dev_priv)
 #define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT)
 #define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT)
 #define HAS_PCH_LPT_LP(dev_priv) \
-       ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE)
+       ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE || \
+        (dev_priv)->pch_id == INTEL_PCH_WPT_LP_DEVICE_ID_TYPE)
 #define HAS_PCH_LPT_H(dev_priv) \
-       ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE)
+       ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE || \
+        (dev_priv)->pch_id == INTEL_PCH_WPT_DEVICE_ID_TYPE)
 #define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT)
 #define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX)
 #define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP)
@@ -3087,6 +3109,8 @@ extern void i915_driver_unload(struct drm_device *dev);
 extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask);
 extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);
 extern void i915_reset(struct drm_i915_private *dev_priv);
+extern int i915_reset_engine(struct intel_engine_cs *engine);
+extern bool intel_has_reset_engine(struct drm_i915_private *dev_priv);
 extern int intel_guc_reset(struct drm_i915_private *dev_priv);
 extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
 extern void intel_hangcheck_init(struct drm_i915_private *dev_priv);
@@ -3459,11 +3483,22 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)
        return READ_ONCE(error->reset_count);
 }
 
+static inline u32 i915_reset_engine_count(struct i915_gpu_error *error,
+                                         struct intel_engine_cs *engine)
+{
+       return READ_ONCE(error->reset_engine_count[engine->id]);
+}
+
+struct drm_i915_gem_request *
+i915_gem_reset_prepare_engine(struct intel_engine_cs *engine);
 int i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
 void i915_gem_reset(struct drm_i915_private *dev_priv);
+void i915_gem_reset_finish_engine(struct intel_engine_cs *engine);
 void i915_gem_reset_finish(struct drm_i915_private *dev_priv);
 void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
 bool i915_gem_unset_wedged(struct drm_i915_private *dev_priv);
+void i915_gem_reset_engine(struct intel_engine_cs *engine,
+                          struct drm_i915_gem_request *request);
 
 void i915_gem_init_mmio(struct drm_i915_private *i915);
 int __must_check i915_gem_init(struct drm_i915_private *dev_priv);
@@ -3497,7 +3532,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 void i915_gem_object_unpin_from_display_plane(struct i915_vma *vma);
 int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
                                int align);
-int i915_gem_open(struct drm_device *dev, struct drm_file *file);
+int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file);
 void i915_gem_release(struct drm_device *dev, struct drm_file *file);
 
 int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
@@ -3529,38 +3564,23 @@ void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
                                         struct sg_table *pages);
 
 static inline struct i915_gem_context *
-i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
+__i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
 {
-       struct i915_gem_context *ctx;
-
-       lockdep_assert_held(&file_priv->dev_priv->drm.struct_mutex);
-
-       ctx = idr_find(&file_priv->context_idr, id);
-       if (!ctx)
-               return ERR_PTR(-ENOENT);
-
-       return ctx;
+       return idr_find(&file_priv->context_idr, id);
 }
 
 static inline struct i915_gem_context *
-i915_gem_context_get(struct i915_gem_context *ctx)
-{
-       kref_get(&ctx->ref);
-       return ctx;
-}
-
-static inline void i915_gem_context_put(struct i915_gem_context *ctx)
+i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
 {
-       lockdep_assert_held(&ctx->i915->drm.struct_mutex);
-       kref_put(&ctx->ref, i915_gem_context_free);
-}
+       struct i915_gem_context *ctx;
 
-static inline void i915_gem_context_put_unlocked(struct i915_gem_context *ctx)
-{
-       struct mutex *lock = &ctx->i915->drm.struct_mutex;
+       rcu_read_lock();
+       ctx = __i915_gem_context_lookup_rcu(file_priv, id);
+       if (ctx && !kref_get_unless_zero(&ctx->ref))
+               ctx = NULL;
+       rcu_read_unlock();
 
-       if (kref_put_mutex(&ctx->ref, i915_gem_context_free, lock))
-               mutex_unlock(lock);
+       return ctx;
 }
 
 static inline struct intel_timeline *