svn commit: r280210 - head/sys/ofed/include/linux
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Mar 18 10:49:19 UTC 2015
Author: hselasky
Date: Wed Mar 18 10:49:17 2015
New Revision: 280210
URL: https://svnweb.freebsd.org/changeset/base/280210
Log:
Fix problems about 32-bit ticks wraparound and unsigned long
conversion:
- The linux compat API layer casts the ticks to unsigned long which
might cause problems when the ticks value is negative.
- Guard against already expired ticks values, by checking if the
passed expiry tick is already elapsed.
- While at it avoid referring the address of an inlined function.
MFC after: 3 days
Sponsored by: Mellanox Technologies
Modified:
head/sys/ofed/include/linux/linux_compat.c
head/sys/ofed/include/linux/timer.h
Modified: head/sys/ofed/include/linux/linux_compat.c
==============================================================================
--- head/sys/ofed/include/linux/linux_compat.c Wed Mar 18 09:39:31 2015 (r280209)
+++ head/sys/ofed/include/linux/linux_compat.c Wed Mar 18 10:49:17 2015 (r280210)
@@ -57,6 +57,7 @@
#include <linux/io.h>
#include <linux/vmalloc.h>
#include <linux/netdevice.h>
+#include <linux/timer.h>
#include <vm/vm_pager.h>
@@ -77,6 +78,8 @@ struct list_head pci_devices;
struct net init_net;
spinlock_t pci_lock;
+unsigned long linux_timer_hz_mask;
+
int
panic_cmp(struct rb_node *one, struct rb_node *two)
{
@@ -724,6 +727,60 @@ kasprintf(gfp_t gfp, const char *fmt, ..
return p;
}
+static int
+linux_timer_jiffies_until(unsigned long expires)
+{
+ int delta = expires - jiffies;
+ /* guard against already expired values */
+ if (delta < 1)
+ delta = 1;
+ return (delta);
+}
+
+static void
+linux_timer_callback_wrapper(void *context)
+{
+ struct timer_list *timer;
+
+ timer = context;
+ timer->function(timer->data);
+}
+
+void
+mod_timer(struct timer_list *timer, unsigned long expires)
+{
+
+ timer->expires = expires;
+ callout_reset(&timer->timer_callout,
+ linux_timer_jiffies_until(expires),
+ &linux_timer_callback_wrapper, timer);
+}
+
+void
+add_timer(struct timer_list *timer)
+{
+
+ callout_reset(&timer->timer_callout,
+ linux_timer_jiffies_until(timer->expires),
+ &linux_timer_callback_wrapper, timer);
+}
+
+static void
+linux_timer_init(void *arg)
+{
+
+ /*
+ * Compute an internal HZ value which can divide 2**32 to
+ * avoid timer rounding problems when the tick value wraps
+ * around 2**32:
+ */
+ linux_timer_hz_mask = 1;
+ while (linux_timer_hz_mask < (unsigned long)hz)
+ linux_timer_hz_mask *= 2;
+ linux_timer_hz_mask--;
+}
+SYSINIT(linux_timer, SI_SUB_DRIVERS, SI_ORDER_FIRST, linux_timer_init, NULL);
+
static void
linux_compat_init(void)
{
Modified: head/sys/ofed/include/linux/timer.h
==============================================================================
--- head/sys/ofed/include/linux/timer.h Wed Mar 18 09:39:31 2015 (r280209)
+++ head/sys/ofed/include/linux/timer.h Wed Mar 18 10:49:17 2015 (r280210)
@@ -27,7 +27,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LINUX_TIMER_H_
-#define _LINUX_TIMER_H_
+#define _LINUX_TIMER_H_
#include <linux/types.h>
@@ -36,20 +36,13 @@
#include <sys/callout.h>
struct timer_list {
- struct callout timer_callout;
- void (*function)(unsigned long);
- unsigned long data;
- unsigned long expires;
+ struct callout timer_callout;
+ void (*function) (unsigned long);
+ unsigned long data;
+ unsigned long expires;
};
-static inline void
-_timer_fn(void *context)
-{
- struct timer_list *timer;
-
- timer = context;
- timer->function(timer->data);
-}
+extern unsigned long linux_timer_hz_mask;
#define setup_timer(timer, func, dat) \
do { \
@@ -65,28 +58,15 @@ do { \
callout_init(&(timer)->timer_callout, CALLOUT_MPSAFE); \
} while (0)
-#define mod_timer(timer, exp) \
-do { \
- (timer)->expires = (exp); \
- callout_reset(&(timer)->timer_callout, (exp) - jiffies, \
- _timer_fn, (timer)); \
-} while (0)
-
-#define add_timer(timer) \
- callout_reset(&(timer)->timer_callout, \
- (timer)->expires - jiffies, _timer_fn, (timer))
+extern void mod_timer(struct timer_list *, unsigned long);
+extern void add_timer(struct timer_list *);
#define del_timer(timer) callout_stop(&(timer)->timer_callout)
#define del_timer_sync(timer) callout_drain(&(timer)->timer_callout)
-
#define timer_pending(timer) callout_pending(&(timer)->timer_callout)
+#define round_jiffies(j) \
+ ((unsigned long)(((j) + linux_timer_hz_mask) & ~linux_timer_hz_mask))
+#define round_jiffies_relative(j) \
+ round_jiffies(j)
-static inline unsigned long
-round_jiffies(unsigned long j)
-{
- return roundup(j, hz);
-}
-
-#define round_jiffies_relative(j) round_jiffies(j)
-
-#endif /* _LINUX_TIMER_H_ */
+#endif /* _LINUX_TIMER_H_ */
More information about the svn-src-all
mailing list