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 *
| 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: head/sys/mips/cavium/octe/octe.c 213156 2010-09-25 04:39:12Z jmallett $
| 26 * $FreeBSD: head/sys/mips/cavium/octe/octe.c 213346 2010-10-02 05:43:17Z jmallett $
|
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 83static int octe_probe(device_t); 84static int octe_attach(device_t); 85static int octe_detach(device_t); 86static int octe_shutdown(device_t); 87 88static int octe_miibus_readreg(device_t, int, int); 89static int octe_miibus_writereg(device_t, int, int, int); 90 91static void octe_init(void *); 92static void octe_stop(void *); 93static void octe_start(struct ifnet *); 94 95static int octe_mii_medchange(struct ifnet *); 96static void octe_mii_medstat(struct ifnet *, struct ifmediareq *); 97 98static int octe_medchange(struct ifnet *); 99static void octe_medstat(struct ifnet *, struct ifmediareq *); 100 101static int octe_ioctl(struct ifnet *, u_long, caddr_t); 102 103static 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 117static driver_t octe_driver = { 118 "octe", 119 octe_methods, 120 sizeof (cvm_oct_private_t), 121}; 122 123static devclass_t octe_devclass; 124 125DRIVER_MODULE(octe, octebus, octe_driver, octe_devclass, 0, 0); 126DRIVER_MODULE(miibus, octe, miibus_driver, miibus_devclass, 0, 0); 127 128static driver_t pow_driver = { 129 "pow", 130 octe_methods, 131 sizeof (cvm_oct_private_t), 132}; 133 134static devclass_t pow_devclass; 135 136DRIVER_MODULE(pow, octebus, pow_driver, pow_devclass, 0, 0); 137 138static int 139octe_probe(device_t dev) 140{ 141 return (0); 142} 143 144static int 145octe_attach(device_t dev) 146{ 147 struct ifnet *ifp; 148 cvm_oct_private_t *priv; 149 unsigned qos; 150 int error; 151 152 priv = device_get_softc(dev); 153 ifp = priv->ifp; 154 155 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 156 157 if (priv->phy_id != -1) { 158 error = mii_phy_probe(dev, &priv->miibus, octe_mii_medchange, 159 octe_mii_medstat); 160 if (error != 0) { 161 device_printf(dev, "missing phy %u\n", priv->phy_id); 162 } 163 } 164 165 if (priv->miibus == NULL) { 166 ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat); 167 168 ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL); 169 ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO); 170 } 171 172 /* 173 * XXX 174 * We don't support programming the multicast filter right now, although it 175 * ought to be easy enough. (Presumably it's just a matter of putting 176 * multicast addresses in the CAM?) 177 */ 178 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI; 179 ifp->if_init = octe_init; 180 ifp->if_ioctl = octe_ioctl; 181 ifp->if_start = octe_start; 182 183 priv->if_flags = ifp->if_flags; 184 185 mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF); 186 187 for (qos = 0; qos < 16; qos++) { 188 mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF); 189 IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH); 190 } 191 192 ether_ifattach(ifp, priv->mac); 193 194 ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 195 ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; 196 ifp->if_capenable = ifp->if_capabilities; 197 ifp->if_hwassist = CSUM_TCP | CSUM_UDP; 198 199 OCTE_TX_LOCK(priv); 200 IFQ_SET_MAXLEN(&ifp->if_snd, MAX_OUT_QUEUE_DEPTH); 201 ifp->if_snd.ifq_drv_maxlen = MAX_OUT_QUEUE_DEPTH; 202 IFQ_SET_READY(&ifp->if_snd); 203 OCTE_TX_UNLOCK(priv); 204 205 return (0); 206} 207 208static int 209octe_detach(device_t dev) 210{ 211 return (0); 212} 213 214static int 215octe_shutdown(device_t dev) 216{ 217 return (octe_detach(dev)); 218} 219 220static int 221octe_miibus_readreg(device_t dev, int phy, int reg) 222{ 223 cvm_oct_private_t *priv; 224 225 priv = device_get_softc(dev); 226
| 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 83static int octe_probe(device_t); 84static int octe_attach(device_t); 85static int octe_detach(device_t); 86static int octe_shutdown(device_t); 87 88static int octe_miibus_readreg(device_t, int, int); 89static int octe_miibus_writereg(device_t, int, int, int); 90 91static void octe_init(void *); 92static void octe_stop(void *); 93static void octe_start(struct ifnet *); 94 95static int octe_mii_medchange(struct ifnet *); 96static void octe_mii_medstat(struct ifnet *, struct ifmediareq *); 97 98static int octe_medchange(struct ifnet *); 99static void octe_medstat(struct ifnet *, struct ifmediareq *); 100 101static int octe_ioctl(struct ifnet *, u_long, caddr_t); 102 103static 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 117static driver_t octe_driver = { 118 "octe", 119 octe_methods, 120 sizeof (cvm_oct_private_t), 121}; 122 123static devclass_t octe_devclass; 124 125DRIVER_MODULE(octe, octebus, octe_driver, octe_devclass, 0, 0); 126DRIVER_MODULE(miibus, octe, miibus_driver, miibus_devclass, 0, 0); 127 128static driver_t pow_driver = { 129 "pow", 130 octe_methods, 131 sizeof (cvm_oct_private_t), 132}; 133 134static devclass_t pow_devclass; 135 136DRIVER_MODULE(pow, octebus, pow_driver, pow_devclass, 0, 0); 137 138static int 139octe_probe(device_t dev) 140{ 141 return (0); 142} 143 144static int 145octe_attach(device_t dev) 146{ 147 struct ifnet *ifp; 148 cvm_oct_private_t *priv; 149 unsigned qos; 150 int error; 151 152 priv = device_get_softc(dev); 153 ifp = priv->ifp; 154 155 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 156 157 if (priv->phy_id != -1) { 158 error = mii_phy_probe(dev, &priv->miibus, octe_mii_medchange, 159 octe_mii_medstat); 160 if (error != 0) { 161 device_printf(dev, "missing phy %u\n", priv->phy_id); 162 } 163 } 164 165 if (priv->miibus == NULL) { 166 ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat); 167 168 ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL); 169 ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO); 170 } 171 172 /* 173 * XXX 174 * We don't support programming the multicast filter right now, although it 175 * ought to be easy enough. (Presumably it's just a matter of putting 176 * multicast addresses in the CAM?) 177 */ 178 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI; 179 ifp->if_init = octe_init; 180 ifp->if_ioctl = octe_ioctl; 181 ifp->if_start = octe_start; 182 183 priv->if_flags = ifp->if_flags; 184 185 mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF); 186 187 for (qos = 0; qos < 16; qos++) { 188 mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF); 189 IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH); 190 } 191 192 ether_ifattach(ifp, priv->mac); 193 194 ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 195 ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; 196 ifp->if_capenable = ifp->if_capabilities; 197 ifp->if_hwassist = CSUM_TCP | CSUM_UDP; 198 199 OCTE_TX_LOCK(priv); 200 IFQ_SET_MAXLEN(&ifp->if_snd, MAX_OUT_QUEUE_DEPTH); 201 ifp->if_snd.ifq_drv_maxlen = MAX_OUT_QUEUE_DEPTH; 202 IFQ_SET_READY(&ifp->if_snd); 203 OCTE_TX_UNLOCK(priv); 204 205 return (0); 206} 207 208static int 209octe_detach(device_t dev) 210{ 211 return (0); 212} 213 214static int 215octe_shutdown(device_t dev) 216{ 217 return (octe_detach(dev)); 218} 219 220static int 221octe_miibus_readreg(device_t dev, int phy, int reg) 222{ 223 cvm_oct_private_t *priv; 224 225 priv = device_get_softc(dev); 226
|
| 227 /* 228 * Try interface-specific MII routine. 229 */ 230 if (priv->mdio_read != NULL) 231 return (priv->mdio_read(priv->ifp, phy, reg)); 232 233 /* 234 * Try generic MII routine. 235 */
|
227 if (phy != priv->phy_id) 228 return (0); 229 230 return (cvm_oct_mdio_read(priv->ifp, phy, reg)); 231} 232 233static int 234octe_miibus_writereg(device_t dev, int phy, int reg, int val) 235{ 236 cvm_oct_private_t *priv; 237 238 priv = device_get_softc(dev); 239
| 236 if (phy != priv->phy_id) 237 return (0); 238 239 return (cvm_oct_mdio_read(priv->ifp, phy, reg)); 240} 241 242static int 243octe_miibus_writereg(device_t dev, int phy, int reg, int val) 244{ 245 cvm_oct_private_t *priv; 246 247 priv = device_get_softc(dev); 248
|
| 249 /* 250 * Try interface-specific MII routine. 251 */ 252 if (priv->mdio_write != NULL) { 253 priv->mdio_write(priv->ifp, phy, reg, val); 254 return (0); 255 } 256 257 /* 258 * Try generic MII routine. 259 */
|
240 KASSERT(phy == priv->phy_id, 241 ("write to phy %u but our phy is %u", phy, priv->phy_id));
| 260 KASSERT(phy == priv->phy_id, 261 ("write to phy %u but our phy is %u", phy, priv->phy_id));
|
242
| |
243 cvm_oct_mdio_write(priv->ifp, phy, reg, val); 244 245 return (0); 246} 247 248static void 249octe_init(void *arg) 250{ 251 struct ifnet *ifp; 252 cvm_oct_private_t *priv; 253 254 priv = arg; 255 ifp = priv->ifp; 256 257 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 258 octe_stop(priv); 259 260 if (priv->open != NULL) 261 priv->open(ifp); 262 263 if (((ifp->if_flags ^ priv->if_flags) & (IFF_ALLMULTI | IFF_MULTICAST | IFF_PROMISC)) != 0) 264 cvm_oct_common_set_multicast_list(ifp); 265 266 cvm_oct_common_set_mac_address(ifp, IF_LLADDR(ifp)); 267 268 if (priv->poll != NULL) 269 priv->poll(ifp); 270 if (priv->miibus != NULL) 271 mii_mediachg(device_get_softc(priv->miibus)); 272 273 ifp->if_drv_flags |= IFF_DRV_RUNNING; 274 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 275} 276 277static void 278octe_stop(void *arg) 279{ 280 struct ifnet *ifp; 281 cvm_oct_private_t *priv; 282 283 priv = arg; 284 ifp = priv->ifp; 285 286 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 287 return; 288 289 if (priv->stop != NULL) 290 priv->stop(ifp); 291 292 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 293} 294 295static void 296octe_start(struct ifnet *ifp) 297{ 298 cvm_oct_private_t *priv; 299 struct mbuf *m; 300 int error; 301 302 priv = ifp->if_softc; 303 304 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) 305 return; 306 307 OCTE_TX_LOCK(priv); 308 while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 309 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 310 311 OCTE_TX_UNLOCK(priv); 312 313 if (priv->queue != -1) { 314 error = cvm_oct_xmit(m, ifp); 315 } else { 316 error = cvm_oct_xmit_pow(m, ifp); 317 } 318 319 if (error != 0) { 320 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 321 return; 322 } 323 324 OCTE_TX_LOCK(priv); 325 } 326 OCTE_TX_UNLOCK(priv); 327} 328 329static int 330octe_mii_medchange(struct ifnet *ifp) 331{ 332 cvm_oct_private_t *priv; 333 struct mii_data *mii; 334 335 priv = ifp->if_softc; 336 mii = device_get_softc(priv->miibus); 337 338 if (mii->mii_instance) { 339 struct mii_softc *miisc; 340 341 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 342 mii_phy_reset(miisc); 343 } 344 mii_mediachg(mii); 345 346 return (0); 347} 348 349static void 350octe_mii_medstat(struct ifnet *ifp, struct ifmediareq *ifm) 351{ 352 cvm_oct_private_t *priv; 353 struct mii_data *mii; 354 355 priv = ifp->if_softc; 356 mii = device_get_softc(priv->miibus); 357 358 mii_pollstat(mii); 359 ifm->ifm_active = mii->mii_media_active; 360 ifm->ifm_status = mii->mii_media_status; 361} 362 363static int 364octe_medchange(struct ifnet *ifp) 365{ 366 return (ENOTSUP); 367} 368 369static void 370octe_medstat(struct ifnet *ifp, struct ifmediareq *ifm) 371{ 372 cvm_oct_private_t *priv; 373 cvmx_helper_link_info_t link_info; 374 375 priv = ifp->if_softc; 376 377 ifm->ifm_status = IFM_AVALID; 378 ifm->ifm_active = IFT_ETHER; 379 380 if (priv->poll == NULL) 381 return; 382 priv->poll(ifp); 383 384 link_info.u64 = priv->link_info; 385 386 if (!link_info.s.link_up) 387 return; 388 389 ifm->ifm_status |= IFM_ACTIVE; 390 391 switch (link_info.s.speed) { 392 case 10: 393 ifm->ifm_active |= IFM_10_T; 394 break; 395 case 100: 396 ifm->ifm_active |= IFM_100_TX; 397 break; 398 case 1000: 399 ifm->ifm_active |= IFM_1000_T; 400 break; 401 case 10000: 402 ifm->ifm_active |= IFM_10G_T; 403 break; 404 } 405 406 if (link_info.s.full_duplex) 407 ifm->ifm_active |= IFM_FDX; 408 else 409 ifm->ifm_active |= IFM_HDX; 410} 411 412static int 413octe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 414{ 415 cvm_oct_private_t *priv; 416 struct mii_data *mii; 417 struct ifreq *ifr; 418#ifdef INET 419 struct ifaddr *ifa; 420#endif 421 int error; 422 423 priv = ifp->if_softc; 424 ifr = (struct ifreq *)data; 425#ifdef INET 426 ifa = (struct ifaddr *)data; 427#endif 428 429 switch (cmd) { 430 case SIOCSIFADDR: 431#ifdef INET 432 /* 433 * Avoid reinitialization unless it's necessary. 434 */ 435 if (ifa->ifa_addr->sa_family == AF_INET) { 436 ifp->if_flags |= IFF_UP; 437 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 438 octe_init(priv); 439 arp_ifinit(ifp, ifa); 440 441 return (0); 442 } 443#endif 444 error = ether_ioctl(ifp, cmd, data); 445 if (error != 0) 446 return (error); 447 return (0); 448 449 case SIOCSIFFLAGS: 450 if (ifp->if_flags == priv->if_flags) 451 return (0); 452 if ((ifp->if_flags & IFF_UP) != 0) { 453 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 454 octe_init(priv); 455 } else { 456 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 457 octe_stop(priv); 458 } 459 priv->if_flags = ifp->if_flags; 460 return (0); 461 462 case SIOCSIFCAP: 463 /* 464 * Just change the capabilities in software, currently none 465 * require reprogramming hardware, they just toggle whether we 466 * make use of already-present facilities in software. 467 */ 468 ifp->if_capenable = ifr->ifr_reqcap; 469 return (0); 470 471 case SIOCSIFMTU: 472 error = cvm_oct_common_change_mtu(ifp, ifr->ifr_mtu); 473 if (error != 0) 474 return (EINVAL); 475 return (0); 476 477 case SIOCSIFMEDIA: 478 case SIOCGIFMEDIA: 479 if (priv->miibus != NULL) { 480 mii = device_get_softc(priv->miibus); 481 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 482 if (error != 0) 483 return (error); 484 return (0); 485 } 486 error = ifmedia_ioctl(ifp, ifr, &priv->media, cmd); 487 if (error != 0) 488 return (error); 489 return (0); 490 491 default: 492 error = ether_ioctl(ifp, cmd, data); 493 if (error != 0) 494 return (error); 495 return (0); 496 } 497}
| 262 cvm_oct_mdio_write(priv->ifp, phy, reg, val); 263 264 return (0); 265} 266 267static void 268octe_init(void *arg) 269{ 270 struct ifnet *ifp; 271 cvm_oct_private_t *priv; 272 273 priv = arg; 274 ifp = priv->ifp; 275 276 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 277 octe_stop(priv); 278 279 if (priv->open != NULL) 280 priv->open(ifp); 281 282 if (((ifp->if_flags ^ priv->if_flags) & (IFF_ALLMULTI | IFF_MULTICAST | IFF_PROMISC)) != 0) 283 cvm_oct_common_set_multicast_list(ifp); 284 285 cvm_oct_common_set_mac_address(ifp, IF_LLADDR(ifp)); 286 287 if (priv->poll != NULL) 288 priv->poll(ifp); 289 if (priv->miibus != NULL) 290 mii_mediachg(device_get_softc(priv->miibus)); 291 292 ifp->if_drv_flags |= IFF_DRV_RUNNING; 293 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 294} 295 296static void 297octe_stop(void *arg) 298{ 299 struct ifnet *ifp; 300 cvm_oct_private_t *priv; 301 302 priv = arg; 303 ifp = priv->ifp; 304 305 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 306 return; 307 308 if (priv->stop != NULL) 309 priv->stop(ifp); 310 311 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 312} 313 314static void 315octe_start(struct ifnet *ifp) 316{ 317 cvm_oct_private_t *priv; 318 struct mbuf *m; 319 int error; 320 321 priv = ifp->if_softc; 322 323 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) 324 return; 325 326 OCTE_TX_LOCK(priv); 327 while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 328 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 329 330 OCTE_TX_UNLOCK(priv); 331 332 if (priv->queue != -1) { 333 error = cvm_oct_xmit(m, ifp); 334 } else { 335 error = cvm_oct_xmit_pow(m, ifp); 336 } 337 338 if (error != 0) { 339 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 340 return; 341 } 342 343 OCTE_TX_LOCK(priv); 344 } 345 OCTE_TX_UNLOCK(priv); 346} 347 348static int 349octe_mii_medchange(struct ifnet *ifp) 350{ 351 cvm_oct_private_t *priv; 352 struct mii_data *mii; 353 354 priv = ifp->if_softc; 355 mii = device_get_softc(priv->miibus); 356 357 if (mii->mii_instance) { 358 struct mii_softc *miisc; 359 360 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 361 mii_phy_reset(miisc); 362 } 363 mii_mediachg(mii); 364 365 return (0); 366} 367 368static void 369octe_mii_medstat(struct ifnet *ifp, struct ifmediareq *ifm) 370{ 371 cvm_oct_private_t *priv; 372 struct mii_data *mii; 373 374 priv = ifp->if_softc; 375 mii = device_get_softc(priv->miibus); 376 377 mii_pollstat(mii); 378 ifm->ifm_active = mii->mii_media_active; 379 ifm->ifm_status = mii->mii_media_status; 380} 381 382static int 383octe_medchange(struct ifnet *ifp) 384{ 385 return (ENOTSUP); 386} 387 388static void 389octe_medstat(struct ifnet *ifp, struct ifmediareq *ifm) 390{ 391 cvm_oct_private_t *priv; 392 cvmx_helper_link_info_t link_info; 393 394 priv = ifp->if_softc; 395 396 ifm->ifm_status = IFM_AVALID; 397 ifm->ifm_active = IFT_ETHER; 398 399 if (priv->poll == NULL) 400 return; 401 priv->poll(ifp); 402 403 link_info.u64 = priv->link_info; 404 405 if (!link_info.s.link_up) 406 return; 407 408 ifm->ifm_status |= IFM_ACTIVE; 409 410 switch (link_info.s.speed) { 411 case 10: 412 ifm->ifm_active |= IFM_10_T; 413 break; 414 case 100: 415 ifm->ifm_active |= IFM_100_TX; 416 break; 417 case 1000: 418 ifm->ifm_active |= IFM_1000_T; 419 break; 420 case 10000: 421 ifm->ifm_active |= IFM_10G_T; 422 break; 423 } 424 425 if (link_info.s.full_duplex) 426 ifm->ifm_active |= IFM_FDX; 427 else 428 ifm->ifm_active |= IFM_HDX; 429} 430 431static int 432octe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 433{ 434 cvm_oct_private_t *priv; 435 struct mii_data *mii; 436 struct ifreq *ifr; 437#ifdef INET 438 struct ifaddr *ifa; 439#endif 440 int error; 441 442 priv = ifp->if_softc; 443 ifr = (struct ifreq *)data; 444#ifdef INET 445 ifa = (struct ifaddr *)data; 446#endif 447 448 switch (cmd) { 449 case SIOCSIFADDR: 450#ifdef INET 451 /* 452 * Avoid reinitialization unless it's necessary. 453 */ 454 if (ifa->ifa_addr->sa_family == AF_INET) { 455 ifp->if_flags |= IFF_UP; 456 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 457 octe_init(priv); 458 arp_ifinit(ifp, ifa); 459 460 return (0); 461 } 462#endif 463 error = ether_ioctl(ifp, cmd, data); 464 if (error != 0) 465 return (error); 466 return (0); 467 468 case SIOCSIFFLAGS: 469 if (ifp->if_flags == priv->if_flags) 470 return (0); 471 if ((ifp->if_flags & IFF_UP) != 0) { 472 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 473 octe_init(priv); 474 } else { 475 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 476 octe_stop(priv); 477 } 478 priv->if_flags = ifp->if_flags; 479 return (0); 480 481 case SIOCSIFCAP: 482 /* 483 * Just change the capabilities in software, currently none 484 * require reprogramming hardware, they just toggle whether we 485 * make use of already-present facilities in software. 486 */ 487 ifp->if_capenable = ifr->ifr_reqcap; 488 return (0); 489 490 case SIOCSIFMTU: 491 error = cvm_oct_common_change_mtu(ifp, ifr->ifr_mtu); 492 if (error != 0) 493 return (EINVAL); 494 return (0); 495 496 case SIOCSIFMEDIA: 497 case SIOCGIFMEDIA: 498 if (priv->miibus != NULL) { 499 mii = device_get_softc(priv->miibus); 500 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 501 if (error != 0) 502 return (error); 503 return (0); 504 } 505 error = ifmedia_ioctl(ifp, ifr, &priv->media, cmd); 506 if (error != 0) 507 return (error); 508 return (0); 509 510 default: 511 error = ether_ioctl(ifp, cmd, data); 512 if (error != 0) 513 return (error); 514 return (0); 515 } 516}
|