Mapping DMA interrupts in the linux kernel - linux

I'm writing a kernel module for a powerpc SoC which contains a DMA controller. I want to map the DMA interrupts in the linux kernel. my DMA structure has two interrupts:
struct dma
{
u32 dma1;
u32 dma2;
}*dma;
I have memory mapped the DMA structure in the Kernel. I have used the function irq_of_parse_and_map() to get the virq number to the corresponding interrupts.
dma->dma1=irq_of_parse_and_map(ofdev->node,0);
dma->dma2=irq_of_parse_and_map(ofdev->node,1);
but i cant get the virq numbers for the above interrupts. What APIs might be available to access the VIRQ numbers?

PowerPC based system uses a Device Tree Blob (DTB), also referred as Device Tree Source (DTS), which is a database that represents the hardware components (Processor Configuration, Buses, Peripherals etc...) on a given board. Linux kernel during its bootup expects certain information on the hardware that it runs on. Hardware information is passed from DTB to kernel by the bootloader software (eg: u-boot) as per Open Firmware standard. Once kernel get the hardware information, it will do all the software setup as a part of the kernel initilization routine.
From here on if any kernel software component (eg: device driver) needs hardware detail, it should get it from the kernel by using a set of Open Firmware Standard Binary Interfaces. Some of them are listed below:
of_register_platform_driver() - Register driver for device
of_unregister_platform_driver() - Unregister driver for device
of_address_to_resource() - Obtain physical address of peripheral
of_get_property() - Find property with a given name for a given node
of_find_node_by_phandle() - Find a node given a phandle
irq_of_parse_and_map() - Parse and map an interrupt into linux virq space
of_irq_to_resourse() - Obtain virtual IRQ of peripheral
...
...
Now coming to the problem raised here. irq_of_parse_and_map() is used to parse and map an interrupt into linux virq space. Usually this will be done by the Interrupt Controller device driver of the system. Once the interrupt mapping is done, you can get the Interrupt Source virq by referring to of_irq_to_resource() call. This step will be required for registering interrupt handler to the interrupt source. So try using of_irq_to_resource() instead of irq_of_parse_and_map().
Ref:
Device Tree Blob: http://www.informit.com/articles/article.aspx?p=1647051&seqNum=5
Open Firmware: http://www.openfirmware.org/
OF IRQ Interface: linux-2.6/drivers/of/irq.c

Related

why firmware is part of a driver. Is it important, Can I exclude it from a driver

First why firmware is important. For example in real drivers I see there is DMA or MMIO read/write is done, but normally driver code in Linux add firmware struct after requesting it from Kernel using request_firmware function.
why should I add firmware in PCI driver when i can read and write to device from driver using direct memory access. DMA is totally different and has nothing to do with firmware. DMA map device object to kernel virtual page and firmware struct object simple has read and write operations.which I don't know why they are needed. For example for typical driver this function is a struct of firmware write operations
typedef void (*my_driver_write_phy)(struct mydriver_private *o, int register, int val);
This function is registered as a callback and member of my driver's firmware struct. so I guess Kernel calls this function. But my question is, when does kernel call this function. is it used for additional features (please explain if it can be excluded) or is it called every time when data transfer happen from device to/from system including when DMA memory is accessed
So basically real question is: IS firmware required also for Direct Memory access? AND can it be excluded

What's the difference between streaming mappings and coherent mapping in DMA

According to Linux Device Drivers book author says something like: one have to make sure that DMA address mapping range between Operating system and The hardware should be equal
The first question that must be answered before attempting DMA is where the given device is
capable of such an operation on the current host
From Kernel.org it says
first step for The setup for streaming mappings is performed via a call to
int dma_set_mask(struct device *dev, u64 mask);
And first step for DMA coherent mapping/consistent allocations is performed via a call
to dma_set_coherent_mask()
In E1000E driver and also in RealTek drivers do both because they use this function call in probe function of pci driver
dma_set_mask_and_coherent
Which is for both streaming and coherent mapping informing kernel the bit mask supported by hardware 64
This is how RealTek Device driver enables both DMA mappings
dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
&tp->RxPhyAddr, GFP_KERNEL);
inside open function of net_device
And for streaming DMA mapping this used
alloc_pages_node // allocating Kernel page for DMA
dma_map_page(d, data, 0, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE); //Enabling Streaming mappingg?
also in open function
My question is why two mappings for DMA, why real drivers use both Streaming and Coherent mappings?
Like in RealTek device it just use single page streaming mappings plus coherent mapping so basically its connecting Rx Descriptor Array represented by pointer with Coherent mapping and Page streaming mapping connected to an array which it calls Rx_databuff[256U] of type page *

relationship between controller interrupt no and interrupt no in linux kernel

I am developing our own CAN kernel module in i.mx6 processor. Now we want to write ISR for CAN TX and RX. We are able to write ISR, but my question is for register my ISR using request_irq function, what is the irq no i have to give. What is the relation between interrupt no specified in controller datasheet and irq no in the above function.
Thanks in advance,
NSN
Are we talking about on-chip FlexCAN or is this an externally connected CAN controller like MCP2515? There is already a FlexCAN driver available in the kernel. For on-chip peripherals the IRQ's are already defined in the Technical Reference Manual. For iMX6D/Q have a look at Chapter 3 Interrupts and DMA events. The interrupts are specified in device tree and retrieved using request_irq. For a CAN controller, let's say connected over SPI, a GPIO can be used as interrupt and the interrupt would be specified in device tree using "interrupt-parents" and "interrupts" property.
For the exact relation, let's consider an example. The CAN1 node is here with the "interrupts" property having a number of 110. If you look at Section 3 of TRM, FlexCAN1 is suppose to have an IRQ number of 142. Since the ARM Cortex A9 domain numbers start from 32, just subtract this from 142 to get the number of 110.
Edit: Seems I was not fully clear and talked from the device tree POV. The IRQ number for request_irq should have come from a call to platform_get_irq which returns Linux IRQ numbers. Also see this.

How linux know which irq number should be used?

I am not a driver programmer, I don't have a clear picture of how linux assign irq number for pcie devices.
From an NIC driver example, it seems Linux already know which irq number should be used before the function of 'probe' or 'open' was excuted.
ex:
https://github.com/torvalds/linux/blob/4608f064532c28c0ea3c03fe26a3a5909852811a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c#L6608
err = ixgbe_request_irq(adapter);
ixgbe can get irq number by using the data of the 'adapter' variable, it means the irq value already inside adapter structure, it is not a generated number, it is an already existed value.
if it is read from pci/pcie configuration space, wasn't it very easy to conflict with other devices?
if it is generated/arrange by kernel, how the irq number already inside the 'adapter' variable? ( or it is assigned by BIOS ? )
For interrupt for MSI, it seems generated by kernel ??

How to learn the structure of Linux wireless drivers (mac80211)?

There is so many structures in the Linux wireless driver mac80211. Things like struct net_device, struct ieee80211_hw, struct ieee80211_vif and struct ieee80211_local and so on. So many structures that I don't understand what information they contain and when them were initialized.
How can I learn about them and the whole architecture of wireless drivers?
You may want to check out Johannes Berg's (mac80211 maintainer) slides here.
They may be somewhat outdated but should give you a place to start.
A high level description of the Linux WiFi kernel stack:
It's important to understand there are 2 paths in which userspace communicates with the kernel when we're talking about WiFi:
Data path: the data being received is passed from the wireless driver to the netdev core (usually using netif_rx()). From there the net core will pass it through the TCP/IP stack code and will queue it on the relevant sockets from which the userspace process will read it. On the Tx path packets will be sent from the netdev core to the wireless driver using the ndo_start_xmit() callback. The driver registers (like other netdevices such as an ethernet driver) a set of operations callbacks by using the struct net_device_ops.
Control path: This path is how userspace controls the WiFi interface/device and performs operations like scan / authentication / association. The userspace interface is based on netlink and called nl80211 (see include/uapi/linux/nl80211.h). You can send commands and get events in response.
When you send an nl80211 command it gets initially handled by cfg80211 kernel module (it's code is under net/wireless and the handlers are in net/wireless/nl80211.c).
cfg80211 will usually call a lower level driver. In case of Full MAC hardware the specific HW driver is right below cfg80211. The driver below cfg80211 registers a set of ops with cfg80211 by using cfg80211_ops struct. For example see brcmfmac driver (drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c)
For Soft MAC hardware there's mac80211 which is a kernel module implementing the 802.11 MAC layer. In this case cfg80211 will talk to mac80211 which will in turn use the hardware specific lower level driver. An example of this is iwlwifi (For Intel chips).
mac80211 registers itself with cfg80211 by using the cfg80211_ops (see net/mac80211/cfg.c). The specific HW driver registers itself with mac80211 by using the ieee80211_ops struct (for example drivers/net/wireless/iwlwifi/mvm/mac80211.c).
Initialization of a new NIC you've connected occurs from the bottom up the stack. The HW specific driver will call mac80211's ieee80211_allow_hw() usually after probing the HW. ieee80211_alloc_hw() gets the size of private data struct used by the HW driver. It in turns calls cfg80211 wiphy_new() which does the actual allocation of space sufficient for the wiphy struct, the ieee80211_local struct (which is used by mac80211) and the HW driver private data (the layering is seen in ieee80211_alloc_hw code).
ieee80211_hw is an embedded struct within ieee80211_local which is "visible" to the the HW driver. All of these (wiphy, ieee80211_local, ieee80211_hw) represent a single physical device connected.
On top of a single physical device (also referred to as phy) you can set up multiple virtual interfaces. These are essentially what you know as wlan0 or wlan1 which you control with ifconfig. Each such virtual interface is represented by an ieee80211_vif. This struct also contains at the end private structs accessed by the HW driver. Multiple interfaces can be used to run something like a station on wlan0 and an AP on wlan1 (this is possible depending on the HW capabilities).

Resources