Hi Johannes,
On 07/27/2017 01:42 PM, Johannes Kliemann wrote:
Hi Sebastian,
yes, that is the function I call from Genode.
And thanks in advance for helping me out.
Good. I will try to explain how the Lx::Task approach is supposed to work in this case:
Your task calls 'i2c_dw_xfer' which sends a request, creates a Linux completion, and calls 'wait_for_completion_timeout'. This leads to a blocking of the task and a call to the task scheduler. Since there should be nothing to schedule at this point, the entrypoint will eventually return to its "wait for RPC" code. When the waited for IRQ occurs, the entrypoint receives a signal RPC and wakes up yet another task, the IRQ task (dde_linux/src/lx_kit/irq.cc:Lx_kit::Irq::Context::unblock). This task calls all registered interrupt handlers ('handle_irq' same file). One of those handlers should, behind your back, call 'complete' (I haven't found the relevant source code for your case, but it is there) for the completion your task is waiting for, which in turn should unblock your task. This way a synchronous execution is accomplished. That is the theory.
Details:
'wait_for_completion_timeout' (dde_linux/src/include/lx_emul/impl/completion.h) will call '__wait_completion' which must be implemented by your driver. Please refer to '__wait_completion' (dde_linux/src/lib/usb/lx_emul.cc) as a guidance. The important part is to call 'block_and_schedule' for the current task. Also notice, the 'complete' function in completion.h that calls 'unblock' for the task within a completion. This should somehow be called by your interrupt handler and lead to the re-scheduling of your task when the IRQ tasks blocks again after interrupt handling.
By the way, these Lx::Taks are also called routine or coroutine in literature and nothing more than a stack and a 'setjmp/longjmp' construct.
I hope this helps,
Sebastian