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