#ifndef _SFXGE_TX_H
#define _SFXGE_TX_H
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define SFXGE_TX_PARSE_EARLY 1
#define SFXGE_TSO_MAX_SIZE (65535)
#define SFXGE_TSO_MAX_SEGS howmany(SFXGE_TSO_MAX_SIZE, 512)
#define SFXGE_TX_MAPPING_MAX_SEG \
(2 + howmany(SFXGE_TSO_MAX_SIZE, MCLBYTES) + 1)
enum sfxge_tx_buf_flags {
TX_BUF_UNMAP = 1,
TX_BUF_MBUF = 2,
};
struct sfxge_tx_mapping {
union {
struct mbuf *mbuf;
caddr_t heap_buf;
} u;
bus_dmamap_t map;
enum sfxge_tx_buf_flags flags;
};
#define SFXGE_TX_DPL_GET_PKT_LIMIT_DEFAULT (64 * 1024)
#define SFXGE_TX_DPL_GET_NON_TCP_PKT_LIMIT_DEFAULT 1024
#define SFXGE_TX_DPL_PUT_PKT_LIMIT_DEFAULT 1024
struct sfxge_tx_dpl {
unsigned int std_get_max;
unsigned int std_get_non_tcp_max;
unsigned int std_put_max;
uintptr_t std_put;
struct mbuf *std_get;
struct mbuf **std_getp;
unsigned int std_get_count;
unsigned int std_get_non_tcp_count;
unsigned int std_get_hiwat;
unsigned int std_put_hiwat;
};
#define SFXGE_TX_BUFFER_SIZE 0x400
#define SFXGE_TX_HEADER_SIZE 0x100
#define SFXGE_TX_COPY_THRESHOLD 0x200
enum sfxge_txq_state {
SFXGE_TXQ_UNINITIALIZED = 0,
SFXGE_TXQ_INITIALIZED,
SFXGE_TXQ_STARTED
};
enum sfxge_txq_type {
SFXGE_TXQ_NON_CKSUM = 0,
SFXGE_TXQ_IP_CKSUM,
SFXGE_TXQ_IP_TCP_UDP_CKSUM,
SFXGE_TXQ_NTYPES
};
#define SFXGE_EVQ0_N_TXQ(_sc) \
((_sc)->txq_dynamic_cksum_toggle_supported ? \
1 : SFXGE_TXQ_NTYPES)
#define SFXGE_TXQ_UNBLOCK_LEVEL(_entries) (EFX_TXQ_LIMIT(_entries) / 4)
#define SFXGE_TX_BATCH 64
#define SFXGE_TXQ_LOCK_INIT(_txq, _ifname, _txq_index) \
do { \
struct sfxge_txq *__txq = (_txq); \
\
snprintf((__txq)->lock_name, \
sizeof((__txq)->lock_name), \
"%s:txq%u", (_ifname), (_txq_index)); \
mtx_init(&(__txq)->lock, (__txq)->lock_name, \
NULL, MTX_DEF); \
} while (B_FALSE)
#define SFXGE_TXQ_LOCK_DESTROY(_txq) \
mtx_destroy(&(_txq)->lock)
#define SFXGE_TXQ_LOCK(_txq) \
mtx_lock(&(_txq)->lock)
#define SFXGE_TXQ_TRYLOCK(_txq) \
mtx_trylock(&(_txq)->lock)
#define SFXGE_TXQ_UNLOCK(_txq) \
mtx_unlock(&(_txq)->lock)
#define SFXGE_TXQ_LOCK_ASSERT_OWNED(_txq) \
mtx_assert(&(_txq)->lock, MA_OWNED)
#define SFXGE_TXQ_LOCK_ASSERT_NOTOWNED(_txq) \
mtx_assert(&(_txq)->lock, MA_NOTOWNED)
struct sfxge_txq {
struct sfxge_softc *sc;
enum sfxge_txq_state init_state;
enum sfxge_flush_state flush_state;
unsigned int tso_fw_assisted;
enum sfxge_txq_type type;
unsigned int evq_index;
efsys_mem_t mem;
unsigned int buf_base_id;
unsigned int entries;
unsigned int ptr_mask;
unsigned int max_pkt_desc;
struct sfxge_tx_mapping *stmp;
bus_dma_tag_t packet_dma_tag;
efx_desc_t *pend_desc;
efx_txq_t *common;
efsys_mem_t *tsoh_buffer;
char lock_name[SFXGE_LOCK_NAME_MAX];
int blocked __aligned(CACHE_LINE_SIZE);
struct mtx lock __aligned(CACHE_LINE_SIZE);
struct sfxge_tx_dpl dpl;
unsigned int n_pend_desc;
unsigned int added;
unsigned int reaped;
uint16_t hw_cksum_flags;
uint16_t hw_vlan_tci;
unsigned long tso_bursts;
unsigned long tso_packets;
unsigned long tso_long_headers;
unsigned long collapses;
unsigned long drops;
unsigned long get_overflow;
unsigned long get_non_tcp_overflow;
unsigned long put_overflow;
unsigned long netdown_drops;
unsigned long tso_pdrop_too_many;
unsigned long tso_pdrop_no_rsrc;
unsigned int pending __aligned(CACHE_LINE_SIZE);
unsigned int completed;
struct sfxge_txq *next;
};
struct sfxge_evq;
extern uint64_t sfxge_tx_get_drops(struct sfxge_softc *sc);
extern int sfxge_tx_init(struct sfxge_softc *sc);
extern void sfxge_tx_fini(struct sfxge_softc *sc);
extern int sfxge_tx_start(struct sfxge_softc *sc);
extern void sfxge_tx_stop(struct sfxge_softc *sc);
extern void sfxge_tx_qcomplete(struct sfxge_txq *txq, struct sfxge_evq *evq);
extern void sfxge_tx_qflush_done(struct sfxge_txq *txq);
extern void sfxge_if_qflush(if_t ifp);
extern int sfxge_if_transmit(if_t ifp, struct mbuf *m);
#endif