diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index 4e696627fdcd..d898787d514c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c | |||
@@ -71,14 +71,17 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) | |||
71 | struct nvkm_alarm *list; | 71 | struct nvkm_alarm *list; |
72 | unsigned long flags; | 72 | unsigned long flags; |
73 | 73 | ||
74 | alarm->timestamp = nvkm_timer_read(tmr) + nsec; | 74 | /* Remove alarm from pending list. |
75 | 75 | * | |
76 | /* append new alarm to list, in soonest-alarm-first order */ | 76 | * This both protects against the corruption of the list, |
77 | * and implements alarm rescheduling/cancellation. | ||
78 | */ | ||
77 | spin_lock_irqsave(&tmr->lock, flags); | 79 | spin_lock_irqsave(&tmr->lock, flags); |
78 | if (!nsec) { | 80 | list_del_init(&alarm->head); |
79 | if (!list_empty(&alarm->head)) | 81 | |
80 | list_del(&alarm->head); | 82 | if (nsec) { |
81 | } else { | 83 | /* Insert into pending list, ordered earliest to latest. */ |
84 | alarm->timestamp = nvkm_timer_read(tmr) + nsec; | ||
82 | list_for_each_entry(list, &tmr->alarms, head) { | 85 | list_for_each_entry(list, &tmr->alarms, head) { |
83 | if (list->timestamp > alarm->timestamp) | 86 | if (list->timestamp > alarm->timestamp) |
84 | break; | 87 | break; |