Since commit 2a991d374670 ("Treat jiffies as msec since boot"), we've been
waiting ten times longer than we should.  For Linux code, jiffies are one
msec, and HZ = 1000.

Similarly, some mlx4 code was using mod_timer() for relative changes.  Once
we started treating jiffies as non-zero, these timers broke.

This fixes some nastiness with mod_timer - there never should have been
'delay', since all callers expect to use absolute time.  We should have
just had jiffies == msec or whatever from the beginning.

Signed-off-by: Barret Rhoden <[email protected]>
---
This fixes the "mlx4 NIC hangs after 45 seconds" bug.

Merged to master at 95f45ef968ee..4541914c444a (from, to]

You can see the entire diff with 'git diff' or at
https://github.com/brho/akaros/compare/95f45ef968ee...4541914c444a


 kern/drivers/net/mlx4/catas.c    |  8 --------
 kern/drivers/net/mlx4/sense.c    |  8 --------
 kern/include/linux/compat_todo.h | 30 +++++++++++++++++++-----------
 kern/src/taskqueue.c             |  5 ++++-
 4 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/kern/drivers/net/mlx4/catas.c b/kern/drivers/net/mlx4/catas.c
index 757974f8c0f9..d117706025e8 100644
--- a/kern/drivers/net/mlx4/catas.c
+++ b/kern/drivers/net/mlx4/catas.c
@@ -247,12 +247,8 @@ static void poll_catas(unsigned long dev_ptr)
                goto internal_err;
        }
 
-#if 0 // AKAROS_PORT
        mod_timer(&priv->catas_err.timer,
                  round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL));
-#else
-       mod_timer(&priv->catas_err.timer, MLX4_CATAS_POLL_INTERVAL);
-#endif
        return;
 
 internal_err:
@@ -297,12 +293,8 @@ void mlx4_start_catas_poll(struct mlx4_dev *dev)
 
        priv->catas_err.timer.data     = (unsigned long) dev;
        priv->catas_err.timer.function = poll_catas;
-#if 0 // AKAROS_PORT
        priv->catas_err.timer.expires  =
                round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL);
-#else
-       priv->catas_err.timer.delay    = MLX4_CATAS_POLL_INTERVAL;
-#endif
        add_timer(&priv->catas_err.timer);
 }
 
diff --git a/kern/drivers/net/mlx4/sense.c b/kern/drivers/net/mlx4/sense.c
index 22a26a422dad..62ff5f48f0b4 100644
--- a/kern/drivers/net/mlx4/sense.c
+++ b/kern/drivers/net/mlx4/sense.c
@@ -107,11 +107,7 @@ static void mlx4_sense_port(struct work_struct *work)
 sense_again:
        qunlock(&priv->port_mutex);
        queue_delayed_work(mlx4_wq , &sense->sense_poll,
-#if 0 // AKAROS_PORT
                           round_jiffies_relative(MLX4_SENSE_RANGE));
-#else
-                          MLX4_SENSE_RANGE);
-#endif
 }
 
 void mlx4_start_sense(struct mlx4_dev *dev)
@@ -123,11 +119,7 @@ void mlx4_start_sense(struct mlx4_dev *dev)
                return;
 
        queue_delayed_work(mlx4_wq , &sense->sense_poll,
-#if 0 // AKAROS_PORT
                           round_jiffies_relative(MLX4_SENSE_RANGE));
-#else
-                          MLX4_SENSE_RANGE);
-#endif
 }
 
 void mlx4_stop_sense(struct mlx4_dev *dev)
diff --git a/kern/include/linux/compat_todo.h b/kern/include/linux/compat_todo.h
index 2969971c014e..a0e88513718d 100644
--- a/kern/include/linux/compat_todo.h
+++ b/kern/include/linux/compat_todo.h
@@ -297,10 +297,20 @@ static inline unsigned long 
wait_for_completion_timeout(struct completion *x,
 
 #define jiffies tsc2msec(read_tsc())
 
+static inline unsigned long round_jiffies(unsigned long j)
+{
+       return j / 1000 * 1000;
+}
+
+static inline unsigned long round_jiffies_relative(unsigned long j)
+{
+       return round_jiffies(j);
+}
+
 struct timer_list {
        spinlock_t lock;
        bool scheduled;
-       unsigned long delay;
+       unsigned long expires;
        void (*function)(unsigned long);
        unsigned long data;
 };
@@ -309,7 +319,7 @@ static inline void init_timer(struct timer_list *timer)
 {
        spinlock_init_irqsave(&timer->lock);
        timer->scheduled = false;
-       timer->delay = 0;
+       timer->expires = -1;
        timer->function = 0;
        timer->data = 0;
 }
@@ -325,14 +335,16 @@ static inline void setup_timer(struct timer_list *timer,
 static void __timer_wrapper(uint32_t srcid, long a0, long a1, long a2)
 {
        struct timer_list *timer = (struct timer_list *)a0;
-       unsigned long delay = 0;
+       unsigned long expires, now_j;
 
        spin_lock_irqsave(&timer->lock);
-       delay = timer->delay;
+       expires = timer->expires;
        timer->scheduled = false;
        spin_unlock_irqsave(&timer->lock);
 
-       kthread_usleep(delay * 10000);
+       now_j = jiffies;
+       if (expires > now_j)
+               kthread_usleep((expires - now_j) * 1000);
        timer->function(timer->data);
 }
 
@@ -343,14 +355,10 @@ static inline void add_timer(struct timer_list *timer)
                            KMSG_ROUTINE);
 }
 
-static inline void mod_timer(struct timer_list *timer, unsigned long abs_msec)
+static inline void mod_timer(struct timer_list *timer, unsigned long expires)
 {
        spin_lock_irqsave(&timer->lock);
-       /* Our callers often use jiffies + rel_time.  This jiffies may be 
slightly
-        * more than the previous jiffies */
-       timer->delay = abs_msec - jiffies;
-       if ((long)timer->delay < 0)
-               timer->delay = 0;
+       timer->expires = expires;
        if (timer->scheduled) {
                spin_unlock_irqsave(&timer->lock);
                return;
diff --git a/kern/src/taskqueue.c b/kern/src/taskqueue.c
index 4e868aaf84f5..e9884099bb1f 100644
--- a/kern/src/taskqueue.c
+++ b/kern/src/taskqueue.c
@@ -47,11 +47,14 @@ static void __wq_wrapper(uint32_t srcid, long a0, long a1, 
long a2)
        work->func(work);
 }
 
+/* Linux callers use jiffies as the unit of delay.  We pretend to be a 1000 HZ
+ * machine with 1 msec jiffies. */
 static void __wq_wrapper_delay(uint32_t srcid, long a0, long a1, long a2)
 {
        struct work_struct *work = (struct work_struct*)a0;
        unsigned long delay = (unsigned long)a1;
-       kthread_usleep(delay * 10000);
+
+       kthread_usleep(delay * 1000);
        work->func(work);
 }
 
-- 
2.15.0.531.g2ccb3012c9-goog

-- 
You received this message because you are subscribed to the Google Groups 
"Akaros" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to