root/sys/dev/virtual/vmware/vmxnet3/if_vmxvar.h
/*-
 * Copyright (c) 2013 Tsubai Masanari
 * Copyright (c) 2013 Bryan Venteicher <bryanv@FreeBSD.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * $FreeBSD: head/sys/dev/vmware/vmxnet3/if_vmxvar.h 313911 2017-02-18 06:18:14Z loos $
 */

#ifndef _IF_VMXVAR_H
#define _IF_VMXVAR_H

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.
 */
#define VMXNET3_DEF_RX_QUEUES   8
#define VMXNET3_DEF_TX_QUEUES   8

/*
 * The number of Rx rings in each Rx queue.
 */
#define VMXNET3_RXRINGS_PERQ    2

/*
 * The number of descriptors in each Rx/Tx ring.
 */
#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)

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;
};

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;
};

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;
        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;
};

struct vmxnet3_txqueue {
        struct lock                      vxtxq_lock;
        struct vmxnet3_softc            *vxtxq_sc;
#ifndef VMXNET3_LEGACY_TX
        struct buf_ring                 *vxtxq_br;
#endif
        int                              vxtxq_id;
        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];
} __cachealign;

#define VMXNET3_TXQ_LOCK(_txq)          lockmgr(&(_txq)->vxtxq_lock, LK_EXCLUSIVE)
#define VMXNET3_TXQ_TRYLOCK(_txq)       lockmgr_try(&(_txq)->vxtxq_lock, LK_EXCLUSIVE)
#define VMXNET3_TXQ_UNLOCK(_txq)        lockmgr(&(_txq)->vxtxq_lock, LK_RELEASE)
#define VMXNET3_TXQ_LOCK_ASSERT(_txq)           \
    KKASSERT(lockowned(&(_txq)->vxtxq_lock) != 0)
#define VMXNET3_TXQ_LOCK_ASSERT_NOTOWNED(_txq)  \
    KKASSERT(lockowned(&(_txq)->vxtxq_lock) == 0)

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 lock                      vxrxq_lock;
        struct vmxnet3_softc            *vxrxq_sc;
        int                              vxrxq_id;
        int                              vxrxq_intr_idx;
        struct mbuf                     *vxrxq_mhead;
        struct mbuf                     *vxrxq_mtail;
        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];
} __cachealign;

#define VMXNET3_RXQ_LOCK(_rxq)          lockmgr(&(_rxq)->vxrxq_lock, LK_EXCLUSIVE)
#define VMXNET3_RXQ_UNLOCK(_rxq)        lockmgr(&(_rxq)->vxrxq_lock, LK_RELEASE)
#define VMXNET3_RXQ_LOCK_ASSERT(_rxq)           \
    KKASSERT(lockowned(&(_rxq)->vxrxq_lock) != 0)
#define VMXNET3_RXQ_LOCK_ASSERT_NOTOWNED(_rxq)  \
    KKASSERT(lockowned(&(_rxq)->vxrxq_lock) == 0)

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;
        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;
        struct vmxnet3_txqueue          *vmx_txq;

        struct resource                 *vmx_res0;
        bus_space_tag_t                  vmx_iot0;
        bus_space_handle_t               vmx_ioh0;
        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_irq_type;
        u_int                            vmx_irq_flags;

        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 lock                      vmx_lock;
#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;
        uint32_t                         vmx_vlan_filter[4096/32];
        uint8_t                          vmx_lladdr[ETHER_ADDR_LEN];
};

#define VMXNET3_CORE_LOCK_INIT(_sc, _name) \
    lockinit(&(_sc)->vmx_lock, "VMXNET3 Lock", 0, 0)
#define VMXNET3_CORE_LOCK_DESTROY(_sc)  lockuninit(&(_sc)->vmx_lock)
#define VMXNET3_CORE_LOCK(_sc)          lockmgr(&(_sc)->vmx_lock, LK_EXCLUSIVE)
#define VMXNET3_CORE_UNLOCK(_sc)        lockmgr(&(_sc)->vmx_lock, LK_RELEASE)
#define VMXNET3_CORE_LOCK_ASSERT(_sc)   KKASSERT(lockowned(&(_sc)->vmx_lock) != 0)
#define VMXNET3_CORE_LOCK_ASSERT_NOTOWNED(_sc) \
    KKASSERT(lockowned(&(_sc)->vmx_lock) == 0)

/*
 * Our driver version we report to the hypervisor; we just keep
 * this value constant.
 */
#define VMXNET3_DRIVER_VERSION 0x00010000

/*
 * 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_MAXSIZE              (VMXNET3_TX_MAXSEGS * MCLBYTES)

/*
 * Maximum support Tx segments size. The length field in the
 * Tx descriptor is 14 bits.
 */
#define VMXNET3_TX_MAXSEGSIZE           (1 << 14)

/*
 * 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.
 */
#define VMXNET3_MAX_RX_SEGS             17

/*
 * 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.
 */
#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.
 */
#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)

/*
 * 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 */