summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2011-02-04 17:49:55 +0000
committeryongari <yongari@FreeBSD.org>2011-02-04 17:49:55 +0000
commit00ca42e5c4fc6291bfb42d7ccf90bcce1b5c9cfe (patch)
tree7814d48dce285bc2767b1e7e87b622b8c872d99d /sys/dev
parentdbecc33067971cfd38a340e4435a163832f7601d (diff)
downloadFreeBSD-src-00ca42e5c4fc6291bfb42d7ccf90bcce1b5c9cfe.zip
FreeBSD-src-00ca42e5c4fc6291bfb42d7ccf90bcce1b5c9cfe.tar.gz
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 )
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/re/if_re.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 9b889e7..8c7d295 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -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;
}
OpenPOWER on IntegriCloud