diff --git a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc index 5184b70b7..088ab903d 100644 --- a/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc +++ b/repos/dde_linux/src/drivers/nic/fec/lx_emul.cc @@ -728,9 +728,16 @@ void reinit_completion(struct completion *work) } +/* + * For compatibility with 4.4.3 drivers, the argument of this callback function + * is the 'data' member of the 'timer_list' object, which normally points to + * the 'timer_list' object itself when initialized with 'timer_setup()', but + * here it was overridden in '__wait_completion()' to point to the 'Lx::Task' + * object instead. + */ static void _completion_timeout(struct timer_list *t) { - Lx::Task *task = (Lx::Task *)t->data; + Lx::Task *task = (Lx::Task *)t; task->unblock(); } diff --git a/repos/dde_linux/src/include/lx_emul/impl/timer.h b/repos/dde_linux/src/include/lx_emul/impl/timer.h index 0c9da0d68..63e11d779 100644 --- a/repos/dde_linux/src/include/lx_emul/impl/timer.h +++ b/repos/dde_linux/src/include/lx_emul/impl/timer.h @@ -30,6 +30,15 @@ void timer_setup(struct timer_list *timer, { timer->function = function; timer->flags = flags; + + /* + * For compatibility with 4.4.3 drivers, the 'data' member is passed as + * argument to the callback function. Since the 4.16.3 callback function + * interface has a 'timer_list' pointer as argument, the 'data' member + * points to the 'timer_list' object itself when set up with this + * function. + */ + timer->data = (unsigned long)timer; } diff --git a/repos/dde_linux/src/include/lx_emul/timer.h b/repos/dde_linux/src/include/lx_emul/timer.h index 207072db4..ea9183df9 100644 --- a/repos/dde_linux/src/include/lx_emul/timer.h +++ b/repos/dde_linux/src/include/lx_emul/timer.h @@ -29,7 +29,14 @@ struct timer_list void (*function)(struct timer_list*); unsigned int flags; - unsigned long data; /* keep for compat with 4.4.3 drivers */ + /* + * For compatibility with 4.4.3 drivers, the 'data' member is kept and + * passed as argument to the callback function. Since the 4.16.3 callback + * function interface has a 'timer_list' pointer as argument, the 'data' + * member points to the 'timer_list' object itself when set up with the + * 'timer_setup()' function. + */ + unsigned long data; }; int mod_timer(struct timer_list *timer, unsigned long expires); diff --git a/repos/dde_linux/src/lib/usb/lx_emul.cc b/repos/dde_linux/src/lib/usb/lx_emul.cc index 82090c1e3..d4b22fc0e 100644 --- a/repos/dde_linux/src/lib/usb/lx_emul.cc +++ b/repos/dde_linux/src/lib/usb/lx_emul.cc @@ -987,9 +987,9 @@ signed long schedule_timeout_uninterruptible(signed long timeout) #include -static void _completion_timeout(struct timer_list *t) +static void _completion_timeout(unsigned long t) { - Lx::Task *task = (Lx::Task *)t->data; + Lx::Task *task = (Lx::Task *)t; task->unblock(); } @@ -1000,8 +1000,8 @@ long __wait_completion(struct completion *work, unsigned long timeout) unsigned long j = timeout ? jiffies + timeout : 0; if (timeout) { - timer_setup(&t, _completion_timeout, 0u); - t.data = (unsigned long)Lx::scheduler().current(); + setup_timer(&t, _completion_timeout, + (unsigned long)Lx::scheduler().current()); mod_timer(&t, j); } @@ -1132,9 +1132,16 @@ struct callback_timer { unsigned long data; }; +/* + * For compatibility with 4.4.3 drivers, the argument of this callback function + * is the 'data' member of the 'timer_list' object, which normally points to + * the 'timer_list' object itself when initialized with 'timer_setup()', but + * here it was overridden in 'setup_timer()' to point to the 'callback_timer' + * object instead. + */ static void timer_callback(struct timer_list *t) { - struct callback_timer * tc = (struct callback_timer *)t->data; + struct callback_timer * tc = (struct callback_timer *)t; tc->function(tc->data); } diff --git a/repos/dde_linux/src/lx_kit/timer.cc b/repos/dde_linux/src/lx_kit/timer.cc index 70be31fe2..86f9da93a 100644 --- a/repos/dde_linux/src/lx_kit/timer.cc +++ b/repos/dde_linux/src/lx_kit/timer.cc @@ -60,8 +60,14 @@ class Lx_kit::Timer : public Lx::Timer case LIST: { timer_list *t = static_cast(timer); - if (t->function) - t->function(t); + if (t->function) { + /* + * Pass 't->data' instead of 't' for compatibility + * with 4.4.3 drivers. When set up with + * 'timer_setup()', 't->data' matches 't'. + */ + t->function((struct timer_list*)t->data); + } } break;