Skip to content

Commit 7fabd25

Browse files
mupufBen Skeggs
authored andcommitted
drm/nouveau/timer: restore the time on resume
This can be useful if some parts of Nouveau try to calculate the time between two events. Without this patch, the time difference would be negative in the case where the computer is suspended/resumed between two events. This patch should fix fan speed probing when done while suspending/resuming. Solve this by saving the current time before suspending and by restoring it on resume. Signed-off-by: Martin Peres <[email protected]> Tested-by: Martin Peres <[email protected]> Signed-off-by: Ben Skeggs <[email protected]>
1 parent 4cc00ad commit 7fabd25

File tree

1 file changed

+14
-1
lines changed
  • drivers/gpu/drm/nouveau/core/subdev/timer

1 file changed

+14
-1
lines changed

drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct nv04_timer_priv {
3636
struct nouveau_timer base;
3737
struct list_head alarms;
3838
spinlock_t lock;
39+
u64 suspend_time;
3940
};
4041

4142
static u64
@@ -146,6 +147,7 @@ nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
146147
priv->base.base.intr = nv04_timer_intr;
147148
priv->base.read = nv04_timer_read;
148149
priv->base.alarm = nv04_timer_alarm;
150+
priv->suspend_time = 0;
149151

150152
INIT_LIST_HEAD(&priv->alarms);
151153
spin_lock_init(&priv->lock);
@@ -164,7 +166,7 @@ nv04_timer_init(struct nouveau_object *object)
164166
{
165167
struct nouveau_device *device = nv_device(object);
166168
struct nv04_timer_priv *priv = (void *)object;
167-
u32 m = 1, f, n, d;
169+
u32 m = 1, f, n, d, lo, hi;
168170
int ret;
169171

170172
ret = nouveau_timer_init(&priv->base);
@@ -221,23 +223,34 @@ nv04_timer_init(struct nouveau_object *object)
221223
d >>= 1;
222224
}
223225

226+
/* restore the time before suspend */
227+
lo = priv->suspend_time;
228+
hi = (priv->suspend_time >> 32);
229+
224230
nv_debug(priv, "input frequency : %dHz\n", f);
225231
nv_debug(priv, "input multiplier: %d\n", m);
226232
nv_debug(priv, "numerator : 0x%08x\n", n);
227233
nv_debug(priv, "denominator : 0x%08x\n", d);
228234
nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n);
235+
nv_debug(priv, "time low : 0x%08x\n", lo);
236+
nv_debug(priv, "time high : 0x%08x\n", hi);
229237

230238
nv_wr32(priv, NV04_PTIMER_NUMERATOR, n);
231239
nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d);
232240
nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff);
233241
nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
242+
nv_wr32(priv, NV04_PTIMER_TIME_1, hi);
243+
nv_wr32(priv, NV04_PTIMER_TIME_0, lo);
244+
234245
return 0;
235246
}
236247

237248
static int
238249
nv04_timer_fini(struct nouveau_object *object, bool suspend)
239250
{
240251
struct nv04_timer_priv *priv = (void *)object;
252+
if (suspend)
253+
priv->suspend_time = nv04_timer_read(&priv->base);
241254
nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
242255
return nouveau_timer_fini(&priv->base, suspend);
243256
}

0 commit comments

Comments
 (0)