From: Ben Skeggs Date: Tue, 11 Dec 2018 04:50:02 +0000 (+1000) Subject: drm/nouveau/tmr: detect stalled gpu timer and break out of waits X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=e4f90a35c9668f8d0469a0160482b1856d07c2b5;p=openwrt%2Fstaging%2Fblogic.git drm/nouveau/tmr: detect stalled gpu timer and break out of waits Signed-off-by: Ben Skeggs --- 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) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index 36de23d12ae4..dd922033628c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -23,6 +23,42 @@ */ #include "priv.h" +s64 +nvkm_timer_wait_test(struct nvkm_timer_wait *wait) +{ + struct nvkm_subdev *subdev = &wait->tmr->subdev; + u64 time = nvkm_timer_read(wait->tmr); + + if (wait->reads == 0) { + wait->time0 = time; + wait->time1 = time; + } + + if (wait->time1 == time) { + if (wait->reads++ == 16) { + nvkm_fatal(subdev, "stalled at %016llx\n", time); + return -ETIMEDOUT; + } + } else { + wait->time1 = time; + wait->reads = 1; + } + + if (wait->time1 - wait->time0 > wait->limit) + return -ETIMEDOUT; + + return wait->time1 - wait->time0; +} + +void +nvkm_timer_wait_init(struct nvkm_device *device, u64 nsec, + struct nvkm_timer_wait *wait) +{ + wait->tmr = device->timer; + wait->limit = nsec; + wait->reads = 0; +} + u64 nvkm_timer_read(struct nvkm_timer *tmr) {