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.