svn commit: r253377 - projects/vmxnet/sys/dev/vmware/vmxnet3

Bryan Venteicher bryanv at FreeBSD.org
Tue Jul 16 04:39:45 UTC 2013


Author: bryanv
Date: Tue Jul 16 04:39:44 2013
New Revision: 253377
URL: http://svnweb.freebsd.org/changeset/base/253377

Log:
  Add TSO support and cleanup checksum offloading

Modified:
  projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c
  projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h

Modified: projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c
==============================================================================
--- projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c	Tue Jul 16 03:12:31 2013	(r253376)
+++ projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c	Tue Jul 16 04:39:44 2013	(r253377)
@@ -112,6 +112,7 @@ static int	vmxnet3_alloc_queue_data(stru
 static void	vmxnet3_free_queue_data(struct vmxnet3_softc *);
 static int	vmxnet3_alloc_mcast_table(struct vmxnet3_softc *);
 static void	vmxnet3_init_shared_data(struct vmxnet3_softc *);
+static void	vmxnet3_reinit_interface(struct vmxnet3_softc *);
 static void	vmxnet3_reinit_shared_data(struct vmxnet3_softc *);
 static int	vmxnet3_alloc_data(struct vmxnet3_softc *);
 static void	vmxnet3_free_data(struct vmxnet3_softc *);
@@ -454,10 +455,8 @@ vmxnet3_alloc_msix_interrupts(struct vmx
 	if (nmsix < required)
 		return (1);
 
-	int error;
-
 	cnt = required;
-	if ((error = pci_alloc_msix(dev, &cnt)) == 0 && cnt >= required) {
+	if (pci_alloc_msix(dev, &cnt) == 0 && cnt >= required) {
 		sc->vmx_nintrs = required;
 		return (0);
 	}
@@ -502,7 +501,6 @@ vmxnet3_alloc_interrupt(struct vmxnet3_s
     struct vmxnet3_interrupt *intr)
 {
 	struct resource *irq;
-	int old_rid = rid;
 
 	irq = bus_alloc_resource_any(sc->vmx_dev, SYS_RES_IRQ, &rid, flags);
 	if (irq == NULL)
@@ -927,10 +925,6 @@ vmxnet3_alloc_txq_data(struct vmxnet3_so
 		txr = &txq->vxtxq_cmd_ring;
 		txc = &txq->vxtxq_comp_ring;
 
-		/*
-		 * XXX BMV Need better way to determine the maximum
-		 * size/segments/segsize arguments.
-		 */
 		error = bus_dma_tag_create(bus_get_dma_tag(dev),
 		    1, 0,			/* alignment, boundary */
 		    BUS_SPACE_MAXADDR,		/* lowaddr */
@@ -938,7 +932,7 @@ vmxnet3_alloc_txq_data(struct vmxnet3_so
 		    NULL, NULL,			/* filter, filterarg */
 		    VMXNET3_TSO_MAXSIZE,	/* maxsize */
 		    VMXNET3_TX_MAXSEGS,		/* nsegments */
-		    PAGE_SIZE,			/* maxsegsize */
+		    VMXNET3_TX_MAXSEGSIZE,	/* maxsegsize */
 		    0,				/* flags */
 		    NULL, NULL,			/* lockfunc, lockarg */
 		    &txr->vxtxr_txtag);
@@ -1294,22 +1288,40 @@ vmxnet3_init_shared_data(struct vmxnet3_
 }
 
 static void
-vmxnet3_reinit_shared_data(struct vmxnet3_softc *sc)
+vmxnet3_reinit_interface(struct vmxnet3_softc *sc)
 {
 	struct ifnet *ifp;
-	struct vmxnet3_driver_shared *ds;
 
 	ifp = sc->vmx_ifp;
-	ds = sc->vmx_ds;
 
 	/* Use the current MAC address. */
 	bcopy(IF_LLADDR(sc->vmx_ifp), sc->vmx_lladdr, ETHER_ADDR_LEN);
 	vmxnet3_set_lladdr(sc);
 
+	ifp->if_hwassist = 0;
+	if (ifp->if_capenable & IFCAP_TXCSUM)
+		ifp->if_hwassist |= VMXNET3_CSUM_OFFLOAD;
+	if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
+		ifp->if_hwassist |= VMXNET3_CSUM_OFFLOAD_IPV6;
+	if (ifp->if_capenable & IFCAP_TSO4)
+		ifp->if_hwassist |= CSUM_TSO;
+	if (ifp->if_capenable & IFCAP_TSO6)
+		ifp->if_hwassist |= CSUM_TSO; /* No CSUM_TSO_IPV6. */
+}
+
+static void
+vmxnet3_reinit_shared_data(struct vmxnet3_softc *sc)
+{
+	struct ifnet *ifp;
+	struct vmxnet3_driver_shared *ds;
+
+	ifp = sc->vmx_ifp;
+	ds = sc->vmx_ds;
+
 	ds->upt_features = 0;
 	if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
 		ds->upt_features |= UPT1_F_VLAN;
-	if (ifp->if_capenable & IFCAP_RXCSUM)
+	if (ifp->if_capenable & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6))
 		ds->upt_features |= UPT1_F_CSUM;
 
 	ds->mtu = ifp->if_mtu;
@@ -1380,9 +1392,11 @@ vmxnet3_setup_interface(struct vmxnet3_s
 	vmxnet3_get_lladdr(sc);
 	ether_ifattach(ifp, sc->vmx_lladdr);
 
-	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
 	ifp->if_capabilities |= IFCAP_RXCSUM | IFCAP_TXCSUM;
-	ifp->if_hwassist |= VMXNET3_CSUM_FEATURES;
+	ifp->if_capabilities |= IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6;
+	ifp->if_capabilities |= IFCAP_TSO4 | IFCAP_TSO6;
+	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
+	ifp->if_hwassist |= VMXNET3_CSUM_ALL_OFFLOAD;
 
 	ifp->if_capenable = ifp->if_capabilities;
 	
@@ -1644,9 +1658,8 @@ vmxnet3_rxeof(struct vmxnet3_softc *sc, 
 		m->m_pkthdr.len = m->m_len = length;
 		m->m_pkthdr.csum_flags = 0;
 
-		if (ifp->if_capenable & IFCAP_RXCSUM && !rxcd->no_csum)
+		if (!rxcd->no_csum)
 			vmxnet3_rx_csum(rxcd, m);
-
 		if (rxcd->vlan) {
 			m->m_flags |= M_VLANTAG;
 			m->m_pkthdr.ether_vtag = rxcd->vtag;
@@ -1965,6 +1978,8 @@ static int
 vmxnet3_reinit(struct vmxnet3_softc *sc)
 {
 
+	vmxnet3_reinit_interface(sc);
+
 	vmxnet3_reinit_shared_data(sc);
 
 	if (vmxnet3_reinit_queues(sc) != 0)
@@ -2063,6 +2078,28 @@ vmxnet3_encap_offload_ctx(struct mbuf *m
 		return (EINVAL);
 	}
 
+	if (m->m_pkthdr.csum_flags & CSUM_TSO) {
+		struct tcphdr *tcp, tcphdr;
+
+		if (__predict_false(*proto != IPPROTO_TCP)) {
+			/* Likely failed to correctly parse the mbuf. */
+			return (EINVAL);
+		}
+
+		if (m->m_len < *start + sizeof(struct tcphdr)) {
+			m_copydata(m, offset, sizeof(struct tcphdr),
+			    (caddr_t) &tcphdr);
+			tcp = &tcphdr;
+		} else
+			tcp = (struct tcphdr *)(m->m_data + *start);
+
+		/*
+		 * For TSO, the size of the protocol header is also
+		 * included in the descriptor header size.
+		 */
+		*start += (tcp->th_off << 2);
+	}
+
 	return (0);
 }
 
@@ -2133,7 +2170,7 @@ vmxnet3_encap(struct vmxnet3_softc *sc, 
 	if (VMXNET3_TXRING_AVAIL(txr) < nsegs) {
 		vmxnet3_encap_unload_mbuf(sc, txr, dmap);
 		return (ENOSPC);
-	} else if (m->m_pkthdr.csum_flags & VMXNET3_CSUM_FEATURES) {
+	} else if (m->m_pkthdr.csum_flags & VMXNET3_CSUM_ALL_OFFLOAD) {
 		error = vmxnet3_encap_offload_ctx(m, &etype, &proto, &start);
 		if (error) {
 			vmxnet3_encap_unload_mbuf(sc, txr, dmap);
@@ -2176,7 +2213,12 @@ vmxnet3_encap(struct vmxnet3_softc *sc, 
 		sop->vtag = m->m_pkthdr.ether_vtag;
 	}
 
-	if (m->m_pkthdr.csum_flags & VMXNET3_CSUM_FEATURES) {
+	if (m->m_pkthdr.csum_flags & CSUM_TSO) {
+		sop->offload_mode = VMXNET3_OM_TSO;
+		sop->hlen = start;
+		sop->offload_pos = m->m_pkthdr.tso_segsz;
+	} else if (m->m_pkthdr.csum_flags & (VMXNET3_CSUM_OFFLOAD |
+	    VMXNET3_CSUM_OFFLOAD_IPV6)) {
 		sop->offload_mode = VMXNET3_OM_CSUM;
 		sop->hlen = start;
 		sop->offload_pos = start + m->m_pkthdr.csum_data;

Modified: projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h
==============================================================================
--- projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h	Tue Jul 16 03:12:31 2013	(r253376)
+++ projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h	Tue Jul 16 04:39:44 2013	(r253377)
@@ -210,10 +210,16 @@ struct vmxnet3_softc {
  * Max descriptors per Tx packet. We must limit the size of the
  * any TSO packets based on the number of segments.
  */
-#define VMXNET3_TX_MAXSEGS		16
+#define VMXNET3_TX_MAXSEGS		32
 #define VMXNET3_TSO_MAXSIZE		65550
 
 /*
+ * Maximum support Tx segments size. The length field in the
+ * Tx descriptor is 14 bits.
+ */
+#define VMXNET3_TX_MAXSEGSIZE		(1 << 14)
+
+/*
  * Predetermined size of the multicast MACs filter table. If the
  * number of multicast addresses exceeds this size, then the
  * ALL_MULTI mode is use instead.
@@ -228,6 +234,10 @@ struct vmxnet3_softc {
 /*
  * IP protocols that we can perform Tx checksum offloading of.
  */
-#define VMXNET3_CSUM_FEATURES		(CSUM_UDP | CSUM_TCP)
+#define VMXNET3_CSUM_OFFLOAD		(CSUM_TCP | CSUM_UDP)
+#define VMXNET3_CSUM_OFFLOAD_IPV6	(CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
+
+#define VMXNET3_CSUM_ALL_OFFLOAD	\
+    (VMXNET3_CSUM_OFFLOAD | VMXNET3_CSUM_OFFLOAD_IPV6 | CSUM_TSO)
 
 #endif /* _IF_VMXVAR_H */


More information about the svn-src-projects mailing list