These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / include / nvkm / subdev / timer.h
index 4ad5508..82d3e28 100644 (file)
@@ -9,53 +9,68 @@ struct nvkm_alarm {
 };
 
 static inline void
-nvkm_alarm_init(struct nvkm_alarm *alarm,
-                  void (*func)(struct nvkm_alarm *))
+nvkm_alarm_init(struct nvkm_alarm *alarm, void (*func)(struct nvkm_alarm *))
 {
        INIT_LIST_HEAD(&alarm->head);
        alarm->func = func;
 }
 
-bool nvkm_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data);
-bool nvkm_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data);
-bool nvkm_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data);
-void nvkm_timer_alarm(void *, u32 nsec, struct nvkm_alarm *);
-void nvkm_timer_alarm_cancel(void *, struct nvkm_alarm *);
-
-#define NV_WAIT_DEFAULT 2000000000ULL
-#define nv_wait(o,a,m,v)                                                       \
-       nvkm_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v))
-#define nv_wait_ne(o,a,m,v)                                                    \
-       nvkm_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v))
-#define nv_wait_cb(o,c,d)                                                      \
-       nvkm_timer_wait_cb((o), NV_WAIT_DEFAULT, (c), (d))
-
 struct nvkm_timer {
-       struct nvkm_subdev base;
-       u64  (*read)(struct nvkm_timer *);
-       void (*alarm)(struct nvkm_timer *, u64 time, struct nvkm_alarm *);
-       void (*alarm_cancel)(struct nvkm_timer *, struct nvkm_alarm *);
+       const struct nvkm_timer_func *func;
+       struct nvkm_subdev subdev;
+
+       struct list_head alarms;
+       spinlock_t lock;
 };
 
-static inline struct nvkm_timer *
-nvkm_timer(void *obj)
-{
-       return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_TIMER);
-}
+u64 nvkm_timer_read(struct nvkm_timer *);
+void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *);
+void nvkm_timer_alarm_cancel(struct nvkm_timer *, struct nvkm_alarm *);
+
+/* Delay based on GPU time (ie. PTIMER).
+ *
+ * Will return -ETIMEDOUT unless the loop was terminated with 'break',
+ * where it will return the number of nanoseconds taken instead.
+ *
+ * NVKM_DELAY can be passed for 'cond' to disable the timeout warning,
+ * which is useful for unconditional delay loops.
+ */
+#define NVKM_DELAY _warn = false;
+#define nvkm_nsec(d,n,cond...) ({                                              \
+       struct nvkm_device *_device = (d);                                     \
+       struct nvkm_timer *_tmr = _device->timer;                              \
+       u64 _nsecs = (n), _time0 = nvkm_timer_read(_tmr);                      \
+       s64 _taken = 0;                                                        \
+       bool _warn = true;                                                     \
+                                                                               \
+       do {                                                                   \
+               cond                                                           \
+       } while (_taken = nvkm_timer_read(_tmr) - _time0, _taken < _nsecs);    \
+                                                                               \
+       if (_taken >= _nsecs) {                                                \
+               if (_warn) {                                                   \
+                       dev_warn(_device->dev, "timeout at %s:%d/%s()!\n",     \
+                                __FILE__, __LINE__, __func__);                \
+               }                                                              \
+               _taken = -ETIMEDOUT;                                           \
+       }                                                                      \
+       _taken;                                                                \
+})
+#define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond)
+#define nvkm_msec(d,m,cond...) nvkm_usec((d), (m) * 1000, ##cond)
+
+#define nvkm_wait_nsec(d,n,addr,mask,data)                                     \
+       nvkm_nsec(d, n,                                                        \
+               if ((nvkm_rd32(d, (addr)) & (mask)) == (data))                 \
+                       break;                                                 \
+               )
+#define nvkm_wait_usec(d,u,addr,mask,data)                                     \
+       nvkm_wait_nsec((d), (u) * 1000, (addr), (mask), (data))
+#define nvkm_wait_msec(d,m,addr,mask,data)                                     \
+       nvkm_wait_usec((d), (m) * 1000, (addr), (mask), (data))
 
-#define nvkm_timer_create(p,e,o,d)                                          \
-       nvkm_subdev_create_((p), (e), (o), 0, "PTIMER", "timer",            \
-                              sizeof(**d), (void **)d)
-#define nvkm_timer_destroy(p)                                               \
-       nvkm_subdev_destroy(&(p)->base)
-#define nvkm_timer_init(p)                                                  \
-       nvkm_subdev_init(&(p)->base)
-#define nvkm_timer_fini(p,s)                                                \
-       nvkm_subdev_fini(&(p)->base, (s))
-
-int nvkm_timer_create_(struct nvkm_object *, struct nvkm_engine *,
-                         struct nvkm_oclass *, int size, void **);
-
-extern struct nvkm_oclass nv04_timer_oclass;
-extern struct nvkm_oclass gk20a_timer_oclass;
+int nv04_timer_new(struct nvkm_device *, int, struct nvkm_timer **);
+int nv40_timer_new(struct nvkm_device *, int, struct nvkm_timer **);
+int nv41_timer_new(struct nvkm_device *, int, struct nvkm_timer **);
+int gk20a_timer_new(struct nvkm_device *, int, struct nvkm_timer **);
 #endif