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
|
/*
* Copyright (c) 2017 Stormshield.
* Copyright (c) 2017 Semihalf.
* All rights reserved.
*
* 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 ``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 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.
*
* $FreeBSD$
*
*/
#ifndef _IF_MVNETAVAR_H_
#define _IF_MVNETAVAR_H_
#include <net/if.h>
#define MVNETA_HWHEADER_SIZE 2 /* Marvell Header */
#define MVNETA_ETHER_SIZE 22 /* Maximum ether size */
#define MVNETA_MAX_CSUM_MTU 1600 /* Port1,2 hw limit */
/*
* Limit support for frame up to hw csum limit
* until jumbo frame support is added.
*/
#define MVNETA_MAX_FRAME (MVNETA_MAX_CSUM_MTU + MVNETA_ETHER_SIZE)
/*
* Default limit of queue length
*
* queue 0 is lowest priority and queue 7 is highest priority.
* IP packet is received on queue 7 by default.
*/
#define MVNETA_TX_RING_CNT 512
#define MVNETA_RX_RING_CNT 256
#define MVNETA_BUFRING_SIZE 1024
#define MVNETA_PACKET_OFFSET 64
#define MVNETA_PACKET_SIZE MCLBYTES
#define MVNETA_RXTH_COUNT 128
#define MVNETA_RX_REFILL_COUNT 8
#define MVNETA_TX_RECLAIM_COUNT 32
/*
* Device Register access
*/
#define MVNETA_READ(sc, reg) \
bus_read_4((sc)->res[0], (reg))
#define MVNETA_WRITE(sc, reg, val) \
bus_write_4((sc)->res[0], (reg), (val))
#define MVNETA_READ_REGION(sc, reg, val, c) \
bus_read_region_4((sc)->res[0], (reg), (val), (c))
#define MVNETA_WRITE_REGION(sc, reg, val, c) \
bus_write_region_4((sc)->res[0], (reg), (val), (c))
#define MVNETA_READ_MIB_4(sc, reg) \
bus_read_4((sc)->res[0], MVNETA_PORTMIB_BASE + (reg))
#define MVNETA_READ_MIB_8(sc, reg) \
bus_read_8((sc)->res[0], MVNETA_PORTMIB_BASE + (reg))
#define MVNETA_IS_LINKUP(sc) \
(MVNETA_READ((sc), MVNETA_PSR) & MVNETA_PSR_LINKUP)
#define MVNETA_IS_QUEUE_SET(queues, q) \
((((queues) >> (q)) & 0x1))
/*
* EEE: Lower Power Idle config
* Default timer is duration of MTU sized frame transmission.
* The timer can be negotiated by LLDP protocol, but we have no
* support.
*/
#define MVNETA_LPI_TS (ETHERMTU * 8 / 1000) /* [us] */
#define MVNETA_LPI_TW (ETHERMTU * 8 / 1000) /* [us] */
#define MVNETA_LPI_LI (ETHERMTU * 8 / 1000) /* [us] */
/*
* DMA Descriptor
*
* the ethernet device has 8 rx/tx DMA queues. each of queue has its own
* decriptor list. descriptors are simply index by counter inside the device.
*/
#define MVNETA_TX_SEGLIMIT 32
#define MVNETA_QUEUE_IDLE 1
#define MVNETA_QUEUE_WORKING 2
#define MVNETA_QUEUE_DISABLED 3
struct mvneta_buf {
struct mbuf * m; /* pointer to related mbuf */
bus_dmamap_t dmap;
};
struct mvneta_rx_ring {
int queue_status;
/* Real descriptors array. shared by RxDMA */
struct mvneta_rx_desc *desc;
bus_dmamap_t desc_map;
bus_addr_t desc_pa;
/* Managment entries for each of descritors */
struct mvneta_buf rxbuf[MVNETA_RX_RING_CNT];
/* locks */
struct mtx ring_mtx;
/* Index */
int dma;
int cpu;
/* Limit */
int queue_th_received;
int queue_th_time; /* [Tclk] */
/* LRO */
struct lro_ctrl lro;
boolean_t lro_enabled;
/* Is this queue out of mbuf */
boolean_t needs_refill;
} __aligned(CACHE_LINE_SIZE);
struct mvneta_tx_ring {
/* Index of this queue */
int qidx;
/* IFNET pointer */
struct ifnet *ifp;
/* Ring buffer for IFNET */
struct buf_ring *br;
/* Real descriptors array. shared by TxDMA */
struct mvneta_tx_desc *desc;
bus_dmamap_t desc_map;
bus_addr_t desc_pa;
/* Managment entries for each of descritors */
struct mvneta_buf txbuf[MVNETA_TX_RING_CNT];
/* locks */
struct mtx ring_mtx;
/* Index */
int used;
int dma;
int cpu;
/* watchdog */
#define MVNETA_WATCHDOG_TXCOMP (hz / 10) /* 100ms */
#define MVNETA_WATCHDOG (10 * hz) /* 10s */
int watchdog_time;
int queue_status;
boolean_t queue_hung;
/* Task */
struct task task;
struct taskqueue *taskq;
/* Stats */
uint32_t drv_error;
} __aligned(CACHE_LINE_SIZE);
static __inline int
tx_counter_adv(int ctr, int n)
{
ctr += n;
while (__predict_false(ctr >= MVNETA_TX_RING_CNT))
ctr -= MVNETA_TX_RING_CNT;
return (ctr);
}
static __inline int
rx_counter_adv(int ctr, int n)
{
ctr += n;
while (__predict_false(ctr >= MVNETA_RX_RING_CNT))
ctr -= MVNETA_RX_RING_CNT;
return (ctr);
}
/*
* Timeout control
*/
#define MVNETA_PHY_TIMEOUT 10000 /* msec */
#define RX_DISABLE_TIMEOUT 0x1000000 /* times */
#define TX_DISABLE_TIMEOUT 0x1000000 /* times */
#define TX_FIFO_EMPTY_TIMEOUT 0x1000000 /* times */
/*
* Debug
*/
#define KASSERT_SC_MTX(sc) \
KASSERT(mtx_owned(&(sc)->mtx), ("SC mutex not owned"))
#define KASSERT_BM_MTX(sc) \
KASSERT(mtx_owned(&(sc)->bm.bm_mtx), ("BM mutex not owned"))
#define KASSERT_RX_MTX(sc, q) \
KASSERT(mtx_owned(&(sc)->rx_ring[(q)].ring_mtx),\
("RX mutex not owned"))
#define KASSERT_TX_MTX(sc, q) \
KASSERT(mtx_owned(&(sc)->tx_ring[(q)].ring_mtx),\
("TX mutex not owned"))
/*
* sysctl(9) parameters
*/
struct mvneta_sysctl_queue {
struct mvneta_softc *sc;
int rxtx;
int queue;
};
#define MVNETA_SYSCTL_RX 0
#define MVNETA_SYSCTL_TX 1
struct mvneta_sysctl_mib {
struct mvneta_softc *sc;
int index;
uint64_t counter;
};
enum mvneta_phy_mode {
MVNETA_PHY_QSGMII,
MVNETA_PHY_SGMII,
MVNETA_PHY_RGMII,
MVNETA_PHY_RGMII_ID
};
/*
* Ethernet Device main context
*/
DECLARE_CLASS(mvneta_driver);
struct mvneta_softc {
device_t dev;
uint32_t version;
/*
* mtx must be held by interface functions to/from
* other frameworks. interrupt hander, sysctl hander,
* ioctl hander, and so on.
*/
struct mtx mtx;
struct resource *res[2];
void *ih_cookie[1];
struct ifnet *ifp;
uint32_t mvneta_if_flags;
uint32_t mvneta_media;
int phy_attached;
enum mvneta_phy_mode phy_mode;
int phy_addr;
int phy_speed; /* PHY speed */
boolean_t phy_fdx; /* Full duplex mode */
boolean_t use_inband_status; /* In-band link status */
/*
* Link State control
*/
boolean_t linkup;
device_t miibus;
struct mii_data *mii;
uint8_t enaddr[ETHER_ADDR_LEN];
struct ifmedia mvneta_ifmedia;
bus_dma_tag_t rx_dtag;
bus_dma_tag_t rxbuf_dtag;
bus_dma_tag_t tx_dtag;
bus_dma_tag_t txmbuf_dtag;
struct mvneta_rx_ring rx_ring[MVNETA_RX_QNUM_MAX];
struct mvneta_tx_ring tx_ring[MVNETA_TX_QNUM_MAX];
/*
* Maintance clock
*/
struct callout tick_ch;
int cf_lpi;
int cf_fc;
int debug;
/*
* Sysctl interfaces
*/
struct mvneta_sysctl_queue sysctl_rx_queue[MVNETA_RX_QNUM_MAX];
struct mvneta_sysctl_queue sysctl_tx_queue[MVNETA_TX_QNUM_MAX];
/*
* MIB counter
*/
struct mvneta_sysctl_mib sysctl_mib[MVNETA_PORTMIB_NOCOUNTER];
uint64_t counter_pdfc;
uint64_t counter_pofc;
uint32_t counter_watchdog; /* manual reset when clearing mib */
uint32_t counter_watchdog_mib; /* reset after each mib update */
};
#define MVNETA_RX_RING(sc, q) \
(&(sc)->rx_ring[(q)])
#define MVNETA_TX_RING(sc, q) \
(&(sc)->tx_ring[(q)])
int mvneta_attach(device_t);
#ifdef FDT
int mvneta_fdt_mac_address(struct mvneta_softc *, uint8_t *);
#endif
#endif /* _IF_MVNETAVAR_H_ */
|