bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data);
 bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data);
 void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *);
+void nouveau_timer_alarm_cancel(void *, struct nouveau_alarm *);
 
 #define NV_WAIT_DEFAULT 2000000000ULL
 #define nv_wait(o,a,m,v)                                                       \
        struct nouveau_subdev base;
        u64  (*read)(struct nouveau_timer *);
        void (*alarm)(struct nouveau_timer *, u64 time, struct nouveau_alarm *);
+       void (*alarm_cancel)(struct nouveau_timer *, struct nouveau_alarm *);
 };
 
 static inline struct nouveau_timer *
 
        struct nouveau_timer *ptimer = nouveau_timer(obj);
        ptimer->alarm(ptimer, nsec, alarm);
 }
+
+void
+nouveau_timer_alarm_cancel(void *obj, struct nouveau_alarm *alarm)
+{
+       struct nouveau_timer *ptimer = nouveau_timer(obj);
+       ptimer->alarm_cancel(ptimer, alarm);
+}
 
        nv04_timer_alarm_trigger(ptimer);
 }
 
+static void
+nv04_timer_alarm_cancel(struct nouveau_timer *ptimer,
+                       struct nouveau_alarm *alarm)
+{
+       struct nv04_timer_priv *priv = (void *)ptimer;
+       unsigned long flags;
+
+       /* avoid deleting an entry while the alarm intr is running */
+       spin_lock_irqsave(&priv->lock, flags);
+
+       /* delete the alarm from the list */
+       list_del(&alarm->head);
+
+       /* reset the head so as list_empty returns 1 */
+       INIT_LIST_HEAD(&alarm->head);
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
 static void
 nv04_timer_intr(struct nouveau_subdev *subdev)
 {
        priv->base.base.intr = nv04_timer_intr;
        priv->base.read = nv04_timer_read;
        priv->base.alarm = nv04_timer_alarm;
+       priv->base.alarm_cancel = nv04_timer_alarm_cancel;
        priv->suspend_time = 0;
 
        INIT_LIST_HEAD(&priv->alarms);