Linux Kernel ALSA Driver DMA to FPGA issue - linux

I'm working on a zynq 7000 SOC. I wrote an ALSA driver. Inside the FPGA, I implemented all the circuitery (FIFO, clocks generator, I2S dac output). From the Linux kernel point of view, there is an address to feed sample in the FPGA FIFO, one address to read the hardware pointer and an interrupt for the "snd_pcm_period_elapsed" function call.
In the "pcm_copy" callback, i copy samples from userspace to kernel space previously allocaded buffer, and then, i use a loop to push data in the FPGA from the kernel buffer.
I would like to USE an AXI dma to be able to copy directly from the pcm buffer to the FPGA FIFO. The DMA works perfectly (i used something very simple and not the linux DMA api witch is for me very difficult to understand...)
To test my DMA, i allocate a coherent buffer "dma_alloc_coherent" and i copy the samples in the coherent buffer and then i launch the transfert.
My issue is: I don't undersand how to get the physical address of the PCM buffer to be able to use the DMA transfert directly without copy in the coherent buffer. I read a lot of documents and i looked a lot of devices drivers, most of them are using PCI DMA witch is an other story ...
I founded somewhere that i have to implement the mmap callback in my alsa driver, but i didn't understand well, i also looked arround the "dma_area" field in the substream data structure witch contain an address, but if i use it, i have a dma error...
I really want to well understand how the pcm ring buffer is allocated and so on, does anybody can help me ?
Best regards,
Nicolas

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 *

Can I determine number of byte transfer using DMA subsystem in linux?

I have a code that write data to a I2C-EEPROM. The i2c-driver is config to use DMA. But is there anyway I can check that data is transfered by i2c using DMA from my program in user-space?
Thanks!

DMA of data in socket buffer (skb) in linux

I was going through the process of packet transmission and packet reception in latest linux kernel. I can see that, there is a framework in skb where it supports "linear" data as well as "paged" data.
It has a separate structure called skb_shared_info to represent page fragments.
Now my doubt is, how will the device DMA the entire contents of the packet? Is it not going to be scattered across the memory?
Thanks
CHID
It depends on the capability of the networking hardware. Most “modern” NICs can do gather/scatter DMA and handle tranferring a packet into multiple, non-contiguous buffers, but the Linux kernel networking stack will only give an skb with nonlinear data to a driver/netdev if NETIF_F_SG is set (indicating the device can handle scatter/gather). If the device driver sets NETIF_F_SG then it is telling the stack that it can handle multiple physical buffers per packet.

Efficient detection if value at memory address has been changed?

This more a general question. Consider an external device. From time to time this device writes data via its device driver to a specific memory address. I want to write a small C program which read out this data. Is there a better way than just polling this address to check if the value has been changed? I want to keep the CPU load low.
I have done some further research
Is "memory mapped IO" an option? My naive idea is to let the external device writes a flag to a "memory mapped IO"-address which triggers a kernel device driver. The driver then "informs" the program which proceed the value. Can this work? How can a driver informs the program?
The answer may depend on what processor you intend to use, what the device is and possibly whether you are using an operating system or RTOS.
Memory mapped I/O per se is not a solution, that simply refers to I/O device registers that can be directly addressed via normal memory access instructions. Most devices will generate an interrupt when certain registers are updated or contain new valid data.
In general if using an RTOS you can arrange for the device driver to signal via a suitable IPC mechanism any client thread(s) that need to handle the data. If you are not using an RTOS, you could simply register a callback with the device driver which it would call whenever the data is updated. What the client does in the call back is its business - including reading the new data.
If the device in question generates interrupts, then the handling can be done on interrupt, if the device is capable of DMA, then it can handle blocks of data autonomously before teh DMA controller generates an DMA interrupt to a handler.

Resources