DAHDI in kernel 4.15: Switch to new timer_setup interface.

Upstream kernel 4.14, in commit (686fef928bba6b "timer: Prepare to change timer
callback argument type") [1], introduced the timer_setup interface to replace
the init_timer/setup_timer interfaces. The primary change is that the timer
callback functions now follow the standard kernel pattern where the structure
the callback sits in is passed to the callback instead of storing a pointer to
an unassociated data type.

The setup_timer functions were removed in upstream kernel v4.15, and therefore
this change is needed in order to compile DAHDI for kernels >= 4.15.

This change follows the same strategy that was done in the kernel to while the
existing users of setup_timer were migrated to the new interface.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=686fef928bba6b
This commit is contained in:
Shaun Ruffell 2018-08-10 00:13:52 -05:00
parent 20328895a2
commit 6667f1c8d8
13 changed files with 77 additions and 71 deletions

View File

@ -10069,7 +10069,7 @@ static inline unsigned long msecs_processed(const struct core_timer *const ct)
return atomic_read(&ct->count) * DAHDI_MSECS_PER_CHUNK; return atomic_read(&ct->count) * DAHDI_MSECS_PER_CHUNK;
} }
static void coretimer_func(unsigned long param) static void coretimer_func(TIMER_DATA_TYPE unused)
{ {
unsigned long flags; unsigned long flags;
unsigned long ms_since_start; unsigned long ms_since_start;
@ -10150,16 +10150,14 @@ static void coretimer_func(unsigned long param)
static void coretimer_init(void) static void coretimer_init(void)
{ {
init_timer(&core_timer.timer); timer_setup(&core_timer.timer, coretimer_func, 0);
core_timer.timer.function = coretimer_func;
ktime_get_ts(&core_timer.start_interval); ktime_get_ts(&core_timer.start_interval);
atomic_set(&core_timer.count, 0); atomic_set(&core_timer.count, 0);
atomic_set(&core_timer.shutdown, 0); atomic_set(&core_timer.shutdown, 0);
core_timer.interval = max(msecs_to_jiffies(DAHDI_MSECS_PER_CHUNK), 1UL); core_timer.interval = max(msecs_to_jiffies(DAHDI_MSECS_PER_CHUNK), 1UL);
if (core_timer.interval < (HZ/250)) if (core_timer.interval < (HZ/250))
core_timer.interval = (HZ/250); core_timer.interval = (HZ/250);
core_timer.timer.expires = jiffies + core_timer.interval; mod_timer(&core_timer.timer, jiffies + core_timer.interval);
add_timer(&core_timer.timer);
} }
static void coretimer_cleanup(void) static void coretimer_cleanup(void)
@ -10455,7 +10453,7 @@ static const struct file_operations dahdi_chan_fops = {
#ifdef CONFIG_DAHDI_WATCHDOG #ifdef CONFIG_DAHDI_WATCHDOG
static struct timer_list watchdogtimer; static struct timer_list watchdogtimer;
static void watchdog_check(unsigned long ignored) static void watchdog_check(TIMER_DATA_TYPE ignored)
{ {
unsigned long flags; unsigned long flags;
static int wdcheck=0; static int wdcheck=0;
@ -10496,10 +10494,7 @@ static void watchdog_check(unsigned long ignored)
static int __init watchdog_init(void) static int __init watchdog_init(void)
{ {
init_timer(&watchdogtimer); timer_setup(&watchdogtimer, watchdog_check, 0);
watchdogtimer.expires = 0;
watchdogtimer.data =0;
watchdogtimer.function = watchdog_check;
/* Run every couple of jiffy or so */ /* Run every couple of jiffy or so */
mod_timer(&watchdogtimer, jiffies + 2); mod_timer(&watchdogtimer, jiffies + 2);
return 0; return 0;

View File

@ -157,7 +157,7 @@ static unsigned long timespec_diff_ms(struct timespec *t0, struct timespec *t1)
return ms; return ms;
} }
static void dahdi_dummy_timer(unsigned long param) static void dahdi_dummy_timer(struct timer_timer *unused)
{ {
unsigned long ms_since_start; unsigned long ms_since_start;
struct timespec now; struct timespec now;
@ -258,12 +258,10 @@ int init_module(void)
hrtimer_start(&zaptimer, ktime_set(0, DAHDI_TIME_NS), HRTIMER_MODE_REL); hrtimer_start(&zaptimer, ktime_set(0, DAHDI_TIME_NS), HRTIMER_MODE_REL);
printk(KERN_INFO "dahdi_dummy: High Resolution Timer started, good to go\n"); printk(KERN_INFO "dahdi_dummy: High Resolution Timer started, good to go\n");
#else #else
init_timer(&timer); timer_setup(&timer, dahdi_dummy_timer);
timer.function = dahdi_dummy_timer;
ztd->start_interval = current_kernel_time(); ztd->start_interval = current_kernel_time();
timer.expires = jiffies + JIFFIES_INTERVAL;
atomic_set(&shutdown, 0); atomic_set(&shutdown, 0);
add_timer(&timer); mod_timer(&timer, jiffies + JIFFIES_INTERVAL);
#endif #endif
if (debug) if (debug)

View File

@ -831,7 +831,7 @@ EXPORT_SYMBOL(dahdi_dynamic_unregister_driver);
static struct timer_list alarmcheck; static struct timer_list alarmcheck;
static void check_for_red_alarm(unsigned long ignored) static void check_for_red_alarm(TIMER_DATA_TYPE unused)
{ {
int newalarm; int newalarm;
int alarmchanged = 0; int alarmchanged = 0;
@ -867,10 +867,7 @@ static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
static int dahdi_dynamic_init(void) static int dahdi_dynamic_init(void)
{ {
/* Start process to check for RED ALARM */ /* Start process to check for RED ALARM */
init_timer(&alarmcheck); timer_setup(&alarmcheck, check_for_red_alarm, 0);
alarmcheck.expires = 0;
alarmcheck.data = 0;
alarmcheck.function = check_for_red_alarm;
/* Check once per second */ /* Check once per second */
mod_timer(&alarmcheck, jiffies + 1 * HZ); mod_timer(&alarmcheck, jiffies + 1 * HZ);
#ifdef ENABLE_TASKLETS #ifdef ENABLE_TASKLETS

View File

@ -681,16 +681,13 @@ static int ethmf_delay_dec(void)
* Timer callback function to allow all spans to be added, prior to any of * Timer callback function to allow all spans to be added, prior to any of
* them being used. * them being used.
*/ */
static void timer_callback(unsigned long param) static void timer_callback(TIMER_DATA_TYPE unused)
{ {
if (ethmf_delay_dec()) { if (ethmf_delay_dec()) {
if (!atomic_read(&timer_deleted)) { if (!atomic_read(&timer_deleted))
timer.expires = jiffies + HZ; mod_timer(&timer, jiffies + HZ);
add_timer(&timer);
}
} else { } else {
printk(KERN_INFO "All TDMoE multiframe span groups are active.\n"); printk(KERN_INFO "All TDMoE multiframe span groups are active.\n");
del_timer(&timer);
} }
} }
@ -764,11 +761,8 @@ static const struct file_operations ztdethmf_proc_fops = {
static int __init ztdethmf_init(void) static int __init ztdethmf_init(void)
{ {
init_timer(&timer); timer_setup(&timer, timer_callback, 0);
timer.expires = jiffies + HZ; mod_timer(&timer, jiffies + HZ);
timer.function = &timer_callback;
if (!timer_pending(&timer))
add_timer(&timer);
dev_add_pack(&ztdethmf_ptype); dev_add_pack(&ztdethmf_ptype);
register_netdevice_notifier(&ztdethmf_nblock); register_netdevice_notifier(&ztdethmf_nblock);

View File

@ -148,7 +148,7 @@ static void sppp_lcp_open (struct sppp *sp);
static void sppp_ipcp_open (struct sppp *sp); static void sppp_ipcp_open (struct sppp *sp);
static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h, static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,
int len, u32 *magic); int len, u32 *magic);
static void sppp_cp_timeout (unsigned long arg); static void sppp_cp_timeout (TIMER_DATA_TYPE timer);
static char *sppp_lcp_type_name (u8 type); static char *sppp_lcp_type_name (u8 type);
static char *sppp_ipcp_type_name (u8 type); static char *sppp_ipcp_type_name (u8 type);
static void sppp_print_bytes (u8 *p, u16 len); static void sppp_print_bytes (u8 *p, u16 len);
@ -189,12 +189,9 @@ static void sppp_set_timeout(struct sppp *p,int s)
{ {
if (! (p->pp_flags & PP_TIMO)) if (! (p->pp_flags & PP_TIMO))
{ {
init_timer(&p->pp_timer);
p->pp_timer.function=sppp_cp_timeout;
p->pp_timer.expires=jiffies+s*HZ;
p->pp_timer.data=(unsigned long)p;
p->pp_flags |= PP_TIMO; p->pp_flags |= PP_TIMO;
add_timer(&p->pp_timer); timer_setup(&p->pp_timer, sppp_cp_timeout, 0);
mod_timer(&p->pp_timer, jiffies + s*HZ);
} }
} }

View File

@ -1000,6 +1000,7 @@ __vb_rx_demand_poll(struct voicebus *vb)
__vb_setctl(vb, 0x0010, 0x00000000); __vb_setctl(vb, 0x0010, 0x00000000);
} }
#ifndef CONFIG_VOICEBUS_TIMER
static void static void
__vb_enable_interrupts(struct voicebus *vb) __vb_enable_interrupts(struct voicebus *vb)
{ {
@ -1008,6 +1009,7 @@ __vb_enable_interrupts(struct voicebus *vb)
else else
__vb_setctl(vb, IER_CSR7, DEFAULT_NORMAL_INTERRUPTS); __vb_setctl(vb, IER_CSR7, DEFAULT_NORMAL_INTERRUPTS);
} }
#endif
static void static void
__vb_disable_interrupts(struct voicebus *vb) __vb_disable_interrupts(struct voicebus *vb)
@ -1033,8 +1035,7 @@ static void start_packet_processing(struct voicebus *vb)
clear_bit(VOICEBUS_STOP, &vb->flags); clear_bit(VOICEBUS_STOP, &vb->flags);
clear_bit(VOICEBUS_STOPPED, &vb->flags); clear_bit(VOICEBUS_STOPPED, &vb->flags);
#if defined(CONFIG_VOICEBUS_TIMER) #if defined(CONFIG_VOICEBUS_TIMER)
vb->timer.expires = jiffies + HZ/1000; mod_timer(&vb->timer, jiffies + HZ/1000);
add_timer(&vb->timer);
#else #else
/* Clear the interrupt status register. */ /* Clear the interrupt status register. */
__vb_setctl(vb, SR_CSR5, 0xffffffff); __vb_setctl(vb, SR_CSR5, 0xffffffff);
@ -1746,18 +1747,17 @@ vb_isr(int irq, void *dev_id)
* the timer. * the timer.
*/ */
static void static void
vb_timer(unsigned long data) vb_timer(TIMER_DATA_TYPE timer)
{ {
unsigned long start = jiffies; unsigned long start = jiffies;
struct voicebus *vb = (struct voicebus *)data; struct voicebus *vb = from_timer(vb, timer, timer);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
vb_isr(0, vb, 0); vb_isr(0, vb, 0);
#else #else
vb_isr(0, vb); vb_isr(0, vb);
#endif #endif
if (!test_bit(VOICEBUS_STOPPED, &vb->flags)) { if (!test_bit(VOICEBUS_STOPPED, &vb->flags)) {
vb->timer.expires = start + HZ/1000; mod_timer(&vb->timer, start + HZ/1000);
add_timer(&vb->timer);
} }
} }
#endif #endif
@ -1800,9 +1800,7 @@ __voicebus_init(struct voicebus *vb, const char *board_name,
INIT_LIST_HEAD(&vb->free_rx); INIT_LIST_HEAD(&vb->free_rx);
#if defined(CONFIG_VOICEBUS_TIMER) #if defined(CONFIG_VOICEBUS_TIMER)
init_timer(&vb->timer); timer_setup(&vb->timer, vb_timer, 0);
vb->timer.function = vb_timer;
vb->timer.data = (unsigned long)vb;
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)

View File

@ -3701,9 +3701,9 @@ wctc4xxp_send_commands(struct wcdte *wc, struct list_head *to_send)
} }
static void static void
wctc4xxp_watchdog(unsigned long data) wctc4xxp_watchdog(TIMER_DATA_TYPE timer)
{ {
struct wcdte *wc = (struct wcdte *)data; struct wcdte *wc = from_timer(wc, timer, watchdog);
struct tcb *cmd, *temp; struct tcb *cmd, *temp;
LIST_HEAD(cmds_to_retry); LIST_HEAD(cmds_to_retry);
const int MAX_RETRIES = 5; const int MAX_RETRIES = 5;
@ -4090,13 +4090,7 @@ wctc4xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error_exit_swinit; goto error_exit_swinit;
} }
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) timer_setup(&wc->watchdog, wctc4xxp_watchdog, 0);
wc->watchdog.function = wctc4xxp_watchdog;
wc->watchdog.data = (unsigned long)wc;
init_timer(&wc->watchdog);
# else
setup_timer(&wc->watchdog, wctc4xxp_watchdog, (unsigned long)wc);
# endif
/* ------------------------------------------------------------------ /* ------------------------------------------------------------------
* Load the firmware and start the DTE. * Load the firmware and start the DTE.

View File

@ -2766,10 +2766,10 @@ static void vpm_check_func(struct work_struct *work)
return; return;
} }
static void te12xp_timer(unsigned long data) static void te12xp_timer(TIMER_DATA_TYPE timer)
{ {
unsigned long flags; unsigned long flags;
struct t1 *wc = (struct t1 *)data; struct t1 *wc = from_timer(wc, timer, timer);
if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags))) if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags)))
return; return;
@ -2944,7 +2944,7 @@ static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_devi
spin_lock_init(&wc->reglock); spin_lock_init(&wc->reglock);
INIT_LIST_HEAD(&wc->active_cmds); INIT_LIST_HEAD(&wc->active_cmds);
INIT_LIST_HEAD(&wc->pending_cmds); INIT_LIST_HEAD(&wc->pending_cmds);
setup_timer(&wc->timer, te12xp_timer, (unsigned long)wc); timer_setup(&wc->timer, te12xp_timer, 0);
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&wc->timer_work, timer_work_func, wc); INIT_WORK(&wc->timer_work, timer_work_func, wc);

View File

@ -2382,9 +2382,9 @@ static void te13x_handle_interrupt(struct wcxb *xb, u32 pending)
} }
} }
static void te13xp_timer(unsigned long data) static void te13xp_timer(TIMER_DATA_TYPE timer)
{ {
struct t13x *wc = (struct t13x *)data; struct t13x *wc = from_timer(wc, timer, timer);
if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags))) if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags)))
return; return;
@ -2583,7 +2583,7 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
wc->ledstate = -1; wc->ledstate = -1;
spin_lock_init(&wc->reglock); spin_lock_init(&wc->reglock);
mutex_init(&wc->lock); mutex_init(&wc->lock);
setup_timer(&wc->timer, te13xp_timer, (unsigned long)wc); timer_setup(&wc->timer, te13xp_timer, 0);
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&wc->timer_work, timer_work_func, wc); INIT_WORK(&wc->timer_work, timer_work_func, wc);

View File

@ -3204,9 +3204,9 @@ static void t43x_handle_interrupt(struct wcxb *xb, u32 pending)
wc->intr_span = 0; wc->intr_span = 0;
} }
static void t43x_timer(unsigned long data) static void t43x_timer(TIMER_DATA_TYPE timer)
{ {
struct t43x *wc = (struct t43x *)data; struct t43x *wc = from_timer(wc, timer, timer);
if (!is_initialized(wc)) if (!is_initialized(wc))
return; return;
@ -3432,7 +3432,7 @@ static int __devinit t43x_init_one(struct pci_dev *pdev,
goto fail_exit; goto fail_exit;
mutex_init(&wc->lock); mutex_init(&wc->lock);
setup_timer(&wc->timer, t43x_timer, (unsigned long)wc); timer_setup(&wc->timer, t43x_timer, 0);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&wc->timer_work, timer_work_func, wc); INIT_WORK(&wc->timer_work, timer_work_func, wc);

View File

@ -1612,7 +1612,6 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
transport_init(xbus, ops, max_send_size, transport_device, priv); transport_init(xbus, ops, max_send_size, transport_device, priv);
spin_lock_init(&xbus->lock); spin_lock_init(&xbus->lock);
init_waitqueue_head(&xbus->command_queue_empty); init_waitqueue_head(&xbus->command_queue_empty);
init_timer(&xbus->command_timer);
atomic_set(&xbus->pcm_rx_counter, 0); atomic_set(&xbus->pcm_rx_counter, 0);
xbus->min_tx_sync = INT_MAX; xbus->min_tx_sync = INT_MAX;
xbus->min_rx_sync = INT_MAX; xbus->min_rx_sync = INT_MAX;

View File

@ -353,9 +353,9 @@ static void xpp_set_syncer(xbus_t *xbus, bool on)
(syncer) ? syncer->busname : "NO-SYNC"); (syncer) ? syncer->busname : "NO-SYNC");
} }
static void xbus_command_timer(unsigned long param) static void xbus_command_timer(TIMER_DATA_TYPE timer)
{ {
xbus_t *xbus = (xbus_t *)param; xbus_t *xbus = from_timer(xbus, timer, command_timer);
struct timeval now; struct timeval now;
BUG_ON(!xbus); BUG_ON(!xbus);
@ -371,10 +371,9 @@ void xbus_set_command_timer(xbus_t *xbus, bool on)
if (on) { if (on) {
if (!timer_pending(&xbus->command_timer)) { if (!timer_pending(&xbus->command_timer)) {
XBUS_DBG(SYNC, xbus, "add_timer\n"); XBUS_DBG(SYNC, xbus, "add_timer\n");
xbus->command_timer.function = xbus_command_timer; timer_setup(&xbus->command_timer,
xbus->command_timer.data = (unsigned long)xbus; xbus_command_timer, 0);
xbus->command_timer.expires = jiffies + 1; mod_timer(&xbus->command_timer, jiffies + 1);
add_timer(&xbus->command_timer);
} }
} else if (timer_pending(&xbus->command_timer)) { } else if (timer_pending(&xbus->command_timer)) {
XBUS_DBG(SYNC, xbus, "del_timer\n"); XBUS_DBG(SYNC, xbus, "del_timer\n");

View File

@ -1404,6 +1404,33 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
/*! Maximum audio mask */ /*! Maximum audio mask */
#define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1) #define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
#ifndef TIMER_DATA_TYPE
#define TIMER_DATA_TYPE unsigned long
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
/**
* timer_setup - Added in 4.13.0. We can make a direct translation to the
* setup_timer interface since DAHDI does not pass any flags to any of the
* timer_setup functions.
*
*/
static inline void
timer_setup(struct timer_list *timer,
void (*timer_callback)(TIMER_DATA_TYPE data),
unsigned long flags)
{
WARN_ON(flags != 0);
setup_timer(timer, timer_callback, (TIMER_DATA_TYPE)timer);
}
#define from_timer(var, callback_timer, timer_fieldname) \
container_of((struct timer_list *)(callback_timer), \
typeof(*var), timer_fieldname)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
#define refcount_read atomic_read #define refcount_read atomic_read
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
@ -1536,6 +1563,14 @@ static inline int strcasecmp(const char *s1, const char *s2)
#endif /* 3.10.0 */ #endif /* 3.10.0 */
#endif /* 3.16.0 */ #endif /* 3.16.0 */
#endif /* 4.11.0 */ #endif /* 4.11.0 */
#endif /* 4.13.0 */
#else /* >= 4.15.0 */
#ifndef TIMER_DATA_TYPE
#define TIMER_DATA_TYPE struct timer_list *
#endif
#endif /* 4.15.0 */
#ifndef DEFINE_SPINLOCK #ifndef DEFINE_SPINLOCK
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED #define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED