xref: /NextBSD/sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c (revision b137080f19736ee33fede2e88bb54438604cf86b)
1 /*-
2  * Copyright (c) 2012-2014 Bjoern A. Zeeb
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249
7  * ("MRC2"), as part of the DARPA MRC research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * This driver is modelled after atse(4).  We need to seriously reduce the
31  * per-driver code we have to write^wcopy & paste.
32  *
33  * TODO:
34  * - figure out on the HW side why some data is LE and some is BE.
35  * - general set of improvements possible (e.g., reduce times of copying,
36  *   do on-the-copy checksum calculations)
37  */
38 
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
41 
42 #include "opt_device_polling.h"
43 #include "opt_netfpga.h"
44 
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/bus.h>
49 #include <sys/endian.h>
50 #include <sys/lock.h>
51 #include <sys/module.h>
52 #include <sys/mutex.h>
53 #include <sys/proc.h>
54 #include <sys/socket.h>
55 #include <sys/sockio.h>
56 #include <sys/types.h>
57 
58 #include <net/ethernet.h>
59 #include <net/if.h>
60 #include <net/if_var.h>
61 #include <net/if_dl.h>
62 #include <net/if_media.h>
63 #include <net/if_types.h>
64 #include <net/if_vlan_var.h>
65 
66 #include <net/bpf.h>
67 
68 #include <machine/bus.h>
69 #include <machine/resource.h>
70 #include <sys/rman.h>
71 
72 #include "if_nf10bmacreg.h"
73 
74 #ifndef	NF10BMAC_MAX_PKTS
75 /*
76  * We have a 4k buffer in HW, so do not try to send more than 3 packets.
77  * At the time of writing HW is orders of magnitude faster than we can
78  * enqueue so it would not matter but need an escape.
79  */
80 #define	NF10BMAC_MAX_PKTS		3
81 #endif
82 
83 #ifndef NF10BMAC_WATCHDOG_TIME
84 #define	NF10BMAC_WATCHDOG_TIME		5	/* seconds */
85 #endif
86 
87 #ifdef DEVICE_POLLING
88 static poll_handler_t nf10bmac_poll;
89 #endif
90 
91 #define	NF10BMAC_LOCK(_sc)		mtx_lock(&(_sc)->nf10bmac_mtx)
92 #define	NF10BMAC_UNLOCK(_sc)		mtx_unlock(&(_sc)->nf10bmac_mtx)
93 #define	NF10BMAC_LOCK_ASSERT(_sc)	\
94 	mtx_assert(&(_sc)->nf10bmac_mtx, MA_OWNED)
95 
96 #define	NF10BMAC_CTRL0			0x00
97 #define	NF10BMAC_TX_DATA		0x00
98 #define	NF10BMAC_TX_META		0x08
99 #define	NF10BMAC_TX_LEN			0x10
100 #define	NF10BMAC_RX_DATA		0x00
101 #define	NF10BMAC_RX_META		0x08
102 #define	NF10BMAC_RX_LEN			0x10
103 #define	NF10BMAC_INTR_CLEAR_DIS		0x00
104 #define	NF10BMAC_INTR_CTRL		0x08
105 
106 #define NF10BMAC_TUSER_MAC0		(1 << 0)
107 #define NF10BMAC_TUSER_CPU0		(1 << 1)
108 #define NF10BMAC_TUSER_MAC1		(1 << 2)
109 #define NF10BMAC_TUSER_CPU1		(1 << 3)
110 #define NF10BMAC_TUSER_MAC2		(1 << 4)
111 #define NF10BMAC_TUSER_CPU2		(1 << 5)
112 #define NF10BMAC_TUSER_MAC3		(1 << 6)
113 #define NF10BMAC_TUSER_CPU3		(1 << 7)
114 
115 #define	NF10BMAC_DATA_LEN_MASK		0x0000ffff
116 #define	NF10BMAC_DATA_DPORT_MASK	0xff000000
117 #define	NF10BMAC_DATA_DPORT_SHIFT	24
118 #define	NF10BMAC_DATA_SPORT_MASK	0x00ff0000
119 #define	NF10BMAC_DATA_SPORT_SHIFT	16
120 #define	NF10BMAC_DATA_LAST		0x00008000
121 #ifdef NF10BMAC_64BIT
122 #define	NF10BMAC_DATA_STRB		0x000000ff
123 #define	REGWTYPE			uint64_t
124 #else
125 #define	NF10BMAC_DATA_STRB		0x0000000f
126 #define	REGWTYPE			uint32_t
127 #endif
128 
129 
130 static inline void
nf10bmac_write(struct resource * res,REGWTYPE reg,REGWTYPE val,const char * f __unused,const int l __unused)131 nf10bmac_write(struct resource *res, REGWTYPE reg, REGWTYPE val,
132     const char *f __unused, const int l __unused)
133 {
134 
135 #ifdef NF10BMAC_64BIT
136 	bus_write_8(res, reg, htole64(val));
137 #else
138 	bus_write_4(res, reg, htole32(val));
139 #endif
140 }
141 
142 static inline REGWTYPE
nf10bmac_read(struct resource * res,REGWTYPE reg,const char * f __unused,const int l __unused)143 nf10bmac_read(struct resource *res, REGWTYPE reg,
144     const char *f __unused, const int l __unused)
145 {
146 
147 #ifdef NF10BMAC_64BIT
148 	return (le64toh(bus_read_8(res, reg)));
149 #else
150 	return (le32toh(bus_read_4(res, reg)));
151 #endif
152 }
153 
154 static inline void
nf10bmac_write_be(struct resource * res,REGWTYPE reg,REGWTYPE val,const char * f __unused,const int l __unused)155 nf10bmac_write_be(struct resource *res, REGWTYPE reg, REGWTYPE val,
156     const char *f __unused, const int l __unused)
157 {
158 
159 #ifdef NF10BMAC_64BIT
160 	bus_write_8(res, reg, htobe64(val));
161 #else
162 	bus_write_4(res, reg, htobe32(val));
163 #endif
164 }
165 
166 
167 static inline REGWTYPE
nf10bmac_read_be(struct resource * res,REGWTYPE reg,const char * f __unused,const int l __unused)168 nf10bmac_read_be(struct resource *res, REGWTYPE reg,
169     const char *f __unused, const int l __unused)
170 {
171 
172 #ifdef NF10BMAC_64BIT
173 	return (be64toh(bus_read_8(res, reg)));
174 #else
175 	return (be32toh(bus_read_4(res, reg)));
176 #endif
177 }
178 
179 #define	NF10BMAC_WRITE_CTRL(sc, reg, val)				\
180 	nf10bmac_write((sc)->nf10bmac_ctrl_res, (reg), (val),		\
181 	    __func__, __LINE__)
182 #define	NF10BMAC_WRITE(sc, reg, val)					\
183 	nf10bmac_write((sc)->nf10bmac_tx_mem_res, (reg), (val),		\
184 	    __func__, __LINE__)
185 #define	NF10BMAC_READ(sc, reg)						\
186 	nf10bmac_read((sc)->nf10bmac_rx_mem_res, (reg),			\
187 	    __func__, __LINE__)
188 #define	NF10BMAC_WRITE_BE(sc, reg, val)					\
189 	nf10bmac_write_be((sc)->nf10bmac_tx_mem_res, (reg), (val),	\
190 	    __func__, __LINE__)
191 #define	NF10BMAC_READ_BE(sc, reg)					\
192 	nf10bmac_read_be((sc)->nf10bmac_rx_mem_res, (reg),		\
193 	    __func__, __LINE__)
194 
195 #define	NF10BMAC_WRITE_INTR(sc, reg, val, _f, _l)			\
196 	nf10bmac_write((sc)->nf10bmac_intr_res, (reg), (val),		\
197 	    (_f), (_l))
198 
199 #define	NF10BMAC_RX_INTR_CLEAR_DIS(sc)					\
200 	NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CLEAR_DIS, 1,		\
201 	__func__, __LINE__)
202 #define	NF10BMAC_RX_INTR_ENABLE(sc)					\
203 	NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 1,		\
204 	__func__, __LINE__)
205 #define	NF10BMAC_RX_INTR_DISABLE(sc)					\
206 	NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 0,		\
207 	__func__, __LINE__)
208 
209 
210 #ifdef ENABLE_WATCHDOG
211 static void nf10bmac_tick(void *);
212 #endif
213 static int nf10bmac_detach(device_t);
214 
215 devclass_t nf10bmac_devclass;
216 
217 
218 static int
nf10bmac_tx_locked(struct nf10bmac_softc * sc,struct mbuf * m)219 nf10bmac_tx_locked(struct nf10bmac_softc *sc, struct mbuf *m)
220 {
221 	int32_t len, l, ml;
222 	REGWTYPE md, val;
223 
224 	NF10BMAC_LOCK_ASSERT(sc);
225 
226 	KASSERT(m != NULL, ("%s: m is null: sc=%p", __func__, sc));
227 	KASSERT(m->m_flags & M_PKTHDR, ("%s: not a pkthdr: m=%p", __func__, m));
228 	/*
229 	 * Copy to buffer to minimize our pain as we can only store
230 	 * double words which, after the first mbuf gets out of alignment
231 	 * quite quickly.
232 	 */
233 	m_copydata(m, 0, m->m_pkthdr.len, sc->nf10bmac_tx_buf);
234 	len = m->m_pkthdr.len;
235 
236 	/* Write the length at start of packet. */
237 	NF10BMAC_WRITE(sc, NF10BMAC_TX_LEN, len);
238 
239 	/* Write the meta data and data. */
240 	ml = len / sizeof(val);
241 	len -= (ml * sizeof(val));
242 	for (l = 0; l <= ml; l++) {
243 		int32_t cl;
244 
245 		cl = sizeof(val);
246 		md = (NF10BMAC_TUSER_CPU0 << NF10BMAC_DATA_SPORT_SHIFT);
247 		if (l == ml || (len == 0 && l == (ml - 1))) {
248 			if (l == ml && len == 0) {
249 				break;
250 			} else {
251 				uint8_t s;
252 				int sl;
253 
254 				if (l == (ml - 1))
255 					len = sizeof(val);
256 				cl = len;
257 
258 				for (s = 0, sl = len; sl > 0; sl--)
259 					s |= (1 << (sl - 1));
260 				md |= (s & NF10BMAC_DATA_STRB);
261 				md |= NF10BMAC_DATA_LAST;
262 			}
263 		} else {
264 			md |= NF10BMAC_DATA_STRB;
265 		}
266 		NF10BMAC_WRITE(sc, NF10BMAC_TX_META, md);
267 		bcopy(&sc->nf10bmac_tx_buf[l*sizeof(val)], &val, cl);
268 		NF10BMAC_WRITE_BE(sc, NF10BMAC_TX_DATA, val);
269 	}
270 
271 	/* If anyone is interested give them a copy. */
272 	BPF_MTAP(sc->nf10bmac_ifp, m);
273 
274 	m_freem(m);
275 
276 	return (0);
277 }
278 
279 static void
nf10bmac_start_locked(struct ifnet * ifp)280 nf10bmac_start_locked(struct ifnet *ifp)
281 {
282 	struct nf10bmac_softc *sc;
283 	int count, error;
284 
285 	sc = ifp->if_softc;
286 	NF10BMAC_LOCK_ASSERT(sc);
287 
288 	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
289 	    IFF_DRV_RUNNING || (sc->nf10bmac_flags & NF10BMAC_FLAGS_LINK) == 0)
290 		return;
291 
292 #ifdef ENABLE_WATCHDOG
293 	/*
294 	 * Disable the watchdog while sending, we are batching packets.
295 	 * Though we should never reach 5 seconds, and are holding the lock,
296 	 * but who knows.
297 	 */
298 	sc->nf10bmac_watchdog_timer = 0;
299 #endif
300 
301 	/* Send up to MAX_PKTS_PER_TX_LOOP packets. */
302 	for (count = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
303 	    count < NF10BMAC_MAX_PKTS; count++) {
304 		struct mbuf *m;
305 
306 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
307 		if (m == NULL)
308 			break;
309 		error = nf10bmac_tx_locked(sc, m);
310 		if (error != 0)
311 			break;
312 	}
313 
314 #ifdef ENABLE_WATCHDOG
315 done:
316 	/* If the IP core walks into Nekromanteion try to bail out. */
317 	/* XXX-BZ useless until we have direct FIFO fill status feedback. */
318 	if (count > 0)
319 		sc->nf10bmac_watchdog_timer = NF10BMAC_WATCHDOG_TIME;
320 #endif
321 }
322 
323 static void
nf10bmac_start(struct ifnet * ifp)324 nf10bmac_start(struct ifnet *ifp)
325 {
326 	struct nf10bmac_softc *sc;
327 
328 	sc = ifp->if_softc;
329 	NF10BMAC_LOCK(sc);
330 	nf10bmac_start_locked(ifp);
331 	NF10BMAC_UNLOCK(sc);
332 }
333 
334 static void
nf10bmac_eat_packet_munch_munch(struct nf10bmac_softc * sc)335 nf10bmac_eat_packet_munch_munch(struct nf10bmac_softc *sc)
336 {
337 	REGWTYPE md, val;
338 
339 	do {
340 		md = NF10BMAC_READ_BE(sc, NF10BMAC_RX_META);
341 		if ((md & NF10BMAC_DATA_STRB) != 0)
342 			val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA);
343 	} while ((md & NF10BMAC_DATA_STRB) != 0 &&
344 	    (md & NF10BMAC_DATA_LAST) == 0);
345 }
346 
347 static int
nf10bmac_rx_locked(struct nf10bmac_softc * sc)348 nf10bmac_rx_locked(struct nf10bmac_softc *sc)
349 {
350 	struct ifnet *ifp;
351 	struct mbuf *m;
352 	REGWTYPE md, val;
353 	int32_t len, l;
354 
355 	/*
356 	 * General problem here in case we need to sync ourselves to the
357 	 * beginning of a packet.  Length will only be set for the first
358 	 * read, and together with strb we can detect the begining (or
359 	 * skip to tlast).
360 	 */
361 
362 	len = NF10BMAC_READ(sc, NF10BMAC_RX_LEN) & NF10BMAC_DATA_LEN_MASK;
363 	if (len > (MCLBYTES - ETHER_ALIGN)) {
364 		nf10bmac_eat_packet_munch_munch(sc);
365 		return (0);
366 	}
367 
368 	md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
369 	if (len == 0 && (md & NF10BMAC_DATA_STRB) == 0) {
370 		/* No packet data available. */
371 		return (0);
372 	} else if (len == 0 && (md & NF10BMAC_DATA_STRB) != 0) {
373 		/* We are in the middle of a packet. */
374 		nf10bmac_eat_packet_munch_munch(sc);
375 		return (0);
376 	} else if ((md & NF10BMAC_DATA_STRB) == 0) {
377 		/* Invalid length "hint". */
378 		device_printf(sc->nf10bmac_dev,
379 		    "Unexpected length %d on zero strb\n", len);
380 		return (0);
381 	}
382 
383 	/* Assume at this point that we have data and a full packet. */
384 	if ((len + ETHER_ALIGN) >= MINCLSIZE) {
385 		/* Get a cluster. */
386 		m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
387 		if (m == NULL)
388 			return (0);
389 		m->m_len = m->m_pkthdr.len = MCLBYTES;
390 	} else {
391 		/* Hey this still fits into the mbuf+pkthdr. */
392 		m = m_gethdr(M_NOWAIT, MT_DATA);
393 		if (m == NULL)
394 			return (0);
395 		m->m_len = m->m_pkthdr.len = MHLEN;
396 	}
397 	/* Make sure upper layers will be aligned. */
398 	m_adj(m, ETHER_ALIGN);
399 
400 	ifp = sc->nf10bmac_ifp;
401 	l = 0;
402 /*
403 	while ((md & NF10BMAC_DATA_STRB) != 0 && l < len) {
404 */
405 	while (l < len) {
406 		size_t cl;
407 
408 		if ((md & NF10BMAC_DATA_LAST) == 0 &&
409 		    (len - l) < sizeof(val)) {
410 			/*
411 			 * Our length and LAST disagree. We have a valid STRB.
412 			 * We could continue until we fill the mbuf and just
413 			 * log the invlid length "hint".  For now drop the
414 			 * packet on the floor and count the error.
415 			 */
416 			nf10bmac_eat_packet_munch_munch(sc);
417 			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
418 			m_freem(m);
419 			return (0);
420 		} else if ((len - l) <= sizeof(val)) {
421 			cl = len - l;
422 		} else {
423 			cl = sizeof(val);
424 		}
425 
426 		/* Read the first bytes of data as well. */
427 		val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA);
428 		bcopy(&val, (uint8_t *)(m->m_data + l), cl);
429 		l += cl;
430 
431 		if ((md & NF10BMAC_DATA_LAST) != 0 || l >= len)
432 			break;
433 		else {
434 			DELAY(50);
435 			md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
436 		}
437 
438 		cl = 10;
439 		while ((md & NF10BMAC_DATA_STRB) == 0 && cl-- > 0) {
440 			DELAY(10);
441 			md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
442 		}
443 	}
444 	/* We should get out of this loop with tlast and tsrb. */
445 	if ((md & NF10BMAC_DATA_LAST) == 0 || (md & NF10BMAC_DATA_STRB) == 0) {
446 		device_printf(sc->nf10bmac_dev, "Unexpected rx loop end state: "
447 		    "md=0x%08jx len=%d l=%d\n", (uintmax_t)md, len, l);
448 		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
449 		m_freem(m);
450 		return (0);
451 	}
452 
453 	m->m_pkthdr.len = m->m_len = len;
454 	m->m_pkthdr.rcvif = ifp;
455 	if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
456 
457 	NF10BMAC_UNLOCK(sc);
458 	(*ifp->if_input)(ifp, m);
459 	NF10BMAC_LOCK(sc);
460 
461 	return (1);
462 }
463 
464 
465 static int
nf10bmac_stop_locked(struct nf10bmac_softc * sc)466 nf10bmac_stop_locked(struct nf10bmac_softc *sc)
467 {
468 	struct ifnet *ifp;
469 
470 	NF10BMAC_LOCK_ASSERT(sc);
471 
472 #ifdef ENABLE_WATCHDOG
473 	sc->nf10bmac_watchdog_timer = 0;
474 	callout_stop(&sc->nf10bmac_tick);
475 #endif
476 
477 	ifp = sc->nf10bmac_ifp;
478 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
479 	NF10BMAC_RX_INTR_CLEAR_DIS(sc);
480 
481 	sc->nf10bmac_flags &= ~NF10BMAC_FLAGS_LINK;
482 	if_link_state_change(ifp, LINK_STATE_DOWN);
483 
484 	return (0);
485 }
486 
487 static int
nf10bmac_reset(struct nf10bmac_softc * sc)488 nf10bmac_reset(struct nf10bmac_softc *sc)
489 {
490 
491 	/*
492 	 * If we do not have an ether address set, initialize to the same
493 	 * OUI as NetFPGA-10G Linux driver does (which luckily seems
494 	 * unallocated).  We just change the NIC specific part from
495 	 * the slightly long "\0NF10C0" to "\0NFBSD".
496 	 * Oh and we keep the way of setting it from a string as they do.
497 	 * It's an amazing way to hide it.
498 	 * XXX-BZ If NetFPGA gets their own OUI we should fix this.
499 	 */
500 	if (sc->nf10bmac_eth_addr[0] == 0x00 &&
501 	    sc->nf10bmac_eth_addr[1] == 0x00 &&
502 	    sc->nf10bmac_eth_addr[2] == 0x00 &&
503 	    sc->nf10bmac_eth_addr[3] == 0x00 &&
504 	    sc->nf10bmac_eth_addr[4] == 0x00 &&
505 	    sc->nf10bmac_eth_addr[5] == 0x00) {
506 		memcpy(&sc->nf10bmac_eth_addr, "\0NFBSD", ETHER_ADDR_LEN);
507 		sc->nf10bmac_eth_addr[5] += sc->nf10bmac_unit;
508 	}
509 
510 	return (0);
511 }
512 
513 static void
nf10bmac_init_locked(struct nf10bmac_softc * sc)514 nf10bmac_init_locked(struct nf10bmac_softc *sc)
515 {
516 	struct ifnet *ifp;
517 	uint8_t *eaddr;
518 
519 	NF10BMAC_LOCK_ASSERT(sc);
520 	ifp = sc->nf10bmac_ifp;
521 
522 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
523 		return;
524 
525 	/*
526 	 * Must update the ether address if changed.  Given we do not handle
527 	 * in nf10bmac_ioctl() but it's in the general framework, just always
528 	 * do it here before nf10bmac_reset().
529 	 */
530 	eaddr = IF_LLADDR(sc->nf10bmac_ifp);
531 	bcopy(eaddr, &sc->nf10bmac_eth_addr, ETHER_ADDR_LEN);
532 	/* XXX-BZ we do not have any way to tell the NIC our ether address. */
533 
534 	/* Make things frind to halt, cleanup, ... */
535 	nf10bmac_stop_locked(sc);
536 	/* ... reset, ... */
537 	nf10bmac_reset(sc);
538 
539 	/* Memory rings?  DMA engine? MC filter?  MII? */
540 	/* Instead drain the FIFO; or at least a possible first packet.. */
541 	nf10bmac_eat_packet_munch_munch(sc);
542 
543 #ifdef DEVICE_POLLING
544 	/* Only enable interrupts if we are not polling. */
545 	if (ifp->if_capenable & IFCAP_POLLING) {
546 		NF10BMAC_RX_INTR_CLEAR_DIS(sc);
547 	} else
548 #endif
549 	{
550 		NF10BMAC_RX_INTR_ENABLE(sc);
551 	}
552 
553 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
554 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
555 
556 	/* We have no underlying media, fake link state. */
557 	sc->nf10bmac_flags = NF10BMAC_FLAGS_LINK;	/* Always up. */
558 	if_link_state_change(sc->nf10bmac_ifp, LINK_STATE_UP);
559 
560 #ifdef ENABLE_WATCHDOG
561 	callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc);
562 #endif
563 }
564 
565 static void
nf10bmac_init(void * xsc)566 nf10bmac_init(void *xsc)
567 {
568 	struct nf10bmac_softc *sc;
569 
570 	sc = (struct nf10bmac_softc *)xsc;
571 	NF10BMAC_LOCK(sc);
572 	nf10bmac_init_locked(sc);
573 	NF10BMAC_UNLOCK(sc);
574 }
575 
576 #ifdef ENABLE_WATCHDOG
577 static void
nf10bmac_watchdog(struct nf10bmac_softc * sc)578 nf10bmac_watchdog(struct nf10bmac_softc *sc)
579 {
580 
581 	NF10BMAC_LOCK_ASSERT(sc);
582 
583 	if (sc->nf10bmac_watchdog_timer == 0 || --sc->nf10bmac_watchdog_timer > 0)
584 		return;
585 
586 	device_printf(sc->nf10bmac_dev, "watchdog timeout\n");
587 	sc->nf10if_inc_counter(bmac_ifp, IFCOUNTER_OERRORS, 1);
588 
589 	sc->nf10bmac_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
590 	nf10bmac_init_locked(sc);
591 
592 	if (!IFQ_DRV_IS_EMPTY(&sc->nf10bmac_ifp->if_snd))
593 		nf10bmac_start_locked(sc->nf10bmac_ifp);
594 }
595 
596 static void
nf10bmac_tick(void * xsc)597 nf10bmac_tick(void *xsc)
598 {
599 	struct nf10bmac_softc *sc;
600 	struct ifnet *ifp;
601 
602 	sc = (struct nf10bmac_softc *)xsc;
603 	NF10BMAC_LOCK_ASSERT(sc);
604 	ifp = sc->nf10bmac_ifp;
605 
606 	nf10bmac_watchdog(sc);
607 	callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc);
608 }
609 #endif
610 
611 static void
nf10bmac_intr(void * arg)612 nf10bmac_intr(void *arg)
613 {
614 	struct nf10bmac_softc *sc;
615 	struct ifnet *ifp;
616 	int rx_npkts;
617 
618 	sc = (struct nf10bmac_softc *)arg;
619 	ifp = sc->nf10bmac_ifp;
620 
621 	NF10BMAC_LOCK(sc);
622 #ifdef DEVICE_POLLING
623 	if (ifp->if_capenable & IFCAP_POLLING) {
624 		NF10BMAC_UNLOCK(sc);
625 		return;
626 	}
627 #endif
628 
629 	/* NF10BMAC_RX_INTR_DISABLE(sc); */
630 	NF10BMAC_RX_INTR_CLEAR_DIS(sc);
631 
632 	/* We only have an RX interrupt and no status information. */
633 	rx_npkts = 0;
634 	while (rx_npkts < NF10BMAC_MAX_PKTS) {
635 		int c;
636 
637 		c = nf10bmac_rx_locked(sc);
638 		rx_npkts += c;
639 		if (c == 0)
640 			break;
641 	}
642 
643 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
644 		/* Re-enable interrupts. */
645 		NF10BMAC_RX_INTR_ENABLE(sc);
646 
647 		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
648 			nf10bmac_start_locked(ifp);
649 	}
650 	NF10BMAC_UNLOCK(sc);
651 }
652 
653 
654 #ifdef DEVICE_POLLING
655 static int
nf10bmac_poll(struct ifnet * ifp,enum poll_cmd cmd,int count)656 nf10bmac_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
657 {
658 	struct nf10bmac_softc *sc;
659 	int rx_npkts = 0;
660 
661 	sc = ifp->if_softc;
662 	NF10BMAC_LOCK(sc);
663 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
664 		NF10BMAC_UNLOCK(sc);
665 		return (rx_npkts);
666 	}
667 
668 	while (rx_npkts < count) {
669 		int c;
670 
671 		c = nf10bmac_rx_locked(sc);
672 		rx_npkts += c;
673 		if (c == 0)
674 			break;
675 	}
676 	nf10bmac_start_locked(ifp);
677 
678 	if (rx_npkts > 0 || cmd == POLL_AND_CHECK_STATUS) {
679 		/* We currently cannot do much. */
680 		;
681 	}
682 
683         NF10BMAC_UNLOCK(sc);
684         return (rx_npkts);
685 }
686 #else
687 #error We only support polling mode
688 #endif /* DEVICE_POLLING */
689 
690 static int
nf10bmac_media_change(struct ifnet * ifp __unused)691 nf10bmac_media_change(struct ifnet *ifp __unused)
692 {
693 
694 	/* Do nothing. */
695 	return (0);
696 }
697 
698 static void
nf10bmac_media_status(struct ifnet * ifp __unused,struct ifmediareq * imr)699 nf10bmac_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr)
700 {
701 
702 	imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
703 	imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX;
704 }
705 
706 static int
nf10bmac_ioctl(struct ifnet * ifp,u_long command,caddr_t data)707 nf10bmac_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
708 {
709 	struct nf10bmac_softc *sc;
710 	struct ifreq *ifr;
711 	int error, mask;
712 
713 	error = 0;
714 	sc = ifp->if_softc;
715 	ifr = (struct ifreq *)data;
716 
717 	switch (command) {
718 	case SIOCSIFFLAGS:
719 		NF10BMAC_LOCK(sc);
720 		if (ifp->if_flags & IFF_UP) {
721 			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
722 			    ((ifp->if_flags ^ sc->nf10bmac_if_flags) &
723 			    (IFF_PROMISC | IFF_ALLMULTI)) != 0)
724 				/* Nothing we can do. */ ;
725 			else
726 				nf10bmac_init_locked(sc);
727 		} else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
728 			nf10bmac_stop_locked(sc);
729 		sc->nf10bmac_if_flags = ifp->if_flags;
730 		NF10BMAC_UNLOCK(sc);
731 		break;
732 	case SIOCSIFCAP:
733 		NF10BMAC_LOCK(sc);
734 		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
735 #ifdef DEVICE_POLLING
736 		if ((mask & IFCAP_POLLING) != 0 &&
737 		    (IFCAP_POLLING & ifp->if_capabilities) != 0) {
738 			ifp->if_capenable ^= IFCAP_POLLING;
739 			if ((IFCAP_POLLING & ifp->if_capenable) != 0) {
740 
741 				error = ether_poll_register(nf10bmac_poll, ifp);
742 				if (error != 0) {
743 					NF10BMAC_UNLOCK(sc);
744 					break;
745 				}
746 
747 				NF10BMAC_RX_INTR_CLEAR_DIS(sc);
748 
749 			/*
750 			 * Do not allow disabling of polling if we do
751 			 * not have interrupts.
752 			 */
753 			} else if (sc->nf10bmac_rx_irq_res != NULL) {
754 				error = ether_poll_deregister(ifp);
755 				/* Enable interrupts. */
756 				NF10BMAC_RX_INTR_ENABLE(sc);
757 			} else {
758 				ifp->if_capenable ^= IFCAP_POLLING;
759 				error = EINVAL;
760 			}
761 		}
762 #endif /* DEVICE_POLLING */
763                 NF10BMAC_UNLOCK(sc);
764                 break;
765 	case SIOCGIFMEDIA:
766 	case SIOCSIFMEDIA:
767                 error = ifmedia_ioctl(ifp, ifr, &sc->nf10bmac_media, command);
768 		break;
769 	default:
770 		error = ether_ioctl(ifp, command, data);
771 		break;
772 	}
773 
774 	return (error);
775 }
776 
777 /*
778  * Generic device handling routines.
779  */
780 int
nf10bmac_attach(device_t dev)781 nf10bmac_attach(device_t dev)
782 {
783 	struct nf10bmac_softc *sc;
784 	struct ifnet *ifp;
785 	int error;
786 
787 	sc = device_get_softc(dev);
788 
789 	mtx_init(&sc->nf10bmac_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
790 	    MTX_DEF);
791 
792 #ifdef	ENABLE_WATCHDOG
793 	callout_init_mtx(&sc->nf10bmac_tick, &sc->nf10bmac_mtx, 0);
794 #endif
795 
796 	sc->nf10bmac_tx_buf = malloc(ETHER_MAX_LEN_JUMBO, M_DEVBUF, M_WAITOK);
797 
798 	/* Reset the adapter. */
799 	nf10bmac_reset(sc);
800 
801 	/* Setup interface. */
802 	ifp = sc->nf10bmac_ifp = if_alloc(IFT_ETHER);
803 	if (ifp == NULL) {
804 		device_printf(dev, "if_alloc() failed\n");
805 		error = ENOSPC;
806 		goto err;
807 	}
808 	ifp->if_softc = sc;
809 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
810 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; /* | IFF_MULTICAST; */
811 	ifp->if_ioctl = nf10bmac_ioctl;
812 	ifp->if_start = nf10bmac_start;
813 	ifp->if_init = nf10bmac_init;
814 	IFQ_SET_MAXLEN(&ifp->if_snd, NF10BMAC_MAX_PKTS - 1);
815 	ifp->if_snd.ifq_drv_maxlen = NF10BMAC_MAX_PKTS - 1;
816 	IFQ_SET_READY(&ifp->if_snd);
817 
818 	/* Call media-indepedent attach routine. */
819 	ether_ifattach(ifp, sc->nf10bmac_eth_addr);
820 
821 	/* Tell the upper layer(s) about vlan mtu support. */
822 	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
823 	ifp->if_capabilities |= IFCAP_VLAN_MTU;
824 	ifp->if_capenable = ifp->if_capabilities;
825 #ifdef DEVICE_POLLING
826 	/* We will enable polling by default if no irqs available. See below. */
827 	ifp->if_capabilities |= IFCAP_POLLING;
828 #endif
829 
830 	/* We need more media attention.  Fake it! */
831         ifmedia_init(&sc->nf10bmac_media, 0, nf10bmac_media_change,
832 	    nf10bmac_media_status);
833         ifmedia_add(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T, 0, NULL);
834         ifmedia_set(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T);
835 
836 	/* Initialise. */
837 	error = 0;
838 
839 	/* Hook up interrupts. Well the one. */
840 	if (sc->nf10bmac_rx_irq_res != NULL) {
841 		error = bus_setup_intr(dev, sc->nf10bmac_rx_irq_res,
842 		    INTR_TYPE_NET | INTR_MPSAFE, NULL, nf10bmac_intr,
843 		    sc, &sc->nf10bmac_rx_intrhand);
844 		if (error != 0) {
845 			device_printf(dev, "enabling RX IRQ failed\n");
846 			ether_ifdetach(ifp);
847 			goto err;
848 		}
849 	}
850 
851 	if ((ifp->if_capenable & IFCAP_POLLING) != 0 ||
852 	    sc->nf10bmac_rx_irq_res == NULL) {
853 #ifdef DEVICE_POLLING
854 		/* If not on and no IRQs force it on. */
855 		if (sc->nf10bmac_rx_irq_res == NULL) {
856 			ifp->if_capenable |= IFCAP_POLLING;
857 			device_printf(dev,
858 			    "forcing to polling due to no interrupts\n");
859 		}
860 		error = ether_poll_register(nf10bmac_poll, ifp);
861 		if (error != 0)
862 			goto err;
863 #else
864 		device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n");
865 		error = ENXIO;
866 #endif
867 	} else {
868 		NF10BMAC_RX_INTR_ENABLE(sc);
869 	}
870 
871 err:
872 	if (error != 0)
873 		nf10bmac_detach(dev);
874 
875 	return (error);
876 }
877 
878 static int
nf10bmac_detach(device_t dev)879 nf10bmac_detach(device_t dev)
880 {
881 	struct nf10bmac_softc *sc;
882 	struct ifnet *ifp;
883 
884 	sc = device_get_softc(dev);
885 	KASSERT(mtx_initialized(&sc->nf10bmac_mtx),
886 	    ("%s: mutex not initialized", device_get_nameunit(dev)));
887 	ifp = sc->nf10bmac_ifp;
888 
889 #ifdef DEVICE_POLLING
890 	if (ifp->if_capenable & IFCAP_POLLING)
891 		ether_poll_deregister(ifp);
892 #endif
893 
894 	/* Only cleanup if attach succeeded. */
895 	if (device_is_attached(dev)) {
896 		NF10BMAC_LOCK(sc);
897 		nf10bmac_stop_locked(sc);
898 		NF10BMAC_UNLOCK(sc);
899 #ifdef ENABLE_WATCHDOG
900 		callout_drain(&sc->nf10bmac_tick);
901 #endif
902 		ether_ifdetach(ifp);
903 	}
904 
905 	if (sc->nf10bmac_rx_intrhand)
906 		bus_teardown_intr(dev, sc->nf10bmac_rx_irq_res,
907 		    sc->nf10bmac_rx_intrhand);
908 
909 	if (ifp != NULL)
910 		if_free(ifp);
911 	ifmedia_removeall(&sc->nf10bmac_media);
912 
913 	mtx_destroy(&sc->nf10bmac_mtx);
914 
915 	return (0);
916 }
917 
918 /* Shared with the attachment specific (e.g., fdt) implementation. */
919 void
nf10bmac_detach_resources(device_t dev)920 nf10bmac_detach_resources(device_t dev)
921 {
922 	struct nf10bmac_softc *sc;
923 
924 	sc = device_get_softc(dev);
925 
926 	if (sc->nf10bmac_rx_irq_res != NULL) {
927 		bus_release_resource(dev, SYS_RES_IRQ, sc->nf10bmac_rx_irq_rid,
928 		    sc->nf10bmac_rx_irq_res);
929 		sc->nf10bmac_rx_irq_res = NULL;
930 	}
931 	if (sc->nf10bmac_intr_res != NULL) {
932 		bus_release_resource(dev, SYS_RES_MEMORY,
933 		    sc->nf10bmac_intr_rid, sc->nf10bmac_intr_res);
934 		sc->nf10bmac_intr_res = NULL;
935 	}
936 	if (sc->nf10bmac_rx_mem_res != NULL) {
937 		bus_release_resource(dev, SYS_RES_MEMORY,
938 		    sc->nf10bmac_rx_mem_rid, sc->nf10bmac_rx_mem_res);
939 		sc->nf10bmac_rx_mem_res = NULL;
940 	}
941 	if (sc->nf10bmac_tx_mem_res != NULL) {
942 		bus_release_resource(dev, SYS_RES_MEMORY,
943 		    sc->nf10bmac_tx_mem_rid, sc->nf10bmac_tx_mem_res);
944 		sc->nf10bmac_tx_mem_res = NULL;
945 	}
946 	if (sc->nf10bmac_ctrl_res != NULL) {
947 		bus_release_resource(dev, SYS_RES_MEMORY,
948 		    sc->nf10bmac_ctrl_rid, sc->nf10bmac_ctrl_res);
949 		sc->nf10bmac_ctrl_res = NULL;
950 	}
951 }
952 
953 int
nf10bmac_detach_dev(device_t dev)954 nf10bmac_detach_dev(device_t dev)
955 {
956 	int error;
957 
958 	error = nf10bmac_detach(dev);
959 	if (error) {
960 		/* We are basically in undefined state now. */
961 		device_printf(dev, "nf10bmac_detach() failed: %d\n", error);
962 		return (error);
963 	}
964 
965 	nf10bmac_detach_resources(dev);
966 
967 	return (0);
968 }
969 
970 /* end */
971