diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux/linux_compat.c index 31252afa1996..452fc7fb08ce 100644 --- a/sys/ofed/include/linux/linux_compat.c +++ b/sys/ofed/include/linux/linux_compat.c @@ -57,6 +57,7 @@ #include #include #include +#include #include @@ -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) { diff --git a/sys/ofed/include/linux/timer.h b/sys/ofed/include/linux/timer.h index 7a948d751161..0bb85b4f8a69 100644 --- a/sys/ofed/include/linux/timer.h +++ b/sys/ofed/include/linux/timer.h @@ -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 @@ -36,20 +36,13 @@ #include 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_ */