2 * Copyright (c) 2010 Juli Mallett <jmallett@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
30 * Cavium Octeon Ethernet devices.
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?
39 #include <sys/param.h>
40 #include <sys/systm.h>
42 #include <sys/endian.h>
43 #include <sys/kernel.h>
46 #include <sys/module.h>
47 #include <sys/mutex.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
51 #include <sys/sysctl.h>
54 #include <net/ethernet.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>
63 #include <netinet/in.h>
64 #include <netinet/if_ether.h>
67 #include <dev/mii/mii.h>
68 #include <dev/mii/miivar.h>
70 #include "wrapper-cvmx-includes.h"
71 #include "cavium-ethernet.h"
73 #include "ethernet-common.h"
74 #include "ethernet-defines.h"
75 #include "ethernet-mdio.h"
76 #include "ethernet-tx.h"
78 #include "miibus_if.h"
80 #define OCTE_TX_LOCK(priv) mtx_lock(&(priv)->tx_mtx)
81 #define OCTE_TX_UNLOCK(priv) mtx_unlock(&(priv)->tx_mtx)
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);
88 static int octe_miibus_readreg(device_t, int, int);
89 static int octe_miibus_writereg(device_t, int, int, int);
91 static void octe_init(void *);
92 static void octe_stop(void *);
93 static void octe_start(struct ifnet *);
95 static int octe_mii_medchange(struct ifnet *);
96 static void octe_mii_medstat(struct ifnet *, struct ifmediareq *);
98 static int octe_medchange(struct ifnet *);
99 static void octe_medstat(struct ifnet *, struct ifmediareq *);
101 static int octe_ioctl(struct ifnet *, u_long, caddr_t);
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),
111 DEVMETHOD(miibus_readreg, octe_miibus_readreg),
112 DEVMETHOD(miibus_writereg, octe_miibus_writereg),
117 static driver_t octe_driver = {
120 sizeof (cvm_oct_private_t),
123 static devclass_t octe_devclass;
125 DRIVER_MODULE(octe, octebus, octe_driver, octe_devclass, 0, 0);
126 DRIVER_MODULE(miibus, octe, miibus_driver, miibus_devclass, 0, 0);
128 static driver_t pow_driver = {
131 sizeof (cvm_oct_private_t),
134 static devclass_t pow_devclass;
136 DRIVER_MODULE(pow, octebus, pow_driver, pow_devclass, 0, 0);
139 octe_probe(device_t dev)
145 octe_attach(device_t dev)
148 cvm_oct_private_t *priv;
153 priv = device_get_softc(dev);
156 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
158 if (priv->phy_id != -1) {
159 if (priv->phy_device == NULL) {
160 error = mii_phy_probe(dev, &priv->miibus, octe_mii_medchange,
163 device_printf(dev, "missing phy %u\n", priv->phy_id);
165 child = device_add_child(dev, priv->phy_device, -1);
167 device_printf(dev, "missing phy %u device %s\n", priv->phy_id, priv->phy_device);
171 if (priv->miibus == NULL) {
172 ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat);
174 ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
175 ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
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?)
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;
189 priv->if_flags = ifp->if_flags;
191 mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF);
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);
198 ether_ifattach(ifp, priv->mac);
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;
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);
211 return (bus_generic_attach(dev));
215 octe_detach(device_t dev)
221 octe_shutdown(device_t dev)
223 return (octe_detach(dev));
227 octe_miibus_readreg(device_t dev, int phy, int reg)
229 cvm_oct_private_t *priv;
231 priv = device_get_softc(dev);
234 * Try interface-specific MII routine.
236 if (priv->mdio_read != NULL)
237 return (priv->mdio_read(priv->ifp, phy, reg));
240 * Try generic MII routine.
242 if (phy != priv->phy_id)
245 return (cvm_oct_mdio_read(priv->ifp, phy, reg));
249 octe_miibus_writereg(device_t dev, int phy, int reg, int val)
251 cvm_oct_private_t *priv;
253 priv = device_get_softc(dev);
256 * Try interface-specific MII routine.
258 if (priv->mdio_write != NULL) {
259 priv->mdio_write(priv->ifp, phy, reg, val);
264 * Try generic MII routine.
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);
277 cvm_oct_private_t *priv;
282 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
285 if (priv->open != NULL)
288 if (((ifp->if_flags ^ priv->if_flags) & (IFF_ALLMULTI | IFF_MULTICAST | IFF_PROMISC)) != 0)
289 cvm_oct_common_set_multicast_list(ifp);
291 cvm_oct_common_set_mac_address(ifp, IF_LLADDR(ifp));
293 if (priv->poll != NULL)
295 if (priv->miibus != NULL)
296 mii_mediachg(device_get_softc(priv->miibus));
298 ifp->if_drv_flags |= IFF_DRV_RUNNING;
299 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
306 cvm_oct_private_t *priv;
311 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
314 if (priv->stop != NULL)
317 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
321 octe_start(struct ifnet *ifp)
323 cvm_oct_private_t *priv;
327 priv = ifp->if_softc;
329 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING)
333 while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
334 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
336 OCTE_TX_UNLOCK(priv);
338 if (priv->queue != -1) {
339 error = cvm_oct_xmit(m, ifp);
341 error = cvm_oct_xmit_pow(m, ifp);
345 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
351 OCTE_TX_UNLOCK(priv);
355 octe_mii_medchange(struct ifnet *ifp)
357 cvm_oct_private_t *priv;
358 struct mii_data *mii;
360 priv = ifp->if_softc;
361 mii = device_get_softc(priv->miibus);
363 if (mii->mii_instance) {
364 struct mii_softc *miisc;
366 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
367 mii_phy_reset(miisc);
375 octe_mii_medstat(struct ifnet *ifp, struct ifmediareq *ifm)
377 cvm_oct_private_t *priv;
378 struct mii_data *mii;
380 priv = ifp->if_softc;
381 mii = device_get_softc(priv->miibus);
384 ifm->ifm_active = mii->mii_media_active;
385 ifm->ifm_status = mii->mii_media_status;
389 octe_medchange(struct ifnet *ifp)
395 octe_medstat(struct ifnet *ifp, struct ifmediareq *ifm)
397 cvm_oct_private_t *priv;
398 cvmx_helper_link_info_t link_info;
400 priv = ifp->if_softc;
402 ifm->ifm_status = IFM_AVALID;
403 ifm->ifm_active = IFT_ETHER;
405 if (priv->poll == NULL)
409 link_info.u64 = priv->link_info;
411 if (!link_info.s.link_up)
414 ifm->ifm_status |= IFM_ACTIVE;
416 switch (link_info.s.speed) {
418 ifm->ifm_active |= IFM_10_T;
421 ifm->ifm_active |= IFM_100_TX;
424 ifm->ifm_active |= IFM_1000_T;
427 ifm->ifm_active |= IFM_10G_T;
431 if (link_info.s.full_duplex)
432 ifm->ifm_active |= IFM_FDX;
434 ifm->ifm_active |= IFM_HDX;
438 octe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
440 cvm_oct_private_t *priv;
441 struct mii_data *mii;
448 priv = ifp->if_softc;
449 ifr = (struct ifreq *)data;
451 ifa = (struct ifaddr *)data;
458 * Avoid reinitialization unless it's necessary.
460 if (ifa->ifa_addr->sa_family == AF_INET) {
461 ifp->if_flags |= IFF_UP;
462 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
464 arp_ifinit(ifp, ifa);
469 error = ether_ioctl(ifp, cmd, data);
475 if (ifp->if_flags == priv->if_flags)
477 if ((ifp->if_flags & IFF_UP) != 0) {
478 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
481 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
484 priv->if_flags = ifp->if_flags;
489 * Just change the capabilities in software, currently none
490 * require reprogramming hardware, they just toggle whether we
491 * make use of already-present facilities in software.
493 ifp->if_capenable = ifr->ifr_reqcap;
497 error = cvm_oct_common_change_mtu(ifp, ifr->ifr_mtu);
504 if (priv->miibus != NULL) {
505 mii = device_get_softc(priv->miibus);
506 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
511 error = ifmedia_ioctl(ifp, ifr, &priv->media, cmd);
517 error = ether_ioctl(ifp, cmd, data);