1 /*-
2 * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: releng/8.4/sys/mips/cavium/octe/octe.c 225492 2011-09-11 20:38:33Z marius $
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 void octe_start(struct ifnet *);
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
114 { 0, 0 }
115 };
116
117 static driver_t octe_driver = {
118 "octe",
119 octe_methods,
120 sizeof (cvm_oct_private_t),
121 };
122
123 static devclass_t octe_devclass;
124
125 DRIVER_MODULE(octe, octebus, octe_driver, octe_devclass, 0, 0);
126 DRIVER_MODULE(miibus, octe, miibus_driver, miibus_devclass, 0, 0);
127
128 static driver_t pow_driver = {
129 "pow",
130 octe_methods,
131 sizeof (cvm_oct_private_t),
132 };
133
134 static devclass_t pow_devclass;
135
136 DRIVER_MODULE(pow, octebus, pow_driver, pow_devclass, 0, 0);
137
138 static int
139 octe_probe(device_t dev)
140 {
141 return (0);
142 }
143
144 static int
145 octe_attach(device_t dev)
146 {
147 struct ifnet *ifp;
148 cvm_oct_private_t *priv;
149 device_t child;
150 unsigned qos;
151 int error;
152
153 priv = device_get_softc(dev);
154 ifp = priv->ifp;
155
156 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
157
158 if (priv->phy_id != -1) {
159 if (priv->phy_device == NULL) {
160 error = mii_phy_probe(dev, &priv->miibus, octe_mii_medchange,
161 octe_mii_medstat);
162 if (error != 0)
163 device_printf(dev, "missing phy %u\n", priv->phy_id);
164 } else {
165 child = device_add_child(dev, priv->phy_device, -1);
166 if (child == NULL)
167 device_printf(dev, "missing phy %u device %s\n", priv->phy_id, priv->phy_device);
168 }
169 }
170
171 if (priv->miibus == NULL) {
172 ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat);
173
174 ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
175 ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
176 }
177
178 /*
179 * XXX
180 * We don't support programming the multicast filter right now, although it
181 * ought to be easy enough. (Presumably it's just a matter of putting
182 * multicast addresses in the CAM?)
183 */
184 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI;
185 ifp->if_init = octe_init;
186 ifp->if_ioctl = octe_ioctl;
187 ifp->if_start = octe_start;
188
189 priv->if_flags = ifp->if_flags;
190
191 mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF);
192
193 for (qos = 0; qos < 16; qos++) {
194 mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF);
195 IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH);
196 }
197
198 ether_ifattach(ifp, priv->mac);
199
200 ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
201 ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM;
202 ifp->if_capenable = ifp->if_capabilities;
203 ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
204
205 OCTE_TX_LOCK(priv);
206 IFQ_SET_MAXLEN(&ifp->if_snd, MAX_OUT_QUEUE_DEPTH);
207 ifp->if_snd.ifq_drv_maxlen = MAX_OUT_QUEUE_DEPTH;
208 IFQ_SET_READY(&ifp->if_snd);
209 OCTE_TX_UNLOCK(priv);
210
211 return (bus_generic_attach(dev));
212 }
213
214 static int
215 octe_detach(device_t dev)
216 {
217 return (0);
218 }
219
220 static int
221 octe_shutdown(device_t dev)
222 {
223 return (octe_detach(dev));
224 }
225
226 static int
227 octe_miibus_readreg(device_t dev, int phy, int reg)
228 {
229 cvm_oct_private_t *priv;
230
231 priv = device_get_softc(dev);
232
233 /*
234 * Try interface-specific MII routine.
235 */
236 if (priv->mdio_read != NULL)
237 return (priv->mdio_read(priv->ifp, phy, reg));
238
239 /*
240 * Try generic MII routine.
241 */
242 if (phy != priv->phy_id)
243 return (0);
244
245 return (cvm_oct_mdio_read(priv->ifp, phy, reg));
246 }
247
248 static int
249 octe_miibus_writereg(device_t dev, int phy, int reg, int val)
250 {
251 cvm_oct_private_t *priv;
252
253 priv = device_get_softc(dev);
254
255 /*
256 * Try interface-specific MII routine.
257 */
258 if (priv->mdio_write != NULL) {
259 priv->mdio_write(priv->ifp, phy, reg, val);
260 return (0);
261 }
262
263 /*
264 * Try generic MII routine.
265 */
266 KASSERT(phy == priv->phy_id,
267 ("write to phy %u but our phy is %u", phy, priv->phy_id));
268 cvm_oct_mdio_write(priv->ifp, phy, reg, val);
269
270 return (0);
271 }
272
273 static void
274 octe_init(void *arg)
275 {
276 struct ifnet *ifp;
277 cvm_oct_private_t *priv;
278
279 priv = arg;
280 ifp = priv->ifp;
281
282 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
283 octe_stop(priv);
284
285 if (priv->open != NULL)
286 priv->open(ifp);
287
288 if (((ifp->if_flags ^ priv->if_flags) & (IFF_ALLMULTI | IFF_MULTICAST | IFF_PROMISC)) != 0)
289 cvm_oct_common_set_multicast_list(ifp);
290
291 cvm_oct_common_set_mac_address(ifp, IF_LLADDR(ifp));
292
293 if (priv->poll != NULL)
294 priv->poll(ifp);
295 if (priv->miibus != NULL)
296 mii_mediachg(device_get_softc(priv->miibus));
297
298 ifp->if_drv_flags |= IFF_DRV_RUNNING;
299 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
300 }
301
302 static void
303 octe_stop(void *arg)
304 {
305 struct ifnet *ifp;
306 cvm_oct_private_t *priv;
307
308 priv = arg;
309 ifp = priv->ifp;
310
311 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
312 return;
313
314 if (priv->stop != NULL)
315 priv->stop(ifp);
316
317 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
318 }
319
320 static void
321 octe_start(struct ifnet *ifp)
322 {
323 cvm_oct_private_t *priv;
324 struct mbuf *m;
325 int error;
326
327 priv = ifp->if_softc;
328
329 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING)
330 return;
331
332 OCTE_TX_LOCK(priv);
333 while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
334 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
335
336 OCTE_TX_UNLOCK(priv);
337
338 if (priv->queue != -1) {
339 error = cvm_oct_xmit(m, ifp);
340 } else {
341 error = cvm_oct_xmit_pow(m, ifp);
342 }
343
344 if (error != 0) {
345 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
346 return;
347 }
348
349 OCTE_TX_LOCK(priv);
350 }
351 OCTE_TX_UNLOCK(priv);
352 }
353
354 static int
355 octe_mii_medchange(struct ifnet *ifp)
356 {
357 cvm_oct_private_t *priv;
358 struct mii_data *mii;
359 struct mii_softc *miisc;
360
361 priv = ifp->if_softc;
362 mii = device_get_softc(priv->miibus);
363 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
364 mii_phy_reset(miisc);
365 mii_mediachg(mii);
366
367 return (0);
368 }
369
370 static void
371 octe_mii_medstat(struct ifnet *ifp, struct ifmediareq *ifm)
372 {
373 cvm_oct_private_t *priv;
374 struct mii_data *mii;
375
376 priv = ifp->if_softc;
377 mii = device_get_softc(priv->miibus);
378
379 mii_pollstat(mii);
380 ifm->ifm_active = mii->mii_media_active;
381 ifm->ifm_status = mii->mii_media_status;
382 }
383
384 static int
385 octe_medchange(struct ifnet *ifp)
386 {
387 return (ENOTSUP);
388 }
389
390 static void
391 octe_medstat(struct ifnet *ifp, struct ifmediareq *ifm)
392 {
393 cvm_oct_private_t *priv;
394 cvmx_helper_link_info_t link_info;
395
396 priv = ifp->if_softc;
397
398 ifm->ifm_status = IFM_AVALID;
399 ifm->ifm_active = IFT_ETHER;
400
401 if (priv->poll == NULL)
402 return;
403 priv->poll(ifp);
404
405 link_info.u64 = priv->link_info;
406
407 if (!link_info.s.link_up)
408 return;
409
410 ifm->ifm_status |= IFM_ACTIVE;
411
412 switch (link_info.s.speed) {
413 case 10:
414 ifm->ifm_active |= IFM_10_T;
415 break;
416 case 100:
417 ifm->ifm_active |= IFM_100_TX;
418 break;
419 case 1000:
420 ifm->ifm_active |= IFM_1000_T;
421 break;
422 case 10000:
423 ifm->ifm_active |= IFM_10G_T;
424 break;
425 }
426
427 if (link_info.s.full_duplex)
428 ifm->ifm_active |= IFM_FDX;
429 else
430 ifm->ifm_active |= IFM_HDX;
431 }
432
433 static int
434 octe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
435 {
436 cvm_oct_private_t *priv;
437 struct mii_data *mii;
438 struct ifreq *ifr;
439 #ifdef INET
440 struct ifaddr *ifa;
441 #endif
442 int error;
443
444 priv = ifp->if_softc;
445 ifr = (struct ifreq *)data;
446 #ifdef INET
447 ifa = (struct ifaddr *)data;
448 #endif
449
450 switch (cmd) {
451 case SIOCSIFADDR:
452 #ifdef INET
453 /*
454 * Avoid reinitialization unless it's necessary.
455 */
456 if (ifa->ifa_addr->sa_family == AF_INET) {
457 ifp->if_flags |= IFF_UP;
458 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
459 octe_init(priv);
460 arp_ifinit(ifp, ifa);
461
462 return (0);
463 }
464 #endif
465 error = ether_ioctl(ifp, cmd, data);
466 if (error != 0)
467 return (error);
468 return (0);
469
470 case SIOCSIFFLAGS:
471 if (ifp->if_flags == priv->if_flags)
472 return (0);
473 if ((ifp->if_flags & IFF_UP) != 0) {
474 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
475 octe_init(priv);
476 } else {
477 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
478 octe_stop(priv);
479 }
480 priv->if_flags = ifp->if_flags;
481 return (0);
482
483 case SIOCSIFCAP:
484 /*
485 * Just change the capabilities in software, currently none
486 * require reprogramming hardware, they just toggle whether we
487 * make use of already-present facilities in software.
488 */
489 ifp->if_capenable = ifr->ifr_reqcap;
490 return (0);
491
492 case SIOCSIFMTU:
493 error = cvm_oct_common_change_mtu(ifp, ifr->ifr_mtu);
494 if (error != 0)
495 return (EINVAL);
496 return (0);
497
498 case SIOCSIFMEDIA:
499 case SIOCGIFMEDIA:
500 if (priv->miibus != NULL) {
501 mii = device_get_softc(priv->miibus);
502 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
503 if (error != 0)
504 return (error);
505 return (0);
506 }
507 error = ifmedia_ioctl(ifp, ifr, &priv->media, cmd);
508 if (error != 0)
509 return (error);
510 return (0);
511
512 default:
513 error = ether_ioctl(ifp, cmd, data);
514 if (error != 0)
515 return (error);
516 return (0);
517 }
518 }
Cache object: 445f13a987198beacfc925b0af45474f
|