How to work with UIO drivers with my network card - linux-kernel

I am trying to learn User mode driver to receive interrupts of my Network Card.
I insmod two kernel components ${KSRC}/drivers/uio/uio.ko and ${KSRC}/drivers/uio/uio_pci_generic.ko.
But I donot see any device getting created which I can then mmap
Typically for UIO I would need something like "/dev/uio0" which I can open then mmap()
So how to go about using UIO framework?
Edit:
My network card is Marvell ethernet controller. My hardware is x86 Ubuntu. Linux kernel 3.13.11.11. So no device tree based.

First of all, the driver has to be compiled into the kernel. Either use menu config or add the following lines to a .cfg file. You can check that the driver has been compiled by looking in /lib/modules/<kernel-name>/modules.builtin.
CONFIG_UIO=y
CONFIG_UIO_PDRV_GENIRQ=y
The next step is to add the following entry to your device tree You can check that the driver has been compiled by looking in /lib/modules/<kernel-name>/modules.builtin.file. Where the middle number is the interrupt you are targeting -32. This means 0x1D == 29 and then add 32 for the interrupt number that is registered in the GIC (Generic Interrupt Controller on ARM systems).
spw0#7aa00000 {
compatible = "generic-uio";
reg = <0x7aa00000 0x10000>;
interrupts = <0x0 0x1D 0x4>;
interrupt-parent = <0x3>;
clocks = <0x1>;
};
and changing the bootargs to console=ttyPS0,115200 root=/dev/mmcblk0p1 rw rootwait earlyprintk uio_pdrv_genirq.of_id=generic-uio.
If everything goes well, you will see the /dev/uio0 device after booting up.

Related

Failed to request_irq for kernel module

I am trying to port drivers from old kernel to new one on ARM based platform. While porting one of the drivers I have noticed that request_irq fails on new kernel. Actually, what this driver have is a number of hard coded irq numbers, and it tries to request_irq for this HW lines. I started to search what is the reason of request_irq failure, - the reason is that the appropriate IRQ descriptor (irq_desc) have IRQ_NOREQUEST flag set.
I started to search where this flag is cleared, and found that it happens here:
of_platform_populate
|
...
|
of_device_alloc
|
...
|
irq_of_parse_and_map
(some levels below this flag is dropped)
So that code is invoked from mach init code and parse DTB, all interrupt numbers that are mentioned in DTB would be mapped to irq virtual space and will be accessible through appropriate devices structures, for example:
irq = platform_get_irq(pdev, 0);
As I already said, this old - fashion drivers just have hard-coded irq numbers in include files, and they don't have no appropriate dtb entries.
The question is what is the right way, from the kernel perspective of view, to port this? Do I need to make this old driver a platform device (now it is just a char device) and create appropriate dtb description for it? Or I can just use some kernel API to mark this interrupts as available? Is it a common/normal style?

Enable hardware SPI on Xillinux

I have a MicroZed board with Xillinux 1.3 running on it. I wanted to interface an external SPI ADC to it, and write an application in linux to read values from the ADC. Zynq device's hardware SPI interface isn't enabled in Xillinux. How can I go about enabling it, I would have to recompile the FSBL and U-boot, but I don't know where to start. Can I just modify the Xillinux's Vivado design and proceed from there or will I have to start from scratch?
You should not have to modify FSBL or U-boot. You should only have to add the SPI controller to the device tree and update the programmable logic so that the SPI pins connect to your ADC.
Xilinx SDK has tools for creating the device tree file, described on the Build Device Tree Blob page.
I usually edit .dts files by hand, but you still need to run dtc to convert them to binary format as described on that page.
For an example, here is a .dts fragment for a zynq-zc770-xm013.dts board enabling SPI connected to a flash chip:
&spi0 {
status = "okay";
num-cs = <4>;
is-decoded-cs = <0>;
eeprom: at25#0 {
at25,byte-len = <8192>;
at25,addr-mode = <2>;
at25,page-size = <32>;
compatible = "atmel,at25";
reg = <2>;
spi-max-frequency = <1000000>;
};
};
you have to do 2 steps.
1- modify the hardware descriptor file (.h) of your board in your kernel sources and add the spi device. First, take a look at the schematic of the board and the datasheet of the processo to make sure to use the right device with the right name
2- add spidev on your kernel config
now build and boot the kernel, if you check on /dev/ you should find spidev** something.

Handle GPIO in Kernel and User Space ARM9 Embedded Linux AM1808

I have to handle (i.e. turn on and off) my LCD Power Pin kernel and userspace both side.
We have configured the gpio pin in Mux.h,da850.c and board-da850-evm.c properly.
The problem is that when we configure this pin in kernel then this pin is not access by /sys/class/gpio.
We have configured this in in board-da850-evm.c as below,
ret = gpio_request(DA850_LCD_GP3, "LCD GP3");
if (ret)
pr_warning("Cannot open GPIO %d\n", DA850_LCD_GP3);
gpio_direction_output(DA850_LCD_GP3, 1);
gpio_set_value(DA850_LCD_GP3,1);
If we comment this section.and export from userspace then we used this pin form userspace successfully.
Is it possible to handle gpio form kernel and userspace?
Or do we need to write the gpio drive ?

Load kernel module prior of device tree's probing

I have developed a working driver for my custom_hardware that relies on the device tree. Because my driver may evolve, I do not want my driver to be part of the kernel (when I say 'be part of the kernel', I mean, to be compiled with the kernel during the kernel creation)
Here is a glimpse of my dts:
custom_hardware: custom_hardware#0x41006000 {
compatible = "mfg,custom";
reg = <0x41006000 0x1000>;
#interrupt-cells = <0x1>;
interrupt-controller;
};
existing_hardware: existing_hardward#41004000 {
compatible = "mfg,existing";
reg = <0x41004000 0x1000>;
interrupt-parent = <&custom_hardware>;
interrupts = <0>;
};
The existing_hardware's driver is already compiled with kernel (the existing_hardware's driver has been compiled with the kernel during the kernel creation).
What I would like to do is to append my custom_hardware's driver to the ramfs and let the kernel loads the custom_hardware's driver prior of the existing_hardware's driver.
This is important since the existing_hardware's driver requests a virq from the irq_domain of the custom_hardware's driver. In order to get the irq_domain, the custom_hardware's driver must be loaded first.
Note that the existing_hardware's driver gets loaded during the probing of the device tree which seems to happen in the early stage of the kernel booting sequence.
That is not the way to do. The order of the module/driver loading must not matter. What you need to do is return -EPROBE_DEFER when getting the IRQ fails in existing_hardware. Then it will get probed again at a later time, hopefully after custom_hardware got probed.
Also, you can apply that patch that will ensure that request_irq() fails because the domain is not present yet and return -EPROBE_DEFER in that case
https://lkml.org/lkml/2014/2/13/114
I had similar problem (probing order was wrong) and the only simple solution what I found is put the modules in the desired probing order into the Makefile.
I've found the solution here: What is the Linux built-in driver load order?

Linux PCI Device Driver - Bus v. Kernel IRQ

I am writing a device driver for a PCIe card in Linux. I am trying to use interrupts in my driver.
Reading the "IRQ Line" section of the PCI configuration register (offset 0x3C) reports that the assigned IRQ line for the device is 11. lspci -b -vv also reports that my device's interrupt number is 11.
Heres where it gets weird... cat /sys/bus/pci/devices/<my_device>/irq reports that the interrupt number is 19. lspci -vv also reports that the interrupt number is 19.
Requesting 11 in my driver does not work. If I request 19 in the driver, I catch interrupts just fine.
What gives?
Thanks!!!
I believe that it has to do with the difference between "physical" and "virtual" IRQ lines. Because the processor has a limited number of physical IRQ lines it assigns virtual IRQ lines to allow the total number of PCI devices to exceed the number of physical lines.
In this instance, 19 is your virtual IRQ line (as recognized by the processor) while 11 is the physical line (as recognized by the PCI device).
By the way, you should probably really get the IRQ number from the struct pci_dev for that device since they're dynamically generated.
Sean's answer is easy to understand. However here I would try to make it more complete.
CPU's IRQ pin, almost always, isn't connected directly to a peripheral device, but via an programmable interrupt controller(PIC, e.g. Intel 8259A). This helps handling large device fan-out and also heterogeneous interrupt format (pin based v.s. message based as in PCIe).
If you run a recent version of lspci, it would print information like
Interrupt: pin A routed to IRQ 26
Here, pin A as 11 in OP, is the physical pin. This is something saved by the PCI device and used by the hardware to exchange between interrupts controller. From LDP:
The PCI set up code writes the pin number of the interrupt controller
into the PCI configuration header for each device. It determines the
interrupt pin (or IRQ) number using its knowledge of the PCI interrupt
routing topology together with the devices PCI slot number and which
PCI interrupt pin that it is using. The interrupt pin that a device
uses is fixed and is kept in a field in the PCI configuration header
for this device. It writes this information into the interrupt line
field that is reserved for this purpose. When the device driver runs,
it reads this information and uses it to request control of the
interrupt from the Linux kernel.
IRQ 26 as 19 in OP is something that kernel code and CPU deal with. According to Linux Documentation/IRQ.txt:
An IRQ number is a kernel identifier used to talk about a hardware
interrupt source. Typically this is an index into the global irq_desc
array, but except for what linux/interrupt.h implements the details
are architecture specific.
So the PCI first receives interrupts from device, translate interrupt source to a IRQ number and informs the CPU. CPU use IRQ number to look into Interrupt Descriptor Table(IDT) and find the correct software handler.
Ref:
http://www.tldp.org/LDP/tlk/dd/interrupts.html
http://www.brokenthorn.com/Resources/OSDevPic.html

Resources