Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b925a75d authored by Martin Peres's avatar Martin Peres Committed by Ben Skeggs
Browse files

drm/nouveau/timer: add a way to cancel alarms



Since alarms don't play well with suspend, it is important every alarm
user cancels his tasks before suspending.

The task should be rescheduled on resume.

Signed-off-by: default avatarMartin Peres <martin.peres@labri.fr>
Tested-by: default avatarMartin Peres <martin.peres@labri.fr>
Tested-by: default avatarDash Four <mr.dash.four@googlemail.com>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 7fabd253
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data);
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)                                                       \
@@ -35,6 +36,7 @@ struct nouveau_timer {
	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 *
+7 −0
Original line number Diff line number Diff line
@@ -85,3 +85,10 @@ nouveau_timer_alarm(void *obj, u32 nsec, struct nouveau_alarm *alarm)
	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);
}
+20 −0
Original line number Diff line number Diff line
@@ -113,6 +113,25 @@ nv04_timer_alarm(struct nouveau_timer *ptimer, u64 time,
	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)
{
@@ -147,6 +166,7 @@ nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
	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);