Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Sep 2017 00:50:07 +0300
From:      Guy Yur <guyyur@gmail.com>
To:        freebsd-arm <freebsd-arm@freebsd.org>
Subject:   if_awg fixes
Message-ID:  <CAC67Hz9GzTeKmBfiCsJj=_cC=63gzEeJ7VbwJss4xk_oNLbaDw@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Hi,

I had issues with if_awg when passing heavy traffic
(transmission, samba, ...)
a. The tx hardware checksum stopped working after a while.
IPv4 packets were sent with IP and TCP/UDO checksum fields unmodified.
so the packets were rejected by the receiving host.
IPv4 checksum was 0 and TCP/UDP checksum only pseudo header.
IPv6 packets were fine since the card doesn't do offload for ipv6.

b. mbuf leaks.
"current" mbuf clusters count kept rising in "netstat -m" for some
traffic types and never went down until eventually reaching max.


Comparing the driver against if_nfe which also uses a ring buffer,
there are several issues with how the rings are programmed.
I made changes inspired by it.

The following fixes improved the card behavior on my boards.
(tested on Orange Pi PC and Orange Pi One)

1.
https://github.com/guyyur/freebsd-src_patches/blob/master/if_awg_fixes_1_reg_offsets.patch

Wrong register offsets for the tx_dma status regs.
Registers are currently only used when dumping them
(AWG_DEBUG defined and doing soft reset).


2.
https://github.com/guyyur/freebsd-src_patches/blob/master/if_awg_fixes_2_fix_txcsum_disabled.patch

Fix behavior when txcsum is disabled by turning
CSUM_UDP and CSUM_TCP on/off along with CSUM_IP.
Only consider IFCAP_TXCSUM to set/unset CSUM_* since the
flags are only checked in tx path.
IFCAP_RXCSUM is checked in rx path.

CSUM_IP is independent from CSUM_UDP and CSUM_TCP.
If only CSUM_IP is turned off but CSUM_UDP and CSUM_TCP are set
the card will not compute the checksum but the OS expects the
tcp/udp field to be hw computed.


3.
https://github.com/guyyur/freebsd-src_patches/blob/master/if_awg_fixes_3_fix_tx_path.patch

Fix tx programming when there are multiple segments.

a. Set TX_DESC_CTL on the first descriptor only after all the
other descriptors have been programmed.
This will prevent the card from advancing on the first descriptor
while the other descriptors are still being written.

b. Put the mbuf and map for release on the last segment.
The map from the first segment is used so swap it with the last.
The data sheet mentions the descriptors are marked as done only
after the frame is transmitted so it might be fine to keep the
map and mbuf in the first segment but it doesn't hurt to keep it
in the last.

c. if m_collapse fails, release the buffer instead of enqueuing it again
where it will keep failing.


4.
https://github.com/guyyur/freebsd-src_patches/blob/master/if_awg_fixes_4_rx_avoid_holes.patch

Avoid hole in the rx ring by keeping a spare dma map.
If new mbuf allocation or dma mapping fails, just reuse the
existing mbuf and increase the drop counter.

Only try to allocate a new buffer if len of packet > 0.
If there were errors or just an empty packet, reuse the buffer.


5.
https://github.com/guyyur/freebsd-src_patches/blob/master/if_awg_fixes_5_cleanup_buffers_on_stop.patch

Cleanup tx and rx buffers on card stop.
ifconfig ... down
ifconfig ... up

tx and rx indices are advanced to where the card expects the next buffer.
I don't see a way to reset the dma_cur_desc regs mentioned in the data
sheet.


Thanks,
Guy



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAC67Hz9GzTeKmBfiCsJj=_cC=63gzEeJ7VbwJss4xk_oNLbaDw>