dma_map_single and dma_map_page - intel

I want to do dma of multiple frames to send a big frame( jumbo ). I am able to send normal frame ( of size 1500 ). I need some doubts on dma.
What is real advantage of dma_map_single() over other api. We could do everything with dma_map_page , right ?
Suppose we need to transmit a big frame( jumbo ) in a driver , and i have stored this frame in multiple buffers. These buffers are not contiguous in physical memory or in virtual memory. But these buffers are in kernel space. How can we send it as a one frame. Should we use scatter-gather dma ?. Is this possible with other dma_api ?

dma_map_single and dma_map_page will eventually call
dam_ops->map_page - the eventual function is decided by the arch and
kernel config. usualy it will be intel_map_page on x86 machines with
IOMMU.
First of all Jumbo frames from the kernels standpoint are irrelevant
at TX time as the network stack coalesce transmitted buffers to up
to 64K packets (LSO/TSO) and the NIC will eventually break the
single 64K packet to several MTU(9K/1500 on ETH) sized packets each
with its own L3 headers.
To your question the SKB can have a scatter-gather list - each buffer then dma-mapped.
The list of dma-addresses and buffer lengths is then written in a send descriptor to the NIC which knows how to combine them all together to be sent.
And by the way there is a dma_map_sg API for scatter lists in the Kernel and it will return a scatter list with a list of dma addresses. This is usually irrelevant to NIC drivers.

Related

STM32H7 | Portenta H7 Data missing during DMA transfer (ADC to Memory)

I'm currently working on STM32H747XI (Portenta H7). I'am programming the ADC1 with the DMA1 to get 16bits data at 1Msps.
I'm sorry, I can't share my entire code but I will therefore try to describe my configuration as precisely as possible.
I'm using the ADC1 trigged by a 1MHz timer. The ADC is working in continus mode with the DMA circular and double buffer mode. I tryed direct mode and burst with a full FIFO. I have no DMA error interrupe and no ADC overrun.
My peripheral are running but I'm stuck front of two issues. First issue, I'am doing buffer of 8192 uint16_t and I send it on the USB CDC with the arduino function USBserial.Write(buf,len). In this case, USB transfer going right but I have some missing data in my buffer. The DMA increments memory but doesn't write. So I don't have missing sample but the value is false (it belongs to the old buffer).
You can see the data plot below :
transfer with buffer of 8192 samples
If I double the buffer size, this issue is fixed but another comes. The USB VPC transfer fail if the data buffer is longer than 16384 byte. Some data are cut. I tried to solve this with differents sending and delays but it doesn't work. I still have the same kind of cut.
Here the data plot of the same script with a longer buffer : transfer withe buffer of 16384 sample (32768 byte)
Thank you for your help. I remain available.
For a fast check try to disable data cache. You're probably not managing cache correctly or you haven't disable caching in the memory space where you're using DMA.
Peripherals are not aware of cache so you must manage it manually. You have also to align buffers to cache lines in this case.
Refer to AN4839

Using 3 different communication protocols in the same MCU

For a project I need to make communicate in a CANBus network, ethernet network and with RS-232. I want to use one single MCU that will act as the main unit of CANBus start topology, Ethernet start topology and that MCU also will be transfering the RS232 data that comes to it to another device. Now I want to use high speed CAN which can be up to 1 Mbits per second. However,RS-232 is max 20 k baud. I wonder if it is doable with 1 MCU to handle 3 different communications ( CANBus, ethernet and RS-232). I am afraid of to get overrun with data at some point. I can buffer data short term if data comes in bursts that can be averaged out. For continuous data where I'll never be able to keep up, I'll need to discard messages, perhaps in a managed way. But I do not want to discard any data. So my question is: Would using 1 MCU for this case work? And are there any software tricks that would help me with this case? (Like giving CANBus a higher priority etc.)
Yes, this can be done with a single MCU. Even a simple MCU should easily be able to handle data rates of 1 Mbps. Most likely you want to use DMA enabled transfer so the CPU core will only need to act when the transmission of a chunk of data has completed.
The problem of being overrun by data due to the mismatch in data rate is a separate topic:
If the mismatch persists, no system can handle it, no matter how capable.
If the mismatch is temporary, it's just a function of the available buffer size.
So if the worst case you want to handle is 10s of incoming data at 1 Mbps (with an outgoing rate of 20kbps), then you will need 10s x (1Mbps - 20kps) = 9.8 Mbit = 1.225 MByte of buffer memory.

TCP buffer in play while using boost::asio::async_write?

I understand from this discussion that boost::asio::async_write writes data to the kernel buffers only. It does not mean that the peer has received the data. But if I am sending big packets of size let's say 200000 bytes each, and then I pull the network cable to kill the connection abruptly. Will it still keep reporting on and on saying 200000 bytes written into kernel buffers for each async_write? My testing says that it doesn't. It gives up with a large buffer like 200000 bytes and does not report all bytes sent. But if its a small buffer like 30-40 bytes, it keeps reporting okay?
Question:
The primary point of raising this question is: Is there an underlying buffer size which gets filled up at one point for async_write to say that now its not able to write anymore because the earlier scheduled data has not gone out? If yes then what is the size of this underlying buffer? Can I query it from the boost::asio::ip::tcp::socket?
You can query/change the underlying system socket buffer size with send_buffer_size socket option.
The operating system though can dynamically adjust the socket buffer size and limit its maximum size:
tcp_wmem (since Linux 2.4)
This is a vector of 3 integers: [min, default, max]. These
parameters are used by TCP to regulate send buffer sizes. TCP
dynamically adjusts the size of the send buffer from the
default values listed below, in the range of these values,
depending on memory available.

Is it possible to send one bit from one computer to another computer through socket?

I am working on a project in which i have to send data in bits.
Is it possible to send 1 bit from one computer to another through internet.Most of the people
said to me that minimum internet packet size is 64bytes.If i send 1bit from one computer to another then packet bandwidth is 64bytes.
A TCP or UDP packet consists of a header and data. Maybe you could have one bit of data in the data section, but you would need the header as well. Without the header it would be impossible to send the packet. The header contains all the information required for sending the packet where it is supposed to go and making sure it arrives safely.
I will take "internet packet" to mean Ethernet frame based on the value you give.
An Ethernet frame has a minimum total size of 64 bytes including both header and payload, this is to ensure that the time to transmit a single frame is greater than the round trip time between nodes.
This requirement is a feature of any network that uses CSMA/CD (specifically the CD (collision detection) part), it allows a sensing node to detect a collision whilst still transmitting a frame.
Whilst Ethernet can be used to send a frame smaller than 64 bytes "padding" will be added to ensure the frame is at least 64 bytes.

Can a single page can be used for multiple skbs which are not fragments

I have a networking hardware which does Rx coalescing , in which frames partaining to a nic device are combined and send as a big chunk ( Greater than mtu) to the driver.
In the driver i have to split them according to mtu size and need to sent up to the stack.
I want to know is there a way to allocate a page so that i can split that after the device DMA's the frame ?
Can a single Page can be shared across multiple skbs (not accross frags in a same skb)? If so what special care i need to take which unmapping the page?
Is there a mechanism to allocate sgs and map them to a page and after the
device does DMA , split this sgs and point to skb and send to the stack
Waiting for the reponses
Thanks
pradeep G

Resources