diff --git a/driver/linux/check_kernel_headers.sh b/driver/linux/check_kernel_headers.sh
index b0b9b851c0a1..7afec9fae138 100755
--- a/driver/linux/check_kernel_headers.sh
+++ b/driver/linux/check_kernel_headers.sh
@@ -330,6 +330,19 @@ else
   echo no
 fi
 
+# timer_setup() added in v4.14-rc3
+echo -n "  checking (in kernel headers) timer_setup() availability ... "
+if test -e ${LINUX_HDR}/include/linux/timer.h > /dev/null ; then
+  if grep timer_setup ${LINUX_HDR}/include/linux/timer.h > /dev/null ; then
+    echo "#define HAVE_TIMER_SETUP 1" >> ${TMP_CHECKS_NAME}
+    echo yes
+  else
+    echo no
+  fi
+else
+  echo no
+fi
+
 # add the footer
 echo "" >> ${TMP_CHECKS_NAME}
 echo "#endif /* __knem_checks_h__ */" >> ${TMP_CHECKS_NAME}
diff --git a/driver/linux/knem_main.c b/driver/linux/knem_main.c
index e12aad3c0ea5..ddae2af14449 100644
--- a/driver/linux/knem_main.c
+++ b/driver/linux/knem_main.c
@@ -2610,9 +2610,17 @@ knem_kthread_func(void *data)
 
 #ifdef KNEM_HAVE_DMA_ENGINE
 static void
+#ifdef HAVE_TIMER_SETUP
+knem_dmacpy_cleanup_timer_handler(struct timer_list *t)
+#else
 knem_dmacpy_cleanup_timer_handler(unsigned long data)
+#endif
 {
+#ifdef HAVE_TIMER_SETUP
+	struct knem_context * ctx = from_timer(ctx, t, dmacpy_cleanup_timer);
+#else
 	struct knem_context * ctx = (void *) data;
+#endif
 
 	wake_up(&ctx->kthread_work_wq);
 	knem_counter_inc(DMACPY_CLEANUP_TIMEOUT);
@@ -2665,7 +2673,11 @@ knem_miscdev_open(struct inode * inode, struct file * file)
 	if (ctx->dmacpy_chan) {
 		INIT_LIST_HEAD(&ctx->dmacpy_cleanup_work_list);
 		spin_lock_init(&ctx->dmacpy_cleanup_work_lock);
+#ifdef HAVE_TIMER_SETUP
+		timer_setup(&ctx->dmacpy_cleanup_timer, knem_dmacpy_cleanup_timer_handler, 0);
+#else
 		setup_timer(&ctx->dmacpy_cleanup_timer, knem_dmacpy_cleanup_timer_handler, (unsigned long) ctx);
+#endif
 #if (defined CONFIG_NUMA) && (defined KNEM_HAVE_CPUMASK_OF_NODE)
 		{
 			int node = dev_to_node(ctx->dmacpy_chan->device->dev);
