Hi Sebastian,
thanks for your explanation, it helped me to understand the problem. I'm just not yet sure how exactly to call the task.
For the interrupt I have registered it via the Lx::Irq class. But I'm not sure how to handle the transfer task. Currently I locally create a Lx::Task that calls the xfer_master function (through a wrapper though) and call Lx::scheduler::schedule() after its creation. But that seems to return while the tasks are not yet completed.
Regards, Johannes
Am 27.07.2017 um 16:20 schrieb Sebastian Sumpf:
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