Reputation: 377
I'm trying to write a linux kernel module which waits for a hardware trigger and then moves some data to an external memory via DMA.
I've got the hardware trigger recognized in my kernel module, now I need to make it perform the DMA. The problem is that the function that performs the DMA involves a point where it sleeps until the DMA is completed. This isn't allowed in interrupts, so I can't call the function directly in my interrupt service routine.
Is there a way I can set some kind of signal so that my kernel module knows to call the DMA function the next chance it gets, but doesn't do so in the interrupt context?
Upvotes: 0
Views: 619
Reputation: 802
You can call from your top half interrupt handler a bottom half rutine which can sleep like Work Queues:
Because workqueue allows users to create a kernel thread and bind work to the kernel thread. So, this will run in the process context and the work queue can sleep. Code deferred to a work queue has all the usual benefits of process context. Most importantly, work queues are schedulable and can therefore sleep.
Another way, you can use threaded interrupts which are scheduled the same way as userspace processes and thus can sleep too:
Upvotes: 0
Reputation: 1875
Would suggest you to use bottom halves by registering a callback. Linux works this way, top half/bottom half.
top half services the interrupt and clear interrupt control register, and queuing the registered callback that is your bottom half, it can sleep.
Would suggest you have a read about it in a book by robert love. it is very good place to start.
https://doc.lagout.org/operating%20system%20/linux/Linux%20Kernel%20Development%2C%203rd%20Edition.pdf
Check any i2c client driver on linuxkernel org source for reference.
https://elixir.bootlin.com/linux/latest/source/drivers/misc/fsa9480.c#L394
register your callback for DMA post data processing there.
this is just gist on how bottom halves can help you with developing drivers. hope it can be of any help to you.
Upvotes: 1