aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Peres <martin.peres@labri.fr>2013-08-11 22:48:51 -0400
committerBen Skeggs <bskeggs@redhat.com>2013-09-03 23:46:46 -0400
commitb925a75d6729cec8debd0c378b354d8c228b36aa (patch)
tree8a0050246254e8c07aca6658a6abae4453c32cf8
parent7fabd25393c7b5cb749d358772ccea2a570f4b49 (diff)
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: Martin Peres <martin.peres@labri.fr> Tested-by: Martin Peres <martin.peres@labri.fr> Tested-by: Dash Four <mr.dash.four@googlemail.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/timer.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/base.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c20
3 files changed, 29 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
index e465d158d352..9ab70dfe5b02 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h
@@ -22,6 +22,7 @@ bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data);
22bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); 22bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data);
23bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); 23bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data);
24void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); 24void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *);
25void nouveau_timer_alarm_cancel(void *, struct nouveau_alarm *);
25 26
26#define NV_WAIT_DEFAULT 2000000000ULL 27#define NV_WAIT_DEFAULT 2000000000ULL
27#define nv_wait(o,a,m,v) \ 28#define nv_wait(o,a,m,v) \
@@ -35,6 +36,7 @@ struct nouveau_timer {
35 struct nouveau_subdev base; 36 struct nouveau_subdev base;
36 u64 (*read)(struct nouveau_timer *); 37 u64 (*read)(struct nouveau_timer *);
37 void (*alarm)(struct nouveau_timer *, u64 time, struct nouveau_alarm *); 38 void (*alarm)(struct nouveau_timer *, u64 time, struct nouveau_alarm *);
39 void (*alarm_cancel)(struct nouveau_timer *, struct nouveau_alarm *);
38}; 40};
39 41
40static inline struct nouveau_timer * 42static inline struct nouveau_timer *
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/base.c b/drivers/gpu/drm/nouveau/core/subdev/timer/base.c
index 5d417cc9949b..cf8a0e0f8ee3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/timer/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/base.c
@@ -85,3 +85,10 @@ nouveau_timer_alarm(void *obj, u32 nsec, struct nouveau_alarm *alarm)
85 struct nouveau_timer *ptimer = nouveau_timer(obj); 85 struct nouveau_timer *ptimer = nouveau_timer(obj);
86 ptimer->alarm(ptimer, nsec, alarm); 86 ptimer->alarm(ptimer, nsec, alarm);
87} 87}
88
89void
90nouveau_timer_alarm_cancel(void *obj, struct nouveau_alarm *alarm)
91{
92 struct nouveau_timer *ptimer = nouveau_timer(obj);
93 ptimer->alarm_cancel(ptimer, alarm);
94}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
index 49350eaf4df5..57711ecb566c 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
@@ -114,6 +114,25 @@ nv04_timer_alarm(struct nouveau_timer *ptimer, u64 time,
114} 114}
115 115
116static void 116static void
117nv04_timer_alarm_cancel(struct nouveau_timer *ptimer,
118 struct nouveau_alarm *alarm)
119{
120 struct nv04_timer_priv *priv = (void *)ptimer;
121 unsigned long flags;
122
123 /* avoid deleting an entry while the alarm intr is running */
124 spin_lock_irqsave(&priv->lock, flags);
125
126 /* delete the alarm from the list */
127 list_del(&alarm->head);
128
129 /* reset the head so as list_empty returns 1 */
130 INIT_LIST_HEAD(&alarm->head);
131
132 spin_unlock_irqrestore(&priv->lock, flags);
133}
134
135static void
117nv04_timer_intr(struct nouveau_subdev *subdev) 136nv04_timer_intr(struct nouveau_subdev *subdev)
118{ 137{
119 struct nv04_timer_priv *priv = (void *)subdev; 138 struct nv04_timer_priv *priv = (void *)subdev;
@@ -147,6 +166,7 @@ nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
147 priv->base.base.intr = nv04_timer_intr; 166 priv->base.base.intr = nv04_timer_intr;
148 priv->base.read = nv04_timer_read; 167 priv->base.read = nv04_timer_read;
149 priv->base.alarm = nv04_timer_alarm; 168 priv->base.alarm = nv04_timer_alarm;
169 priv->base.alarm_cancel = nv04_timer_alarm_cancel;
150 priv->suspend_time = 0; 170 priv->suspend_time = 0;
151 171
152 INIT_LIST_HEAD(&priv->alarms); 172 INIT_LIST_HEAD(&priv->alarms);