mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-28 02:45:21 +00:00
The SAM E70 Ethernet driver uses scatter gather DMA to transmit data. Each fragment of a network packet is mapped from a set of descriptors that is used by the controller to do the DMA transfer. Each descriptor contain an address and a length/status. The important status bits are GMAC_TXW1_LASTBUFFER to indicate the last fragment of a packet and GMAC_TXW1_USED to indicate that a descriptor has been processed by the controller. When starting a transmission, the controller start at the descriptor after the last one that has been processed. If the descriptor is NOT flagged by GMAC_TXW1_USED, it sends a first packet by sending all the fragments up to a descriptor flagged with GMAC_TXW1_LASTBUFFER. The first descriptor of a packet *and only the first descriptor of a packet* is then modified to flag it with GMAC_TXW1_USED and to provide a status (mostly related to errors and checksum offloading). It then continues with the next packet and so on and only stops if the next descriptor after GMAC_TXW1_LASTBUFFER is flagged with GMAC_TXW1_USED. Therefore in order for the controller to stop processing descriptors, the strategy is to flag the next descriptor after the last fragment to be sent with GMAC_TXW1_USED. When the next packet has to be queued, the flag can be removed before starting a transmission. This is what is currently done in the current driver. However there is a small race condition in the implementation: if packets are queued fast enough, the controller is still sending the fragment of the previous packet when the descriptor are written. When writing the first descriptor, the GMAC_TXW1_USED flag is removed. This is done after writing the address (with a memory barrier) so that looks safe. However given that the GMAC_TXW1_USED flag is only added by the controller to the first descriptor of a packet it means the next descriptor might have it cleared. In that case the descriptor is processed, and a junk packet is sent. That also desynchronize eth_tx and tx_complete as one or more packets than expected are transmitted. In order to fix that the strategy is slightly changed to initially write the first descriptor with the GMAC_TXW1_USED flag set. Once all the descriptors from the packet are written the bit is cleared (after a memory barrier). Then the transmission can be started safely. The patch also does a small optimization writing the next descriptor with only the GMAC_TXW1_USED bit set instead of setting this bit. As this will be a non-cached area, it's better avoiding a read followed by a write if not necessary. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> |
||
---|---|---|
.. | ||
adc | ||
aio | ||
audio | ||
bluetooth | ||
can | ||
clock_control | ||
console | ||
counter | ||
crypto | ||
display | ||
dma | ||
entropy | ||
ethernet | ||
flash | ||
gpio | ||
i2c | ||
i2s | ||
ieee802154 | ||
interrupt_controller | ||
ipm | ||
led | ||
led_strip | ||
modem | ||
net | ||
neural_net | ||
pci | ||
pinmux | ||
ptp_clock | ||
pwm | ||
rtc | ||
sensor | ||
serial | ||
spi | ||
timer | ||
usb | ||
watchdog | ||
wifi | ||
CMakeLists.txt | ||
Kconfig |