xref: /freebsd/sys/dev/sfxge/sfxge_tx.h (revision a411fe4e805d0678e1d04b16d1316dfafd25d60d)
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