root/sys/dev/hyperv/netvsc/if_hnvar.h
/*-
 * Copyright (c) 2016-2017 Microsoft Corp.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _IF_HNVAR_H_
#define _IF_HNVAR_H_

#define HN_USE_TXDESC_BUFRING

#define HN_CHIM_SIZE                    (15 * 1024 * 1024)

#define HN_RXBUF_SIZE                   (31 * 1024 * 1024)
#define HN_RXBUF_SIZE_COMPAT            (15 * 1024 * 1024)

#define HN_MTU_MAX                      (65535 - ETHER_ADDR_LEN)

#define HN_TXBR_SIZE                    (128 * PAGE_SIZE)
#define HN_RXBR_SIZE                    (128 * PAGE_SIZE)

#define HN_XACT_REQ_PGCNT               2
#define HN_XACT_RESP_PGCNT              2
#define HN_XACT_REQ_SIZE                (HN_XACT_REQ_PGCNT * PAGE_SIZE)
#define HN_XACT_RESP_SIZE               (HN_XACT_RESP_PGCNT * PAGE_SIZE)

#define HN_GPACNT_MAX                   32

struct hn_txdesc;
#ifndef HN_USE_TXDESC_BUFRING
SLIST_HEAD(hn_txdesc_list, hn_txdesc);
#else
struct buf_ring;
#endif
struct hn_tx_ring;

#define HN_NVS_RSC_MAX          562     /* Max RSC frags in one vmbus packet */

struct hn_rx_rsc {
        const uint32_t          *vlan_info;
        const uint32_t          *csum_info;
        const uint32_t          *hash_info;
        const uint32_t          *hash_value;
        uint32_t                cnt;            /* fragment count */
        uint32_t                pktlen;         /* full packet length */
        uint8_t                 is_last;        /* last fragment */
        const void              *frag_data[HN_NVS_RSC_MAX];
        uint32_t                frag_len[HN_NVS_RSC_MAX];
};

struct hn_rx_ring {
        if_t            hn_ifp;
        if_t            hn_rxvf_ifp;    /* SR-IOV VF for RX */
        struct hn_tx_ring *hn_txr;
        void            *hn_pktbuf;
        int             hn_pktbuf_len;
        int             hn_rx_flags;    /* HN_RX_FLAG_ */
        uint32_t        hn_mbuf_hash;   /* NDIS_HASH_ */
        uint8_t         *hn_rxbuf;      /* shadow sc->hn_rxbuf */
        int             hn_rx_idx;
        struct hn_rx_rsc rsc;

        /* Trust csum verification on host side */
        int             hn_trust_hcsum; /* HN_TRUST_HCSUM_ */
        struct lro_ctrl hn_lro;

        u_long          hn_csum_ip;
        u_long          hn_csum_tcp;
        u_long          hn_csum_udp;
        u_long          hn_csum_trusted;
        u_long          hn_lro_tried;
        u_long          hn_small_pkts;
        u_long          hn_pkts;
        u_long          hn_rss_pkts;
        u_long          hn_ack_failed;
        u_long          hn_rsc_pkts;
        u_long          hn_rsc_drop;

        /* Rarely used stuffs */
        struct sysctl_oid *hn_rx_sysctl_tree;

        void            *hn_br;         /* TX/RX bufring */

        struct vmbus_channel *hn_chan;
} __aligned(CACHE_LINE_SIZE);

#define HN_TRUST_HCSUM_IP       0x0001
#define HN_TRUST_HCSUM_TCP      0x0002
#define HN_TRUST_HCSUM_UDP      0x0004

#define HN_RX_FLAG_ATTACHED     0x0001
#define HN_RX_FLAG_BR_REF       0x0002
#define HN_RX_FLAG_XPNT_VF      0x0004
#define HN_RX_FLAG_UDP_HASH     0x0008

struct hn_tx_ring {
#ifndef HN_USE_TXDESC_BUFRING
        struct mtx      hn_txlist_spin;
        struct hn_txdesc_list hn_txlist;
#else
        struct buf_ring *hn_txdesc_br;
#endif
        int             hn_txdesc_cnt;
        int             hn_txdesc_avail;
        u_short         hn_has_txeof;
        u_short         hn_txdone_cnt;

        int             hn_sched_tx;
        void            (*hn_txeof)(struct hn_tx_ring *);
        struct taskqueue *hn_tx_taskq;
        struct task     hn_tx_task;
        struct task     hn_txeof_task;

        struct buf_ring *hn_mbuf_br;
        int             hn_oactive;
        int             hn_tx_idx;
        int             hn_tx_flags;

        struct mtx      hn_tx_lock;
        struct hn_softc *hn_sc;
        struct vmbus_channel *hn_chan;

        int             hn_direct_tx_size;
        int             hn_chim_size;
        bus_dma_tag_t   hn_tx_data_dtag;
        uint64_t        hn_csum_assist;

        /* Applied packet transmission aggregation limits. */
        int             hn_agg_szmax;
        short           hn_agg_pktmax;
        short           hn_agg_align;

        /* Packet transmission aggregation states. */
        struct hn_txdesc *hn_agg_txd;
        int             hn_agg_szleft;
        short           hn_agg_pktleft;
        struct rndis_packet_msg *hn_agg_prevpkt;

        /* Temporary stats for each sends. */
        int             hn_stat_size;
        short           hn_stat_pkts;
        short           hn_stat_mcasts;

        int             (*hn_sendpkt)(struct hn_tx_ring *, struct hn_txdesc *);
        int             hn_suspended;
        int             hn_gpa_cnt;
        struct vmbus_gpa hn_gpa[HN_GPACNT_MAX];

        u_long          hn_no_txdescs;
        u_long          hn_send_failed;
        u_long          hn_txdma_failed;
        u_long          hn_tx_collapsed;
        u_long          hn_tx_chimney_tried;
        u_long          hn_tx_chimney;
        u_long          hn_pkts;
        u_long          hn_sends;
        u_long          hn_flush_failed;

        /* Rarely used stuffs */
        struct hn_txdesc *hn_txdesc;
        bus_dma_tag_t   hn_tx_rndis_dtag;
        struct sysctl_oid *hn_tx_sysctl_tree;
} __aligned(CACHE_LINE_SIZE);

#define HN_TX_FLAG_ATTACHED     0x0001
#define HN_TX_FLAG_HASHVAL      0x0002  /* support HASHVAL pktinfo */

/*
 * Device-specific softc structure
 */
struct hn_softc {
        if_t            hn_ifp;
        struct ifmedia  hn_media;
        device_t        hn_dev;
        int             hn_if_flags;
        struct sx       hn_lock;
        struct vmbus_channel *hn_prichan;

        int             hn_rx_ring_cnt;
        int             hn_rx_ring_inuse;
        struct hn_rx_ring *hn_rx_ring;

        struct rmlock   hn_vf_lock;
        if_t            hn_vf_ifp;      /* SR-IOV VF */
        uint32_t        hn_xvf_flags;   /* transparent VF flags */

        int             hn_tx_ring_cnt;
        int             hn_tx_ring_inuse;
        struct hn_tx_ring *hn_tx_ring;

        uint8_t         *hn_chim;
        u_long          *hn_chim_bmap;
        int             hn_chim_bmap_cnt;
        int             hn_chim_cnt;
        int             hn_chim_szmax;

        int             hn_cpu;
        struct taskqueue **hn_tx_taskqs;
        struct sysctl_oid *hn_tx_sysctl_tree;
        struct sysctl_oid *hn_rx_sysctl_tree;
        struct vmbus_xact_ctx *hn_xact;
        uint32_t        hn_nvs_ver;
        uint32_t        hn_rx_filter;

        /* Packet transmission aggregation user settings. */
        int                     hn_agg_size;
        int                     hn_agg_pkts;

        struct taskqueue        *hn_mgmt_taskq;
        struct taskqueue        *hn_mgmt_taskq0;
        struct task             hn_link_task;
        struct task             hn_netchg_init;
        struct timeout_task     hn_netchg_status;
        uint32_t                hn_link_flags;  /* HN_LINK_FLAG_ */

        uint32_t                hn_caps;        /* HN_CAP_ */
        uint32_t                hn_flags;       /* HN_FLAG_ */
        u_int                   hn_pollhz;

        void                    *hn_rxbuf;
        uint32_t                hn_rxbuf_gpadl;

        uint32_t                hn_chim_gpadl;

        uint32_t                hn_rndis_rid;
        uint32_t                hn_ndis_ver;
        int                     hn_ndis_tso_szmax;
        int                     hn_ndis_tso_sgmin;
        uint32_t                hn_rndis_agg_size;
        uint32_t                hn_rndis_agg_pkts;
        uint32_t                hn_rndis_agg_align;

        int                     hn_rss_ind_size;
        uint32_t                hn_rss_hash;    /* setting, NDIS_HASH_ */
        uint32_t                hn_rss_hcap;    /* caps, NDIS_HASH_ */
        struct ndis_rssprm_toeplitz hn_rss;

        eventhandler_tag        hn_ifaddr_evthand;
        eventhandler_tag        hn_ifnet_evthand;
        eventhandler_tag        hn_ifnet_atthand;
        eventhandler_tag        hn_ifnet_dethand;
        eventhandler_tag        hn_ifnet_lnkhand;

        /*
         * Transparent VF delayed initialization.
         */
        int                     hn_vf_rdytick;  /* ticks, 0 == ready */
        struct taskqueue        *hn_vf_taskq;
        struct timeout_task     hn_vf_init;

        /*
         * Saved information for VF under transparent mode.
         */
        void                    (*hn_vf_input)
                                (if_t, struct mbuf *);
        int                     hn_saved_caps;
        u_int                   hn_saved_tsomax;
        u_int                   hn_saved_tsosegcnt;
        u_int                   hn_saved_tsosegsz;
        u_int                   hn_saved_capenable;
        u_int                   hn_saved_hwassist;

        /*
         * RSC switch, default off
         */
        u_int                   hn_rsc_ctrl;
};

#define HN_FLAG_RXBUF_CONNECTED         0x0001
#define HN_FLAG_CHIM_CONNECTED          0x0002
#define HN_FLAG_HAS_RSSKEY              0x0004
#define HN_FLAG_HAS_RSSIND              0x0008
#define HN_FLAG_SYNTH_ATTACHED          0x0010
#define HN_FLAG_NO_SLEEPING             0x0020
#define HN_FLAG_RXBUF_REF               0x0040
#define HN_FLAG_CHIM_REF                0x0080
#define HN_FLAG_RXVF                    0x0100

#define HN_FLAG_ERRORS                  (HN_FLAG_RXBUF_REF | HN_FLAG_CHIM_REF)

#define HN_XVFFLAG_ENABLED              0x0001
#define HN_XVFFLAG_ACCBPF               0x0002

#define HN_NO_SLEEPING(sc)                      \
do {                                            \
        (sc)->hn_flags |= HN_FLAG_NO_SLEEPING;  \
} while (0)

#define HN_SLEEPING_OK(sc)                      \
do {                                            \
        (sc)->hn_flags &= ~HN_FLAG_NO_SLEEPING; \
} while (0)

#define HN_CAN_SLEEP(sc)                \
        (((sc)->hn_flags & HN_FLAG_NO_SLEEPING) == 0)

#define HN_CAP_VLAN                     0x0001
#define HN_CAP_MTU                      0x0002
#define HN_CAP_IPCS                     0x0004
#define HN_CAP_TCP4CS                   0x0008
#define HN_CAP_TCP6CS                   0x0010
#define HN_CAP_UDP4CS                   0x0020
#define HN_CAP_UDP6CS                   0x0040
#define HN_CAP_TSO4                     0x0080
#define HN_CAP_TSO6                     0x0100
#define HN_CAP_HASHVAL                  0x0200
#define HN_CAP_UDPHASH                  0x0400

/* Capability description for use with printf(9) %b identifier. */
#define HN_CAP_BITS                             \
        "\020\1VLAN\2MTU\3IPCS\4TCP4CS\5TCP6CS" \
        "\6UDP4CS\7UDP6CS\10TSO4\11TSO6\12HASHVAL\13UDPHASH"

#define HN_LINK_FLAG_LINKUP             0x0001
#define HN_LINK_FLAG_NETCHG             0x0002

#endif  /* !_IF_HNVAR_H_ */