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
This commit is contained in:
Bryan Venteicher 2013-08-30 05:53:00 +00:00
parent 32e9219012
commit 3c5dfe892d
3 changed files with 92 additions and 25 deletions

View File

@ -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@freebsd.org .
The
.Ox

View File

@ -199,6 +199,8 @@ static int vmxnet3_dma_malloc(struct vmxnet3_softc *, bus_size_t,
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_softc *sc)
static void
vmxnet3_initial_config(struct vmxnet3_softc *sc)
{
int ndesc;
sc->vmx_ntxqueues = 1;
sc->vmx_nrxqueues = 1;
sc->vmx_ntxdescs = VMXNET3_MAX_TX_NDESC;
sc->vmx_nrxdescs = VMXNET3_MAX_RX_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;
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 vmxnet3_softc *sc)
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_softc *sc)
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.
*/
/* These capabilities are not enabled by default. */
ifp->if_capabilities |= IFCAP_LRO | IFCAP_VLAN_HWFILTER;
ifp->if_capabilities |= IFCAP_LRO;
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 cmd, caddr_t data)
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 cmd, caddr_t data)
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 cmd, caddr_t data)
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 *sc, struct vmxnet3_dma_alloc *dma)
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

View File

@ -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)