diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h')
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h index 2c27ce691939..b26ae6fa5ba7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h @@ -16,12 +16,63 @@ nvkm_alarm_init(struct nvkm_alarm *alarm, 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 *); +/* 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 = _tmr->read(_tmr); \ + s64 _taken = 0; \ + bool _warn = true; \ + \ + do { \ + cond \ + } while (_taken = _tmr->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_timer_wait_eq(o,n,a,m,v) ({ \ + struct nvkm_device *__device = nv_device(o); \ + nvkm_nsec(__device, (n), \ + if ((nvkm_rd32(__device, (a)) & (m)) == (v)) \ + break; \ + ) >= 0; \ +}) +#define nvkm_timer_wait_ne(o,n,a,m,v) ({ \ + struct nvkm_device *__device = nv_device(o); \ + nvkm_nsec(__device, (n), \ + if ((nvkm_rd32(__device, (a)) & (m)) != (v)) \ + break; \ + ) >= 0; \ +}) +#define nvkm_timer_wait_cb(o,n,c,d) ({ \ + struct nvkm_device *__device = nv_device(o); \ + nvkm_nsec(__device, (n), \ + if (c(d)) \ + break; \ + ) >= 0; \ +}) + #define NV_WAIT_DEFAULT 2000000000ULL #define nv_wait(o,a,m,v) \ nvkm_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v)) |