@@ -41,6 +41,10 @@ gk20a_timer_init(struct nvkm_object *object)
/* restore the time before suspend */
nv_wr32(priv, NV04_PTIMER_TIME_1, hi);
nv_wr32(priv, NV04_PTIMER_TIME_0, lo);
+
+ /* save kernel time as fallback */
+ priv->suspend_ktime = ktime_to_ns(ktime_get()) - priv->suspend_time;
+
return 0;
}
@@ -36,6 +36,11 @@ nv04_timer_read(struct nvkm_timer *ptimer)
lo = nv_rd32(priv, NV04_PTIMER_TIME_0);
} while (hi != nv_rd32(priv, NV04_PTIMER_TIME_1));
+ if (unlikely(hi == -1 && lo == -1)) {
+ nv_spam(priv, "read failed, falling back to kernel timer\n");
+ return ktime_to_ns(ktime_get()) - priv->suspend_ktime;
+ }
+
return ((u64)hi << 32 | lo);
}
@@ -216,6 +221,10 @@ nv04_timer_init(struct nvkm_object *object)
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);
+
+ /* save kernel time as fallback */
+ priv->suspend_ktime = ktime_to_ns(ktime_get()) - priv->suspend_time;
+
return 0;
}
@@ -15,6 +15,7 @@ struct nv04_timer_priv {
struct list_head alarms;
spinlock_t lock;
u64 suspend_time;
+ u64 suspend_ktime;
};
int nv04_timer_ctor(struct nvkm_object *, struct nvkm_object *,