onvert vmx(4) to being an iflib driver.
Also, expose IFLIB_MAX_RX_SEGS to iflib drivers and add iflib_dma_alloc_align() to the iflib API. Performance is generally better with the tunable/sysctl dev.vmx.<index>.iflib.tx_abdicate=1. Reviewed by: shurd MFC after: 1 week Relnotes: yes Sponsored by: RG Nets Differential Revision: https://reviews.freebsd.org/D18761
This commit is contained in:
parent
727fbe43e7
commit
2dafd72cd4
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Tsubai Masanari
|
||||
* Copyright (c) 2013 Bryan Venteicher <bryanv@FreeBSD.org>
|
||||
* Copyright (c) 2018 Patrick Kelsey
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
@ -22,14 +23,6 @@
|
||||
|
||||
struct vmxnet3_softc;
|
||||
|
||||
struct vmxnet3_dma_alloc {
|
||||
bus_addr_t dma_paddr;
|
||||
caddr_t dma_vaddr;
|
||||
bus_dma_tag_t dma_tag;
|
||||
bus_dmamap_t dma_map;
|
||||
bus_size_t dma_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* The number of Rx/Tx queues this driver prefers.
|
||||
*/
|
||||
@ -57,153 +50,68 @@ struct vmxnet3_dma_alloc {
|
||||
#define VMXNET3_MAX_RX_NCOMPDESC \
|
||||
(VMXNET3_MAX_RX_NDESC * VMXNET3_RXRINGS_PERQ)
|
||||
|
||||
struct vmxnet3_txbuf {
|
||||
bus_dmamap_t vtxb_dmamap;
|
||||
struct mbuf *vtxb_m;
|
||||
};
|
||||
|
||||
struct vmxnet3_txring {
|
||||
struct vmxnet3_txbuf *vxtxr_txbuf;
|
||||
u_int vxtxr_head;
|
||||
u_int vxtxr_next;
|
||||
u_int vxtxr_ndesc;
|
||||
int vxtxr_gen;
|
||||
bus_dma_tag_t vxtxr_txtag;
|
||||
struct vmxnet3_txdesc *vxtxr_txd;
|
||||
struct vmxnet3_dma_alloc vxtxr_dma;
|
||||
};
|
||||
|
||||
static inline int
|
||||
VMXNET3_TXRING_AVAIL(struct vmxnet3_txring *txr)
|
||||
{
|
||||
int avail = txr->vxtxr_next - txr->vxtxr_head - 1;
|
||||
return (avail < 0 ? txr->vxtxr_ndesc + avail : avail);
|
||||
}
|
||||
|
||||
struct vmxnet3_rxbuf {
|
||||
bus_dmamap_t vrxb_dmamap;
|
||||
struct mbuf *vrxb_m;
|
||||
bus_addr_t vxtxr_paddr;
|
||||
};
|
||||
|
||||
struct vmxnet3_rxring {
|
||||
struct vmxnet3_rxbuf *vxrxr_rxbuf;
|
||||
struct vmxnet3_rxdesc *vxrxr_rxd;
|
||||
u_int vxrxr_fill;
|
||||
u_int vxrxr_ndesc;
|
||||
int vxrxr_gen;
|
||||
int vxrxr_rid;
|
||||
bus_dma_tag_t vxrxr_rxtag;
|
||||
struct vmxnet3_dma_alloc vxrxr_dma;
|
||||
bus_dmamap_t vxrxr_spare_dmap;
|
||||
bus_addr_t vxrxr_paddr;
|
||||
};
|
||||
|
||||
static inline void
|
||||
vmxnet3_rxr_increment_fill(struct vmxnet3_rxring *rxr)
|
||||
{
|
||||
|
||||
if (++rxr->vxrxr_fill == rxr->vxrxr_ndesc) {
|
||||
rxr->vxrxr_fill = 0;
|
||||
rxr->vxrxr_gen ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct vmxnet3_comp_ring {
|
||||
union {
|
||||
struct vmxnet3_txcompdesc *txcd;
|
||||
struct vmxnet3_rxcompdesc *rxcd;
|
||||
} vxcr_u;
|
||||
/*
|
||||
* vxcr_next is used on the transmit side to track the next index to
|
||||
* begin cleaning at. It is not used on the receive side.
|
||||
*/
|
||||
u_int vxcr_next;
|
||||
u_int vxcr_ndesc;
|
||||
int vxcr_gen;
|
||||
struct vmxnet3_dma_alloc vxcr_dma;
|
||||
};
|
||||
|
||||
struct vmxnet3_txq_stats {
|
||||
uint64_t vmtxs_opackets; /* if_opackets */
|
||||
uint64_t vmtxs_obytes; /* if_obytes */
|
||||
uint64_t vmtxs_omcasts; /* if_omcasts */
|
||||
uint64_t vmtxs_csum;
|
||||
uint64_t vmtxs_tso;
|
||||
uint64_t vmtxs_full;
|
||||
uint64_t vmtxs_offload_failed;
|
||||
bus_addr_t vxcr_paddr;
|
||||
};
|
||||
|
||||
struct vmxnet3_txqueue {
|
||||
struct mtx vxtxq_mtx;
|
||||
struct vmxnet3_softc *vxtxq_sc;
|
||||
#ifndef VMXNET3_LEGACY_TX
|
||||
struct buf_ring *vxtxq_br;
|
||||
#endif
|
||||
int vxtxq_id;
|
||||
int vxtxq_last_flush;
|
||||
int vxtxq_intr_idx;
|
||||
int vxtxq_watchdog;
|
||||
struct vmxnet3_txring vxtxq_cmd_ring;
|
||||
struct vmxnet3_comp_ring vxtxq_comp_ring;
|
||||
struct vmxnet3_txq_stats vxtxq_stats;
|
||||
struct vmxnet3_txq_shared *vxtxq_ts;
|
||||
struct sysctl_oid_list *vxtxq_sysctl;
|
||||
#ifndef VMXNET3_LEGACY_TX
|
||||
struct task vxtxq_defrtask;
|
||||
#endif
|
||||
char vxtxq_name[16];
|
||||
} __aligned(CACHE_LINE_SIZE);
|
||||
|
||||
#define VMXNET3_TXQ_LOCK(_txq) mtx_lock(&(_txq)->vxtxq_mtx)
|
||||
#define VMXNET3_TXQ_TRYLOCK(_txq) mtx_trylock(&(_txq)->vxtxq_mtx)
|
||||
#define VMXNET3_TXQ_UNLOCK(_txq) mtx_unlock(&(_txq)->vxtxq_mtx)
|
||||
#define VMXNET3_TXQ_LOCK_ASSERT(_txq) \
|
||||
mtx_assert(&(_txq)->vxtxq_mtx, MA_OWNED)
|
||||
#define VMXNET3_TXQ_LOCK_ASSERT_NOTOWNED(_txq) \
|
||||
mtx_assert(&(_txq)->vxtxq_mtx, MA_NOTOWNED)
|
||||
|
||||
struct vmxnet3_rxq_stats {
|
||||
uint64_t vmrxs_ipackets; /* if_ipackets */
|
||||
uint64_t vmrxs_ibytes; /* if_ibytes */
|
||||
uint64_t vmrxs_iqdrops; /* if_iqdrops */
|
||||
uint64_t vmrxs_ierrors; /* if_ierrors */
|
||||
};
|
||||
|
||||
struct vmxnet3_rxqueue {
|
||||
struct mtx vxrxq_mtx;
|
||||
struct vmxnet3_softc *vxrxq_sc;
|
||||
int vxrxq_id;
|
||||
int vxrxq_intr_idx;
|
||||
struct mbuf *vxrxq_mhead;
|
||||
struct mbuf *vxrxq_mtail;
|
||||
struct if_irq vxrxq_irq;
|
||||
struct vmxnet3_rxring vxrxq_cmd_ring[VMXNET3_RXRINGS_PERQ];
|
||||
struct vmxnet3_comp_ring vxrxq_comp_ring;
|
||||
struct vmxnet3_rxq_stats vxrxq_stats;
|
||||
struct vmxnet3_rxq_shared *vxrxq_rs;
|
||||
struct sysctl_oid_list *vxrxq_sysctl;
|
||||
char vxrxq_name[16];
|
||||
} __aligned(CACHE_LINE_SIZE);
|
||||
|
||||
#define VMXNET3_RXQ_LOCK(_rxq) mtx_lock(&(_rxq)->vxrxq_mtx)
|
||||
#define VMXNET3_RXQ_UNLOCK(_rxq) mtx_unlock(&(_rxq)->vxrxq_mtx)
|
||||
#define VMXNET3_RXQ_LOCK_ASSERT(_rxq) \
|
||||
mtx_assert(&(_rxq)->vxrxq_mtx, MA_OWNED)
|
||||
#define VMXNET3_RXQ_LOCK_ASSERT_NOTOWNED(_rxq) \
|
||||
mtx_assert(&(_rxq)->vxrxq_mtx, MA_NOTOWNED)
|
||||
|
||||
struct vmxnet3_statistics {
|
||||
uint32_t vmst_defragged;
|
||||
uint32_t vmst_defrag_failed;
|
||||
uint32_t vmst_mgetcl_failed;
|
||||
uint32_t vmst_mbuf_load_failed;
|
||||
};
|
||||
|
||||
struct vmxnet3_interrupt {
|
||||
struct resource *vmxi_irq;
|
||||
int vmxi_rid;
|
||||
void *vmxi_handler;
|
||||
};
|
||||
|
||||
struct vmxnet3_softc {
|
||||
device_t vmx_dev;
|
||||
if_ctx_t vmx_ctx;
|
||||
if_shared_ctx_t vmx_sctx;
|
||||
if_softc_ctx_t vmx_scctx;
|
||||
struct ifnet *vmx_ifp;
|
||||
struct vmxnet3_driver_shared *vmx_ds;
|
||||
uint32_t vmx_flags;
|
||||
#define VMXNET3_FLAG_NO_MSIX 0x0001
|
||||
#define VMXNET3_FLAG_RSS 0x0002
|
||||
|
||||
struct vmxnet3_rxqueue *vmx_rxq;
|
||||
@ -215,56 +123,24 @@ struct vmxnet3_softc {
|
||||
struct resource *vmx_res1;
|
||||
bus_space_tag_t vmx_iot1;
|
||||
bus_space_handle_t vmx_ioh1;
|
||||
struct resource *vmx_msix_res;
|
||||
|
||||
int vmx_link_active;
|
||||
int vmx_link_speed;
|
||||
int vmx_if_flags;
|
||||
int vmx_ntxqueues;
|
||||
int vmx_nrxqueues;
|
||||
int vmx_ntxdescs;
|
||||
int vmx_nrxdescs;
|
||||
int vmx_max_rxsegs;
|
||||
int vmx_rx_max_chain;
|
||||
|
||||
struct vmxnet3_statistics vmx_stats;
|
||||
|
||||
int vmx_intr_type;
|
||||
int vmx_intr_mask_mode;
|
||||
int vmx_event_intr_idx;
|
||||
int vmx_nintrs;
|
||||
struct vmxnet3_interrupt vmx_intrs[VMXNET3_MAX_INTRS];
|
||||
struct if_irq vmx_event_intr_irq;
|
||||
|
||||
struct mtx vmx_mtx;
|
||||
#ifndef VMXNET3_LEGACY_TX
|
||||
struct taskqueue *vmx_tq;
|
||||
#endif
|
||||
uint8_t *vmx_mcast;
|
||||
void *vmx_qs;
|
||||
struct vmxnet3_rss_shared *vmx_rss;
|
||||
struct callout vmx_tick;
|
||||
struct vmxnet3_dma_alloc vmx_ds_dma;
|
||||
struct vmxnet3_dma_alloc vmx_qs_dma;
|
||||
struct vmxnet3_dma_alloc vmx_mcast_dma;
|
||||
struct vmxnet3_dma_alloc vmx_rss_dma;
|
||||
struct ifmedia vmx_media;
|
||||
int vmx_max_ntxqueues;
|
||||
int vmx_max_nrxqueues;
|
||||
eventhandler_tag vmx_vlan_attach;
|
||||
eventhandler_tag vmx_vlan_detach;
|
||||
struct iflib_dma_info vmx_ds_dma;
|
||||
struct iflib_dma_info vmx_qs_dma;
|
||||
struct iflib_dma_info vmx_mcast_dma;
|
||||
struct iflib_dma_info vmx_rss_dma;
|
||||
struct ifmedia *vmx_media;
|
||||
uint32_t vmx_vlan_filter[4096/32];
|
||||
uint8_t vmx_lladdr[ETHER_ADDR_LEN];
|
||||
};
|
||||
|
||||
#define VMXNET3_CORE_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->vmx_mtx, _name, "VMXNET3 Lock", MTX_DEF)
|
||||
#define VMXNET3_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->vmx_mtx)
|
||||
#define VMXNET3_CORE_LOCK(_sc) mtx_lock(&(_sc)->vmx_mtx)
|
||||
#define VMXNET3_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->vmx_mtx)
|
||||
#define VMXNET3_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->vmx_mtx, MA_OWNED)
|
||||
#define VMXNET3_CORE_LOCK_ASSERT_NOTOWNED(_sc) \
|
||||
mtx_assert(&(_sc)->vmx_mtx, MA_NOTOWNED)
|
||||
|
||||
/*
|
||||
* Our driver version we report to the hypervisor; we just keep
|
||||
* this value constant.
|
||||
@ -275,21 +151,28 @@ 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 32
|
||||
#define VMXNET3_TX_MAXSEGS 32 /* 64K @ 2K segment size */
|
||||
#define VMXNET3_TX_MAXSIZE (VMXNET3_TX_MAXSEGS * MCLBYTES)
|
||||
#define VMXNET3_TSO_MAXSIZE (VMXNET3_TX_MAXSIZE - ETHER_VLAN_ENCAP_LEN)
|
||||
|
||||
/*
|
||||
* Maximum support Tx segments size. The length field in the
|
||||
* Maximum supported Tx segment size. The length field in the
|
||||
* Tx descriptor is 14 bits.
|
||||
*
|
||||
* XXX It's possible a descriptor length field of 0 means 2^14, but this
|
||||
* isn't confirmed, so limit to 2^14 - 1 for now.
|
||||
*/
|
||||
#define VMXNET3_TX_MAXSEGSIZE (1 << 14)
|
||||
#define VMXNET3_TX_MAXSEGSIZE ((1 << 14) - 1)
|
||||
|
||||
/*
|
||||
* The maximum number of Rx segments we accept. When LRO is enabled,
|
||||
* this allows us to receive the maximum sized frame with one MCLBYTES
|
||||
* cluster followed by 16 MJUMPAGESIZE clusters.
|
||||
* Maximum supported Rx segment size. The length field in the
|
||||
* Rx descriptor is 14 bits.
|
||||
*
|
||||
* The reference drivers skip zero-length descriptors, which seems to be a
|
||||
* strong indication that on the receive side, a descriptor length field of
|
||||
* zero does not mean 2^14.
|
||||
*/
|
||||
#define VMXNET3_MAX_RX_SEGS 17
|
||||
#define VMXNET3_RX_MAXSEGSIZE ((1 << 14) - 1)
|
||||
|
||||
/*
|
||||
* Predetermined size of the multicast MACs filter table. If the
|
||||
@ -298,17 +181,6 @@ struct vmxnet3_softc {
|
||||
*/
|
||||
#define VMXNET3_MULTICAST_MAX 32
|
||||
|
||||
/*
|
||||
* Our Tx watchdog timeout.
|
||||
*/
|
||||
#define VMXNET3_WATCHDOG_TIMEOUT 5
|
||||
|
||||
/*
|
||||
* Number of slots in the Tx bufrings. This value matches most other
|
||||
* multiqueue drivers.
|
||||
*/
|
||||
#define VMXNET3_DEF_BUFRING_SIZE 4096
|
||||
|
||||
/*
|
||||
* IP protocols that we can perform Tx checksum offloading of.
|
||||
*/
|
||||
@ -318,28 +190,4 @@ struct vmxnet3_softc {
|
||||
#define VMXNET3_CSUM_ALL_OFFLOAD \
|
||||
(VMXNET3_CSUM_OFFLOAD | VMXNET3_CSUM_OFFLOAD_IPV6 | CSUM_TSO)
|
||||
|
||||
/*
|
||||
* Compat macros to keep this driver compiling on old releases.
|
||||
*/
|
||||
|
||||
#if !defined(SYSCTL_ADD_UQUAD)
|
||||
#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD
|
||||
#endif
|
||||
|
||||
#if !defined(IFCAP_TXCSUM_IPV6)
|
||||
#define IFCAP_TXCSUM_IPV6 0
|
||||
#endif
|
||||
|
||||
#if !defined(IFCAP_RXCSUM_IPV6)
|
||||
#define IFCAP_RXCSUM_IPV6 0
|
||||
#endif
|
||||
|
||||
#if !defined(CSUM_TCP_IPV6)
|
||||
#define CSUM_TCP_IPV6 0
|
||||
#endif
|
||||
|
||||
#if !defined(CSUM_UDP_IPV6)
|
||||
#define CSUM_UDP_IPV6 0
|
||||
#endif
|
||||
|
||||
#endif /* _IF_VMXVAR_H */
|
||||
|
@ -289,8 +289,6 @@ typedef struct iflib_sw_tx_desc_array {
|
||||
|
||||
/* magic number that should be high enough for any hardware */
|
||||
#define IFLIB_MAX_TX_SEGS 128
|
||||
/* bnxt supports 64 with hardware LRO enabled */
|
||||
#define IFLIB_MAX_RX_SEGS 64
|
||||
#define IFLIB_RX_COPY_THRESH 128
|
||||
#define IFLIB_MAX_RX_REFRESH 32
|
||||
/* The minimum descriptors per second before we start coalescing */
|
||||
@ -1327,16 +1325,13 @@ _iflib_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
|
||||
}
|
||||
|
||||
int
|
||||
iflib_dma_alloc(if_ctx_t ctx, int size, iflib_dma_info_t dma, int mapflags)
|
||||
iflib_dma_alloc_align(if_ctx_t ctx, int size, int align, iflib_dma_info_t dma, int mapflags)
|
||||
{
|
||||
int err;
|
||||
if_shared_ctx_t sctx = ctx->ifc_sctx;
|
||||
device_t dev = ctx->ifc_dev;
|
||||
|
||||
KASSERT(sctx->isc_q_align != 0, ("alignment value not initialized"));
|
||||
|
||||
err = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
|
||||
sctx->isc_q_align, 0, /* alignment, bounds */
|
||||
err = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
|
||||
align, 0, /* alignment, bounds */
|
||||
BUS_SPACE_MAXADDR, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
@ -1386,6 +1381,16 @@ iflib_dma_alloc(if_ctx_t ctx, int size, iflib_dma_info_t dma, int mapflags)
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
iflib_dma_alloc(if_ctx_t ctx, int size, iflib_dma_info_t dma, int mapflags)
|
||||
{
|
||||
if_shared_ctx_t sctx = ctx->ifc_sctx;
|
||||
|
||||
KASSERT(sctx->isc_q_align != 0, ("alignment value not initialized"));
|
||||
|
||||
return (iflib_dma_alloc_align(ctx, size, sctx->isc_q_align, dma, mapflags));
|
||||
}
|
||||
|
||||
int
|
||||
iflib_dma_alloc_multi(if_ctx_t ctx, int *sizes, iflib_dma_info_t *dmalist, int mapflags, int count)
|
||||
{
|
||||
|
@ -69,6 +69,9 @@ typedef struct if_rxd_frag {
|
||||
uint16_t irf_len;
|
||||
} *if_rxd_frag_t;
|
||||
|
||||
/* bnxt supports 64 with hardware LRO enabled */
|
||||
#define IFLIB_MAX_RX_SEGS 64
|
||||
|
||||
typedef struct if_rxd_info {
|
||||
/* set by iflib */
|
||||
uint16_t iri_qsidx; /* qset index */
|
||||
@ -428,6 +431,7 @@ void iflib_iov_intr_deferred(if_ctx_t ctx);
|
||||
void iflib_link_state_change(if_ctx_t ctx, int linkstate, uint64_t baudrate);
|
||||
|
||||
int iflib_dma_alloc(if_ctx_t ctx, int size, iflib_dma_info_t dma, int mapflags);
|
||||
int iflib_dma_alloc_align(if_ctx_t ctx, int size, int align, iflib_dma_info_t dma, int mapflags);
|
||||
void iflib_dma_free(iflib_dma_info_t dma);
|
||||
|
||||
int iflib_dma_alloc_multi(if_ctx_t ctx, int *sizes, iflib_dma_info_t *dmalist, int mapflags, int count);
|
||||
|
Loading…
Reference in New Issue
Block a user