svn commit: r255055 - in head: share/man/man4 sys/dev/vmware/vmxnet3

Bryan Venteicher bryanv at FreeBSD.org
Fri Aug 30 05:53:01 UTC 2013


Author: bryanv
Date: Fri Aug 30 05:53:00 2013
New Revision: 255055
URL: http://svnweb.freebsd.org/changeset/base/255055

Log:
  Few more minor if_vmx tweaks
  
   - Allow the Rx/Tx queue sizes to be configured by tunables
   - Bail out earlier if the Tx queue unlikely has enough free
     descriptors to hold the frame
   - Cleanup some of the offloading capabilities handling

Modified:
  head/share/man/man4/vmx.4
  head/sys/dev/vmware/vmxnet3/if_vmx.c
  head/sys/dev/vmware/vmxnet3/if_vmxvar.h

Modified: head/share/man/man4/vmx.4
==============================================================================
--- head/share/man/man4/vmx.4	Fri Aug 30 05:36:29 2013	(r255054)
+++ head/share/man/man4/vmx.4	Fri Aug 30 05:53:00 2013	(r255055)
@@ -81,6 +81,25 @@ VMware Fusion 2.0 and newer
 .Pp
 For more information on configuring this device, see
 .Xr ifconfig 8 .
+.Sh LOADER TUNABLES
+Tunables can be set at the
+.Xr loader 8
+prompt before booting the kernel or stored in
+.Xr loader.conf 5 .
+.Bl -tag -width indent
+.It Va hw.vmx.txndesc
+.It Va hw.vmx. Ns Ar X Ns Va .txndesc
+.Pp
+Number of transmit descriptors allocated by the driver.
+The default value is 512.
+The value must be a multiple of 32, and the maximum is 4096.
+.It Va hw.vmx.rxndesc
+.It Va hw.vmx. Ns Ar X Ns Va .rxndesc
+.Pp
+Number of receive descriptors per ring allocated by the driver.
+The default value is 256.
+The value must be a multiple of 32, and the maximum is 2048.
+There are two rings so the actual usage is doubled.
 .Sh EXAMPLES
 The following entry must be added to the VMware configuration file
 to provide the
@@ -104,7 +123,7 @@ The
 .Nm
 driver was ported from
 .Ox
-by
+and significantly rewritten by
 .An Bryan Venteicher Aq bryanv at freebsd.org .
 The
 .Ox

Modified: head/sys/dev/vmware/vmxnet3/if_vmx.c
==============================================================================
--- head/sys/dev/vmware/vmxnet3/if_vmx.c	Fri Aug 30 05:36:29 2013	(r255054)
+++ head/sys/dev/vmware/vmxnet3/if_vmx.c	Fri Aug 30 05:53:00 2013	(r255055)
@@ -199,6 +199,8 @@ static int	vmxnet3_dma_malloc(struct vmx
 		    bus_size_t, struct vmxnet3_dma_alloc *);
 static void	vmxnet3_dma_free(struct vmxnet3_softc *,
 		    struct vmxnet3_dma_alloc *);
+static int	vmxnet3_tunable_int(struct vmxnet3_softc *,
+		    const char *, int);
 
 typedef enum {
 	VMXNET3_BARRIER_RD,
@@ -208,6 +210,12 @@ typedef enum {
 
 static void	vmxnet3_barrier(struct vmxnet3_softc *, vmxnet3_barrier_t);
 
+/* Tunables. */
+static int vmxnet3_default_txndesc = VMXNET3_DEF_TX_NDESC;
+TUNABLE_INT("hw.vmx.txndesc", &vmxnet3_default_txndesc);
+static int vmxnet3_default_rxndesc = VMXNET3_DEF_RX_NDESC;
+TUNABLE_INT("hw.vmx.rxndesc", &vmxnet3_default_rxndesc);
+
 static device_method_t vmxnet3_methods[] = {
 	/* Device interface. */
 	DEVMETHOD(device_probe,		vmxnet3_probe),
@@ -453,11 +461,28 @@ vmxnet3_check_version(struct vmxnet3_sof
 static void
 vmxnet3_initial_config(struct vmxnet3_softc *sc)
 {
+	int ndesc;
+
+	/*
+	 * BMV Much of the work is already done, but this driver does
+	 * not support multiqueue yet.
+	 */
+	sc->vmx_ntxqueues = VMXNET3_TX_QUEUES;
+	sc->vmx_nrxqueues = VMXNET3_RX_QUEUES;
 
-	sc->vmx_ntxqueues = 1;
-	sc->vmx_nrxqueues = 1;
-	sc->vmx_ntxdescs = VMXNET3_MAX_TX_NDESC;
-	sc->vmx_nrxdescs = VMXNET3_MAX_RX_NDESC;
+	ndesc = vmxnet3_tunable_int(sc, "txd", vmxnet3_default_txndesc);
+	if (ndesc > VMXNET3_MAX_TX_NDESC || ndesc < VMXNET3_MIN_TX_NDESC)
+		ndesc = VMXNET3_DEF_TX_NDESC;
+	if (ndesc & VMXNET3_MASK_TX_NDESC)
+		ndesc &= ~VMXNET3_MASK_TX_NDESC;
+	sc->vmx_ntxdescs = ndesc;
+
+	ndesc = vmxnet3_tunable_int(sc, "rxd", vmxnet3_default_rxndesc);
+	if (ndesc > VMXNET3_MAX_RX_NDESC || ndesc < VMXNET3_MIN_RX_NDESC)
+		ndesc = VMXNET3_DEF_RX_NDESC;
+	if (ndesc & VMXNET3_MASK_RX_NDESC)
+		ndesc &= ~VMXNET3_MASK_RX_NDESC;
+	sc->vmx_nrxdescs = ndesc;
 	sc->vmx_max_rxsegs = VMXNET3_MAX_RX_SEGS;
 }
 
@@ -1382,10 +1407,10 @@ vmxnet3_reinit_shared_data(struct vmxnet
 	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 | IFCAP_RXCSUM_IPV6))
 		ds->upt_features |= UPT1_F_CSUM;
+	if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
+		ds->upt_features |= UPT1_F_VLAN;
 	if (ifp->if_capenable & IFCAP_LRO)
 		ds->upt_features |= UPT1_F_LRO;
 
@@ -1464,18 +1489,13 @@ vmxnet3_setup_interface(struct vmxnet3_s
 	ifp->if_capabilities |= IFCAP_RXCSUM | IFCAP_TXCSUM;
 	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_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING |
+	    IFCAP_VLAN_HWCSUM;
 	ifp->if_capenable = ifp->if_capabilities;
 
-	/*
-	 * Capabilities after here are not enabled by default.
-	 */
-
-	ifp->if_capabilities |= IFCAP_LRO;
+	/* These capabilities are not enabled by default. */
+	ifp->if_capabilities |= IFCAP_LRO | IFCAP_VLAN_HWFILTER;
 
-	ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
 	sc->vmx_vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
 	    vmxnet3_register_vlan, sc, EVENTHANDLER_PRI_FIRST);
 	sc->vmx_vlan_detach = EVENTHANDLER_REGISTER(vlan_config,
@@ -2517,7 +2537,7 @@ vmxnet3_start_locked(struct ifnet *ifp)
 	struct vmxnet3_txqueue *txq;
 	struct vmxnet3_txring *txr;
 	struct mbuf *m_head;
-	int tx;
+	int tx, avail;
 
 	sc = ifp->if_softc;
 	txq = &sc->vmx_txq[0];
@@ -2530,11 +2550,20 @@ vmxnet3_start_locked(struct ifnet *ifp)
 	    sc->vmx_link_active == 0)
 		return;
 
-	while (VMXNET3_TXRING_AVAIL(txr) > 0) {
+	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
+		if ((avail = VMXNET3_TXRING_AVAIL(txr)) < 2)
+			break;
+
 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
 
+		/* Assume worse case if this mbuf is the head of a chain. */
+		if (m_head->m_next != NULL && avail < VMXNET3_TX_MAXSEGS) {
+			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
+			break;
+		}
+
 		if (vmxnet3_txq_encap(txq, &m_head) != 0) {
 			if (m_head != NULL)
 				IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
@@ -2752,8 +2781,8 @@ vmxnet3_ioctl(struct ifnet *ifp, u_long 
 			ifp->if_capenable ^= IFCAP_TSO6;
 
 		if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_LRO |
-		    IFCAP_VLAN_HWFILTER)) {
-			/* These Rx features require us to renegotiate. */
+		    IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWFILTER)) {
+			/* Changing these features requires us to reinit. */
 			reinit = 1;
 
 			if (mask & IFCAP_RXCSUM)
@@ -2762,6 +2791,8 @@ vmxnet3_ioctl(struct ifnet *ifp, u_long 
 				ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
 			if (mask & IFCAP_LRO)
 				ifp->if_capenable ^= IFCAP_LRO;
+			if (mask & IFCAP_VLAN_HWTAGGING)
+				ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
 			if (mask & IFCAP_VLAN_HWFILTER)
 				ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
 		} else
@@ -2769,8 +2800,6 @@ vmxnet3_ioctl(struct ifnet *ifp, u_long 
 
 		if (mask & IFCAP_VLAN_HWTSO)
 			ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
-		if (mask & IFCAP_VLAN_HWTAGGING)
-			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
 
 		if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
 			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
@@ -3282,6 +3311,18 @@ vmxnet3_dma_free(struct vmxnet3_softc *s
 	bzero(dma, sizeof(struct vmxnet3_dma_alloc));
 }
 
+static int
+vmxnet3_tunable_int(struct vmxnet3_softc *sc, const char *knob, int def)
+{
+	char path[64];
+
+	snprintf(path, sizeof(path),
+	    "hw.vmx.%d.%s", device_get_unit(sc->vmx_dev), knob);
+	TUNABLE_INT_FETCH(path, &def);
+
+	return (def);
+}
+
 /*
  * Since this is a purely paravirtualized device, we do not have
  * to worry about DMA coherency. But at times, we must make sure

Modified: head/sys/dev/vmware/vmxnet3/if_vmxvar.h
==============================================================================
--- head/sys/dev/vmware/vmxnet3/if_vmxvar.h	Fri Aug 30 05:36:29 2013	(r255054)
+++ head/sys/dev/vmware/vmxnet3/if_vmxvar.h	Fri Aug 30 05:53:00 2013	(r255055)
@@ -42,10 +42,17 @@ struct vmxnet3_dma_alloc {
 #define VMXNET3_RXRINGS_PERQ	2
 
 /*
- * The maximum number of descriptors in each Rx/Tx ring.
+ * The number of descriptors in each Rx/Tx ring.
  */
-#define VMXNET3_MAX_TX_NDESC		512
-#define VMXNET3_MAX_RX_NDESC		256
+#define VMXNET3_DEF_TX_NDESC		512
+#define VMXNET3_MAX_TX_NDESC		4096
+#define VMXNET3_MIN_TX_NDESC		32
+#define VMXNET3_MASK_TX_NDESC		0x1F
+#define VMXNET3_DEF_RX_NDESC		256
+#define VMXNET3_MAX_RX_NDESC		2048
+#define VMXNET3_MIN_RX_NDESC		32
+#define VMXNET3_MASK_RX_NDESC		0x1F
+
 #define VMXNET3_MAX_TX_NCOMPDESC	VMXNET3_MAX_TX_NDESC
 #define VMXNET3_MAX_RX_NCOMPDESC \
     (VMXNET3_MAX_RX_NDESC * VMXNET3_RXRINGS_PERQ)


More information about the svn-src-all mailing list