summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>2001-07-06 01:55:26 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>2001-07-06 01:55:26 +0000
commita256f9cba4b8dbd21444d114d0f31b0450af19b3 (patch)
treecf91f29140f42196e17999d02abfc5ac74f35117
parent7fbec9cbbc02b89d7d6356aa5f748b357490d1bc (diff)
IP/TCP/UDP checksumming on the NIC; from rtecco@umich.edu
-rw-r--r--sys/dev/pci/if_nge.c69
1 files changed, 53 insertions, 16 deletions
diff --git a/sys/dev/pci/if_nge.c b/sys/dev/pci/if_nge.c
index ad521935d14..25598f3aeaf 100644
--- a/sys/dev/pci/if_nge.c
+++ b/sys/dev/pci/if_nge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_nge.c,v 1.4 2001/07/02 06:53:43 nate Exp $ */
+/* $OpenBSD: if_nge.c,v 1.5 2001/07/06 01:55:25 angelos Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
* Copyright (c) 1997, 1998, 1999, 2000, 2001
@@ -124,8 +124,6 @@
#include <dev/pci/if_ngereg.h>
-#define NGE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP)
-
int nge_probe __P((struct device *, void *, void *));
void nge_attach __P((struct device *, struct device *, void *));
@@ -905,6 +903,7 @@ void nge_attach(parent, self, aux)
ifp->if_watchdog = nge_watchdog;
ifp->if_baudrate = 1000000000;
ifp->if_snd.ifq_maxlen = NGE_TX_LIST_CNT - 1;
+ ifp->if_capabilities = IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
DPRINTFN(5, ("bcopy\n"));
bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
@@ -1279,13 +1278,22 @@ void nge_rxeof(sc)
bpf_mtap(ifp->if_bpf, m);
#endif
-#ifdef NGE_CSUM_OFFLOAD
/* Do IP checksum checking. */
- if (extsts & NGE_RXEXTSTS_IPPKT)
- m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
- if (!(extsts & NGE_RXEXTSTS_IPCSUMERR))
- m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
-#endif
+ if (extsts & NGE_RXEXTSTS_IPPKT &&
+ !(extsts & NGE_RXEXTSTS_IPCSUMERR))
+ m->m_pkthdr.csum |= M_IPV4_CSUM_IN_OK;
+ else if (extsts & NGE_RXEXTSTS_IPCSUMERR)
+ m->m_pkthdr.csum |= M_IPV4_CSUM_IN_BAD;
+ if (extsts & NGE_RXEXTSTS_TCPPKT &&
+ !(extsts & NGE_RXEXTSTS_TCPCSUMERR))
+ m->m_pkthdr.csum |= M_TCP_CSUM_IN_OK;
+ else if (extsts & NGE_RXEXTSTS_TCPCSUMERR)
+ m->m_pkthdr.csum |= M_TCP_CSUM_IN_BAD;
+ if (extsts & NGE_RXEXTSTS_UDPPKT &&
+ !(extsts & NGE_RXEXTSTS_UDPCSUMERR))
+ m->m_pkthdr.csum |= M_UDP_CSUM_IN_OK;
+ else if (extsts & NGE_RXEXTSTS_UDPCSUMERR)
+ m->m_pkthdr.csum |= M_UDP_CSUM_IN_BAD;
#if NVLAN > 0
/*
@@ -1541,7 +1549,21 @@ int nge_encap(sc, m_head, txidx)
if (m != NULL)
return(ENOBUFS);
- sc->nge_ldata->nge_tx_list[cur].nge_extsts = 0;
+ /*
+ * Card handles checksumming on a packet by packet
+ * basis.
+ */
+ if (m_head->m_pkthdr.csum) {
+ if (m_head->m_pkthdr.csum & M_IPV4_CSUM_OUT)
+ sc->nge_ldata->nge_tx_list[*txidx].nge_extsts |=
+ NGE_TXEXTSTS_IPCSUM;
+ if (m_head->m_pkthdr.csum & M_TCPV4_CSUM_OUT)
+ sc->nge_ldata->nge_tx_list[*txidx].nge_extsts |=
+ NGE_TXEXTSTS_TCPCSUM;
+ if (m_head->m_pkthdr.csum & M_UDPV4_CSUM_OUT)
+ sc->nge_ldata->nge_tx_list[*txidx].nge_extsts |=
+ NGE_TXEXTSTS_UDPCSUM;
+ }
#if NVLAN > 0
if (ifv != NULL) {
@@ -1712,9 +1734,7 @@ void nge_init(xsc)
* Enable hardware checksum validation for all IPv4
* packets, do not reject packets with bad checksums.
*/
-#ifdef NGE_CSUM_OFFLOAD
CSR_WRITE_4(sc, NGE_VLAN_IP_RXCTL, NGE_VIPRXCTL_IPCSUM_ENB);
-#endif
#if NVLAN > 0
/*
@@ -1733,9 +1753,7 @@ void nge_init(xsc)
/*
* Enable TX IPv4 checksumming on a per-packet basis.
*/
-#ifdef NGE_CSUM_OFFLOAD
CSR_WRITE_4(sc, NGE_VLAN_IP_TXCTL, NGE_VIPTXCTL_CSUM_PER_PKT);
-#endif
#if NVLAN > 0
/*
@@ -1759,10 +1777,12 @@ void nge_init(xsc)
/*
* Enable the delivery of PHY interrupts based on
- * link/speed/duplex status changes.
+ * link/speed/duplex status changes and enable return
+ * of extended status information in the DMA descriptors,
+ * required for checksum offloading.
*/
NGE_SETBIT(sc, NGE_CFG, NGE_CFG_PHYINTR_SPD|NGE_CFG_PHYINTR_LNK|
- NGE_CFG_PHYINTR_DUP);
+ NGE_CFG_PHYINTR_DUP|NGE_CFG_EXTSTS_ENB);
DPRINTFN("NGE_CFG: 0x%08X\n", CSR_READ_4(sc, NGE_CFG));
@@ -1839,6 +1859,23 @@ int nge_ioctl(ifp, command, data)
}
switch(command) {
+ case SIOCSIFMTU:
+ if (ifr->ifr_mtu > NGE_JUMBO_MTU || ifr->ifr_mtu < ETHERMIN)
+ error = EINVAL;
+ else {
+ ifp->if_mtu = ifr->ifr_mtu;
+ /*
+ * If requested MTU is larger than the
+ * size of the TX buffer, turn off TX
+ * checksumming.
+ */
+ if (ifr->ifr_mtu >= 8152)
+ ifp->if_capabilities = 0;
+ else
+ ifp->if_capabilities = IFCAP_CSUM_IPv4 |
+ IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
+ }
+ break;
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
switch (ifa->ifa_addr->sa_family) {