Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Add TX checksum offload supports for ixl(4)



details:   https://anonhg.NetBSD.org/src/rev/60870ce6b859
branches:  trunk
changeset: 1006771:60870ce6b859
user:      yamaguchi <yamaguchi%NetBSD.org@localhost>
date:      Mon Jan 27 09:40:43 2020 +0000

description:
Add TX checksum offload supports for ixl(4)

diffstat:

 sys/dev/pci/if_ixl.c |  104 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 92 insertions(+), 12 deletions(-)

diffs (164 lines):

diff -r c3b24b3892dd -r 60870ce6b859 sys/dev/pci/if_ixl.c
--- a/sys/dev/pci/if_ixl.c      Mon Jan 27 08:40:46 2020 +0000
+++ b/sys/dev/pci/if_ixl.c      Mon Jan 27 09:40:43 2020 +0000
@@ -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 @@
 #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 @@
        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 @@
        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 @@
        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 @@
                        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 @@
                        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);



Home | Main Index | Thread Index | Old Index