aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/al_eth/al_eth.h
blob: c49cffabb44cc6d6c323092a52d9a647edc7509f (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
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
/*-
 * Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates
 * All rights reserved.
 *
 * Developed by Semihalf.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef __AL_ETH_H__
#define	__AL_ETH_H__

#include "al_init_eth_lm.h"
#include "al_hal_eth.h"
#include "al_hal_udma_iofic.h"
#include "al_hal_udma_debug.h"
#include "al_serdes.h"

enum board_t {
	ALPINE_INTEGRATED = 0,
	ALPINE_NIC = 1,
	ALPINE_FPGA_NIC = 2,
};

#define	AL_ETH_MAX_HW_QUEUES	4
#define	AL_ETH_NUM_QUEUES	4
#define	AL_ETH_MAX_MSIX_VEC	(1 + 2 * AL_ETH_MAX_HW_QUEUES)

#define AL_ETH_DEFAULT_TX_SW_DESCS	(512)
#define AL_ETH_DEFAULT_TX_HW_DESCS	(512)
#define AL_ETH_DEFAULT_RX_DESCS		(512)

#if ((AL_ETH_DEFAULT_TX_SW_DESCS / 4) < (AL_ETH_PKT_MAX_BUFS + 2))
#define	AL_ETH_TX_WAKEUP_THRESH		(AL_ETH_DEFAULT_TX_SW_DESCS / 4)
#else
#define	AL_ETH_TX_WAKEUP_THRESH		(AL_ETH_PKT_MAX_BUFS + 2)
#endif

#define	NET_IP_ALIGN				2
#define	AL_ETH_DEFAULT_SMALL_PACKET_LEN		(128 - NET_IP_ALIGN)
#define	AL_ETH_HEADER_COPY_SIZE			(128 - NET_IP_ALIGN)

#define	AL_ETH_DEFAULT_MAX_RX_BUFF_ALLOC_SIZE	9216
/*
 * Minimum the buffer size to 600 to avoid situation the mtu will be changed
 * from too little buffer to very big one and then the number of buffer per
 * packet could reach the maximum AL_ETH_PKT_MAX_BUFS
 */
#define	AL_ETH_DEFAULT_MIN_RX_BUFF_ALLOC_SIZE	600
#define	AL_ETH_DEFAULT_FORCE_1000_BASEX FALSE

#define	AL_ETH_DEFAULT_LINK_POLL_INTERVAL	100
#define	AL_ETH_FIRST_LINK_POLL_INTERVAL		1

#define	AL_ETH_NAME_MAX_LEN	20
#define	AL_ETH_IRQNAME_SIZE	40

#define	AL_ETH_DEFAULT_MDIO_FREQ_KHZ	2500
#define	AL_ETH_MDIO_FREQ_1000_KHZ	1000

struct al_eth_irq {
	driver_filter_t *handler;
	void		*data;
	unsigned int	vector;
	uint8_t		requested;
	char		name[AL_ETH_IRQNAME_SIZE];
	struct resource *res;
	void		*cookie;
};

struct al_eth_tx_buffer {
	struct mbuf *m;
	struct al_eth_pkt hal_pkt;
	bus_dmamap_t	dma_map;
	unsigned int	tx_descs;
};

struct al_eth_rx_buffer {
	struct mbuf	*m;
	unsigned int	data_size;
	bus_dmamap_t	dma_map;
	struct al_buf	al_buf;
};

struct al_eth_ring {
	device_t dev;
	struct al_eth_adapter *adapter;
	/* Used to get rx packets from hal */
	struct al_eth_pkt hal_pkt;
	/* Udma queue handler */
	struct al_udma_q *dma_q;
	uint32_t ring_id;
	uint16_t next_to_use;
	uint16_t next_to_clean;
	/* The offset of the interrupt unmask register */
	uint32_t *unmask_reg_offset;
	/* 
	 * The value to write to the above register to
	 * unmask the interrupt of this ring
	 */
	uint32_t unmask_val;
	struct al_eth_meta_data hal_meta;
	/* Contex of tx packet */
	struct al_eth_tx_buffer *tx_buffer_info;
	/* Contex of rx packet */
	struct al_eth_rx_buffer *rx_buffer_info;
	/* Number of tx/rx_buffer_info's entries */
	int sw_count;
	/* Number of hw descriptors */
	int hw_count;
	/* Size (in bytes) of hw descriptors */
	size_t descs_size;
	/* Size (in bytes) of hw completion descriptors, used for rx */
	size_t cdescs_size;
	struct ifnet *netdev;
	struct al_udma_q_params	q_params;
	struct buf_ring *br;
	struct mtx br_mtx;
	struct task enqueue_task;
	struct taskqueue *enqueue_tq;
	volatile uint32_t enqueue_is_running;
	struct task cmpl_task;
	struct taskqueue *cmpl_tq;
	volatile uint32_t cmpl_is_running;
	uint32_t lro_enabled;
	struct lro_ctrl lro;
	bus_dma_tag_t dma_buf_tag;
	volatile uint32_t stall;
};

#define	AL_ETH_TX_RING_IDX_NEXT(tx_ring, idx) (((idx) + 1) & (AL_ETH_DEFAULT_TX_SW_DESCS - 1))

#define	AL_ETH_RX_RING_IDX_NEXT(rx_ring, idx) (((idx) + 1) & (AL_ETH_DEFAULT_RX_DESCS - 1))
#define	AL_ETH_RX_RING_IDX_ADD(rx_ring, idx, n) (((idx) + (n)) & (AL_ETH_DEFAULT_RX_DESCS - 1))

/* flow control configuration */
#define	AL_ETH_FLOW_CTRL_RX_FIFO_TH_HIGH	0x160
#define	AL_ETH_FLOW_CTRL_RX_FIFO_TH_LOW		0x90
#define	AL_ETH_FLOW_CTRL_QUANTA			0xffff
#define	AL_ETH_FLOW_CTRL_QUANTA_TH		0x8000

#define	AL_ETH_FLOW_CTRL_AUTONEG	1 
#define	AL_ETH_FLOW_CTRL_RX_PAUSE	2
#define	AL_ETH_FLOW_CTRL_TX_PAUSE	4

/* link configuration for 1G port */
struct al_eth_link_config {
	int old_link;
	/* Describes what we actually have. */
	int	active_duplex;
	int	active_speed;

	/* current flow control status */
	uint8_t flow_ctrl_active;
	/* supported configuration (can be changed from ethtool) */
	uint8_t flow_ctrl_supported;

	/* the following are not relevant to RGMII */
	bool	force_1000_base_x;
	bool	autoneg;
};

/* SFP detection event */
enum al_eth_sfp_detect_evt {
	/* No change (no connect, disconnect, or new SFP module */
	AL_ETH_SFP_DETECT_EVT_NO_CHANGE,
	/* SFP module connected */
	AL_ETH_SFP_DETECT_EVT_CONNECTED,
	/* SFP module disconnected */
	AL_ETH_SFP_DETECT_EVT_DISCONNECTED,
	/* SFP module replaced */
	AL_ETH_SFP_DETECT_EVT_CHANGED,
};

/* SFP detection status */
struct al_eth_sfp_detect_stat {
	/* Status is valid (i.e. rest of fields are valid) */
	bool			valid;
	bool			connected;
	uint8_t			sfp_10g;
	uint8_t			sfp_1g;
	uint8_t			sfp_cable_tech;
	bool			lt_en;
	bool			an_en;
	enum al_eth_mac_mode	mac_mode;
};

struct al_eth_retimer_params {
	bool				exist;
	uint8_t				bus_id;
	uint8_t				i2c_addr;
	enum al_eth_retimer_channel	channel;
};

struct msix_entry {
	int entry;
	int vector;
};

/* board specific private data structure */
struct al_eth_adapter {
	enum board_t	board_type;
	device_t	miibus;
	struct mii_data *mii;
	uint16_t dev_id;
	uint8_t rev_id;

	device_t dev;
	struct ifnet *netdev;
	struct ifmedia media;
	struct resource	*udma_res;
	struct resource	*mac_res;
	struct resource	*ec_res;
	int if_flags;
	struct callout wd_callout;
	struct mtx     wd_mtx;
	struct callout stats_callout;
	struct mtx     stats_mtx;

	/* this is for intx mode */
	void *irq_cookie;
	struct resource *irq_res;

	/* 
	 * Some features need tri-state capability,
	 * thus the additional *_CAPABLE flags.
	 */
	uint32_t flags;
#define	AL_ETH_FLAG_MSIX_CAPABLE		(uint32_t)(1 << 1)
#define	AL_ETH_FLAG_MSIX_ENABLED		(uint32_t)(1 << 2)
#define	AL_ETH_FLAG_IN_NETPOLL			(uint32_t)(1 << 3)
#define	AL_ETH_FLAG_MQ_CAPABLE			(uint32_t)(1 << 4)
#define	AL_ETH_FLAG_SRIOV_CAPABLE		(uint32_t)(1 << 5)
#define	AL_ETH_FLAG_SRIOV_ENABLED		(uint32_t)(1 << 6)
#define	AL_ETH_FLAG_RESET_REQUESTED		(uint32_t)(1 << 7)

	struct al_hal_eth_adapter hal_adapter;

	/*
	 * Rx packets that shorter that this len will be copied to the mbuf 
	 */
	unsigned int small_copy_len;

	/* Maximum size for rx buffer */
	unsigned int max_rx_buff_alloc_size;
	uint32_t rx_mbuf_sz;

	/* Tx fast path data */
	int num_tx_queues;

	/* Rx fast path data */
	int num_rx_queues;

	/* TX */
	struct al_eth_ring tx_ring[AL_ETH_NUM_QUEUES];

	/* RX */
	struct al_eth_ring rx_ring[AL_ETH_NUM_QUEUES];

	enum al_iofic_mode int_mode;

#define	AL_ETH_MGMT_IRQ_IDX		0
#define	AL_ETH_RXQ_IRQ_IDX(adapter, q)	(1 + (q))
#define	AL_ETH_TXQ_IRQ_IDX(adapter, q)	(1 + (adapter)->num_rx_queues + (q))
	struct al_eth_irq irq_tbl[AL_ETH_MAX_MSIX_VEC];
	struct msix_entry *msix_entries;
	int	msix_vecs;
	int	irq_vecs;

	unsigned int tx_usecs, rx_usecs; /* interrupt coalescing */

	unsigned int tx_ring_count;
	unsigned int tx_descs_count;
	unsigned int rx_ring_count;
	unsigned int rx_descs_count;

	/* RSS */
	uint32_t toeplitz_hash_key[AL_ETH_RX_HASH_KEY_NUM];
#define	AL_ETH_RX_RSS_TABLE_SIZE	AL_ETH_RX_THASH_TABLE_SIZE
	uint8_t	 rss_ind_tbl[AL_ETH_RX_RSS_TABLE_SIZE];

	uint32_t msg_enable;
	struct al_eth_mac_stats mac_stats;

	enum al_eth_mac_mode	mac_mode;
	bool			mac_mode_set; /* Relevant only when 'auto_speed' is set */
	uint8_t mac_addr[ETHER_ADDR_LEN];
	/* mdio and phy*/
	bool			phy_exist;
	struct mii_bus		*mdio_bus;
	struct phy_device	*phydev;
	uint8_t			phy_addr;
	struct al_eth_link_config	link_config;

	/* HAL layer data */
	int			id_number;
	char			name[AL_ETH_NAME_MAX_LEN];
	void			*internal_pcie_base; /* use for ALPINE_NIC devices */
	void			*udma_base;
	void			*ec_base;
	void			*mac_base;

	struct al_eth_flow_control_params flow_ctrl_params;

	struct al_eth_adapter_params eth_hal_params;

	struct task			link_status_task;
	uint32_t			link_poll_interval; /* task interval in mSec */

	bool				serdes_init;
	struct al_serdes_grp_obj	serdes_obj;
	uint8_t				serdes_grp;
	uint8_t				serdes_lane;

	bool				an_en;	/* run kr auto-negotiation */
	bool				lt_en;	/* run kr link-training */

	bool				sfp_detection_needed; /* true if need to run sfp detection */
	bool				auto_speed; /* true if allowed to change SerDes speed configuration */
	uint8_t				i2c_adapter_id; /* identifier for the i2c adapter to use to access SFP+ module */
	enum al_eth_ref_clk_freq	ref_clk_freq; /* reference clock frequency */
	unsigned int			mdio_freq; /* MDIO frequency [Khz] */

	bool up;

	bool				last_link;
	bool				last_establish_failed;
	struct al_eth_lm_context	lm_context;
	bool				use_lm;

	bool				dont_override_serdes; /* avoid overriding serdes parameters
								   to preset static values */
	struct mtx			serdes_config_lock;
	struct mtx			if_rx_lock;

	uint32_t wol;

	struct al_eth_retimer_params	retimer;

	bool				phy_fixup_needed;

	enum al_eth_lm_max_speed	max_speed;
};

#endif /* !(AL_ETH_H) */