aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/vmware/vmxnet3/if_vmxvar.h
blob: bbe5a4a547a5e58eb9b7afae2990236f47120412 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
/*-
 * Copyright (c) 2013 Tsubai Masanari
 * Copyright (c) 2013 Bryan Venteicher <bryanv@FreeBSD.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * $FreeBSD$
 */

#ifndef _IF_VMXVAR_H
#define _IF_VMXVAR_H

struct vmxnet3_softc;

struct vmxnet3_dma_alloc {
	bus_addr_t		dma_paddr;
	caddr_t			dma_vaddr;
	bus_dma_tag_t		dma_tag;
	bus_dmamap_t		dma_map;
	bus_size_t		dma_size;
};

/*
 * The number of Rx/Tx queues this driver supports.
 */
#define VMXNET3_RX_QUEUES	1
#define VMXNET3_TX_QUEUES	1

/*
 * The number of Rx rings in each Rx queue.
 */
#define VMXNET3_RXRINGS_PERQ	2

/*
 * The number of descriptors in each Rx/Tx ring.
 */
#define VMXNET3_DEF_TX_NDESC		512
#define VMXNET3_MAX_TX_NDESC		4096
#define VMXNET3_MIN_TX_NDESC		32
#define VMXNET3_MASK_TX_NDESC		0x1F
#define VMXNET3_DEF_RX_NDESC		256
#define VMXNET3_MAX_RX_NDESC		2048
#define VMXNET3_MIN_RX_NDESC		32
#define VMXNET3_MASK_RX_NDESC		0x1F

#define VMXNET3_MAX_TX_NCOMPDESC	VMXNET3_MAX_TX_NDESC
#define VMXNET3_MAX_RX_NCOMPDESC \
    (VMXNET3_MAX_RX_NDESC * VMXNET3_RXRINGS_PERQ)

struct vmxnet3_txbuf {
	bus_dmamap_t		 vtxb_dmamap;
	struct mbuf		*vtxb_m;
};

struct vmxnet3_txring {
	struct vmxnet3_txbuf	*vxtxr_txbuf;
	u_int			 vxtxr_head;
	u_int			 vxtxr_next;
	u_int			 vxtxr_ndesc;
	int			 vxtxr_gen;
	bus_dma_tag_t		 vxtxr_txtag;
	struct vmxnet3_txdesc	*vxtxr_txd;
	struct vmxnet3_dma_alloc vxtxr_dma;
};

static inline int
VMXNET3_TXRING_AVAIL(struct vmxnet3_txring *txr)
{
	int avail = txr->vxtxr_next - txr->vxtxr_head - 1;
	return (avail < 0 ? txr->vxtxr_ndesc + avail : avail);
}

struct vmxnet3_rxbuf {
	bus_dmamap_t		 vrxb_dmamap;
	struct mbuf		*vrxb_m;
};

struct vmxnet3_rxring {
	struct vmxnet3_rxbuf	*vxrxr_rxbuf;
	struct vmxnet3_rxdesc	*vxrxr_rxd;
	u_int			 vxrxr_fill;
	u_int			 vxrxr_ndesc;
	int			 vxrxr_gen;
	int			 vxrxr_rid;
	bus_dma_tag_t		 vxrxr_rxtag;
	struct vmxnet3_dma_alloc vxrxr_dma;
	bus_dmamap_t		 vxrxr_spare_dmap;
};

static inline void
vmxnet3_rxr_increment_fill(struct vmxnet3_rxring *rxr)
{

	if (++rxr->vxrxr_fill == rxr->vxrxr_ndesc) {
		rxr->vxrxr_fill = 0;
		rxr->vxrxr_gen ^= 1;
	}
}

struct vmxnet3_comp_ring {
	union {
		struct vmxnet3_txcompdesc *txcd;
		struct vmxnet3_rxcompdesc *rxcd;
	}			 vxcr_u;
	u_int			 vxcr_next;
	u_int			 vxcr_ndesc;
	int			 vxcr_gen;
	struct vmxnet3_dma_alloc vxcr_dma;
};

struct vmxnet3_txq_stats {
	uint64_t		vtxrs_full;
	uint64_t		vtxrs_offload_failed;
};

struct vmxnet3_txqueue {
	struct mtx			 vxtxq_mtx;
	struct vmxnet3_softc		*vxtxq_sc;
	int				 vxtxq_id;
	int				 vxtxq_intr_idx;
	int				 vxtxq_watchdog;
	struct vmxnet3_txring		 vxtxq_cmd_ring;
	struct vmxnet3_comp_ring	 vxtxq_comp_ring;
	struct vmxnet3_txq_stats	 vxtxq_stats;
	struct vmxnet3_txq_shared	*vxtxq_ts;
	struct sysctl_oid_list		*vxtxq_sysctl;
	char				 vxtxq_name[16];
};

#define VMXNET3_TXQ_LOCK(_txq)		mtx_lock(&(_txq)->vxtxq_mtx)
#define VMXNET3_TXQ_TRYLOCK(_txq)	mtx_trylock(&(_txq)->vxtxq_mtx)
#define VMXNET3_TXQ_UNLOCK(_txq)	mtx_unlock(&(_txq)->vxtxq_mtx)
#define VMXNET3_TXQ_LOCK_ASSERT(_txq)		\
    mtx_assert(&(_txq)->vxtxq_mtx, MA_OWNED)
#define VMXNET3_TXQ_LOCK_ASSERT_NOTOWNED(_txq)	\
    mtx_assert(&(_txq)->vxtxq_mtx, MA_NOTOWNED)

struct vmxnet3_rxq_stats {

};

struct vmxnet3_rxqueue {
	struct mtx			 vxrxq_mtx;
	struct vmxnet3_softc		*vxrxq_sc;
	int				 vxrxq_id;
	int				 vxrxq_intr_idx;
	struct vmxnet3_rxring		 vxrxq_cmd_ring[VMXNET3_RXRINGS_PERQ];
	struct vmxnet3_comp_ring	 vxrxq_comp_ring;
	struct vmxnet3_rxq_stats	 vxrxq_stats;
	struct vmxnet3_rxq_shared	*vxrxq_rs;
	struct sysctl_oid_list		*vxrxq_sysctl;
	char				 vxrxq_name[16];
};

#define VMXNET3_RXQ_LOCK(_rxq)		mtx_lock(&(_rxq)->vxrxq_mtx)
#define VMXNET3_RXQ_UNLOCK(_rxq)	mtx_unlock(&(_rxq)->vxrxq_mtx)
#define VMXNET3_RXQ_LOCK_ASSERT(_rxq)		\
    mtx_assert(&(_rxq)->vxrxq_mtx, MA_OWNED)
#define VMXNET3_RXQ_LOCK_ASSERT_NOTOWNED(_rxq)	\
    mtx_assert(&(_rxq)->vxrxq_mtx, MA_NOTOWNED)

struct vmxnet3_statistics {
	uint32_t		vmst_collapsed;
	uint32_t		vmst_mgetcl_failed;
	uint32_t		vmst_mbuf_load_failed;

};

struct vmxnet3_interrupt {
	struct resource		*vmxi_irq;
	int			 vmxi_rid;
	void			*vmxi_handler;
};

struct vmxnet3_softc {
	device_t			 vmx_dev;
	struct ifnet			*vmx_ifp;
	struct vmxnet3_driver_shared	*vmx_ds;
	uint32_t			 vmx_flags;
#define VMXNET3_FLAG_NO_MSIX	0x0001

	struct vmxnet3_rxqueue		*vmx_rxq;
	struct vmxnet3_txqueue		*vmx_txq;

	struct resource			*vmx_res0;
	bus_space_tag_t			 vmx_iot0;
	bus_space_handle_t		 vmx_ioh0;
	struct resource			*vmx_res1;
	bus_space_tag_t			 vmx_iot1;
	bus_space_handle_t		 vmx_ioh1;
	struct resource			*vmx_msix_res;

	int				 vmx_link_active;
	int				 vmx_link_speed;
	int				 vmx_if_flags;
	int				 vmx_ntxqueues;
	int				 vmx_nrxqueues;
	int				 vmx_ntxdescs;
	int				 vmx_nrxdescs;
	int				 vmx_max_rxsegs;
	int				 vmx_rx_max_chain;

	struct vmxnet3_statistics	 vmx_stats;

	int				 vmx_intr_type;
	int				 vmx_intr_mask_mode;
	int				 vmx_event_intr_idx;
	int				 vmx_nintrs;
	struct vmxnet3_interrupt	 vmx_intrs[VMXNET3_MAX_INTRS];

	struct mtx			 vmx_mtx;
	uint8_t				*vmx_mcast;
	void				*vmx_qs;
	struct callout			 vmx_tick;
	struct vmxnet3_dma_alloc	 vmx_ds_dma;
	struct vmxnet3_dma_alloc	 vmx_qs_dma;
	struct vmxnet3_dma_alloc	 vmx_mcast_dma;
	struct ifmedia			 vmx_media;
	eventhandler_tag		 vmx_vlan_attach;
	eventhandler_tag		 vmx_vlan_detach;
	uint8_t				 vmx_vlan_filter[4096/32];
	uint8_t				 vmx_lladdr[ETHER_ADDR_LEN];
};

#define VMXNET3_CORE_LOCK_INIT(_sc, _name) \
    mtx_init(&(_sc)->vmx_mtx, _name, "VMXNET3 Lock", MTX_DEF)
#define VMXNET3_CORE_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->vmx_mtx)
#define VMXNET3_CORE_LOCK(_sc)		mtx_lock(&(_sc)->vmx_mtx)
#define VMXNET3_CORE_UNLOCK(_sc)	mtx_unlock(&(_sc)->vmx_mtx)
#define VMXNET3_CORE_LOCK_ASSERT(_sc)	mtx_assert(&(_sc)->vmx_mtx, MA_OWNED)
#define VMXNET3_CORE_LOCK_ASSERT_NOTOWNED(_sc) \
    mtx_assert(&(_sc)->vmx_mtx, MA_NOTOWNED)

/*
 * Our driver version we report to the hypervisor; we just keep
 * this value constant.
 */
#define VMXNET3_DRIVER_VERSION 0x00010000

/*
 * Convert the FreeBSD version in to something the hypervisor
 * understands. This is apparently what VMware's driver reports
 * so mimic it even though it probably is not required.
 */
#define VMXNET3_GUEST_OS_VERSION \
   (((__FreeBSD_version / 100000) << 14)	| \
    (((__FreeBSD_version / 1000) % 100)	<< 6 )	| \
    (((__FreeBSD_version / 100) % 10) << 30)	| \
    ((__FreeBSD_version % 100) << 22))

/*
 * Max descriptors per Tx packet. We must limit the size of the
 * any TSO packets based on the number of segments.
 */
#define VMXNET3_TX_MAXSEGS		32
#define VMXNET3_TSO_MAXSIZE		65550

/*
 * Maximum support Tx segments size. The length field in the
 * Tx descriptor is 14 bits.
 */
#define VMXNET3_TX_MAXSEGSIZE		(1 << 14)

/*
 * The maximum number of Rx segments we accept. When LRO is enabled,
 * this allows us to receive the maximum sized frame with one MCLBYTES
 * cluster followed by 16 MJUMPAGESIZE clusters.
 */
#define VMXNET3_MAX_RX_SEGS		17

/*
 * Predetermined size of the multicast MACs filter table. If the
 * number of multicast addresses exceeds this size, then the
 * ALL_MULTI mode is use instead.
 */
#define VMXNET3_MULTICAST_MAX		32

/*
 * Our Tx watchdog timeout.
 */
#define VMXNET3_WATCHDOG_TIMEOUT	5

/*
 * IP protocols that we can perform Tx checksum offloading of.
 */
#define VMXNET3_CSUM_OFFLOAD		(CSUM_TCP | CSUM_UDP)
#define VMXNET3_CSUM_OFFLOAD_IPV6	(CSUM_TCP_IPV6 | CSUM_UDP_IPV6)

#define VMXNET3_CSUM_ALL_OFFLOAD	\
    (VMXNET3_CSUM_OFFLOAD | VMXNET3_CSUM_OFFLOAD_IPV6 | CSUM_TSO)

/*
 * Compat macros to keep this driver compiling on old releases.
 */

#if !defined(SYSCTL_ADD_UQUAD)
#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD
#endif

#if !defined(IFCAP_TXCSUM_IPV6)
#define IFCAP_TXCSUM_IPV6 0
#endif

#if !defined(IFCAP_RXCSUM_IPV6)
#define IFCAP_RXCSUM_IPV6 0
#endif

#if !defined(CSUM_TCP_IPV6)
#define CSUM_TCP_IPV6 0
#endif

#if !defined(CSUM_UDP_IPV6)
#define CSUM_UDP_IPV6	0
#endif

#endif /* _IF_VMXVAR_H */