diff options
-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 07dc82bfe346..182f27c73aeb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c | |||
@@ -65,14 +65,17 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) | |||
65 | struct nvkm_alarm *list; | 65 | struct nvkm_alarm *list; |
66 | unsigned long flags; | 66 | unsigned long flags; |
67 | 67 | ||
68 | alarm->timestamp = nvkm_timer_read(tmr) + nsec; | 68 | /* Remove alarm from pending list. |
69 | 69 | * | |
70 | /* append new alarm to list, in soonest-alarm-first order */ | 70 | * This both protects against the corruption of the list, |
71 | * and implements alarm rescheduling/cancellation. | ||
72 | */ | ||
71 | spin_lock_irqsave(&tmr->lock, flags); | 73 | spin_lock_irqsave(&tmr->lock, flags); |
72 | if (!nsec) { | 74 | list_del_init(&alarm->head); |
73 | if (!list_empty(&alarm->head)) | 75 | |
74 | list_del(&alarm->head); | 76 | if (nsec) { |
75 | } else { | 77 | /* Insert into pending list, ordered earliest to latest. */ |
78 | alarm->timestamp = nvkm_timer_read(tmr) + nsec; | ||
76 | list_for_each_entry(list, &tmr->alarms, head) { | 79 | list_for_each_entry(list, &tmr->alarms, head) { |
77 | if (list->timestamp > alarm->timestamp) | 80 | if (list->timestamp > alarm->timestamp) |
78 | break; | 81 | break; |