1e948693eSPhilip Paeps /*- 2e948693eSPhilip Paeps * Copyright (c) 2010-2011 Solarflare Communications, Inc. 3e948693eSPhilip Paeps * All rights reserved. 4e948693eSPhilip Paeps * 5e948693eSPhilip Paeps * This software was developed in part by Philip Paeps under contract for 6e948693eSPhilip Paeps * Solarflare Communications, Inc. 7e948693eSPhilip Paeps * 8e948693eSPhilip Paeps * Redistribution and use in source and binary forms, with or without 9e948693eSPhilip Paeps * modification, are permitted provided that the following conditions 10e948693eSPhilip Paeps * are met: 11e948693eSPhilip Paeps * 1. Redistributions of source code must retain the above copyright 12e948693eSPhilip Paeps * notice, this list of conditions and the following disclaimer. 13e948693eSPhilip Paeps * 2. Redistributions in binary form must reproduce the above copyright 14e948693eSPhilip Paeps * notice, this list of conditions and the following disclaimer in the 15e948693eSPhilip Paeps * documentation and/or other materials provided with the distribution. 16e948693eSPhilip Paeps * 17e948693eSPhilip Paeps * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18e948693eSPhilip Paeps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19e948693eSPhilip Paeps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20e948693eSPhilip Paeps * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21e948693eSPhilip Paeps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22e948693eSPhilip Paeps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23e948693eSPhilip Paeps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24e948693eSPhilip Paeps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25e948693eSPhilip Paeps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26e948693eSPhilip Paeps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27e948693eSPhilip Paeps * SUCH DAMAGE. 28e948693eSPhilip Paeps * 29e948693eSPhilip Paeps * $FreeBSD$ 30e948693eSPhilip Paeps */ 31e948693eSPhilip Paeps 32e948693eSPhilip Paeps #ifndef _SFXGE_TX_H 33e948693eSPhilip Paeps #define _SFXGE_TX_H 34e948693eSPhilip Paeps 35e948693eSPhilip Paeps #include <netinet/in.h> 36e948693eSPhilip Paeps #include <netinet/ip.h> 37e948693eSPhilip Paeps #include <netinet/tcp.h> 38e948693eSPhilip Paeps 3945923e76SAndrew Rybchenko /* Maximum size of TSO packet */ 4045923e76SAndrew Rybchenko #define SFXGE_TSO_MAX_SIZE (65535) 4145923e76SAndrew Rybchenko 4245923e76SAndrew Rybchenko /* 4345923e76SAndrew Rybchenko * Maximum number of segments to be created for a TSO packet. 4445923e76SAndrew Rybchenko * Allow for a reasonable minimum MSS of 512. 4545923e76SAndrew Rybchenko */ 4645923e76SAndrew Rybchenko #define SFXGE_TSO_MAX_SEGS howmany(SFXGE_TSO_MAX_SIZE, 512) 4745923e76SAndrew Rybchenko 48e948693eSPhilip Paeps /* Maximum number of DMA segments needed to map an mbuf chain. With 49e948693eSPhilip Paeps * TSO, the mbuf length may be just over 64K, divided into 2K mbuf 50e948693eSPhilip Paeps * clusters. (The chain could be longer than this initially, but can 51e948693eSPhilip Paeps * be shortened with m_collapse().) 52e948693eSPhilip Paeps */ 5345923e76SAndrew Rybchenko #define SFXGE_TX_MAPPING_MAX_SEG \ 5445923e76SAndrew Rybchenko (1 + howmany(SFXGE_TSO_MAX_SIZE, MCLBYTES)) 55e948693eSPhilip Paeps 56e948693eSPhilip Paeps /* 57e948693eSPhilip Paeps * Buffer mapping flags. 58e948693eSPhilip Paeps * 59e948693eSPhilip Paeps * Buffers and DMA mappings must be freed when the last descriptor 60e948693eSPhilip Paeps * referring to them is completed. Set the TX_BUF_UNMAP and 61e948693eSPhilip Paeps * TX_BUF_MBUF flags on the last descriptor generated for an mbuf 62e948693eSPhilip Paeps * chain. Set only the TX_BUF_UNMAP flag on a descriptor referring to 63e948693eSPhilip Paeps * a heap buffer. 64e948693eSPhilip Paeps */ 65e948693eSPhilip Paeps enum sfxge_tx_buf_flags { 66e948693eSPhilip Paeps TX_BUF_UNMAP = 1, 67e948693eSPhilip Paeps TX_BUF_MBUF = 2, 68e948693eSPhilip Paeps }; 69e948693eSPhilip Paeps 70e948693eSPhilip Paeps /* 71e948693eSPhilip Paeps * Buffer mapping information for descriptors in flight. 72e948693eSPhilip Paeps */ 73e948693eSPhilip Paeps struct sfxge_tx_mapping { 74e948693eSPhilip Paeps union { 75e948693eSPhilip Paeps struct mbuf *mbuf; 76e948693eSPhilip Paeps caddr_t heap_buf; 77e948693eSPhilip Paeps } u; 78e948693eSPhilip Paeps bus_dmamap_t map; 79e948693eSPhilip Paeps enum sfxge_tx_buf_flags flags; 80e948693eSPhilip Paeps }; 81e948693eSPhilip Paeps 8293929f25SAndrew Rybchenko #define SFXGE_TX_DPL_GET_PKT_LIMIT_DEFAULT (64 * 1024) 8393929f25SAndrew Rybchenko #define SFXGE_TX_DPL_GET_NON_TCP_PKT_LIMIT_DEFAULT 1024 8422ff426cSAndrew Rybchenko #define SFXGE_TX_DPL_PUT_PKT_LIMIT_DEFAULT 1024 85e948693eSPhilip Paeps 86e948693eSPhilip Paeps /* 87e948693eSPhilip Paeps * Deferred packet list. 88e948693eSPhilip Paeps */ 89e948693eSPhilip Paeps struct sfxge_tx_dpl { 90060a95efSGeorge V. Neville-Neil unsigned int std_get_max; /* Maximum number of packets 91060a95efSGeorge V. Neville-Neil * in get list */ 9293929f25SAndrew Rybchenko unsigned int std_get_non_tcp_max; /* Maximum number 9393929f25SAndrew Rybchenko * of non-TCP packets 9493929f25SAndrew Rybchenko * in get list */ 95060a95efSGeorge V. Neville-Neil unsigned int std_put_max; /* Maximum number of packets 96060a95efSGeorge V. Neville-Neil * in put list */ 97e948693eSPhilip Paeps uintptr_t std_put; /* Head of put list. */ 98e948693eSPhilip Paeps struct mbuf *std_get; /* Head of get list. */ 99e948693eSPhilip Paeps struct mbuf **std_getp; /* Tail of get list. */ 100bc85c897SGeorge V. Neville-Neil unsigned int std_get_count; /* Packets in get list. */ 10193929f25SAndrew Rybchenko unsigned int std_get_non_tcp_count; /* Non-TCP packets 10293929f25SAndrew Rybchenko * in get list */ 10393929f25SAndrew Rybchenko unsigned int std_get_hiwat; /* Packets in get list 10493929f25SAndrew Rybchenko * high watermark */ 105bce6d281SAndrew Rybchenko unsigned int std_put_hiwat; /* Packets in put list 106bce6d281SAndrew Rybchenko * high watermark */ 107e948693eSPhilip Paeps }; 108e948693eSPhilip Paeps 109e948693eSPhilip Paeps 110e948693eSPhilip Paeps #define SFXGE_TX_BUFFER_SIZE 0x400 111e948693eSPhilip Paeps #define SFXGE_TX_HEADER_SIZE 0x100 112e948693eSPhilip Paeps #define SFXGE_TX_COPY_THRESHOLD 0x200 113e948693eSPhilip Paeps 114e948693eSPhilip Paeps enum sfxge_txq_state { 115e948693eSPhilip Paeps SFXGE_TXQ_UNINITIALIZED = 0, 116e948693eSPhilip Paeps SFXGE_TXQ_INITIALIZED, 117e948693eSPhilip Paeps SFXGE_TXQ_STARTED 118e948693eSPhilip Paeps }; 119e948693eSPhilip Paeps 120e948693eSPhilip Paeps enum sfxge_txq_type { 121e948693eSPhilip Paeps SFXGE_TXQ_NON_CKSUM = 0, 122e948693eSPhilip Paeps SFXGE_TXQ_IP_CKSUM, 123e948693eSPhilip Paeps SFXGE_TXQ_IP_TCP_UDP_CKSUM, 124e948693eSPhilip Paeps SFXGE_TXQ_NTYPES 125e948693eSPhilip Paeps }; 126e948693eSPhilip Paeps 127385b1d8eSGeorge V. Neville-Neil #define SFXGE_TXQ_UNBLOCK_LEVEL(_entries) (EFX_TXQ_LIMIT(_entries) / 4) 128e948693eSPhilip Paeps 129e948693eSPhilip Paeps #define SFXGE_TX_BATCH 64 130e948693eSPhilip Paeps 13133d45dc5SAndrew Rybchenko #define SFXGE_TXQ_LOCK_INIT(_txq, _ifname, _txq_index) \ 13233d45dc5SAndrew Rybchenko do { \ 13333d45dc5SAndrew Rybchenko struct sfxge_txq *__txq = (_txq); \ 13433d45dc5SAndrew Rybchenko \ 13533d45dc5SAndrew Rybchenko snprintf((__txq)->lock_name, \ 13633d45dc5SAndrew Rybchenko sizeof((__txq)->lock_name), \ 13733d45dc5SAndrew Rybchenko "%s:txq%u", (_ifname), (_txq_index)); \ 13833d45dc5SAndrew Rybchenko mtx_init(&(__txq)->lock, (__txq)->lock_name, \ 13933d45dc5SAndrew Rybchenko NULL, MTX_DEF); \ 14033d45dc5SAndrew Rybchenko } while (B_FALSE) 141763cab71SAndrew Rybchenko #define SFXGE_TXQ_LOCK_DESTROY(_txq) \ 142763cab71SAndrew Rybchenko mtx_destroy(&(_txq)->lock) 143763cab71SAndrew Rybchenko #define SFXGE_TXQ_LOCK(_txq) \ 144*a411fe4eSAndrew Rybchenko mtx_lock(&(_txq)->lock) 145763cab71SAndrew Rybchenko #define SFXGE_TXQ_TRYLOCK(_txq) \ 146*a411fe4eSAndrew Rybchenko mtx_trylock(&(_txq)->lock) 147763cab71SAndrew Rybchenko #define SFXGE_TXQ_UNLOCK(_txq) \ 148*a411fe4eSAndrew Rybchenko mtx_unlock(&(_txq)->lock) 149763cab71SAndrew Rybchenko #define SFXGE_TXQ_LOCK_ASSERT_OWNED(_txq) \ 150*a411fe4eSAndrew Rybchenko mtx_assert(&(_txq)->lock, MA_OWNED) 151763cab71SAndrew Rybchenko 152763cab71SAndrew Rybchenko 153e948693eSPhilip Paeps struct sfxge_txq { 154e948693eSPhilip Paeps /* The following fields should be written very rarely */ 155e948693eSPhilip Paeps struct sfxge_softc *sc; 156e948693eSPhilip Paeps enum sfxge_txq_state init_state; 157e948693eSPhilip Paeps enum sfxge_flush_state flush_state; 158e948693eSPhilip Paeps enum sfxge_txq_type type; 159e948693eSPhilip Paeps unsigned int txq_index; 160e948693eSPhilip Paeps unsigned int evq_index; 161e948693eSPhilip Paeps efsys_mem_t mem; 162e948693eSPhilip Paeps unsigned int buf_base_id; 163385b1d8eSGeorge V. Neville-Neil unsigned int entries; 164385b1d8eSGeorge V. Neville-Neil unsigned int ptr_mask; 165e948693eSPhilip Paeps 166e948693eSPhilip Paeps struct sfxge_tx_mapping *stmp; /* Packets in flight. */ 167e948693eSPhilip Paeps bus_dma_tag_t packet_dma_tag; 168e948693eSPhilip Paeps efx_buffer_t *pend_desc; 169e948693eSPhilip Paeps efx_txq_t *common; 170e948693eSPhilip Paeps 171e948693eSPhilip Paeps efsys_mem_t *tsoh_buffer; 172e948693eSPhilip Paeps 17333d45dc5SAndrew Rybchenko char lock_name[SFXGE_LOCK_NAME_MAX]; 17433d45dc5SAndrew Rybchenko 175e948693eSPhilip Paeps /* This field changes more often and is read regularly on both 176e948693eSPhilip Paeps * the initiation and completion paths 177e948693eSPhilip Paeps */ 178e948693eSPhilip Paeps int blocked __aligned(CACHE_LINE_SIZE); 179e948693eSPhilip Paeps 180e948693eSPhilip Paeps /* The following fields change more often, and are used mostly 181e948693eSPhilip Paeps * on the initiation path 182e948693eSPhilip Paeps */ 183e948693eSPhilip Paeps struct mtx lock __aligned(CACHE_LINE_SIZE); 184e948693eSPhilip Paeps struct sfxge_tx_dpl dpl; /* Deferred packet list. */ 185e948693eSPhilip Paeps unsigned int n_pend_desc; 186e948693eSPhilip Paeps unsigned int added; 187e948693eSPhilip Paeps unsigned int reaped; 188e948693eSPhilip Paeps /* Statistics */ 189e948693eSPhilip Paeps unsigned long tso_bursts; 190e948693eSPhilip Paeps unsigned long tso_packets; 191e948693eSPhilip Paeps unsigned long tso_long_headers; 192e948693eSPhilip Paeps unsigned long collapses; 193e948693eSPhilip Paeps unsigned long drops; 19493929f25SAndrew Rybchenko unsigned long get_overflow; 19593929f25SAndrew Rybchenko unsigned long get_non_tcp_overflow; 19693929f25SAndrew Rybchenko unsigned long put_overflow; 19793929f25SAndrew Rybchenko unsigned long netdown_drops; 198e1a3d10eSAndrew Rybchenko unsigned long tso_pdrop_too_many; 199e1a3d10eSAndrew Rybchenko unsigned long tso_pdrop_no_rsrc; 200e948693eSPhilip Paeps 201e948693eSPhilip Paeps /* The following fields change more often, and are used mostly 202e948693eSPhilip Paeps * on the completion path 203e948693eSPhilip Paeps */ 204e948693eSPhilip Paeps unsigned int pending __aligned(CACHE_LINE_SIZE); 205e948693eSPhilip Paeps unsigned int completed; 206e5e31360SAndrew Rybchenko struct sfxge_txq *next; 207e948693eSPhilip Paeps }; 208e948693eSPhilip Paeps 209cc933626SAndrew Rybchenko struct sfxge_evq; 210cc933626SAndrew Rybchenko 211e948693eSPhilip Paeps extern int sfxge_tx_packet_add(struct sfxge_txq *, struct mbuf *); 2123d8fce27SAndrew Rybchenko extern uint64_t sfxge_tx_get_drops(struct sfxge_softc *sc); 213e948693eSPhilip Paeps 214e948693eSPhilip Paeps extern int sfxge_tx_init(struct sfxge_softc *sc); 215e948693eSPhilip Paeps extern void sfxge_tx_fini(struct sfxge_softc *sc); 216e948693eSPhilip Paeps extern int sfxge_tx_start(struct sfxge_softc *sc); 217e948693eSPhilip Paeps extern void sfxge_tx_stop(struct sfxge_softc *sc); 218cc933626SAndrew Rybchenko extern void sfxge_tx_qcomplete(struct sfxge_txq *txq, struct sfxge_evq *evq); 219e948693eSPhilip Paeps extern void sfxge_tx_qflush_done(struct sfxge_txq *txq); 220e948693eSPhilip Paeps extern void sfxge_if_qflush(struct ifnet *ifp); 221e948693eSPhilip Paeps extern int sfxge_if_transmit(struct ifnet *ifp, struct mbuf *m); 222e948693eSPhilip Paeps 223e948693eSPhilip Paeps #endif 224