dde_linux: fix timer callback compatibility with older drivers

Fixes #3137
This commit is contained in:
Christian Prochaska 2019-01-31 17:55:54 +01:00 committed by Norman Feske
parent 845253af3a
commit e9e048c4ea
5 changed files with 45 additions and 9 deletions

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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);

View File

@ -987,9 +987,9 @@ signed long schedule_timeout_uninterruptible(signed long timeout)
#include <lx_emul/impl/completion.h>
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);
}

View File

@ -60,8 +60,14 @@ class Lx_kit::Timer : public Lx::Timer
case LIST:
{
timer_list *t = static_cast<timer_list *>(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;