1227569Sphilip/*- 2227569Sphilip * Copyright (c) 2010-2011 Solarflare Communications, Inc. 3227569Sphilip * All rights reserved. 4227569Sphilip * 5227569Sphilip * This software was developed in part by Philip Paeps under contract for 6227569Sphilip * Solarflare Communications, Inc. 7227569Sphilip * 8227569Sphilip * Redistribution and use in source and binary forms, with or without 9227569Sphilip * modification, are permitted provided that the following conditions 10227569Sphilip * are met: 11227569Sphilip * 1. Redistributions of source code must retain the above copyright 12227569Sphilip * notice, this list of conditions and the following disclaimer. 13227569Sphilip * 2. Redistributions in binary form must reproduce the above copyright 14227569Sphilip * notice, this list of conditions and the following disclaimer in the 15227569Sphilip * documentation and/or other materials provided with the distribution. 16227569Sphilip * 17227569Sphilip * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18227569Sphilip * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19227569Sphilip * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20227569Sphilip * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21227569Sphilip * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22227569Sphilip * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23227569Sphilip * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24227569Sphilip * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25227569Sphilip * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26227569Sphilip * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27227569Sphilip * SUCH DAMAGE. 28227569Sphilip * 29227569Sphilip * $FreeBSD$ 30227569Sphilip */ 31227569Sphilip 32227569Sphilip#ifndef _SFXGE_TX_H 33227569Sphilip#define _SFXGE_TX_H 34227569Sphilip 35227569Sphilip#include <netinet/in.h> 36227569Sphilip#include <netinet/ip.h> 37227569Sphilip#include <netinet/tcp.h> 38227569Sphilip 39227569Sphilip/* Maximum number of DMA segments needed to map an mbuf chain. With 40227569Sphilip * TSO, the mbuf length may be just over 64K, divided into 2K mbuf 41227569Sphilip * clusters. (The chain could be longer than this initially, but can 42227569Sphilip * be shortened with m_collapse().) 43227569Sphilip */ 44227569Sphilip#define SFXGE_TX_MAPPING_MAX_SEG (64 / 2 + 1) 45227569Sphilip 46227569Sphilip/* Maximum number of DMA segments needed to map an output packet. It 47227569Sphilip * could overlap all mbufs in the chain and also require an extra 48227569Sphilip * segment for a TSO header. 49227569Sphilip */ 50227569Sphilip#define SFXGE_TX_PACKET_MAX_SEG (SFXGE_TX_MAPPING_MAX_SEG + 1) 51227569Sphilip 52227569Sphilip/* 53227569Sphilip * Buffer mapping flags. 54227569Sphilip * 55227569Sphilip * Buffers and DMA mappings must be freed when the last descriptor 56227569Sphilip * referring to them is completed. Set the TX_BUF_UNMAP and 57227569Sphilip * TX_BUF_MBUF flags on the last descriptor generated for an mbuf 58227569Sphilip * chain. Set only the TX_BUF_UNMAP flag on a descriptor referring to 59227569Sphilip * a heap buffer. 60227569Sphilip */ 61227569Sphilipenum sfxge_tx_buf_flags { 62227569Sphilip TX_BUF_UNMAP = 1, 63227569Sphilip TX_BUF_MBUF = 2, 64227569Sphilip}; 65227569Sphilip 66227569Sphilip/* 67227569Sphilip * Buffer mapping information for descriptors in flight. 68227569Sphilip */ 69227569Sphilipstruct sfxge_tx_mapping { 70227569Sphilip union { 71227569Sphilip struct mbuf *mbuf; 72227569Sphilip caddr_t heap_buf; 73227569Sphilip } u; 74227569Sphilip bus_dmamap_t map; 75227569Sphilip enum sfxge_tx_buf_flags flags; 76227569Sphilip}; 77227569Sphilip 78227569Sphilip#define SFXGE_TX_MAX_DEFERRED 64 79227569Sphilip 80227569Sphilip/* 81227569Sphilip * Deferred packet list. 82227569Sphilip */ 83227569Sphilipstruct sfxge_tx_dpl { 84227569Sphilip uintptr_t std_put; /* Head of put list. */ 85227569Sphilip struct mbuf *std_get; /* Head of get list. */ 86227569Sphilip struct mbuf **std_getp; /* Tail of get list. */ 87227569Sphilip unsigned int std_count; /* Count of packets. */ 88227569Sphilip}; 89227569Sphilip 90227569Sphilip 91227569Sphilip#define SFXGE_TX_BUFFER_SIZE 0x400 92227569Sphilip#define SFXGE_TX_HEADER_SIZE 0x100 93227569Sphilip#define SFXGE_TX_COPY_THRESHOLD 0x200 94227569Sphilip 95227569Sphilipenum sfxge_txq_state { 96227569Sphilip SFXGE_TXQ_UNINITIALIZED = 0, 97227569Sphilip SFXGE_TXQ_INITIALIZED, 98227569Sphilip SFXGE_TXQ_STARTED 99227569Sphilip}; 100227569Sphilip 101227569Sphilipenum sfxge_txq_type { 102227569Sphilip SFXGE_TXQ_NON_CKSUM = 0, 103227569Sphilip SFXGE_TXQ_IP_CKSUM, 104227569Sphilip SFXGE_TXQ_IP_TCP_UDP_CKSUM, 105227569Sphilip SFXGE_TXQ_NTYPES 106227569Sphilip}; 107227569Sphilip 108227569Sphilip#define SFXGE_TXQ_UNBLOCK_LEVEL (EFX_TXQ_LIMIT(SFXGE_NDESCS) / 4) 109227569Sphilip 110227569Sphilip#define SFXGE_TX_BATCH 64 111227569Sphilip 112227569Sphilip#ifdef SFXGE_HAVE_MQ 113227569Sphilip#define SFXGE_TXQ_LOCK(txq) (&(txq)->lock) 114227569Sphilip#define SFXGE_TX_SCALE(sc) ((sc)->intr.n_alloc) 115227569Sphilip#else 116227569Sphilip#define SFXGE_TXQ_LOCK(txq) (&(txq)->sc->tx_lock) 117227569Sphilip#define SFXGE_TX_SCALE(sc) 1 118227569Sphilip#endif 119227569Sphilip 120227569Sphilipstruct sfxge_txq { 121227569Sphilip /* The following fields should be written very rarely */ 122227569Sphilip struct sfxge_softc *sc; 123227569Sphilip enum sfxge_txq_state init_state; 124227569Sphilip enum sfxge_flush_state flush_state; 125227569Sphilip enum sfxge_txq_type type; 126227569Sphilip unsigned int txq_index; 127227569Sphilip unsigned int evq_index; 128227569Sphilip efsys_mem_t mem; 129227569Sphilip unsigned int buf_base_id; 130227569Sphilip 131227569Sphilip struct sfxge_tx_mapping *stmp; /* Packets in flight. */ 132227569Sphilip bus_dma_tag_t packet_dma_tag; 133227569Sphilip efx_buffer_t *pend_desc; 134227569Sphilip efx_txq_t *common; 135227569Sphilip struct sfxge_txq *next; 136227569Sphilip 137227569Sphilip efsys_mem_t *tsoh_buffer; 138227569Sphilip 139227569Sphilip /* This field changes more often and is read regularly on both 140227569Sphilip * the initiation and completion paths 141227569Sphilip */ 142227569Sphilip int blocked __aligned(CACHE_LINE_SIZE); 143227569Sphilip 144227569Sphilip /* The following fields change more often, and are used mostly 145227569Sphilip * on the initiation path 146227569Sphilip */ 147227569Sphilip#ifdef SFXGE_HAVE_MQ 148227569Sphilip struct mtx lock __aligned(CACHE_LINE_SIZE); 149227569Sphilip struct sfxge_tx_dpl dpl; /* Deferred packet list. */ 150227569Sphilip unsigned int n_pend_desc; 151227569Sphilip#else 152227569Sphilip unsigned int n_pend_desc __aligned(CACHE_LINE_SIZE); 153227569Sphilip#endif 154227569Sphilip unsigned int added; 155227569Sphilip unsigned int reaped; 156227569Sphilip /* Statistics */ 157227569Sphilip unsigned long tso_bursts; 158227569Sphilip unsigned long tso_packets; 159227569Sphilip unsigned long tso_long_headers; 160227569Sphilip unsigned long collapses; 161227569Sphilip unsigned long drops; 162227569Sphilip 163227569Sphilip /* The following fields change more often, and are used mostly 164227569Sphilip * on the completion path 165227569Sphilip */ 166227569Sphilip unsigned int pending __aligned(CACHE_LINE_SIZE); 167227569Sphilip unsigned int completed; 168227569Sphilip}; 169227569Sphilip 170227569Sphilipextern int sfxge_tx_packet_add(struct sfxge_txq *, struct mbuf *); 171227569Sphilip 172227569Sphilipextern int sfxge_tx_init(struct sfxge_softc *sc); 173227569Sphilipextern void sfxge_tx_fini(struct sfxge_softc *sc); 174227569Sphilipextern int sfxge_tx_start(struct sfxge_softc *sc); 175227569Sphilipextern void sfxge_tx_stop(struct sfxge_softc *sc); 176227569Sphilipextern void sfxge_tx_qcomplete(struct sfxge_txq *txq); 177227569Sphilipextern void sfxge_tx_qflush_done(struct sfxge_txq *txq); 178227569Sphilip#ifdef SFXGE_HAVE_MQ 179227569Sphilipextern void sfxge_if_qflush(struct ifnet *ifp); 180227569Sphilipextern int sfxge_if_transmit(struct ifnet *ifp, struct mbuf *m); 181227569Sphilip#else 182227569Sphilipextern void sfxge_if_start(struct ifnet *ifp); 183227569Sphilip#endif 184227569Sphilip 185227569Sphilip#endif 186