sfxge_tx.h revision 282942
1288943Sdim/*-
2249259Sdim * Copyright (c) 2010-2011 Solarflare Communications, Inc.
3249259Sdim * All rights reserved.
4249259Sdim *
5249259Sdim * This software was developed in part by Philip Paeps under contract for
6249259Sdim * Solarflare Communications, Inc.
7249259Sdim *
8249259Sdim * Redistribution and use in source and binary forms, with or without
9249259Sdim * modification, are permitted provided that the following conditions
10249259Sdim * are met:
11249259Sdim * 1. Redistributions of source code must retain the above copyright
12249259Sdim *    notice, this list of conditions and the following disclaimer.
13249259Sdim * 2. Redistributions in binary form must reproduce the above copyright
14249259Sdim *    notice, this list of conditions and the following disclaimer in the
15249259Sdim *    documentation and/or other materials provided with the distribution.
16288943Sdim *
17249259Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18249259Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19249259Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20276479Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21249259Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22249259Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23276479Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24288943Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25249259Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26249259Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27249259Sdim * SUCH DAMAGE.
28276479Sdim *
29280031Sdim * $FreeBSD: head/sys/dev/sfxge/sfxge_tx.h 282942 2015-05-15 06:50:59Z arybchik $
30249259Sdim */
31249259Sdim
32280031Sdim#ifndef _SFXGE_TX_H
33280031Sdim#define	_SFXGE_TX_H
34280031Sdim
35280031Sdim#include <netinet/in.h>
36249259Sdim#include <netinet/ip.h>
37280031Sdim#include <netinet/tcp.h>
38280031Sdim
39280031Sdim/* Maximum size of TSO packet */
40280031Sdim#define	SFXGE_TSO_MAX_SIZE		(65535)
41249259Sdim
42280031Sdim/*
43280031Sdim * Maximum number of segments to be created for a TSO packet.
44280031Sdim * Allow for a reasonable minimum MSS of 512.
45280031Sdim */
46280031Sdim#define	SFXGE_TSO_MAX_SEGS		howmany(SFXGE_TSO_MAX_SIZE, 512)
47280031Sdim
48280031Sdim/* Maximum number of DMA segments needed to map an mbuf chain.  With
49280031Sdim * TSO, the mbuf length may be just over 64K, divided into 2K mbuf
50280031Sdim * clusters.  (The chain could be longer than this initially, but can
51280031Sdim * be shortened with m_collapse().)
52280031Sdim */
53280031Sdim#define	SFXGE_TX_MAPPING_MAX_SEG					\
54280031Sdim	(1 + howmany(SFXGE_TSO_MAX_SIZE, MCLBYTES))
55280031Sdim
56280031Sdim/*
57280031Sdim * Buffer mapping flags.
58249259Sdim *
59280031Sdim * Buffers and DMA mappings must be freed when the last descriptor
60280031Sdim * referring to them is completed.  Set the TX_BUF_UNMAP and
61280031Sdim * TX_BUF_MBUF flags on the last descriptor generated for an mbuf
62280031Sdim * chain.  Set only the TX_BUF_UNMAP flag on a descriptor referring to
63249259Sdim * a heap buffer.
64280031Sdim */
65280031Sdimenum sfxge_tx_buf_flags {
66280031Sdim	TX_BUF_UNMAP = 1,
67249259Sdim	TX_BUF_MBUF = 2,
68280031Sdim};
69280031Sdim
70280031Sdim/*
71249259Sdim * Buffer mapping information for descriptors in flight.
72280031Sdim */
73280031Sdimstruct sfxge_tx_mapping {
74249259Sdim	union {
75280031Sdim		struct mbuf	*mbuf;
76280031Sdim		caddr_t		heap_buf;
77280031Sdim	}			u;
78280031Sdim	bus_dmamap_t		map;
79280031Sdim	enum sfxge_tx_buf_flags	flags;
80280031Sdim};
81280031Sdim
82249259Sdim#define	SFXGE_TX_DPL_GET_PKT_LIMIT_DEFAULT		(64 * 1024)
83280031Sdim#define	SFXGE_TX_DPL_GET_NON_TCP_PKT_LIMIT_DEFAULT	1024
84280031Sdim#define	SFXGE_TX_DPL_PUT_PKT_LIMIT_DEFAULT		1024
85280031Sdim
86280031Sdim/*
87288943Sdim * Deferred packet list.
88280031Sdim */
89249259Sdimstruct sfxge_tx_dpl {
90280031Sdim	unsigned int	std_get_max;		/* Maximum number  of packets
91280031Sdim						 * in get list */
92280031Sdim	unsigned int	std_get_non_tcp_max;	/* Maximum number
93280031Sdim						 * of non-TCP packets
94249259Sdim						 * in get list */
95280031Sdim	unsigned int	std_put_max;		/* Maximum number of packets
96280031Sdim						 * in put list */
97280031Sdim	uintptr_t	std_put;		/* Head of put list. */
98280031Sdim	struct mbuf	*std_get;		/* Head of get list. */
99249259Sdim	struct mbuf	**std_getp;		/* Tail of get list. */
100280031Sdim	unsigned int	std_get_count;		/* Packets in get list. */
101280031Sdim	unsigned int	std_get_non_tcp_count;	/* Non-TCP packets
102280031Sdim						 * in get list */
103280031Sdim	unsigned int	std_get_hiwat;		/* Packets in get list
104280031Sdim						 * high watermark */
105280031Sdim	unsigned int	std_put_hiwat;		/* Packets in put list
106280031Sdim						 * high watermark */
107249259Sdim};
108280031Sdim
109280031Sdim
110280031Sdim#define	SFXGE_TX_BUFFER_SIZE	0x400
111280031Sdim#define	SFXGE_TX_HEADER_SIZE	0x100
112249259Sdim#define	SFXGE_TX_COPY_THRESHOLD	0x200
113280031Sdim
114280031Sdimenum sfxge_txq_state {
115280031Sdim	SFXGE_TXQ_UNINITIALIZED = 0,
116249259Sdim	SFXGE_TXQ_INITIALIZED,
117249259Sdim	SFXGE_TXQ_STARTED
118280031Sdim};
119280031Sdim
120280031Sdimenum sfxge_txq_type {
121249259Sdim	SFXGE_TXQ_NON_CKSUM = 0,
122249259Sdim	SFXGE_TXQ_IP_CKSUM,
123296417Sdim	SFXGE_TXQ_IP_TCP_UDP_CKSUM,
124296417Sdim	SFXGE_TXQ_NTYPES
125296417Sdim};
126296417Sdim
127296417Sdim#define	SFXGE_TXQ_UNBLOCK_LEVEL(_entries)	(EFX_TXQ_LIMIT(_entries) / 4)
128296417Sdim
129296417Sdim#define	SFXGE_TX_BATCH	64
130296417Sdim
131296417Sdim#define	SFXGE_TXQ_LOCK_INIT(_txq, _ifname, _txq_index)			\
132296417Sdim	do {								\
133296417Sdim		struct sfxge_txq  *__txq = (_txq);			\
134296417Sdim									\
135296417Sdim		snprintf((__txq)->lock_name,				\
136296417Sdim			 sizeof((__txq)->lock_name),			\
137296417Sdim			 "%s:txq%u", (_ifname), (_txq_index));		\
138296417Sdim		mtx_init(&(__txq)->lock, (__txq)->lock_name,		\
139296417Sdim			 NULL, MTX_DEF);				\
140296417Sdim	} while (B_FALSE)
141296417Sdim#define	SFXGE_TXQ_LOCK_DESTROY(_txq)					\
142296417Sdim	mtx_destroy(&(_txq)->lock)
143296417Sdim#define	SFXGE_TXQ_LOCK(_txq)						\
144296417Sdim	mtx_lock(&(_txq)->lock)
145296417Sdim#define	SFXGE_TXQ_TRYLOCK(_txq)						\
146296417Sdim	mtx_trylock(&(_txq)->lock)
147296417Sdim#define	SFXGE_TXQ_UNLOCK(_txq)						\
148296417Sdim	mtx_unlock(&(_txq)->lock)
149296417Sdim#define	SFXGE_TXQ_LOCK_ASSERT_OWNED(_txq)				\
150296417Sdim	mtx_assert(&(_txq)->lock, MA_OWNED)
151296417Sdim#define	SFXGE_TXQ_LOCK_ASSERT_NOTOWNED(_txq)				\
152296417Sdim	mtx_assert(&(_txq)->lock, MA_NOTOWNED)
153296417Sdim
154296417Sdim
155280031Sdimstruct sfxge_txq {
156280031Sdim	/* The following fields should be written very rarely */
157280031Sdim	struct sfxge_softc		*sc;
158280031Sdim	enum sfxge_txq_state		init_state;
159280031Sdim	enum sfxge_flush_state		flush_state;
160280031Sdim	enum sfxge_txq_type		type;
161249259Sdim	unsigned int			txq_index;
162280031Sdim	unsigned int			evq_index;
163280031Sdim	efsys_mem_t			mem;
164249259Sdim	unsigned int			buf_base_id;
165249259Sdim	unsigned int			entries;
166280031Sdim	unsigned int			ptr_mask;
167280031Sdim
168280031Sdim	struct sfxge_tx_mapping		*stmp;	/* Packets in flight. */
169280031Sdim	bus_dma_tag_t			packet_dma_tag;
170249259Sdim	efx_buffer_t			*pend_desc;
171249259Sdim	efx_txq_t			*common;
172280031Sdim
173280031Sdim	efsys_mem_t			*tsoh_buffer;
174280031Sdim
175280031Sdim	char				lock_name[SFXGE_LOCK_NAME_MAX];
176280031Sdim
177280031Sdim	/* This field changes more often and is read regularly on both
178280031Sdim	 * the initiation and completion paths
179280031Sdim	 */
180280031Sdim	int				blocked __aligned(CACHE_LINE_SIZE);
181249259Sdim
182280031Sdim	/* The following fields change more often, and are used mostly
183280031Sdim	 * on the initiation path
184280031Sdim	 */
185280031Sdim	struct mtx			lock __aligned(CACHE_LINE_SIZE);
186280031Sdim	struct sfxge_tx_dpl		dpl;	/* Deferred packet list. */
187280031Sdim	unsigned int			n_pend_desc;
188280031Sdim	unsigned int			added;
189249259Sdim	unsigned int			reaped;
190280031Sdim	/* Statistics */
191288943Sdim	unsigned long			tso_bursts;
192288943Sdim	unsigned long			tso_packets;
193296417Sdim	unsigned long			tso_long_headers;
194296417Sdim	unsigned long			collapses;
195249259Sdim	unsigned long			drops;
196280031Sdim	unsigned long			get_overflow;
197280031Sdim	unsigned long			get_non_tcp_overflow;
198280031Sdim	unsigned long			put_overflow;
199280031Sdim	unsigned long			netdown_drops;
200280031Sdim	unsigned long			tso_pdrop_too_many;
201280031Sdim	unsigned long			tso_pdrop_no_rsrc;
202280031Sdim
203280031Sdim	/* The following fields change more often, and are used mostly
204280031Sdim	 * on the completion path
205280031Sdim	 */
206280031Sdim	unsigned int			pending __aligned(CACHE_LINE_SIZE);
207280031Sdim	unsigned int			completed;
208280031Sdim	struct sfxge_txq		*next;
209280031Sdim};
210280031Sdim
211280031Sdimstruct sfxge_evq;
212280031Sdim
213280031Sdimextern int sfxge_tx_packet_add(struct sfxge_txq *, struct mbuf *);
214280031Sdimextern uint64_t sfxge_tx_get_drops(struct sfxge_softc *sc);
215280031Sdim
216280031Sdimextern int sfxge_tx_init(struct sfxge_softc *sc);
217280031Sdimextern void sfxge_tx_fini(struct sfxge_softc *sc);
218280031Sdimextern int sfxge_tx_start(struct sfxge_softc *sc);
219280031Sdimextern void sfxge_tx_stop(struct sfxge_softc *sc);
220280031Sdimextern void sfxge_tx_qcomplete(struct sfxge_txq *txq, struct sfxge_evq *evq);
221280031Sdimextern void sfxge_tx_qflush_done(struct sfxge_txq *txq);
222280031Sdimextern void sfxge_if_qflush(struct ifnet *ifp);
223280031Sdimextern int sfxge_if_transmit(struct ifnet *ifp, struct mbuf *m);
224280031Sdim
225280031Sdim#endif
226280031Sdim