Disable TX IP checksum offloading for RTL8168C controllers. The

controller in question generates frames with bad IP checksum value
if packets contain IP options.  For instance, packets generated by
ping(8) with record route option have wrong IP checksum value. The
controller correctly computes checksum for normal TCP/UDP packets
though.
There are two known RTL8168/8111C variants in market and the issue
I observed happened on RL_HWREV_8168C_SPIN2. I'm not sure
RL_HWREV_8168C also has the same issue but it would be better to
assume it has the same issue since they shall share same core.
RTL8102E which is supposed to be released at the time of
RTL8168/8111C announcement does not have the issue.

Tested by:	Konstantin V. Krotov ( kkv <> insysnet dot ru )
This commit is contained in:
Pyun YongHyeon 2011-02-04 17:49:55 +00:00
parent 12dacf622b
commit bc2a100257
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=218289

View file

@ -1527,7 +1527,16 @@ re_attach(device_t dev)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = re_ioctl;
ifp->if_start = re_start;
ifp->if_hwassist = RE_CSUM_FEATURES | CSUM_TSO;
/*
* RTL8168/8111C generates wrong IP checksummed frame if the
* packet has IP options so disable TX IP checksum offloading.
*/
if (sc->rl_hwrev->rl_rev == RL_HWREV_8168C ||
sc->rl_hwrev->rl_rev == RL_HWREV_8168C_SPIN2)
ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
else
ifp->if_hwassist = CSUM_IP | CSUM_TCP | CSUM_UDP;
ifp->if_hwassist |= CSUM_TSO;
ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_TSO4;
ifp->if_capenable = ifp->if_capabilities;
ifp->if_init = re_init;
@ -3209,6 +3218,7 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct rl_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
struct mii_data *mii;
uint32_t rev;
int error = 0;
switch (command) {
@ -3294,9 +3304,14 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if ((mask & IFCAP_TXCSUM) != 0 &&
(ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
ifp->if_capenable ^= IFCAP_TXCSUM;
if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
ifp->if_hwassist |= RE_CSUM_FEATURES;
else
if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) {
rev = sc->rl_hwrev->rl_rev;
if (rev == RL_HWREV_8168C ||
rev == RL_HWREV_8168C_SPIN2)
ifp->if_hwassist |= CSUM_TCP | CSUM_UDP;
else
ifp->if_hwassist |= RE_CSUM_FEATURES;
} else
ifp->if_hwassist &= ~RE_CSUM_FEATURES;
reinit = 1;
}