Skip to content

Commit

Permalink
drm/nouveau/timer: restore the time on resume
Browse files Browse the repository at this point in the history
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 <martin.peres@labri.fr>
Tested-by: Martin Peres <martin.peres@labri.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Martin Peres authored and Ben Skeggs committed Sep 4, 2013
1 parent 4cc00ad commit 7fabd25
Showing 1 changed file with 14 additions and 1 deletion.
15 changes: 14 additions & 1 deletion drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct nv04_timer_priv {
struct nouveau_timer base;
struct list_head alarms;
spinlock_t lock;
u64 suspend_time;
};

static u64
Expand Down Expand Up @@ -146,6 +147,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->suspend_time = 0;

INIT_LIST_HEAD(&priv->alarms);
spin_lock_init(&priv->lock);
Expand All @@ -164,7 +166,7 @@ nv04_timer_init(struct nouveau_object *object)
{
struct nouveau_device *device = nv_device(object);
struct nv04_timer_priv *priv = (void *)object;
u32 m = 1, f, n, d;
u32 m = 1, f, n, d, lo, hi;
int ret;

ret = nouveau_timer_init(&priv->base);
Expand Down Expand Up @@ -221,23 +223,34 @@ nv04_timer_init(struct nouveau_object *object)
d >>= 1;
}

/* restore the time before suspend */
lo = priv->suspend_time;
hi = (priv->suspend_time >> 32);

nv_debug(priv, "input frequency : %dHz\n", f);
nv_debug(priv, "input multiplier: %d\n", m);
nv_debug(priv, "numerator : 0x%08x\n", n);
nv_debug(priv, "denominator : 0x%08x\n", d);
nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n);
nv_debug(priv, "time low : 0x%08x\n", lo);
nv_debug(priv, "time high : 0x%08x\n", hi);

nv_wr32(priv, NV04_PTIMER_NUMERATOR, n);
nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d);
nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff);
nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
nv_wr32(priv, NV04_PTIMER_TIME_1, hi);
nv_wr32(priv, NV04_PTIMER_TIME_0, lo);

return 0;
}

static int
nv04_timer_fini(struct nouveau_object *object, bool suspend)
{
struct nv04_timer_priv *priv = (void *)object;
if (suspend)
priv->suspend_time = nv04_timer_read(&priv->base);
nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000);
return nouveau_timer_fini(&priv->base, suspend);
}
Expand Down

0 comments on commit 7fabd25

Please sign in to comment.