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