Index: sys/compat/linuxkpi/common/include/linux/timer.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/timer.h +++ sys/compat/linuxkpi/common/include/linux/timer.h @@ -47,7 +47,7 @@ int expires; }; -extern unsigned long linux_timer_hz_mask; +extern unsigned long lkpi_timer_hz_mask; #define TIMER_IRQSAFE 0x0001 @@ -78,15 +78,27 @@ callout_init(&(timer)->callout, 1); \ } while (0) -extern int mod_timer(struct timer_list *, int); -extern void add_timer(struct timer_list *); -extern void add_timer_on(struct timer_list *, int cpu); -extern int del_timer(struct timer_list *); -extern int del_timer_sync(struct timer_list *); +int lkpi_mod_timer(struct timer_list *timer, int expires); +void lkpi_add_timer(struct timer_list *timer); +void lkpi_add_timer_on(struct timer_list *timer, int cpu); +int lkpi_del_timer(struct timer_list *timer); +int lkpi_del_timer_sync(struct timer_list *timer); + + +#define mod_timer(timer, expires) \ + lkpi_mod_timer(timer, expires) +#define add_timer(timer) \ + lkpi_add_timer(timer) +#define add_timer_on(timer, cpu) \ + lkpi_timer_on(timer, cpu) +#define del_timer(timer) \ + lkpi_del_timer(timer) +#define del_timer_sync(timer) \ + lkpi_del_timer_sync(timer) #define timer_pending(timer) callout_pending(&(timer)->callout) #define round_jiffies(j) \ - ((int)(((j) + linux_timer_hz_mask) & ~linux_timer_hz_mask)) + ((int)(((j) + lkpi_timer_hz_mask) & ~lkpi_timer_hz_mask)) #define round_jiffies_relative(j) round_jiffies(j) #define round_jiffies_up(j) round_jiffies(j) #define round_jiffies_up_relative(j) round_jiffies_up(j) Index: sys/compat/linuxkpi/common/src/linux_compat.c =================================================================== --- sys/compat/linuxkpi/common/src/linux_compat.c +++ sys/compat/linuxkpi/common/src/linux_compat.c @@ -118,8 +118,6 @@ struct list_head pci_devices; spinlock_t pci_lock; -unsigned long linux_timer_hz_mask; - wait_queue_head_t linux_bit_waitq; wait_queue_head_t linux_var_waitq; @@ -1747,134 +1745,6 @@ return (p); } -static void -linux_timer_callback_wrapper(void *context) -{ - struct timer_list *timer; - - linux_set_current(curthread); - - timer = context; - timer->function(timer->data); -} - -int -mod_timer(struct timer_list *timer, int expires) -{ - int ret; - - timer->expires = expires; - ret = callout_reset(&timer->callout, - linux_timer_jiffies_until(expires), - &linux_timer_callback_wrapper, timer); - - MPASS(ret == 0 || ret == 1); - - return (ret == 1); -} - -void -add_timer(struct timer_list *timer) -{ - - callout_reset(&timer->callout, - linux_timer_jiffies_until(timer->expires), - &linux_timer_callback_wrapper, timer); -} - -void -add_timer_on(struct timer_list *timer, int cpu) -{ - - callout_reset_on(&timer->callout, - linux_timer_jiffies_until(timer->expires), - &linux_timer_callback_wrapper, timer, cpu); -} - -int -del_timer(struct timer_list *timer) -{ - - if (callout_stop(&(timer)->callout) == -1) - return (0); - return (1); -} - -int -del_timer_sync(struct timer_list *timer) -{ - - if (callout_drain(&(timer)->callout) == -1) - return (0); - return (1); -} - -/* greatest common divisor, Euclid equation */ -static uint64_t -lkpi_gcd_64(uint64_t a, uint64_t b) -{ - uint64_t an; - uint64_t bn; - - while (b != 0) { - an = b; - bn = a % b; - a = an; - b = bn; - } - return (a); -} - -uint64_t lkpi_nsec2hz_rem; -uint64_t lkpi_nsec2hz_div = 1000000000ULL; -uint64_t lkpi_nsec2hz_max; - -uint64_t lkpi_usec2hz_rem; -uint64_t lkpi_usec2hz_div = 1000000ULL; -uint64_t lkpi_usec2hz_max; - -uint64_t lkpi_msec2hz_rem; -uint64_t lkpi_msec2hz_div = 1000ULL; -uint64_t lkpi_msec2hz_max; - -static void -linux_timer_init(void *arg) -{ - uint64_t gcd; - - /* - * 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--; - - /* compute some internal constants */ - - lkpi_nsec2hz_rem = hz; - lkpi_usec2hz_rem = hz; - lkpi_msec2hz_rem = hz; - - gcd = lkpi_gcd_64(lkpi_nsec2hz_rem, lkpi_nsec2hz_div); - lkpi_nsec2hz_rem /= gcd; - lkpi_nsec2hz_div /= gcd; - lkpi_nsec2hz_max = -1ULL / lkpi_nsec2hz_rem; - - gcd = lkpi_gcd_64(lkpi_usec2hz_rem, lkpi_usec2hz_div); - lkpi_usec2hz_rem /= gcd; - lkpi_usec2hz_div /= gcd; - lkpi_usec2hz_max = -1ULL / lkpi_usec2hz_rem; - - gcd = lkpi_gcd_64(lkpi_msec2hz_rem, lkpi_msec2hz_div); - lkpi_msec2hz_rem /= gcd; - lkpi_msec2hz_div /= gcd; - lkpi_msec2hz_max = -1ULL / lkpi_msec2hz_rem; -} -SYSINIT(linux_timer, SI_SUB_DRIVERS, SI_ORDER_FIRST, linux_timer_init, NULL); - void linux_complete_common(struct completion *c, int all) { Index: sys/compat/linuxkpi/common/src/linux_timer.c =================================================================== --- /dev/null +++ sys/compat/linuxkpi/common/src/linux_timer.c @@ -0,0 +1,165 @@ +/*- + * Copyright (c) 2010 Isilon Systems, Inc. + * Copyright (c) 2010 iX Systems, Inc. + * Copyright (c) 2010 Panasas, Inc. + * Copyright (c) 2013-2018 Mellanox Technologies, Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +unsigned long lkpi_timer_hz_mask; + +uint64_t lkpi_nsec2hz_rem; +uint64_t lkpi_nsec2hz_div = 1000000000ULL; +uint64_t lkpi_nsec2hz_max; + +uint64_t lkpi_usec2hz_rem; +uint64_t lkpi_usec2hz_div = 1000000ULL; +uint64_t lkpi_usec2hz_max; + +uint64_t lkpi_msec2hz_rem; +uint64_t lkpi_msec2hz_div = 1000ULL; +uint64_t lkpi_msec2hz_max; + +/* greatest common divisor, Euclid equation */ +static uint64_t +lkpi_gcd_64(uint64_t a, uint64_t b) +{ + uint64_t an; + uint64_t bn; + + while (b != 0) { + an = b; + bn = a % b; + a = an; + b = bn; + } + return (a); +} + +static void +lkpi_timer_callback_wrapper(void *context) +{ + struct timer_list *timer; + + linux_set_current(curthread); + + timer = context; + timer->function(timer->data); +} + +int +lkpi_mod_timer(struct timer_list *timer, int expires) +{ + int ret; + + timer->expires = expires; + ret = callout_reset(&timer->callout, + linux_timer_jiffies_until(expires), + &lkpi_timer_callback_wrapper, timer); + + MPASS(ret == 0 || ret == 1); + + return (ret == 1); +} + +void +lkpi_add_timer(struct timer_list *timer) +{ + + callout_reset(&timer->callout, + linux_timer_jiffies_until(timer->expires), + &lkpi_timer_callback_wrapper, timer); +} + +void +lkpi_add_timer_on(struct timer_list *timer, int cpu) +{ + + callout_reset_on(&timer->callout, + linux_timer_jiffies_until(timer->expires), + &lkpi_timer_callback_wrapper, timer, cpu); +} + +int +lkpi_del_timer(struct timer_list *timer) +{ + + if (callout_stop(&(timer)->callout) == -1) + return (0); + return (1); +} + +int +lkpi_del_timer_sync(struct timer_list *timer) +{ + + if (callout_drain(&(timer)->callout) == -1) + return (0); + return (1); +} + +static void +lkpi_timer_init(void *arg) +{ + uint64_t gcd; + + /* + * Compute an internal HZ value which can divide 2**32 to + * avoid timer rounding problems when the tick value wraps + * around 2**32: + */ + lkpi_timer_hz_mask = 1; + while (lkpi_timer_hz_mask < (unsigned long)hz) + lkpi_timer_hz_mask *= 2; + lkpi_timer_hz_mask--; + + /* compute some internal constants */ + + lkpi_nsec2hz_rem = hz; + lkpi_usec2hz_rem = hz; + lkpi_msec2hz_rem = hz; + + gcd = lkpi_gcd_64(lkpi_nsec2hz_rem, lkpi_nsec2hz_div); + lkpi_nsec2hz_rem /= gcd; + lkpi_nsec2hz_div /= gcd; + lkpi_nsec2hz_max = -1ULL / lkpi_nsec2hz_rem; + + gcd = lkpi_gcd_64(lkpi_usec2hz_rem, lkpi_usec2hz_div); + lkpi_usec2hz_rem /= gcd; + lkpi_usec2hz_div /= gcd; + lkpi_usec2hz_max = -1ULL / lkpi_usec2hz_rem; + + gcd = lkpi_gcd_64(lkpi_msec2hz_rem, lkpi_msec2hz_div); + lkpi_msec2hz_rem /= gcd; + lkpi_msec2hz_div /= gcd; + lkpi_msec2hz_max = -1ULL / lkpi_msec2hz_rem; +} +SYSINIT(lkpi_timer, SI_SUB_DRIVERS, SI_ORDER_FIRST, lkpi_timer_init, NULL); Index: sys/modules/linuxkpi/Makefile =================================================================== --- sys/modules/linuxkpi/Makefile +++ sys/modules/linuxkpi/Makefile @@ -20,6 +20,7 @@ linux_shmemfs.c \ linux_slab.c \ linux_tasklet.c \ + linux_timer.c \ linux_usb.c \ linux_work.c \ linux_xarray.c