Module Name: src Committed By: yamaguchi Date: Mon Jan 27 09:40:43 UTC 2020
Modified Files: src/sys/dev/pci: if_ixl.c Log Message: Add TX checksum offload supports for ixl(4) To generate a diff of this commit: cvs rdiff -u -r1.27 -r1.28 src/sys/dev/pci/if_ixl.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_ixl.c diff -u src/sys/dev/pci/if_ixl.c:1.27 src/sys/dev/pci/if_ixl.c:1.28 --- src/sys/dev/pci/if_ixl.c:1.27 Mon Jan 27 08:40:46 2020 +++ src/sys/dev/pci/if_ixl.c Mon Jan 27 09:40:43 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ixl.c,v 1.27 2020/01/27 08:40:46 yamaguchi Exp $ */ +/* $NetBSD: if_ixl.c,v 1.28 2020/01/27 09:40:43 yamaguchi Exp $ */ /* * Copyright (c) 2013-2015, Intel Corporation @@ -104,6 +104,9 @@ #include <net/if_ether.h> #include <net/rss_config.h> +#include <netinet/tcp.h> /* for struct tcphdr */ +#include <netinet/udp.h> /* for struct udphdr */ + #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> @@ -704,11 +707,19 @@ struct ixl_softc { #define IXL_TX_INTR_PROCESS_LIMIT 256 #define IXL_RX_INTR_PROCESS_LIMIT 0U -#define IXL_IFCAP_RXCSUM (IFCAP_CSUM_IPv4_Rx| \ - IFCAP_CSUM_TCPv4_Rx| \ - IFCAP_CSUM_UDPv4_Rx| \ - IFCAP_CSUM_TCPv6_Rx| \ +#define IXL_IFCAP_RXCSUM (IFCAP_CSUM_IPv4_Rx | \ + IFCAP_CSUM_TCPv4_Rx | \ + IFCAP_CSUM_UDPv4_Rx | \ + IFCAP_CSUM_TCPv6_Rx | \ IFCAP_CSUM_UDPv6_Rx) +#define IXL_IFCAP_TXCSUM (IFCAP_CSUM_IPv4_Tx | \ + IFCAP_CSUM_TCPv4_Tx | \ + IFCAP_CSUM_UDPv4_Tx | \ + IFCAP_CSUM_TCPv6_Tx | \ + IFCAP_CSUM_UDPv6_Tx) +#define IXL_CSUM_ALL_OFFLOAD (M_CSUM_IPv4 | \ + M_CSUM_TCPv4 | M_CSUM_TCPv6 | \ + M_CSUM_UDPv4 | M_CSUM_UDPv6) #define delaymsec(_x) DELAY(1000 * (_x)) #ifdef IXL_DEBUG @@ -1340,8 +1351,9 @@ ixl_attach(device_t parent, device_t sel IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_tx_ring_ndescs); IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities |= IXL_IFCAP_RXCSUM; + ifp->if_capabilities |= IXL_IFCAP_TXCSUM; #if 0 - ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx; + ifp->if_capabilities |= IFCAP_TSOv4 | IFCAP_TSOv6; #endif ether_set_vlan_cb(&sc->sc_ec, ixl_vlan_cb); sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU; @@ -2548,6 +2560,71 @@ ixl_load_mbuf(bus_dma_tag_t dmat, bus_dm return error; } +static inline int +ixl_tx_setup_offloads(struct mbuf *m, uint64_t *cmd_txd) +{ + struct ether_header *eh; + size_t len; + uint64_t cmd; + + cmd = 0; + + eh = mtod(m, struct ether_header *); + switch (htons(eh->ether_type)) { + case ETHERTYPE_IP: + case ETHERTYPE_IPV6: + len = ETHER_HDR_LEN; + break; + case ETHERTYPE_VLAN: + len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; + break; + default: + len = 0; + } + cmd |= ((len >> 1) << IXL_TX_DESC_MACLEN_SHIFT); + + if (m->m_pkthdr.csum_flags & + (M_CSUM_TSOv4 | M_CSUM_TCPv4 | M_CSUM_UDPv4)) { + cmd |= IXL_TX_DESC_CMD_IIPT_IPV4; + } + if (m->m_pkthdr.csum_flags & M_CSUM_IPv4) { + cmd |= IXL_TX_DESC_CMD_IIPT_IPV4_CSUM; + } + + if (m->m_pkthdr.csum_flags & + (M_CSUM_TSOv6 | M_CSUM_TCPv6 | M_CSUM_UDPv6)) { + cmd |= IXL_TX_DESC_CMD_IIPT_IPV6; + } + + switch (cmd & IXL_TX_DESC_CMD_IIPT_MASK) { + case IXL_TX_DESC_CMD_IIPT_IPV4: + case IXL_TX_DESC_CMD_IIPT_IPV4_CSUM: + len = M_CSUM_DATA_IPv4_IPHL(m->m_pkthdr.csum_data); + break; + case IXL_TX_DESC_CMD_IIPT_IPV6: + len = M_CSUM_DATA_IPv6_IPHL(m->m_pkthdr.csum_data); + break; + default: + len = 0; + } + cmd |= ((len >> 2) << IXL_TX_DESC_IPLEN_SHIFT); + + if (m->m_pkthdr.csum_flags & + (M_CSUM_TSOv4 | M_CSUM_TSOv6 | M_CSUM_TCPv4 | M_CSUM_TCPv6)) { + len = sizeof(struct tcphdr); + cmd |= IXL_TX_DESC_CMD_L4T_EOFT_TCP; + } else if (m->m_pkthdr.csum_flags & (M_CSUM_UDPv4 | M_CSUM_UDPv6)) { + len = sizeof(struct udphdr); + cmd |= IXL_TX_DESC_CMD_L4T_EOFT_UDP; + } else { + len = 0; + } + cmd |= ((len >> 2) << IXL_TX_DESC_L4LEN_SHIFT); + + *cmd_txd |= cmd; + return 0; +} + static void ixl_tx_common_locked(struct ifnet *ifp, struct ixl_tx_ring *txr, bool is_transmit) @@ -2557,7 +2634,7 @@ ixl_tx_common_locked(struct ifnet *ifp, struct ixl_tx_map *txm; bus_dmamap_t map; struct mbuf *m; - uint64_t cmd, cmd_vlan; + uint64_t cmd, cmd_txd; unsigned int prod, free, last, i; unsigned int mask; int post = 0; @@ -2611,12 +2688,15 @@ ixl_tx_common_locked(struct ifnet *ifp, continue; } + cmd_txd = 0; + if (m->m_pkthdr.csum_flags & IXL_CSUM_ALL_OFFLOAD) { + ixl_tx_setup_offloads(m, &cmd_txd); + } + if (vlan_has_tag(m)) { - cmd_vlan = (uint64_t)vlan_get_tag(m) << + cmd_txd |= (uint64_t)vlan_get_tag(m) << IXL_TX_DESC_L2TAG1_SHIFT; - cmd_vlan |= IXL_TX_DESC_CMD_IL2TAG1; - } else { - cmd_vlan = 0; + cmd_txd |= IXL_TX_DESC_CMD_IL2TAG1; } bus_dmamap_sync(sc->sc_dmat, map, 0, @@ -2628,7 +2708,7 @@ ixl_tx_common_locked(struct ifnet *ifp, cmd = (uint64_t)map->dm_segs[i].ds_len << IXL_TX_DESC_BSIZE_SHIFT; cmd |= IXL_TX_DESC_DTYPE_DATA | IXL_TX_DESC_CMD_ICRC; - cmd |= cmd_vlan; + cmd |= cmd_txd; txd->addr = htole64(map->dm_segs[i].ds_addr); txd->cmd = htole64(cmd);