8

I'm implementing a custom serial bus driver for a certain ARM-based Linux board (a custom UART driver, actually). This driver shall enable communication with a certain MCU on the other end of the bus via a custom protocol. The driver will not (and actually must not) expose any of its functions to the userspace, nor it is possible to implement it in userspace at all (hence, the need for the custom driver instead of using the stock TTY subsystem).

The driver will implement the communication protocol and UART reads/writes, and it has to export a set of higher-level functions to its users to allow them to communicate with the MCU (e.g. read_register(), drive_gpios(), all this stuff). There will be only one user of this module.

The calling module will have to wait for the completion of the operations (the aforementioned read_register() and others). I'm currently considering using semaphores: the user module will call my driver's function, which will initiate the transfers and wait on a semaphore; the IRQ handler of my driver will send requests to the MCU and read the answers, and, when done, post to the semaphore, thus waking up the calling module. But I'm not really familiar with kernel programming, and I'm baffled by the multitude of possible alternative implementations (tasklets? wait queues?).

The question is: is my semaphore-based approach OK, or too naïve? What are the possible alternatives? Are there any pitfalls I may be missing?

Roman Dmitrienko
  • 3,375
  • 3
  • 37
  • 48
  • 3
    Semaphores should do the job from what I understand, to enderstand better linux internals please refer to nice book "linex kernel development 3rd edition" which is available as free pdf and is up to date (.39 kernel I believe). That book does not go really deep, but it explains basic principles and shows options. Have fun hacking. – Tomas Pruzina Apr 02 '12 at 11:21
  • A nice book, thank you! If anyone else is interested, I would also suggest obtaining Linux Drivers Development and Linux Kernel Module Development (both are available online for free) – Roman Dmitrienko Apr 02 '12 at 12:17

1 Answers1

6

Traditionally IRQ handling in Linux is done in two parts:

  1. So called "upper-half" is actual working in IRQ context (IRQ handler itself). This part must exit as fast as possible. So it basically checks interrupt source and then starts bottom-half.

  2. "Bottom-half". It may be implemented as work queue. It is where actual job is done. It runs in normal context, so it can use blocking functions, etc.

If you only want to wait for IRQ in your worker thread, better to use special object called completion. It is exactly created for this task.

werewindle
  • 3,009
  • 17
  • 27