mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-03 11:13:56 +08:00
drm/nouveau/tmr: detect stalled gpu timer and break out of waits
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
a31e24a781
commit
e4f90a35c9
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user