How to send Notification from Kernel to user space application using SYSFS - linux-kernel

I'm working in an USB ACM driver, "where i need to send notification from kernel space to user space application for invoking a call back function". I'm not much aware of using kernel to user interfaces in code. how well can sysfs help for this scenario. Please send some sample code to use sysfs so that I'll get an idea to implement in my code. I could not find it anywhere. Also pls tell anyother easy way to achieve kernel to user space notification. Thanks in advance.

My suggestion would be to create a sysfs interface to your kernel driver that userspace can access. Each sysfs attribute if created with the correct properties can be read like a file from userspace. You can then use the poll function from userspace to poll for an action on that file. To trigger this action from Kernel space, you can use the sysfs_notify function on your attribute and it will cause your userspace code to wake up. Here is how I would do it
Kernel
1. Create Kobject or attach an attribute to a previous kobject
2. When you want to signal userspace call sysfs_notify on the kobject and attribute
Userspace
Create a new thread that will block while waiting for the sysfs_notify
Open the sysfs attribute from this thread
poll the attribute, once sysfs_notify from the kernel is called it will unblock your poll
call your event handling function

Another alternative would be to use eventfd. You create eventfd, pass the integer file descriptor to kernel space (e.g. through sysfs, or ioctl), then convert the file descriptor you got from user space to eventfd_ctx in kernel space. This is it - you have your notification channel.
User space
#include <sys/eventfd.h>
int efd = eventfd(0, 0);
// pass 'efd' to kernel space
Kernel space
#include <linux/eventfd.h>
// Set up
int efd = /* get from user space - sysfs/ioctl/write/... */;
struct eventfd_ctx* efd_ctx = eventfd_ctx_fdget(efd);
// Signal user space
eventfd_signal(efd_ctx, 1);
// Tear down
eventfd_ctx_put(efd_ctx);

Related

How to Send a Value to Another Driver's Sysfs Attribute

This is all in Linux 4.14.73. I'd upgrade if I could but I cant.
I'm trying to trigger an LED flash in a standard LED class instance from another kernel space driver. I know all about the "bad form" of not accessing files from Kernel Space so I figure there must be some way already defined way for accessing Sysfs attributes from Kernel Space.
The LED is defined here:
/sys/class/leds/fpga_led0
Its trigger is set to [oneshot] so it has a device attribute called "shot" exposed. To get a single LED flash all I need to do from the command line is this:
echo 1 > /sys/class/leds/fpga_led0/shot
I can easily write a User Space program to open the "shot" attribute and write a "1" string to it. There are various published methods of forcing file operations into a kernel driver. Most of them are fairly limited. I've yet to see one that exposes file seek operations which are key to repeatedly writing to an attribute without wasting time opening and closing the file. To be clear, this is not setting values at boot time. In this case I have one driver that needs to send a value to another driver's Sysfs entry at a specific moment in its own operation. Is there a standard, accepted way of sending a value from one running kernel driver to the Sysfs attribute of another kernel driver?

How do I write to a __user memory from within the top half of an interrupt handler?

I am working on a proprietary device driver. The driver is implemented as a kernel module. This module is then coupled with an user-space process.
It is essential that each time the device generates an interrupt, the driver updates a set of counters directly in the address space of the user-space process from within the top half of the interrupt handler. The driver knows the PID and the task_struct of the user-process and is also aware of the virtual address where the counters lie in the user-process context. However, I am having trouble in figuring out how code running in the interrupt context could take up the mm context of the user-process and write to it. Let me sum up what I need to do:
Get the address of the physical page and offset corresponding to the virtual address of the counters in the context of the user-process.
Set up mappings in the page table and write to the physical page corresponding to the counter.
For this, I have tried the following:
Try to take up the mm context of the user-task, like below:
use_mm(tsk->mm);
/* write to counters. */
unuse_mm(tsk->mm);
This apparently causes the entire system to hang.
Wait for the interrupt to occur when our user-process was the
current process. Then use copy_to_user().
I'm not much of an expert on kernel programming. If there's a good way to do this, please do advise and thank you in advance.
Your driver should be the one, who maps kernel's memory for user space process. E.g., you may implement .mmap callback for struct file_operation for your device.
Kernel driver may write to kernel's address, which it have mapped, at any time (even in interrupt handler). The user-space process will immediately see all modifications on its side of the mapping (using address obtained with mmap() system call).
Unix's architecture frowns on interrupt routines accessing user space
because a process could (in theory) be swapped out when the interrupt occurs. 
If the process is running on another CPU, that could be a problem, too. 
I suggest that you write an ioctl to synchronize the counters,
and then have the the process call that ioctl
every time it needs to access the counters.
Outside of an interrupt context, your driver will need to check the user memory is accessible (using access_ok), and pin the user memory using get_user_pages or get_user_pages_fast (after determining the page offset of the start of the region to be pinned, and the number of pages spanned by the region to be pinned, including page alignment at both ends). It will also need to map the list of pages to kernel address space using vmap. The return address from vmap, plus the offset of the start of the region within its page, will give you an address that your interrupt handler can access.
At some point, you will want to terminate access to the user memory, which will involve ensuring that your interrupt routine no longer accesses it, a call to vunmap (passing the pointer returned by vmap), and a sequence of calls to put_page for each of the pages pinned by get_user_pages or get_user_pages_fast.
I don't think what you are trying to do is possible. Consider this situation:
(assuming how your device works)
Some function allocates the user-space memory for the counters and
supplies its address in PROCESS X.
A switch occurs and PROCESS Y executes.
Your device interrupts.
The address for your counters is inaccessible.
You need to schedule a kernel mode asynchronous event (lower half) that will execute when PROCESS X is executing.

Interrupt handling in Device Driver

I have written a simple character driver and requested IRQ on a gpio pin and wrtten a handler for it.
err = request_irq( irq, irq_handler,IRQF_SHARED | IRQF_TRIGGER_RISING, INTERRUPT_DEVICE_NAME, raspi_gpio_devp);
static irqreturn_t irq_handler(int irq, void *arg);
now from theory i know that Upon interrupt the interrupt Controller with tell the processor to call do_IRQ() which will check the IDT and call my interrupt handler for this line.
how does the kernel know that the interrupt handler was for this particular device file
Also I know that Interrupt handlers do not run in any process context. But let say I am accessing any variable declared out side scope of handler, a static global flag = 0, In the handler I make flag = 1 indicating that an interrupt has occurred. That variable is in process context. So I am confused how this handler not in any process context modify a variable in process context.
Thanks
The kernel does not know that this particular interrupt is for a particular device.
The only thing it knows is that it must call irq_handler with raspi_gpio_devp as a parameter. (like this: irq_handler(irq, raspi_gpio_devp)).
If your irq line is shared, you should check if your device generated an IRQ or not. Code:
int irq_handler(int irq, void* dev_id) {
struct raspi_gpio_dev *raspi_gpio_devp = (struct raspi_gpio_dev *) dev_id;
if (!my_gpio_irq_occured(raspi_gpio_devp))
return IRQ_NONE;
/* do stuff here */
return IRQ_HANDLED;
}
The interrupt handler runs in interrupt context. But you can access static variables declared outside the scope of the interrupt.
Usually, what an interrupt handler does is:
check interrupt status
retrieve information from the hardware and store it somewhere (a buffer/fifo for example)
wake_up() a kernel process waiting for that information
If you want to be really confident with the do and don't of interrupt handling, the best thing to read about is what a process is for the kernel.
An excellent book dealing with this is Linux Kernel Developpement by Robert Love.
The kernel doesn't know which device the interrupt pertains to. It is possible for a single interrupt to be shared among multiple devices. Previously this was quite common. It is becoming less so due to improved interrupt support in interrupt controllers and introduction of message-signaled interrupts. Your driver must determine whether the interrupt was from your device (i.e. whether your device needs "service").
You can provide context to your interrupt handler via the "void *arg" provided. This should never be process-specific context, because a process might exit leaving pointers dangling (i.e. referencing memory which has been freed and/or possibly reallocated for other purposes).
A global variable is not "in process context". It is in every context -- or no context if you prefer. When you hear "not in process context", that means a few things: (1) you cannot block/sleep (because what process would you be putting to sleep?), (2) you cannot make any references to user-space virtual addresses (because what would those references be pointing to?), (3) you cannot make references to "current task" (since there isn't one or it's unknown).
Typically, a driver's interrupt handler pushes or pulls data into "driver global" data areas from which/to which the process context end of the driver can transfer data.
This is to reply your question :-
how does the kernel know that the interrupt handler was for this particular >device file?
Each System-On-Chip documents will mention interrupt numbers for different devices connected to different interrupt lines.
The Same Interrupt number has to be mentioned in the Device Tree entry for instantiation of device driver.
The Device driver's usual probe function parses the Device tree data structure and reads the IRQ number and registers the handler using the register_irq function.
If there are multiple devices to a single IRQ number/line, then the IRQ status register(for different devices if mapped under the same VM space) can be used inside the IRQ handler to differentiate.
Please read more in my blog

what does `ioctl` do in `struct tty_driver`?

What does ioctl do in the structure struct tty_driver?
I know the ioctl() function provides the means to control the hardware (Keyboard, Mouse, Print) but for example a driver to control the leds on the keyboard I think that the ioctl is more than enough to do this task...
So why I need a tty_driver? I know tty_driver is a struct
P.D I've never tried to program a Device Driver. I've only read a bit of code in some books.
When developing a new driver, the struct tty_driver structure is used to register a tty_driver (using tty_register_driver() 1). This code creates a new device file and set the file operations to some tty specific functions.
The ioctl entry in the newly created file operations is set to tty_ioctl() 2 which after handling some of the basic commands will call the .ioctl function set in the struct tty_operations 3 referenced in the struct tty_driver.
By defining ioctl (note that it is checked if it is not NULL in 3) the developer can implement ioctl commands specific to its device or simply be notified of some other standard commands.

bypassing tty layer and copy to user

I would like to copy data to user space from kernel module which receives data from serial port and transfers it to DMA, which in turn forwards the data to tty layer and finally to user space.
the current flow is
serial driver FIFO--> DMA-->TTY layer -->User space (the data to tty layer is emptied from DMA upon expiration of timer)
What I want to achieve is
serial driver FIFO-->DMA-->user space. (I am OK with using timer to send the data to user space, if there is a better way let me know)
Also the kernel module handling the serialFIFO->DMA is not a character device.
I would like to bypass tty layer completely. what is the best way to achieve so?
Any pointers/code snippet would be appreciated.
In >=3.10.5 the "serial FIFO" that you refer to is called a uart_port. These are defined in drivers/tty/serial.
I assume that what you want to do is to copy the driver for your UART to a new file, then instead of using uart_insert_char to insert characters from the UART RX FIFO, you want to insert the characters into a buffer that you can access from user space.
The way to do this is to create a second driver, a misc class device driver that has file operations, including mmap, and that allocates kernel memory that the driver's mmap file operation function associates with the userspace mapped memory. There is a good example of code for this written by Maxime Ripard. This example was written for a FIQ handled device, but you can use just the probe routine's dma_zalloc_coherent call and the mmap routine, with it's call to remap_pfn_range, to do the trick, that is, to associate a user space mmap on the misc device file with the alloc'ed memory.
You need to connect the memory that you allocated in your misc driver to the buffer that you write to in your UART driver using either a global void pointer, or else by using an exported symbol, if your misc driver is a module. Initialize the pointer to a known invalid value in the UART driver and test it to make sure the misc driver has assigned it before you try to insert characters to the address to which it points.
Note that you can't add an mmap function to the UART driver directly because the UART driver class does not support an mmap file operation. It only supports the operations defined in the include/linux/serial_core.h struct uart_ops.
Admittedly this is a cumbersome solution - two device drivers, but the alternative is to write a new device class, a UART device that has an mmap operation, and that would be a lot of work compared with the above solution although it would be elegant. No one has done this to date because as Jonathan Corbet say's "...not every device lends itself to the mmap abstraction; it makes no sense, for instance, for serial ports and other stream-oriented devices", though this is exactly what you are asking for.
I implemented this solution for a polling mode UART driver based on the mxs-auart.c code and Maxime's example. It was non-trivial effort but mostly because I am using a FIQ handler for the polling timer. You should allow two to three weeks to get the whole thing up and running.
The DMA aspect of your question depends on whether the UART supports DMA transfer mode. If so, then you should be able to set it using the serial flags. The i.MX28's PrimeCell auarts support DMA transfer but for my application there was no advantage over simply reading bytes directly from the UART RX FIFO.

Resources