summaryrefslogtreecommitdiffstats
path: root/sys/dev/fxp
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2010-04-19 22:10:40 +0000
committeryongari <yongari@FreeBSD.org>2010-04-19 22:10:40 +0000
commit66db61c8c0e978eac926b1b47c6c81a108bdaa98 (patch)
tree4e38df74b4ad94becb3a95f35a704d97f0681706 /sys/dev/fxp
parent35d5bf4c1d2ab71a150954bf3464549e9e2c9efc (diff)
downloadFreeBSD-src-66db61c8c0e978eac926b1b47c6c81a108bdaa98.zip
FreeBSD-src-66db61c8c0e978eac926b1b47c6c81a108bdaa98.tar.gz
With r206844, CSUM_TCP is also set for CSUM_TSO case. Modify
drivers to take into account for the change. Basically CSUM_TSO should be checked before checking CSUM_TCP.
Diffstat (limited to 'sys/dev/fxp')
-rw-r--r--sys/dev/fxp/if_fxp.c106
1 files changed, 52 insertions, 54 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index a8d961e..a480e7c 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -1417,60 +1417,6 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
FXP_IPCB_HARDWAREPARSING_ENABLE;
m = *m_head;
- /*
- * Deal with TCP/IP checksum offload. Note that
- * in order for TCP checksum offload to work,
- * the pseudo header checksum must have already
- * been computed and stored in the checksum field
- * in the TCP header. The stack should have
- * already done this for us.
- */
- if (m->m_pkthdr.csum_flags & FXP_CSUM_FEATURES) {
- txp->tx_cb->ipcb_ip_schedule = FXP_IPCB_TCPUDP_CHECKSUM_ENABLE;
- if (m->m_pkthdr.csum_flags & CSUM_TCP)
- txp->tx_cb->ipcb_ip_schedule |= FXP_IPCB_TCP_PACKET;
-
-#ifdef FXP_IP_CSUM_WAR
- /*
- * XXX The 82550 chip appears to have trouble
- * dealing with IP header checksums in very small
- * datagrams, namely fragments from 1 to 3 bytes
- * in size. For example, say you want to transmit
- * a UDP packet of 1473 bytes. The packet will be
- * fragmented over two IP datagrams, the latter
- * containing only one byte of data. The 82550 will
- * botch the header checksum on the 1-byte fragment.
- * As long as the datagram contains 4 or more bytes
- * of data, you're ok.
- *
- * The following code attempts to work around this
- * problem: if the datagram is less than 38 bytes
- * in size (14 bytes ether header, 20 bytes IP header,
- * plus 4 bytes of data), we punt and compute the IP
- * header checksum by hand. This workaround doesn't
- * work very well, however, since it can be fooled
- * by things like VLAN tags and IP options that make
- * the header sizes/offsets vary.
- */
-
- if (m->m_pkthdr.csum_flags & CSUM_IP) {
- if (m->m_pkthdr.len < 38) {
- struct ip *ip;
- m->m_data += ETHER_HDR_LEN;
- ip = mtod(m, struct ip *);
- ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
- m->m_data -= ETHER_HDR_LEN;
- m->m_pkthdr.csum_flags &= ~CSUM_IP;
- } else {
- txp->tx_cb->ipcb_ip_activation_high =
- FXP_IPCB_HARDWAREPARSING_ENABLE;
- txp->tx_cb->ipcb_ip_schedule |=
- FXP_IPCB_IP_CHECKSUM_ENABLE;
- }
- }
-#endif
- }
-
if (m->m_pkthdr.csum_flags & CSUM_TSO) {
/*
* 82550/82551 requires ethernet/IP/TCP headers must be
@@ -1539,6 +1485,58 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
tcp_payload = m->m_pkthdr.len - ip_off - (ip->ip_hl << 2);
tcp_payload -= tcp->th_off << 2;
*m_head = m;
+ } else if (m->m_pkthdr.csum_flags & FXP_CSUM_FEATURES) {
+ /*
+ * Deal with TCP/IP checksum offload. Note that
+ * in order for TCP checksum offload to work,
+ * the pseudo header checksum must have already
+ * been computed and stored in the checksum field
+ * in the TCP header. The stack should have
+ * already done this for us.
+ */
+ txp->tx_cb->ipcb_ip_schedule = FXP_IPCB_TCPUDP_CHECKSUM_ENABLE;
+ if (m->m_pkthdr.csum_flags & CSUM_TCP)
+ txp->tx_cb->ipcb_ip_schedule |= FXP_IPCB_TCP_PACKET;
+
+#ifdef FXP_IP_CSUM_WAR
+ /*
+ * XXX The 82550 chip appears to have trouble
+ * dealing with IP header checksums in very small
+ * datagrams, namely fragments from 1 to 3 bytes
+ * in size. For example, say you want to transmit
+ * a UDP packet of 1473 bytes. The packet will be
+ * fragmented over two IP datagrams, the latter
+ * containing only one byte of data. The 82550 will
+ * botch the header checksum on the 1-byte fragment.
+ * As long as the datagram contains 4 or more bytes
+ * of data, you're ok.
+ *
+ * The following code attempts to work around this
+ * problem: if the datagram is less than 38 bytes
+ * in size (14 bytes ether header, 20 bytes IP header,
+ * plus 4 bytes of data), we punt and compute the IP
+ * header checksum by hand. This workaround doesn't
+ * work very well, however, since it can be fooled
+ * by things like VLAN tags and IP options that make
+ * the header sizes/offsets vary.
+ */
+
+ if (m->m_pkthdr.csum_flags & CSUM_IP) {
+ if (m->m_pkthdr.len < 38) {
+ struct ip *ip;
+ m->m_data += ETHER_HDR_LEN;
+ ip = mtod(m, struct ip *);
+ ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
+ m->m_data -= ETHER_HDR_LEN;
+ m->m_pkthdr.csum_flags &= ~CSUM_IP;
+ } else {
+ txp->tx_cb->ipcb_ip_activation_high =
+ FXP_IPCB_HARDWAREPARSING_ENABLE;
+ txp->tx_cb->ipcb_ip_schedule |=
+ FXP_IPCB_IP_CHECKSUM_ENABLE;
+ }
+ }
+#endif
}
error = bus_dmamap_load_mbuf_sg(sc->fxp_txmtag, txp->tx_map, *m_head,
OpenPOWER on IntegriCloud