return -ENOMEM;
}
+// The timer API introduced in Linux 4.14.0 includes a from_timer() macro built
+// atop the container_of() macro. As the kernel moves away from using
+// timer_list.data, it quasi-assumes that the timer_list struct will be
+// contained in some larger struct that also contains the data, hence this
+// softlockup_wrapper struct since it allows us to avoid any serious code
+// changes to the driver.
+struct softlockup_wrapper {
+ struct timer_list timer;
+ unsigned long timer_fired;
+};
+
#if !defined(WINDOWS) && !defined(CONFIG_PREEMPT)
static int softlockup_threshold = 60;
-static void avert_softlockup(unsigned long data)
+static void avert_softlockup(struct timer_list *timer)
{
- *(unsigned long*)data = 1;
+ struct softlockup_wrapper *container= from_timer(container, timer, timer);
+ container->timer_fired = 1;
}
/*
* timers are run at softirq context)
*
*/
-static inline void add_softlockup_timer(struct timer_list *timer, unsigned long *data)
+static inline void add_softlockup_timer(struct timer_list *timer)
{
- setup_timer(timer, avert_softlockup, (unsigned long) data);
timer->expires = jiffies + usecs_to_jiffies(softlockup_threshold * 1000000 / 3);
- add_timer(timer);
+ timer_setup(timer, avert_softlockup, 0);
}
static inline void del_softlockup_timer(struct timer_list *timer)
uint64_t src_start_offset, dst_start_offset;
int ret = 0;
#if !defined(WINDOWS) && !defined(CONFIG_PREEMPT)
- unsigned long timer_fired = 0;
- struct timer_list timer;
+ struct softlockup_wrapper tm_wrap;
int cpu = smp_processor_id();
- add_softlockup_timer(&timer, &timer_fired);
+ tm_wrap.timer_fired = 0;
+ add_softlockup_timer(&tm_wrap.timer);
#endif
remaining_len = work->len;
/* Ideally we should call schedule only if we didn't sleep
* in between. But there is no way to know that.
*/
- if (timer_fired) {
- timer_fired = 0;
+ if (tm_wrap.timer_fired) {
+ tm_wrap.timer_fired = 0;
if (smp_processor_id() == cpu)
touch_softlockup_watchdog();
else
cpu = smp_processor_id();
- add_softlockup_timer(&timer, &timer_fired);
+ add_softlockup_timer(&tm_wrap.timer);
}
#endif
src_cache_off = src_offset & ~PAGE_MASK;
}
error:
#if !defined(WINDOWS) && !defined(CONFIG_PREEMPT)
- del_softlockup_timer(&timer);
+ del_softlockup_timer(&tm_wrap.timer);
#endif
return ret;
}