diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2018-12-11 14:50:02 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2018-12-11 15:37:45 +1000 |
commit | e4f90a35c9668f8d0469a0160482b1856d07c2b5 (patch) | |
tree | 5fd2d6c73da8c7936c2776f2f054b3a9c15cf43e /drivers/gpu/drm/nouveau/include | |
parent | a31e24a781bc0cb60ec43499673ef49460597fec (diff) | |
download | linux-e4f90a35c9668f8d0469a0160482b1856d07c2b5.tar.gz linux-e4f90a35c9668f8d0469a0160482b1856d07c2b5.tar.bz2 linux-e4f90a35c9668f8d0469a0160482b1856d07c2b5.zip |
drm/nouveau/tmr: detect stalled gpu timer and break out of waits
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/include')
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h index e9b0746826ca..3693ebf371b6 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h @@ -28,6 +28,18 @@ struct nvkm_timer { u64 nvkm_timer_read(struct nvkm_timer *); void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *); +struct nvkm_timer_wait { + struct nvkm_timer *tmr; + u64 limit; + u64 time0; + u64 time1; + int reads; +}; + +void nvkm_timer_wait_init(struct nvkm_device *, u64 nsec, + struct nvkm_timer_wait *); +s64 nvkm_timer_wait_test(struct nvkm_timer_wait *); + /* Delay based on GPU time (ie. PTIMER). * * Will return -ETIMEDOUT unless the loop was terminated with 'break', @@ -38,21 +50,17 @@ void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *); */ #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; \ + struct nvkm_timer_wait _wait; \ bool _warn = true; \ + s64 _taken = 0; \ \ + nvkm_timer_wait_init((d), (n), &_wait); \ do { \ cond \ - } while (_taken = nvkm_timer_read(_tmr) - _time0, _taken < _nsecs); \ + } while ((_taken = nvkm_timer_wait_test(&_wait)) >= 0); \ \ - if (_taken >= _nsecs) { \ - if (_warn) \ - dev_WARN(_device->dev, "timeout\n"); \ - _taken = -ETIMEDOUT; \ - } \ + if (_warn && _taken < 0) \ + dev_WARN(_wait.tmr->subdev.device->dev, "timeout\n"); \ _taken; \ }) #define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond) |