Hacker News new | past | comments | ask | show | jobs | submit login
Writing a Linux Kernel Module — Part 3: Buttons and LEDs (derekmolloy.ie)
116 points by OrangeTux on Aug 25, 2015 | hide | past | web | favorite | 12 comments

Nice article; however, in 'real life' I always try to do without having to use all of these APIs if I can get away with it. The overhead is quite massive, even with something as simple as the GPIO library.

Also, I'd rather use a tasklet than a kthread to offload 'work' from interrupt contexts.

> The overhead is quite massive, even with something as simple as the GPIO library.

Amen. On another platform, I ended up mmapping and writing registers from userspace (which is obviously only useful when no interrupt handlers must be attached and the register word in question does not have any other functions that would require synchronized access). Implementing the proper kernel GPIO api (and device tree etc.) would have taken more than a week (this was a rather obscure PowerPC platform).

I strongly disagree with that. Especially with the GPIO library which is as thin as it gets (you can even redefine gpio_get_value, gpio_set_value etc... in the BSP if you want an extra-fast board-specific version). In my experience the overhead is really small actually and it gives you some nice debugging tools (the sysfs interface and debugfs entry in particular).

If you implement a GPIO controller driver using the gpiolib means that all other drivers and userland tools will be able to interface with you at no cost. If you write a device driver that uses a GPIO using the gpiolib means that you'll be able to use your driver even if the GPIO gets wired on an external I2C "expander" or something like that.

Pushing your logic to the extreme one might as well get rid of the kernel and write on bare metal to make sure not to waste any CPU cycle or memory byte on a abstraction layer. What is a kernel in the end if not a set of standardized APIs?

It's true that there's some bloat in a few of the kernel's APIs (the video comes to mind, although I won't pretend I would be able to do it better) but that shouldn't be a reason to "always try to do without having to use all of these APIs". Unless you only write code that's only intended to be used on a particular software configuration on a single board without any possible evolution or reuse it's really asking for trouble in the long term.

If I have to integrate a third party driver and I see that they use some custom made GPIO interface instead of the standard kernel API I'm going to be very annoyed.

I don't disagree with the fact gpiolib is a good idea etc, however more often than not, if I'm hired to make a firmware for a particular device, the work required to tailor a driver for best efficiency is worth it, and will be minimal compared to the rest. You can always #ifdef the changes too...

If you use GPIOs for a couple LED, pin configuration and stuff like that it's perfectly adequate, and won't require a driver anyway. If your GPIO expander is on i2c then you clearly are not worrying about latency anyway, so gpiolib is just fine.

If you make a driver to use the gpios for more critical time sensitive things (overcurrent/thermal protections and that sort of things, or bitbanging), and then realize that actually, it's pretty crap and you'd be better off mmaping /dev/mem and poke at the registers directly from userland to get the performance/latency that is needed, your driver was a waste of time if you went that way first...

Can you point out exactly why it's pretty crap?

Again, gpiolib lets you redefine gpio_get_value, gpio_set_value, gpio_cansleep and gpio_to_irq in the BSP to be specialized inline macros if you want to, it means that for a specific board you can just straight to the hardware if you want to avoid any kind of indirection. I don't see what you could possibly do to make it even faster, gpiolib or not.

But even if you don't do that the only cost will mostly be an indirect function pointer call to the GPIO controller's driver, we're talking nanoseconds here (assuming it's in cache). Might be worth it for bitbanging applications.

At any rate, while I totally believe there are situations where the gpiolib doesn't quite cut it I don't think it's good advice to tell kernel beginners (the audience of TFA) to avoid it on principle alone. In my experience 99% of the time I use GPIOs to de-reset a chip, read a switch/button or, when I feel fancy, light up a LED.

for overcurrent and thermal protection, shouldn't you make an hwmon interface get lmsensors to look at it? Also how time sensitive are you looking at for those things?

Many people will ask "why not do this in user space?" The article answers this:

Unlike Linux user space, the Linux kernel space has support for interrupts. The first example in this article demonstrates how you can write an LKM that uses GPIOs and interrupts to achieve a faster response time than is possible in user space.

But what if you've a complex app which interacts with GPIOs? You don't want to write the whole app a LMK and run in in kernel space, do you?

I've written a JSON-RPC API which can be used to interact with GPIOs. Currently I set/get a GPIO using sysfs. During handling of a request the operations on sysfs take most of the response time, far more time than parsing the request and writing the result to the client. How could I speed up the GPIO interaction with a LKM?

As much as it's fun to create kernel modules and experiment with kernel space, I'll have to agree with this. If you can keep things simple and use existing facilities, that should generally be the goal.

You'd want to separate that complexity from your kernel modules by using some intermediate, e.g. mqueues, named pipes or shared memory.

None of this needs an actual kernel driver. You can use interrupt gpios from userspace using poll.

You can, or you can use the gpio_keys driver to nicely handle it in kernel space and give you key presses via the event subsystem. One small device tree snippet, and you're sorted. There is even a gpio_keys_polled variant if you can't get interrupts from your GPIO controller.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact