1 #ifndef __NVKM_TIMER_H__ 2 #define __NVKM_TIMER_H__ 3 #include <core/subdev.h> 4 5 struct nvkm_alarm { 6 struct list_head head; 7 u64 timestamp; 8 void (*func)(struct nvkm_alarm *); 9 }; 10 11 static inline void 12 nvkm_alarm_init(struct nvkm_alarm *alarm, 13 void (*func)(struct nvkm_alarm *)) 14 { 15 INIT_LIST_HEAD(&alarm->head); 16 alarm->func = func; 17 } 18 19 void nvkm_timer_alarm(void *, u32 nsec, struct nvkm_alarm *); 20 void nvkm_timer_alarm_cancel(void *, struct nvkm_alarm *); 21 22 /* Delay based on GPU time (ie. PTIMER). 23 * 24 * Will return -ETIMEDOUT unless the loop was terminated with 'break', 25 * where it will return the number of nanoseconds taken instead. 26 * 27 * NVKM_DELAY can be passed for 'cond' to disable the timeout warning, 28 * which is useful for unconditional delay loops. 29 */ 30 #define NVKM_DELAY _warn = false; 31 #define nvkm_nsec(d,n,cond...) ({ \ 32 struct nvkm_device *_device = (d); \ 33 struct nvkm_timer *_tmr = _device->timer; \ 34 u64 _nsecs = (n), _time0 = _tmr->read(_tmr); \ 35 s64 _taken = 0; \ 36 bool _warn = true; \ 37 \ 38 do { \ 39 cond \ 40 } while (_taken = _tmr->read(_tmr) - _time0, _taken < _nsecs); \ 41 \ 42 if (_taken >= _nsecs) { \ 43 if (_warn) { \ 44 dev_warn(_device->dev, "timeout at %s:%d/%s()!\n", \ 45 __FILE__, __LINE__, __func__); \ 46 } \ 47 _taken = -ETIMEDOUT; \ 48 } \ 49 _taken; \ 50 }) 51 #define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond) 52 #define nvkm_msec(d,m,cond...) nvkm_usec((d), (m) * 1000, ##cond) 53 54 struct nvkm_timer { 55 struct nvkm_subdev subdev; 56 u64 (*read)(struct nvkm_timer *); 57 void (*alarm)(struct nvkm_timer *, u64 time, struct nvkm_alarm *); 58 void (*alarm_cancel)(struct nvkm_timer *, struct nvkm_alarm *); 59 }; 60 61 static inline struct nvkm_timer * 62 nvkm_timer(void *obj) 63 { 64 return (void *)nvkm_subdev(obj, NVDEV_SUBDEV_TIMER); 65 } 66 67 #define nvkm_timer_create(p,e,o,d) \ 68 nvkm_subdev_create_((p), (e), (o), 0, "PTIMER", "timer", \ 69 sizeof(**d), (void **)d) 70 #define nvkm_timer_destroy(p) \ 71 nvkm_subdev_destroy(&(p)->subdev) 72 #define nvkm_timer_init(p) \ 73 nvkm_subdev_init_old(&(p)->subdev) 74 #define nvkm_timer_fini(p,s) \ 75 nvkm_subdev_fini_old(&(p)->subdev, (s)) 76 77 int nvkm_timer_create_(struct nvkm_object *, struct nvkm_engine *, 78 struct nvkm_oclass *, int size, void **); 79 80 extern struct nvkm_oclass nv04_timer_oclass; 81 extern struct nvkm_oclass gk20a_timer_oclass; 82 #endif 83