xref: /f-stack/freebsd/mips/cavium/octe/octe.c (revision 22ce4aff)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2010 Juli Mallett <[email protected]>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 /*
32  * Cavium Octeon Ethernet devices.
33  *
34  * XXX This file should be moved to if_octe.c
35  * XXX The driver may have sufficient locking but we need locking to protect
36  *     the interfaces presented here, right?
37  */
38 
39 #include "opt_inet.h"
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/bus.h>
44 #include <sys/endian.h>
45 #include <sys/kernel.h>
46 #include <sys/mbuf.h>
47 #include <sys/lock.h>
48 #include <sys/module.h>
49 #include <sys/mutex.h>
50 #include <sys/rman.h>
51 #include <sys/socket.h>
52 #include <sys/sockio.h>
53 #include <sys/sysctl.h>
54 
55 #include <net/bpf.h>
56 #include <net/ethernet.h>
57 #include <net/if.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_types.h>
61 #include <net/if_var.h>
62 #include <net/if_vlan_var.h>
63 
64 #ifdef INET
65 #include <netinet/in.h>
66 #include <netinet/if_ether.h>
67 #endif
68 
69 #include <dev/mii/mii.h>
70 #include <dev/mii/miivar.h>
71 
72 #include "wrapper-cvmx-includes.h"
73 #include "cavium-ethernet.h"
74 
75 #include "ethernet-common.h"
76 #include "ethernet-defines.h"
77 #include "ethernet-mdio.h"
78 #include "ethernet-tx.h"
79 
80 #include "miibus_if.h"
81 
82 #define	OCTE_TX_LOCK(priv)	mtx_lock(&(priv)->tx_mtx)
83 #define	OCTE_TX_UNLOCK(priv)	mtx_unlock(&(priv)->tx_mtx)
84 
85 static int		octe_probe(device_t);
86 static int		octe_attach(device_t);
87 static int		octe_detach(device_t);
88 static int		octe_shutdown(device_t);
89 
90 static int		octe_miibus_readreg(device_t, int, int);
91 static int		octe_miibus_writereg(device_t, int, int, int);
92 
93 static void		octe_init(void *);
94 static void		octe_stop(void *);
95 static int		octe_transmit(struct ifnet *, struct mbuf *);
96 
97 static int		octe_mii_medchange(struct ifnet *);
98 static void		octe_mii_medstat(struct ifnet *, struct ifmediareq *);
99 
100 static int		octe_medchange(struct ifnet *);
101 static void		octe_medstat(struct ifnet *, struct ifmediareq *);
102 
103 static int		octe_ioctl(struct ifnet *, u_long, caddr_t);
104 
105 static device_method_t octe_methods[] = {
106 	/* Device interface */
107 	DEVMETHOD(device_probe,		octe_probe),
108 	DEVMETHOD(device_attach,	octe_attach),
109 	DEVMETHOD(device_detach,	octe_detach),
110 	DEVMETHOD(device_shutdown,	octe_shutdown),
111 
112 	/* MII interface */
113 	DEVMETHOD(miibus_readreg,	octe_miibus_readreg),
114 	DEVMETHOD(miibus_writereg,	octe_miibus_writereg),
115 	{ 0, 0 }
116 };
117 
118 static driver_t octe_driver = {
119 	"octe",
120 	octe_methods,
121 	sizeof (cvm_oct_private_t),
122 };
123 
124 static devclass_t octe_devclass;
125 
126 DRIVER_MODULE(octe, octebus, octe_driver, octe_devclass, 0, 0);
127 DRIVER_MODULE(miibus, octe, miibus_driver, miibus_devclass, 0, 0);
128 
129 static int
octe_probe(device_t dev)130 octe_probe(device_t dev)
131 {
132 	return (0);
133 }
134 
135 static int
octe_attach(device_t dev)136 octe_attach(device_t dev)
137 {
138 	struct ifnet *ifp;
139 	cvm_oct_private_t *priv;
140 	device_t child;
141 	unsigned qos;
142 	int error;
143 
144 	priv = device_get_softc(dev);
145 	ifp = priv->ifp;
146 
147 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
148 
149 	if (priv->phy_id != -1) {
150 		if (priv->phy_device == NULL) {
151 			error = mii_attach(dev, &priv->miibus, ifp,
152 			    octe_mii_medchange, octe_mii_medstat,
153 			    BMSR_DEFCAPMASK, priv->phy_id, MII_OFFSET_ANY, 0);
154 			if (error != 0)
155 				device_printf(dev, "attaching PHYs failed\n");
156 		} else {
157 			child = device_add_child(dev, priv->phy_device, -1);
158 			if (child == NULL)
159 				device_printf(dev, "missing phy %u device %s\n", priv->phy_id, priv->phy_device);
160 		}
161 	}
162 
163 	if (priv->miibus == NULL) {
164 		ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat);
165 
166 		ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
167 		ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
168 	}
169 
170 	/*
171 	 * XXX
172 	 * We don't support programming the multicast filter right now, although it
173 	 * ought to be easy enough.  (Presumably it's just a matter of putting
174 	 * multicast addresses in the CAM?)
175 	 */
176 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI;
177 	ifp->if_init = octe_init;
178 	ifp->if_ioctl = octe_ioctl;
179 
180 	priv->if_flags = ifp->if_flags;
181 
182 	mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF);
183 
184 	for (qos = 0; qos < 16; qos++) {
185 		mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF);
186 		IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH);
187 	}
188 
189 	ether_ifattach(ifp, priv->mac);
190 
191 	ifp->if_transmit = octe_transmit;
192 
193 	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
194 	ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM;
195 	ifp->if_capenable = ifp->if_capabilities;
196 	ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
197 
198 	OCTE_TX_LOCK(priv);
199 	IFQ_SET_MAXLEN(&ifp->if_snd, MAX_OUT_QUEUE_DEPTH);
200 	ifp->if_snd.ifq_drv_maxlen = MAX_OUT_QUEUE_DEPTH;
201 	IFQ_SET_READY(&ifp->if_snd);
202 	OCTE_TX_UNLOCK(priv);
203 
204 	return (bus_generic_attach(dev));
205 }
206 
207 static int
octe_detach(device_t dev)208 octe_detach(device_t dev)
209 {
210 	return (0);
211 }
212 
213 static int
octe_shutdown(device_t dev)214 octe_shutdown(device_t dev)
215 {
216 	return (octe_detach(dev));
217 }
218 
219 static int
octe_miibus_readreg(device_t dev,int phy,int reg)220 octe_miibus_readreg(device_t dev, int phy, int reg)
221 {
222 	cvm_oct_private_t *priv;
223 
224 	priv = device_get_softc(dev);
225 
226 	/*
227 	 * Try interface-specific MII routine.
228 	 */
229 	if (priv->mdio_read != NULL)
230 		return (priv->mdio_read(priv->ifp, phy, reg));
231 
232 	/*
233 	 * Try generic MII routine.
234 	 */
235 	KASSERT(phy == priv->phy_id,
236 	    ("read from phy %u but our phy is %u", phy, priv->phy_id));
237 	return (cvm_oct_mdio_read(priv->ifp, phy, reg));
238 }
239 
240 static int
octe_miibus_writereg(device_t dev,int phy,int reg,int val)241 octe_miibus_writereg(device_t dev, int phy, int reg, int val)
242 {
243 	cvm_oct_private_t *priv;
244 
245 	priv = device_get_softc(dev);
246 
247 	/*
248 	 * Try interface-specific MII routine.
249 	 */
250 	if (priv->mdio_write != NULL) {
251 		priv->mdio_write(priv->ifp, phy, reg, val);
252 		return (0);
253 	}
254 
255 	/*
256 	 * Try generic MII routine.
257 	 */
258 	KASSERT(phy == priv->phy_id,
259 	    ("write to phy %u but our phy is %u", phy, priv->phy_id));
260 	cvm_oct_mdio_write(priv->ifp, phy, reg, val);
261 
262 	return (0);
263 }
264 
265 static void
octe_init(void * arg)266 octe_init(void *arg)
267 {
268 	struct ifnet *ifp;
269 	cvm_oct_private_t *priv;
270 
271 	priv = arg;
272 	ifp = priv->ifp;
273 
274 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
275 		octe_stop(priv);
276 
277 	if (priv->open != NULL)
278 		priv->open(ifp);
279 
280 	if (((ifp->if_flags ^ priv->if_flags) & (IFF_ALLMULTI | IFF_MULTICAST | IFF_PROMISC)) != 0)
281 		cvm_oct_common_set_multicast_list(ifp);
282 
283 	cvm_oct_common_set_mac_address(ifp, IF_LLADDR(ifp));
284 
285 	cvm_oct_common_poll(ifp);
286 
287 	if (priv->miibus != NULL)
288 		mii_mediachg(device_get_softc(priv->miibus));
289 
290 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
291 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
292 }
293 
294 static void
octe_stop(void * arg)295 octe_stop(void *arg)
296 {
297 	struct ifnet *ifp;
298 	cvm_oct_private_t *priv;
299 
300 	priv = arg;
301 	ifp = priv->ifp;
302 
303 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
304 		return;
305 
306 	if (priv->stop != NULL)
307 		priv->stop(ifp);
308 
309 	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
310 }
311 
312 static int
octe_transmit(struct ifnet * ifp,struct mbuf * m)313 octe_transmit(struct ifnet *ifp, struct mbuf *m)
314 {
315 	cvm_oct_private_t *priv;
316 
317 	priv = ifp->if_softc;
318 
319 	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
320 	    IFF_DRV_RUNNING) {
321 		m_freem(m);
322 		return (0);
323 	}
324 
325 	return (cvm_oct_xmit(m, ifp));
326 }
327 
328 static int
octe_mii_medchange(struct ifnet * ifp)329 octe_mii_medchange(struct ifnet *ifp)
330 {
331 	cvm_oct_private_t *priv;
332 	struct mii_data *mii;
333 	struct mii_softc *miisc;
334 
335 	priv = ifp->if_softc;
336 	mii = device_get_softc(priv->miibus);
337 	LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
338 		PHY_RESET(miisc);
339 	mii_mediachg(mii);
340 
341 	return (0);
342 }
343 
344 static void
octe_mii_medstat(struct ifnet * ifp,struct ifmediareq * ifm)345 octe_mii_medstat(struct ifnet *ifp, struct ifmediareq *ifm)
346 {
347 	cvm_oct_private_t *priv;
348 	struct mii_data *mii;
349 
350 	priv = ifp->if_softc;
351 	mii = device_get_softc(priv->miibus);
352 
353 	mii_pollstat(mii);
354 	ifm->ifm_active = mii->mii_media_active;
355 	ifm->ifm_status = mii->mii_media_status;
356 }
357 
358 static int
octe_medchange(struct ifnet * ifp)359 octe_medchange(struct ifnet *ifp)
360 {
361 	return (ENOTSUP);
362 }
363 
364 static void
octe_medstat(struct ifnet * ifp,struct ifmediareq * ifm)365 octe_medstat(struct ifnet *ifp, struct ifmediareq *ifm)
366 {
367 	cvm_oct_private_t *priv;
368 	cvmx_helper_link_info_t link_info;
369 
370 	priv = ifp->if_softc;
371 
372 	ifm->ifm_status = IFM_AVALID;
373 	ifm->ifm_active = IFT_ETHER;
374 
375 	if (priv->poll == NULL)
376 		return;
377 	priv->poll(ifp);
378 
379 	link_info.u64 = priv->link_info;
380 
381 	if (!link_info.s.link_up)
382 		return;
383 
384 	ifm->ifm_status |= IFM_ACTIVE;
385 
386 	switch (link_info.s.speed) {
387 	case 10:
388 		ifm->ifm_active |= IFM_10_T;
389 		break;
390 	case 100:
391 		ifm->ifm_active |= IFM_100_TX;
392 		break;
393 	case 1000:
394 		ifm->ifm_active |= IFM_1000_T;
395 		break;
396 	case 10000:
397 		ifm->ifm_active |= IFM_10G_T;
398 		break;
399 	}
400 
401 	if (link_info.s.full_duplex)
402 		ifm->ifm_active |= IFM_FDX;
403 	else
404 		ifm->ifm_active |= IFM_HDX;
405 }
406 
407 static int
octe_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)408 octe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
409 {
410 	cvm_oct_private_t *priv;
411 	struct mii_data *mii;
412 	struct ifreq *ifr;
413 #ifdef INET
414 	struct ifaddr *ifa;
415 #endif
416 	int error;
417 
418 	priv = ifp->if_softc;
419 	ifr = (struct ifreq *)data;
420 #ifdef INET
421 	ifa = (struct ifaddr *)data;
422 #endif
423 
424 	switch (cmd) {
425 	case SIOCSIFADDR:
426 #ifdef INET
427 		/*
428 		 * Avoid reinitialization unless it's necessary.
429 		 */
430 		if (ifa->ifa_addr->sa_family == AF_INET) {
431 			ifp->if_flags |= IFF_UP;
432 			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
433 				octe_init(priv);
434 			arp_ifinit(ifp, ifa);
435 
436 			return (0);
437 		}
438 #endif
439 		error = ether_ioctl(ifp, cmd, data);
440 		if (error != 0)
441 			return (error);
442 		return (0);
443 
444 	case SIOCSIFFLAGS:
445 		if (ifp->if_flags == priv->if_flags)
446 			return (0);
447 		if ((ifp->if_flags & IFF_UP) != 0) {
448 			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
449 				octe_init(priv);
450 		} else {
451 			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
452 				octe_stop(priv);
453 		}
454 		priv->if_flags = ifp->if_flags;
455 		return (0);
456 
457 	case SIOCSIFCAP:
458 		/*
459 		 * Just change the capabilities in software, currently none
460 		 * require reprogramming hardware, they just toggle whether we
461 		 * make use of already-present facilities in software.
462 		 */
463 		ifp->if_capenable = ifr->ifr_reqcap;
464 		return (0);
465 
466 	case SIOCSIFMTU:
467 		error = cvm_oct_common_change_mtu(ifp, ifr->ifr_mtu);
468 		if (error != 0)
469 			return (EINVAL);
470 		return (0);
471 
472 	case SIOCSIFMEDIA:
473 	case SIOCGIFMEDIA:
474 		if (priv->miibus != NULL) {
475 			mii = device_get_softc(priv->miibus);
476 			error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
477 			if (error != 0)
478 				return (error);
479 			return (0);
480 		}
481 		error = ifmedia_ioctl(ifp, ifr, &priv->media, cmd);
482 		if (error != 0)
483 			return (error);
484 		return (0);
485 
486 	default:
487 		error = ether_ioctl(ifp, cmd, data);
488 		if (error != 0)
489 			return (error);
490 		return (0);
491 	}
492 }
493