summaryrefslogtreecommitdiff
path: root/sys/dev/enic/enic.h
blob: eec6de823c9de5ab0c1b02d85219525e2389a21d (plain)
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
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright 2008-2017 Cisco Systems, Inc.  All rights reserved.
 * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
 */

#ifndef _ENIC_H
#define _ENIC_H

#include <sys/param.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>

#include <machine/bus.h>

#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/iflib.h>

#define u8  uint8_t
#define u16 uint16_t
#define u32 uint32_t
#define u64 uint64_t

struct enic_bar_info {
	struct resource		*res;
	bus_space_tag_t		tag;
	bus_space_handle_t	handle;
	bus_size_t		size;
	int			rid;
	int			offset;
};

#define ENIC_BUS_WRITE_8(res, index, value) \
    bus_space_write_8(res->bar.tag, res->bar.handle, \
    res->bar.offset + (index), value)
#define ENIC_BUS_WRITE_4(res, index, value) \
    bus_space_write_4(res->bar.tag, res->bar.handle, \
    res->bar.offset + (index), value)
#define ENIC_BUS_WRITE_REGION_4(res, index, values, count) \
    bus_space_write_region_4(res->bar.tag, res->bar.handle, \
    res->bar.offset + (index), values, count);

#define ENIC_BUS_READ_8(res, index) \
    bus_space_read_8(res->bar.tag, res->bar.handle, \
    res->bar.offset + (index))
#define ENIC_BUS_READ_4(res, index) \
    bus_space_read_4(res->bar.tag, res->bar.handle, \
    res->bar.offset + (index))
#define ENIC_BUS_READ_REGION_4(res, type, index, values, count) \
    bus_space_read_region_4(res->type.tag, res->type.handle, \
    res->type.offset + (index), values, count);

struct vnic_res {
	unsigned int count;
	struct enic_bar_info bar;
};

#include "vnic_enet.h"
#include "vnic_dev.h"
#include "vnic_wq.h"
#include "vnic_rq.h"
#include "vnic_cq.h"
#include "vnic_intr.h"
#include "vnic_stats.h"
#include "vnic_nic.h"
#include "vnic_rss.h"
#include "enic_res.h"
#include "cq_enet_desc.h"

#define ENIC_LOCK(_softc)	mtx_lock(&(_softc)->enic_lock)
#define ENIC_UNLOCK(_softc)	mtx_unlock(&(_softc)->enic_lock)

#define DRV_NAME		"enic"
#define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC"
#define DRV_COPYRIGHT		"Copyright 2008-2015 Cisco Systems, Inc"

#define ENIC_MAX_MAC_ADDR	64

#define VLAN_ETH_HLEN           18

#define ENICPMD_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0)

#define ENICPMD_BDF_LENGTH		13   /* 0000:00:00.0'\0' */
#define ENIC_CALC_IP_CKSUM		1
#define ENIC_CALC_TCP_UDP_CKSUM		2
#define ENIC_MAX_MTU			9000
#define ENIC_PAGE_SIZE			4096
#define PAGE_ROUND_UP(x) \
	((((unsigned long)(x)) + ENIC_PAGE_SIZE-1) & (~(ENIC_PAGE_SIZE-1)))

/* must be >= VNIC_COUNTER_DMA_MIN_PERIOD */
#define VNIC_FLOW_COUNTER_UPDATE_MSECS 500

/* PCI IDs */
#define CISCO_VENDOR_ID	0x1137

#define PCI_DEVICE_ID_CISCO_VIC_ENET	0x0043  /* ethernet vnic */
#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF	0x0071  /* enet SRIOV VF */

/* Special Filter id for non-specific packet flagging. Don't change value */
#define ENIC_MAGIC_FILTER_ID 0xffff

#define ENICPMD_FDIR_MAX		64

/* HW default VXLAN port */
#define ENIC_DEFAULT_VXLAN_PORT		4789

/*
 * Interrupt 1: rx queue 0
 * Interrupt 2: rx queue 1
 * ...
 * Interrupt x: LSC and errors
 */
#define ENICPMD_LSC_INTR_OFFSET 0
#define ENICPMD_RXQ_INTR_OFFSET 0

#include "vnic_devcmd.h"

enum vnic_proxy_type {
	PROXY_NONE,
	PROXY_BY_BDF,
	PROXY_BY_INDEX,
};

struct vnic_intr_coal_timer_info {
	u32 mul;
	u32 div;
	u32 max_usec;
};

struct enic_softc;
struct vnic_dev {
	void *priv;
	struct rte_pci_device *pdev;
	struct vnic_res res[RES_TYPE_MAX];
	enum vnic_dev_intr_mode intr_mode;
	struct vnic_res __iomem *devcmd;
	struct vnic_devcmd_notify *notify;
	struct vnic_devcmd_notify notify_copy;
	bus_addr_t notify_pa;
	struct iflib_dma_info notify_res;
	u32 notify_sz;
	struct iflib_dma_info linkstatus_res;
	struct vnic_stats *stats;
	struct iflib_dma_info stats_res;
	struct vnic_devcmd_fw_info *fw_info;
	struct iflib_dma_info fw_info_res;
	enum vnic_proxy_type proxy;
	u32 proxy_index;
	u64 args[VNIC_DEVCMD_NARGS];
	int in_reset;
	struct vnic_intr_coal_timer_info intr_coal_timer_info;
	struct devcmd2_controller *devcmd2;
	int (*devcmd_rtn)(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
	    int wait);
	void *(*alloc_consistent)(void *priv, size_t size,
	    bus_addr_t *dma_handle, struct iflib_dma_info *res, u8 *name);
	void (*free_consistent)(void *priv, size_t size, void *vaddr,
	    bus_addr_t dma_handle, struct iflib_dma_info *res);
	struct vnic_counter_counts *flow_counters;
	struct iflib_dma_info flow_counters_res;
	u8 flow_counters_dma_active;
	struct enic_softc *softc;
};

struct enic_soft_stats {
	uint64_t rx_nombuf;
	uint64_t rx_packet_errors;
	uint64_t tx_oversized;
};

struct intr_queue {
	struct if_irq intr_irq;
	struct resource *res;
	int rid;
	struct enic_softc *softc;
};

#define ENIC_MAX_LINK_SPEEDS		3
#define ENIC_LINK_SPEED_10G		10000
#define ENIC_LINK_SPEED_4G		4000
#define ENIC_LINK_40G_INDEX		2
#define ENIC_LINK_10G_INDEX		1
#define ENIC_LINK_4G_INDEX		0
#define ENIC_RX_COALESCE_RANGE_END	125
#define ENIC_AIC_TS_BREAK		100

struct enic_rx_coal {
	u32 small_pkt_range_start;
	u32 large_pkt_range_start;
	u32 range_end;
	u32 use_adaptive_rx_coalesce;
};

/* Store only the lower range.  Higher range is given by fw. */
struct enic_intr_mod_range {
	u32 small_pkt_range_start;
	u32 large_pkt_range_start;
};

struct enic {
	struct enic *next;
	struct rte_pci_device *pdev;
	struct vnic_enet_config config;
	struct vnic_dev_bar bar0;
	struct vnic_dev *vdev;

	/*
	 * mbuf_initializer contains 64 bits of mbuf rearm_data, used by
	 * the avx2 handler at this time.
	 */
	uint64_t mbuf_initializer;
	unsigned int port_id;
	bool overlay_offload;
	char bdf_name[ENICPMD_BDF_LENGTH];
	int dev_fd;
	int iommu_group_fd;
	int iommu_groupid;
	int eventfd;
	uint8_t mac_addr[ETH_ALEN];
	pthread_t err_intr_thread;
	u8 ig_vlan_strip_en;
	int link_status;
	u8 hw_ip_checksum;
	u16 max_mtu;
	u8 adv_filters;
	u32 flow_filter_mode;
	u8 filter_actions; /* HW supported actions */
	bool vxlan;
	bool disable_overlay; /* devargs disable_overlay=1 */
	uint8_t enable_avx2_rx;  /* devargs enable-avx2-rx=1 */
	bool nic_cfg_chk;     /* NIC_CFG_CHK available */
	bool udp_rss_weak;    /* Bodega style UDP RSS */
	uint8_t ig_vlan_rewrite_mode; /* devargs ig-vlan-rewrite */
	uint16_t vxlan_port;  /* current vxlan port pushed to NIC */

	unsigned int flags;
	unsigned int priv_flags;

	/* work queue (len = conf_wq_count) */
	struct vnic_wq *wq;
	unsigned int wq_count; /* equals eth_dev nb_tx_queues */

	/* receive queue (len = conf_rq_count) */
	struct vnic_rq *rq;
	unsigned int rq_count; /* equals eth_dev nb_rx_queues */

	/* completion queue (len = conf_cq_count) */
	struct vnic_cq *cq;
	unsigned int cq_count; /* equals rq_count + wq_count */

	/* interrupt vectors (len = conf_intr_count) */
	struct vnic_intr *intr;
	struct intr_queue *intr_queues;
	unsigned int intr_count; /* equals enabled interrupts (lsc + rxqs) */


	/* software counters */
	struct enic_soft_stats soft_stats;

	/* configured resources on vic */
	unsigned int conf_rq_count;
	unsigned int conf_wq_count;
	unsigned int conf_cq_count;
	unsigned int conf_intr_count;

	/* linked list storing memory allocations */
	LIST_HEAD(enic_memzone_list, enic_memzone_entry) memzone_list;

	LIST_HEAD(enic_flows, rte_flow) flows;
	int max_flow_counter;

	/* RSS */
	uint16_t reta_size;
	uint8_t hash_key_size;
	uint64_t flow_type_rss_offloads; /* 0 indicates RSS not supported */
	/*
	 * Keep a copy of current RSS config for queries, as we cannot retrieve
	 * it from the NIC.
	 */
	uint8_t rss_hash_type; /* NIC_CFG_RSS_HASH_TYPE flags */
	uint8_t rss_enable;
	uint64_t rss_hf; /* ETH_RSS flags */
	union vnic_rss_key rss_key;
	union vnic_rss_cpu rss_cpu;

	uint64_t rx_offload_capa; /* DEV_RX_OFFLOAD flags */
	uint64_t tx_offload_capa; /* DEV_TX_OFFLOAD flags */
	uint64_t tx_queue_offload_capa; /* DEV_TX_OFFLOAD flags */
	uint64_t tx_offload_mask; /* PKT_TX flags accepted */
	struct enic_softc *softc;
	int port_mtu;
	struct enic_rx_coal rx_coalesce_setting;
	u32 rx_coalesce_usecs;
	u32 tx_coalesce_usecs;
};

struct enic_softc {
	device_t		dev;
	if_ctx_t		ctx;
	if_softc_ctx_t		scctx;
	if_shared_ctx_t		sctx;
	struct ifmedia		*media;
	if_t			ifp;

	struct mtx		enic_lock;

	struct enic_bar_info	mem;
	struct enic_bar_info	io;

	struct vnic_dev		vdev;
	struct enic		enic;

	int ntxqsets;
	int nrxqsets;

	struct if_irq		enic_event_intr_irq;
	struct if_irq		enic_err_intr_irq;
	uint8_t			lladdr[ETHER_ADDR_LEN];
	int			link_active;
	int			stopped;
	uint8_t			mac_addr[ETHER_ADDR_LEN];

	int			directed;
	int			multicast;
	int			broadcast;
	int			promisc;
	int 			allmulti;

	u_int			mc_count;
	uint8_t			*mta;
};

/* Per-instance private data structure */

static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq)
{
	return rq;
}

static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq)
{
	return enic->rq_count + wq;
}

static inline uint32_t
enic_ring_incr(uint32_t n_descriptors, uint32_t idx)
{
	idx++;
	if (unlikely(idx == n_descriptors))
		idx = 0;
	return idx;
}

int enic_setup_finish(struct enic *enic);
void enic_start_wq(struct enic *enic, uint16_t queue_idx);
int enic_stop_wq(struct enic *enic, uint16_t queue_idx);
void enic_start_rq(struct enic *enic, uint16_t queue_idx);
int enic_stop_rq(struct enic *enic, uint16_t queue_idx);
void enic_dev_disable(struct enic *enic);
int enic_enable(struct enic *enic);
int enic_disable(struct enic *enic);
int enic_link_update(struct enic *enic);
bool enic_use_vector_rx_handler(struct enic *enic);
void enic_fdir_info(struct enic *enic);
void enic_prep_wq_for_simple_tx(struct enic *, uint16_t);

struct enic_ring {
	uint64_t		paddr;
	caddr_t			 vaddr;
	struct enic_softc	*softc;
	uint32_t		ring_size; /* Must be a power of two */
	uint16_t		id;	   /* Logical ID */
	uint16_t		phys_id;
};

struct enic_cp_ring {
	struct enic_ring	ring;
	struct if_irq		irq;
	uint32_t		cons;
	bool			v_bit;	  /* Value of valid bit */
	struct ctx_hw_stats	*stats;
	uint32_t		stats_ctx_id;
	uint32_t		last_idx; /* Used by RX rings only
					   * set to the last read pidx
					   */
};

#endif /* _ENIC_H_ */