if_mge.c (271849) | if_mge.c (289945) |
---|---|
1/*- 2 * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. | 1/*- 2 * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. |
3 * Copyright (C) 2009-2015 Semihalf 4 * Copyright (C) 2015 Stormshield |
|
3 * All rights reserved. 4 * 5 * Developed by Semihalf. 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 --- 18 unchanged lines hidden (view full) --- 29 * SUCH DAMAGE. 30 */ 31 32#ifdef HAVE_KERNEL_OPTION_HEADERS 33#include "opt_device_polling.h" 34#endif 35 36#include <sys/cdefs.h> | 5 * All rights reserved. 6 * 7 * Developed by Semihalf. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright --- 18 unchanged lines hidden (view full) --- 31 * SUCH DAMAGE. 32 */ 33 34#ifdef HAVE_KERNEL_OPTION_HEADERS 35#include "opt_device_polling.h" 36#endif 37 38#include <sys/cdefs.h> |
37__FBSDID("$FreeBSD: head/sys/dev/mge/if_mge.c 271849 2014-09-19 03:51:26Z glebius $"); | 39__FBSDID("$FreeBSD: head/sys/dev/mge/if_mge.c 289945 2015-10-25 22:00:56Z zbb $"); |
38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/endian.h> 42#include <sys/mbuf.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45#include <sys/kernel.h> 46#include <sys/module.h> 47#include <sys/socket.h> 48#include <sys/sysctl.h> 49 50#include <net/ethernet.h> 51#include <net/bpf.h> 52#include <net/if.h> | 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/endian.h> 44#include <sys/mbuf.h> 45#include <sys/lock.h> 46#include <sys/mutex.h> 47#include <sys/kernel.h> 48#include <sys/module.h> 49#include <sys/socket.h> 50#include <sys/sysctl.h> 51 52#include <net/ethernet.h> 53#include <net/bpf.h> 54#include <net/if.h> |
53#include <net/if_var.h> | |
54#include <net/if_arp.h> 55#include <net/if_dl.h> 56#include <net/if_media.h> 57#include <net/if_types.h> 58#include <net/if_vlan_var.h> 59 60#include <netinet/in_systm.h> 61#include <netinet/in.h> --- 6 unchanged lines hidden (view full) --- 68#include <machine/resource.h> 69 70#include <dev/mii/mii.h> 71#include <dev/mii/miivar.h> 72 73#include <dev/fdt/fdt_common.h> 74#include <dev/ofw/ofw_bus.h> 75#include <dev/ofw/ofw_bus_subr.h> | 55#include <net/if_arp.h> 56#include <net/if_dl.h> 57#include <net/if_media.h> 58#include <net/if_types.h> 59#include <net/if_vlan_var.h> 60 61#include <netinet/in_systm.h> 62#include <netinet/in.h> --- 6 unchanged lines hidden (view full) --- 69#include <machine/resource.h> 70 71#include <dev/mii/mii.h> 72#include <dev/mii/miivar.h> 73 74#include <dev/fdt/fdt_common.h> 75#include <dev/ofw/ofw_bus.h> 76#include <dev/ofw/ofw_bus_subr.h> |
77#include <dev/etherswitch/mdio.h> |
|
76 77#include <dev/mge/if_mgevar.h> 78#include <arm/mv/mvreg.h> 79#include <arm/mv/mvvar.h> 80 81#include "miibus_if.h" | 78 79#include <dev/mge/if_mgevar.h> 80#include <arm/mv/mvreg.h> 81#include <arm/mv/mvvar.h> 82 83#include "miibus_if.h" |
84#include "mdio_if.h" |
|
82 | 85 |
86#define MGE_DELAY(x) pause("SMI access sleep", (x) / tick_sbt) 87 |
|
83static int mge_probe(device_t dev); 84static int mge_attach(device_t dev); 85static int mge_detach(device_t dev); 86static int mge_shutdown(device_t dev); 87static int mge_suspend(device_t dev); 88static int mge_resume(device_t dev); 89 90static int mge_miibus_readreg(device_t dev, int phy, int reg); 91static int mge_miibus_writereg(device_t dev, int phy, int reg, int value); 92 | 88static int mge_probe(device_t dev); 89static int mge_attach(device_t dev); 90static int mge_detach(device_t dev); 91static int mge_shutdown(device_t dev); 92static int mge_suspend(device_t dev); 93static int mge_resume(device_t dev); 94 95static int mge_miibus_readreg(device_t dev, int phy, int reg); 96static int mge_miibus_writereg(device_t dev, int phy, int reg, int value); 97 |
98static int mge_mdio_readreg(device_t dev, int phy, int reg); 99static int mge_mdio_writereg(device_t dev, int phy, int reg, int value); 100 |
|
93static int mge_ifmedia_upd(struct ifnet *ifp); 94static void mge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); 95 96static void mge_init(void *arg); 97static void mge_init_locked(void *arg); 98static void mge_start(struct ifnet *ifp); 99static void mge_start_locked(struct ifnet *ifp); 100static void mge_watchdog(struct mge_softc *sc); --- 48 unchanged lines hidden (view full) --- 149 DEVMETHOD(device_attach, mge_attach), 150 DEVMETHOD(device_detach, mge_detach), 151 DEVMETHOD(device_shutdown, mge_shutdown), 152 DEVMETHOD(device_suspend, mge_suspend), 153 DEVMETHOD(device_resume, mge_resume), 154 /* MII interface */ 155 DEVMETHOD(miibus_readreg, mge_miibus_readreg), 156 DEVMETHOD(miibus_writereg, mge_miibus_writereg), | 101static int mge_ifmedia_upd(struct ifnet *ifp); 102static void mge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); 103 104static void mge_init(void *arg); 105static void mge_init_locked(void *arg); 106static void mge_start(struct ifnet *ifp); 107static void mge_start_locked(struct ifnet *ifp); 108static void mge_watchdog(struct mge_softc *sc); --- 48 unchanged lines hidden (view full) --- 157 DEVMETHOD(device_attach, mge_attach), 158 DEVMETHOD(device_detach, mge_detach), 159 DEVMETHOD(device_shutdown, mge_shutdown), 160 DEVMETHOD(device_suspend, mge_suspend), 161 DEVMETHOD(device_resume, mge_resume), 162 /* MII interface */ 163 DEVMETHOD(miibus_readreg, mge_miibus_readreg), 164 DEVMETHOD(miibus_writereg, mge_miibus_writereg), |
165 /* MDIO interface */ 166 DEVMETHOD(mdio_readreg, mge_mdio_readreg), 167 DEVMETHOD(mdio_writereg, mge_mdio_writereg), |
|
157 { 0, 0 } 158}; 159 | 168 { 0, 0 } 169}; 170 |
160static driver_t mge_driver = { 161 "mge", 162 mge_methods, 163 sizeof(struct mge_softc), 164}; | 171DEFINE_CLASS_0(mge, mge_driver, mge_methods, sizeof(struct mge_softc)); |
165 166static devclass_t mge_devclass; | 172 173static devclass_t mge_devclass; |
174static int switch_attached = 0; |
|
167 168DRIVER_MODULE(mge, simplebus, mge_driver, mge_devclass, 0, 0); 169DRIVER_MODULE(miibus, mge, miibus_driver, miibus_devclass, 0, 0); | 175 176DRIVER_MODULE(mge, simplebus, mge_driver, mge_devclass, 0, 0); 177DRIVER_MODULE(miibus, mge, miibus_driver, miibus_devclass, 0, 0); |
178DRIVER_MODULE(mdio, mge, mdio_driver, mdio_devclass, 0, 0); |
|
170MODULE_DEPEND(mge, ether, 1, 1, 1); 171MODULE_DEPEND(mge, miibus, 1, 1, 1); | 179MODULE_DEPEND(mge, ether, 1, 1, 1); 180MODULE_DEPEND(mge, miibus, 1, 1, 1); |
181MODULE_DEPEND(mge, mdio, 1, 1, 1); |
|
172 173static struct resource_spec res_spec[] = { 174 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 175 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, 176 { SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE }, 177 { SYS_RES_IRQ, 2, RF_ACTIVE | RF_SHAREABLE }, 178 { -1, 0 } 179}; --- 5 unchanged lines hidden (view full) --- 185 { mge_intr_rxtx,"GbE aggregated interrupt" }, 186 { mge_intr_rx, "GbE receive interrupt" }, 187 { mge_intr_tx, "GbE transmit interrupt" }, 188 { mge_intr_misc,"GbE misc interrupt" }, 189 { mge_intr_sum, "GbE summary interrupt" }, 190 { mge_intr_err, "GbE error interrupt" }, 191}; 192 | 182 183static struct resource_spec res_spec[] = { 184 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 185 { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, 186 { SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE }, 187 { SYS_RES_IRQ, 2, RF_ACTIVE | RF_SHAREABLE }, 188 { -1, 0 } 189}; --- 5 unchanged lines hidden (view full) --- 195 { mge_intr_rxtx,"GbE aggregated interrupt" }, 196 { mge_intr_rx, "GbE receive interrupt" }, 197 { mge_intr_tx, "GbE transmit interrupt" }, 198 { mge_intr_misc,"GbE misc interrupt" }, 199 { mge_intr_sum, "GbE summary interrupt" }, 200 { mge_intr_err, "GbE error interrupt" }, 201}; 202 |
203/* SMI access interlock */ 204static struct sx sx_smi; 205 206static uint32_t 207mv_read_ge_smi(device_t dev, int phy, int reg) 208{ 209 uint32_t timeout; 210 uint32_t ret; 211 struct mge_softc *sc; 212 213 sc = device_get_softc(dev); 214 KASSERT(sc != NULL, ("NULL softc ptr!")); 215 timeout = MGE_SMI_WRITE_RETRIES; 216 217 MGE_SMI_LOCK(); 218 while (--timeout && 219 (MGE_READ(sc, MGE_REG_SMI) & MGE_SMI_BUSY)) 220 MGE_DELAY(MGE_SMI_WRITE_DELAY); 221 222 if (timeout == 0) { 223 device_printf(dev, "SMI write timeout.\n"); 224 ret = ~0U; 225 goto out; 226 } 227 228 MGE_WRITE(sc, MGE_REG_SMI, MGE_SMI_MASK & 229 (MGE_SMI_READ | (reg << 21) | (phy << 16))); 230 231 /* Wait till finished. */ 232 timeout = MGE_SMI_WRITE_RETRIES; 233 while (--timeout && 234 !((MGE_READ(sc, MGE_REG_SMI) & MGE_SMI_READVALID))) 235 MGE_DELAY(MGE_SMI_WRITE_DELAY); 236 237 if (timeout == 0) { 238 device_printf(dev, "SMI write validation timeout.\n"); 239 ret = ~0U; 240 goto out; 241 } 242 243 /* Wait for the data to update in the SMI register */ 244 MGE_DELAY(MGE_SMI_DELAY); 245 ret = MGE_READ(sc, MGE_REG_SMI) & MGE_SMI_DATA_MASK; 246 247out: 248 MGE_SMI_UNLOCK(); 249 return (ret); 250 251} 252 |
|
193static void | 253static void |
254mv_write_ge_smi(device_t dev, int phy, int reg, uint32_t value) 255{ 256 uint32_t timeout; 257 struct mge_softc *sc; 258 259 sc = device_get_softc(dev); 260 KASSERT(sc != NULL, ("NULL softc ptr!")); 261 262 MGE_SMI_LOCK(); 263 timeout = MGE_SMI_READ_RETRIES; 264 while (--timeout && 265 (MGE_READ(sc, MGE_REG_SMI) & MGE_SMI_BUSY)) 266 MGE_DELAY(MGE_SMI_READ_DELAY); 267 268 if (timeout == 0) { 269 device_printf(dev, "SMI read timeout.\n"); 270 goto out; 271 } 272 273 MGE_WRITE(sc, MGE_REG_SMI, MGE_SMI_MASK & 274 (MGE_SMI_WRITE | (reg << 21) | (phy << 16) | 275 (value & MGE_SMI_DATA_MASK))); 276 277out: 278 MGE_SMI_UNLOCK(); 279} 280 281static int 282mv_read_ext_phy(device_t dev, int phy, int reg) 283{ 284 uint32_t retries; 285 struct mge_softc *sc; 286 uint32_t ret; 287 288 sc = device_get_softc(dev); 289 290 MGE_SMI_LOCK(); 291 MGE_WRITE(sc->phy_sc, MGE_REG_SMI, MGE_SMI_MASK & 292 (MGE_SMI_READ | (reg << 21) | (phy << 16))); 293 294 retries = MGE_SMI_READ_RETRIES; 295 while (--retries && 296 !(MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_READVALID)) 297 DELAY(MGE_SMI_READ_DELAY); 298 299 if (retries == 0) 300 device_printf(dev, "Timeout while reading from PHY\n"); 301 302 ret = MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_DATA_MASK; 303 MGE_SMI_UNLOCK(); 304 305 return (ret); 306} 307 308static void 309mv_write_ext_phy(device_t dev, int phy, int reg, int value) 310{ 311 uint32_t retries; 312 struct mge_softc *sc; 313 314 sc = device_get_softc(dev); 315 316 MGE_SMI_LOCK(); 317 MGE_WRITE(sc->phy_sc, MGE_REG_SMI, MGE_SMI_MASK & 318 (MGE_SMI_WRITE | (reg << 21) | (phy << 16) | 319 (value & MGE_SMI_DATA_MASK))); 320 321 retries = MGE_SMI_WRITE_RETRIES; 322 while (--retries && MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_BUSY) 323 DELAY(MGE_SMI_WRITE_DELAY); 324 325 if (retries == 0) 326 device_printf(dev, "Timeout while writing to PHY\n"); 327 MGE_SMI_UNLOCK(); 328} 329 330static void |
|
194mge_get_mac_address(struct mge_softc *sc, uint8_t *addr) 195{ 196 uint32_t mac_l, mac_h; 197 uint8_t lmac[6]; 198 int i, valid; 199 200 /* 201 * Retrieve hw address from the device tree. --- 398 unchanged lines hidden (view full) --- 600 601static int 602mge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 603{ 604 struct mge_softc *sc = ifp->if_softc; 605 uint32_t int_cause, int_cause_ext; 606 int rx_npkts = 0; 607 | 331mge_get_mac_address(struct mge_softc *sc, uint8_t *addr) 332{ 333 uint32_t mac_l, mac_h; 334 uint8_t lmac[6]; 335 int i, valid; 336 337 /* 338 * Retrieve hw address from the device tree. --- 398 unchanged lines hidden (view full) --- 737 738static int 739mge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 740{ 741 struct mge_softc *sc = ifp->if_softc; 742 uint32_t int_cause, int_cause_ext; 743 int rx_npkts = 0; 744 |
608 MGE_GLOBAL_LOCK(sc); | 745 MGE_RECEIVE_LOCK(sc); |
609 610 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { | 746 747 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { |
611 MGE_GLOBAL_UNLOCK(sc); | 748 MGE_RECEIVE_UNLOCK(sc); |
612 return (rx_npkts); 613 } 614 615 if (cmd == POLL_AND_CHECK_STATUS) { 616 int_cause = MGE_READ(sc, MGE_PORT_INT_CAUSE); 617 int_cause_ext = MGE_READ(sc, MGE_PORT_INT_CAUSE_EXT); 618 619 /* Check for resource error */ 620 if (int_cause & MGE_PORT_INT_RXERRQ0) 621 mge_reinit_rx(sc); 622 623 if (int_cause || int_cause_ext) { 624 MGE_WRITE(sc, MGE_PORT_INT_CAUSE, ~int_cause); 625 MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT, ~int_cause_ext); 626 } 627 } 628 | 749 return (rx_npkts); 750 } 751 752 if (cmd == POLL_AND_CHECK_STATUS) { 753 int_cause = MGE_READ(sc, MGE_PORT_INT_CAUSE); 754 int_cause_ext = MGE_READ(sc, MGE_PORT_INT_CAUSE_EXT); 755 756 /* Check for resource error */ 757 if (int_cause & MGE_PORT_INT_RXERRQ0) 758 mge_reinit_rx(sc); 759 760 if (int_cause || int_cause_ext) { 761 MGE_WRITE(sc, MGE_PORT_INT_CAUSE, ~int_cause); 762 MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT, ~int_cause_ext); 763 } 764 } 765 |
629 mge_intr_tx_locked(sc); | 766 |
630 rx_npkts = mge_intr_rx_locked(sc, count); 631 | 767 rx_npkts = mge_intr_rx_locked(sc, count); 768 |
632 MGE_GLOBAL_UNLOCK(sc); | 769 MGE_RECEIVE_UNLOCK(sc); 770 MGE_TRANSMIT_LOCK(sc); 771 mge_intr_tx_locked(sc); 772 MGE_TRANSMIT_UNLOCK(sc); |
633 return (rx_npkts); 634} 635#endif /* DEVICE_POLLING */ 636 637static int 638mge_attach(device_t dev) 639{ 640 struct mge_softc *sc; 641 struct mii_softc *miisc; 642 struct ifnet *ifp; 643 uint8_t hwaddr[ETHER_ADDR_LEN]; 644 int i, error, phy; 645 646 sc = device_get_softc(dev); 647 sc->dev = dev; 648 sc->node = ofw_bus_get_node(dev); | 773 return (rx_npkts); 774} 775#endif /* DEVICE_POLLING */ 776 777static int 778mge_attach(device_t dev) 779{ 780 struct mge_softc *sc; 781 struct mii_softc *miisc; 782 struct ifnet *ifp; 783 uint8_t hwaddr[ETHER_ADDR_LEN]; 784 int i, error, phy; 785 786 sc = device_get_softc(dev); 787 sc->dev = dev; 788 sc->node = ofw_bus_get_node(dev); |
789 phy = 0; |
|
649 | 790 |
791 if (fdt_get_phyaddr(sc->node, sc->dev, &phy, (void **)&sc->phy_sc) == 0) { 792 device_printf(dev, "PHY%i attached, phy_sc points to %s\n", phy, 793 device_get_nameunit(sc->phy_sc->dev)); 794 sc->phy_attached = 1; 795 } else { 796 device_printf(dev, "PHY not attached.\n"); 797 sc->phy_attached = 0; 798 sc->phy_sc = sc; 799 } 800 801 if (fdt_find_compatible(sc->node, "mrvl,sw", 1) != 0) { 802 device_printf(dev, "Switch attached.\n"); 803 sc->switch_attached = 1; 804 /* additional variable available across instances */ 805 switch_attached = 1; 806 } else { 807 sc->switch_attached = 0; 808 } 809 810 if (device_get_unit(dev) == 0) { 811 sx_init(&sx_smi, "mge_tick() SMI access threads interlock"); 812 } 813 |
|
650 /* Set chip version-dependent parameters */ 651 mge_ver_params(sc); 652 | 814 /* Set chip version-dependent parameters */ 815 mge_ver_params(sc); 816 |
653 /* Get phy address and used softc from fdt */ 654 if (fdt_get_phyaddr(sc->node, sc->dev, &phy, (void **)&sc->phy_sc) != 0) 655 return (ENXIO); 656 | |
657 /* Initialize mutexes */ 658 mtx_init(&sc->transmit_lock, device_get_nameunit(dev), "mge TX lock", MTX_DEF); 659 mtx_init(&sc->receive_lock, device_get_nameunit(dev), "mge RX lock", MTX_DEF); 660 661 /* Allocate IO and IRQ resources */ 662 error = bus_alloc_resources(dev, res_spec, sc->res); 663 if (error) { 664 device_printf(dev, "could not allocate resources\n"); --- 49 unchanged lines hidden (view full) --- 714 IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 715 IFQ_SET_READY(&ifp->if_snd); 716 717 mge_get_mac_address(sc, hwaddr); 718 ether_ifattach(ifp, hwaddr); 719 callout_init(&sc->wd_callout, 0); 720 721 /* Attach PHY(s) */ | 817 /* Initialize mutexes */ 818 mtx_init(&sc->transmit_lock, device_get_nameunit(dev), "mge TX lock", MTX_DEF); 819 mtx_init(&sc->receive_lock, device_get_nameunit(dev), "mge RX lock", MTX_DEF); 820 821 /* Allocate IO and IRQ resources */ 822 error = bus_alloc_resources(dev, res_spec, sc->res); 823 if (error) { 824 device_printf(dev, "could not allocate resources\n"); --- 49 unchanged lines hidden (view full) --- 874 IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 875 IFQ_SET_READY(&ifp->if_snd); 876 877 mge_get_mac_address(sc, hwaddr); 878 ether_ifattach(ifp, hwaddr); 879 callout_init(&sc->wd_callout, 0); 880 881 /* Attach PHY(s) */ |
722 error = mii_attach(dev, &sc->miibus, ifp, mge_ifmedia_upd, 723 mge_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); 724 if (error) { 725 device_printf(dev, "attaching PHYs failed\n"); 726 mge_detach(dev); 727 return (error); | 882 if (sc->phy_attached) { 883 error = mii_attach(dev, &sc->miibus, ifp, mge_ifmedia_upd, 884 mge_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); 885 if (error) { 886 device_printf(dev, "MII failed to find PHY\n"); 887 if_free(ifp); 888 sc->ifp = NULL; 889 mge_detach(dev); 890 return (error); 891 } 892 sc->mii = device_get_softc(sc->miibus); 893 894 /* Tell the MAC where to find the PHY so autoneg works */ 895 miisc = LIST_FIRST(&sc->mii->mii_phys); 896 MGE_WRITE(sc, MGE_REG_PHYDEV, miisc->mii_phy); 897 } else { 898 /* no PHY, so use hard-coded values */ 899 ifmedia_init(&sc->mge_ifmedia, 0, 900 mge_ifmedia_upd, 901 mge_ifmedia_sts); 902 ifmedia_add(&sc->mge_ifmedia, 903 IFM_ETHER | IFM_1000_T | IFM_FDX, 904 0, NULL); 905 ifmedia_set(&sc->mge_ifmedia, 906 IFM_ETHER | IFM_1000_T | IFM_FDX); |
728 } | 907 } |
729 sc->mii = device_get_softc(sc->miibus); | |
730 | 908 |
731 /* Tell the MAC where to find the PHY so autoneg works */ 732 miisc = LIST_FIRST(&sc->mii->mii_phys); 733 MGE_WRITE(sc, MGE_REG_PHYDEV, miisc->mii_phy); 734 | |
735 /* Attach interrupt handlers */ 736 /* TODO: review flags, in part. mark RX as INTR_ENTROPY ? */ 737 for (i = 1; i <= sc->mge_intr_cnt; ++i) { 738 error = bus_setup_intr(dev, sc->res[i], 739 INTR_TYPE_NET | INTR_MPSAFE, 740 NULL, *mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i)].handler, 741 sc, &sc->ih_cookie[i - 1]); 742 if (error) { 743 device_printf(dev, "could not setup %s\n", 744 mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i)].description); 745 mge_detach(dev); 746 return (error); 747 } 748 } 749 | 909 /* Attach interrupt handlers */ 910 /* TODO: review flags, in part. mark RX as INTR_ENTROPY ? */ 911 for (i = 1; i <= sc->mge_intr_cnt; ++i) { 912 error = bus_setup_intr(dev, sc->res[i], 913 INTR_TYPE_NET | INTR_MPSAFE, 914 NULL, *mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i)].handler, 915 sc, &sc->ih_cookie[i - 1]); 916 if (error) { 917 device_printf(dev, "could not setup %s\n", 918 mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i)].description); 919 mge_detach(dev); 920 return (error); 921 } 922 } 923 |
924 if (sc->switch_attached) { 925 device_t child; 926 MGE_WRITE(sc, MGE_REG_PHYDEV, MGE_SWITCH_PHYDEV); 927 child = device_add_child(dev, "mdio", -1); 928 bus_generic_attach(dev); 929 } 930 |
|
750 return (0); 751} 752 753static int 754mge_detach(device_t dev) 755{ 756 struct mge_softc *sc; 757 int error,i; --- 29 unchanged lines hidden (view full) --- 787 788 /* Free IO memory handler */ 789 bus_release_resources(dev, res_spec, sc->res); 790 791 /* Destroy mutexes */ 792 mtx_destroy(&sc->receive_lock); 793 mtx_destroy(&sc->transmit_lock); 794 | 931 return (0); 932} 933 934static int 935mge_detach(device_t dev) 936{ 937 struct mge_softc *sc; 938 int error,i; --- 29 unchanged lines hidden (view full) --- 968 969 /* Free IO memory handler */ 970 bus_release_resources(dev, res_spec, sc->res); 971 972 /* Destroy mutexes */ 973 mtx_destroy(&sc->receive_lock); 974 mtx_destroy(&sc->transmit_lock); 975 |
976 if (device_get_unit(dev) == 0) 977 sx_destroy(&sx_smi); 978 |
|
795 return (0); 796} 797 798static void 799mge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 800{ 801 struct mge_softc *sc = ifp->if_softc; 802 struct mii_data *mii; 803 | 979 return (0); 980} 981 982static void 983mge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 984{ 985 struct mge_softc *sc = ifp->if_softc; 986 struct mii_data *mii; 987 |
804 MGE_TRANSMIT_LOCK(sc); | 988 MGE_GLOBAL_LOCK(sc); |
805 | 989 |
990 if (!sc->phy_attached) { 991 ifmr->ifm_active = IFM_1000_T | IFM_FDX | IFM_ETHER; 992 ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 993 goto out_unlock; 994 } 995 |
|
806 mii = sc->mii; 807 mii_pollstat(mii); 808 809 ifmr->ifm_active = mii->mii_media_active; 810 ifmr->ifm_status = mii->mii_media_status; 811 | 996 mii = sc->mii; 997 mii_pollstat(mii); 998 999 ifmr->ifm_active = mii->mii_media_active; 1000 ifmr->ifm_status = mii->mii_media_status; 1001 |
812 MGE_TRANSMIT_UNLOCK(sc); | 1002out_unlock: 1003 MGE_GLOBAL_UNLOCK(sc); |
813} 814 815static uint32_t 816mge_set_port_serial_control(uint32_t media) 817{ 818 uint32_t port_config; 819 820 port_config = PORT_SERIAL_RES_BIT9 | PORT_SERIAL_FORCE_LINK_FAIL | 821 PORT_SERIAL_MRU(PORT_SERIAL_MRU_1552); 822 823 if (IFM_TYPE(media) == IFM_ETHER) { 824 switch(IFM_SUBTYPE(media)) { 825 case IFM_AUTO: 826 break; 827 case IFM_1000_T: 828 port_config |= (PORT_SERIAL_GMII_SPEED_1000 | | 1004} 1005 1006static uint32_t 1007mge_set_port_serial_control(uint32_t media) 1008{ 1009 uint32_t port_config; 1010 1011 port_config = PORT_SERIAL_RES_BIT9 | PORT_SERIAL_FORCE_LINK_FAIL | 1012 PORT_SERIAL_MRU(PORT_SERIAL_MRU_1552); 1013 1014 if (IFM_TYPE(media) == IFM_ETHER) { 1015 switch(IFM_SUBTYPE(media)) { 1016 case IFM_AUTO: 1017 break; 1018 case IFM_1000_T: 1019 port_config |= (PORT_SERIAL_GMII_SPEED_1000 | |
829 PORT_SERIAL_AUTONEG | PORT_SERIAL_AUTONEG_FC | 830 PORT_SERIAL_SPEED_AUTONEG); | 1020 PORT_SERIAL_AUTONEG | PORT_SERIAL_AUTONEG_FC 1021 | PORT_SERIAL_SPEED_AUTONEG); |
831 break; 832 case IFM_100_TX: 833 port_config |= (PORT_SERIAL_MII_SPEED_100 | | 1022 break; 1023 case IFM_100_TX: 1024 port_config |= (PORT_SERIAL_MII_SPEED_100 | |
834 PORT_SERIAL_AUTONEG | PORT_SERIAL_AUTONEG_FC | 835 PORT_SERIAL_SPEED_AUTONEG); | 1025 PORT_SERIAL_AUTONEG | PORT_SERIAL_AUTONEG_FC 1026 | PORT_SERIAL_SPEED_AUTONEG); |
836 break; 837 case IFM_10_T: 838 port_config |= (PORT_SERIAL_AUTONEG | 839 PORT_SERIAL_AUTONEG_FC | 840 PORT_SERIAL_SPEED_AUTONEG); 841 break; 842 } 843 if (media & IFM_FDX) 844 port_config |= PORT_SERIAL_FULL_DUPLEX; 845 } 846 return (port_config); 847} 848 849static int 850mge_ifmedia_upd(struct ifnet *ifp) 851{ 852 struct mge_softc *sc = ifp->if_softc; 853 | 1027 break; 1028 case IFM_10_T: 1029 port_config |= (PORT_SERIAL_AUTONEG | 1030 PORT_SERIAL_AUTONEG_FC | 1031 PORT_SERIAL_SPEED_AUTONEG); 1032 break; 1033 } 1034 if (media & IFM_FDX) 1035 port_config |= PORT_SERIAL_FULL_DUPLEX; 1036 } 1037 return (port_config); 1038} 1039 1040static int 1041mge_ifmedia_upd(struct ifnet *ifp) 1042{ 1043 struct mge_softc *sc = ifp->if_softc; 1044 |
854 if (ifp->if_flags & IFF_UP) { | 1045 /* 1046 * Do not do anything for switch here, as updating media between 1047 * MGE MAC and switch MAC is hardcoded in PCB. Changing it here would 1048 * break the link. 1049 */ 1050 if (sc->phy_attached) { |
855 MGE_GLOBAL_LOCK(sc); | 1051 MGE_GLOBAL_LOCK(sc); |
1052 if (ifp->if_flags & IFF_UP) { 1053 sc->mge_media_status = sc->mii->mii_media.ifm_media; 1054 mii_mediachg(sc->mii); |
|
856 | 1055 |
857 sc->mge_media_status = sc->mii->mii_media.ifm_media; 858 mii_mediachg(sc->mii); 859 mge_init_locked(sc); | 1056 /* MGE MAC needs to be reinitialized. */ 1057 mge_init_locked(sc); |
860 | 1058 |
1059 } |
|
861 MGE_GLOBAL_UNLOCK(sc); 862 } 863 864 return (0); 865} 866 867static void 868mge_init(void *arg) --- 9 unchanged lines hidden (view full) --- 878 879static void 880mge_init_locked(void *arg) 881{ 882 struct mge_softc *sc = arg; 883 struct mge_desc_wrapper *dw; 884 volatile uint32_t reg_val; 885 int i, count; | 1060 MGE_GLOBAL_UNLOCK(sc); 1061 } 1062 1063 return (0); 1064} 1065 1066static void 1067mge_init(void *arg) --- 9 unchanged lines hidden (view full) --- 1077 1078static void 1079mge_init_locked(void *arg) 1080{ 1081 struct mge_softc *sc = arg; 1082 struct mge_desc_wrapper *dw; 1083 volatile uint32_t reg_val; 1084 int i, count; |
1085 uint32_t media_status; |
|
886 887 888 MGE_GLOBAL_LOCK_ASSERT(sc); 889 890 /* Stop interface */ 891 mge_stop(sc); 892 893 /* Disable interrupts */ --- 26 unchanged lines hidden (view full) --- 920 MGE_WRITE(sc, sc->mge_mtu, 0); 921 922 /* Port configuration */ 923 MGE_WRITE(sc, MGE_PORT_CONFIG, 924 PORT_CONFIG_RXCS | PORT_CONFIG_DFLT_RXQ(0) | 925 PORT_CONFIG_ARO_RXQ(0)); 926 MGE_WRITE(sc, MGE_PORT_EXT_CONFIG , 0x0); 927 | 1086 1087 1088 MGE_GLOBAL_LOCK_ASSERT(sc); 1089 1090 /* Stop interface */ 1091 mge_stop(sc); 1092 1093 /* Disable interrupts */ --- 26 unchanged lines hidden (view full) --- 1120 MGE_WRITE(sc, sc->mge_mtu, 0); 1121 1122 /* Port configuration */ 1123 MGE_WRITE(sc, MGE_PORT_CONFIG, 1124 PORT_CONFIG_RXCS | PORT_CONFIG_DFLT_RXQ(0) | 1125 PORT_CONFIG_ARO_RXQ(0)); 1126 MGE_WRITE(sc, MGE_PORT_EXT_CONFIG , 0x0); 1127 |
1128 /* Configure promisc mode */ 1129 mge_set_prom_mode(sc, MGE_RX_DEFAULT_QUEUE); 1130 1131 media_status = sc->mge_media_status; 1132 if (sc->switch_attached) { 1133 media_status &= ~IFM_TMASK; 1134 media_status |= IFM_1000_T; 1135 } 1136 |
|
928 /* Setup port configuration */ | 1137 /* Setup port configuration */ |
929 reg_val = mge_set_port_serial_control(sc->mge_media_status); | 1138 reg_val = mge_set_port_serial_control(media_status); |
930 MGE_WRITE(sc, MGE_PORT_SERIAL_CTRL, reg_val); 931 932 /* Setup SDMA configuration */ 933 MGE_WRITE(sc, MGE_SDMA_CONFIG , MGE_SDMA_RX_BYTE_SWAP | 934 MGE_SDMA_TX_BYTE_SWAP | 935 MGE_SDMA_RX_BURST_SIZE(MGE_SDMA_BURST_16_WORD) | 936 MGE_SDMA_TX_BURST_SIZE(MGE_SDMA_BURST_16_WORD)); 937 --- 54 unchanged lines hidden (view full) --- 992 mge_intrs_ctrl(sc, 1); 993 994 /* Activate network interface */ 995 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; 996 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 997 sc->wd_timer = 0; 998 999 /* Schedule watchdog timeout */ | 1139 MGE_WRITE(sc, MGE_PORT_SERIAL_CTRL, reg_val); 1140 1141 /* Setup SDMA configuration */ 1142 MGE_WRITE(sc, MGE_SDMA_CONFIG , MGE_SDMA_RX_BYTE_SWAP | 1143 MGE_SDMA_TX_BYTE_SWAP | 1144 MGE_SDMA_RX_BURST_SIZE(MGE_SDMA_BURST_16_WORD) | 1145 MGE_SDMA_TX_BURST_SIZE(MGE_SDMA_BURST_16_WORD)); 1146 --- 54 unchanged lines hidden (view full) --- 1201 mge_intrs_ctrl(sc, 1); 1202 1203 /* Activate network interface */ 1204 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; 1205 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1206 sc->wd_timer = 0; 1207 1208 /* Schedule watchdog timeout */ |
1000 callout_reset(&sc->wd_callout, hz, mge_tick, sc); | 1209 if (sc->phy_attached) 1210 callout_reset(&sc->wd_callout, hz, mge_tick, sc); |
1001} 1002 1003static void 1004mge_intr_rxtx(void *arg) 1005{ 1006 struct mge_softc *sc = arg; 1007 uint32_t int_cause, int_cause_ext; 1008 --- 317 unchanged lines hidden (view full) --- 1326 ifp->if_capenable &= ~IFCAP_POLLING; 1327 MGE_GLOBAL_UNLOCK(sc); 1328 } 1329 } 1330#endif 1331 break; 1332 case SIOCGIFMEDIA: /* fall through */ 1333 case SIOCSIFMEDIA: | 1211} 1212 1213static void 1214mge_intr_rxtx(void *arg) 1215{ 1216 struct mge_softc *sc = arg; 1217 uint32_t int_cause, int_cause_ext; 1218 --- 317 unchanged lines hidden (view full) --- 1536 ifp->if_capenable &= ~IFCAP_POLLING; 1537 MGE_GLOBAL_UNLOCK(sc); 1538 } 1539 } 1540#endif 1541 break; 1542 case SIOCGIFMEDIA: /* fall through */ 1543 case SIOCSIFMEDIA: |
1544 /* 1545 * Setting up media type via ioctls is *not* supported for MAC 1546 * which is connected to switch. Use etherswitchcfg. 1547 */ 1548 if (!sc->phy_attached && (command == SIOCSIFMEDIA)) 1549 return (0); 1550 else if (!sc->phy_attached) { 1551 error = ifmedia_ioctl(ifp, ifr, &sc->mge_ifmedia, 1552 command); 1553 break; 1554 } 1555 |
|
1334 if (IFM_SUBTYPE(ifr->ifr_media) == IFM_1000_T 1335 && !(ifr->ifr_media & IFM_FDX)) { 1336 device_printf(sc->dev, 1337 "1000baseTX half-duplex unsupported\n"); 1338 return 0; 1339 } 1340 error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command); 1341 break; 1342 default: 1343 error = ether_ioctl(ifp, command, data); 1344 } 1345 return (error); 1346} 1347 1348static int 1349mge_miibus_readreg(device_t dev, int phy, int reg) 1350{ 1351 struct mge_softc *sc; | 1556 if (IFM_SUBTYPE(ifr->ifr_media) == IFM_1000_T 1557 && !(ifr->ifr_media & IFM_FDX)) { 1558 device_printf(sc->dev, 1559 "1000baseTX half-duplex unsupported\n"); 1560 return 0; 1561 } 1562 error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command); 1563 break; 1564 default: 1565 error = ether_ioctl(ifp, command, data); 1566 } 1567 return (error); 1568} 1569 1570static int 1571mge_miibus_readreg(device_t dev, int phy, int reg) 1572{ 1573 struct mge_softc *sc; |
1352 uint32_t retries; 1353 | |
1354 sc = device_get_softc(dev); 1355 | 1574 sc = device_get_softc(dev); 1575 |
1356 MGE_WRITE(sc->phy_sc, MGE_REG_SMI, 0x1fffffff & 1357 (MGE_SMI_READ | (reg << 21) | (phy << 16))); | 1576 KASSERT(!switch_attached, ("miibus used with switch attached")); |
1358 | 1577 |
1359 retries = MGE_SMI_READ_RETRIES; 1360 while (--retries && 1361 !(MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_READVALID)) 1362 DELAY(MGE_SMI_READ_DELAY); 1363 1364 if (retries == 0) 1365 device_printf(dev, "Timeout while reading from PHY\n"); 1366 1367 return (MGE_READ(sc->phy_sc, MGE_REG_SMI) & 0xffff); | 1578 return (mv_read_ext_phy(dev, phy, reg)); |
1368} 1369 1370static int 1371mge_miibus_writereg(device_t dev, int phy, int reg, int value) 1372{ 1373 struct mge_softc *sc; | 1579} 1580 1581static int 1582mge_miibus_writereg(device_t dev, int phy, int reg, int value) 1583{ 1584 struct mge_softc *sc; |
1374 uint32_t retries; 1375 | |
1376 sc = device_get_softc(dev); 1377 | 1585 sc = device_get_softc(dev); 1586 |
1378 MGE_WRITE(sc->phy_sc, MGE_REG_SMI, 0x1fffffff & 1379 (MGE_SMI_WRITE | (reg << 21) | (phy << 16) | (value & 0xffff))); | 1587 KASSERT(!switch_attached, ("miibus used with switch attached")); |
1380 | 1588 |
1381 retries = MGE_SMI_WRITE_RETRIES; 1382 while (--retries && MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_BUSY) 1383 DELAY(MGE_SMI_WRITE_DELAY); | 1589 mv_write_ext_phy(dev, phy, reg, value); |
1384 | 1590 |
1385 if (retries == 0) 1386 device_printf(dev, "Timeout while writing to PHY\n"); | |
1387 return (0); 1388} 1389 1390static int 1391mge_probe(device_t dev) 1392{ 1393 1394 if (!ofw_bus_status_okay(dev)) --- 89 unchanged lines hidden (view full) --- 1484 return (0); 1485} 1486 1487static void 1488mge_tick(void *msc) 1489{ 1490 struct mge_softc *sc = msc; 1491 | 1591 return (0); 1592} 1593 1594static int 1595mge_probe(device_t dev) 1596{ 1597 1598 if (!ofw_bus_status_okay(dev)) --- 89 unchanged lines hidden (view full) --- 1688 return (0); 1689} 1690 1691static void 1692mge_tick(void *msc) 1693{ 1694 struct mge_softc *sc = msc; 1695 |
1696 KASSERT(sc->phy_attached == 1, ("mge_tick while PHY not attached")); 1697 1698 MGE_GLOBAL_LOCK(sc); 1699 |
|
1492 /* Check for TX timeout */ 1493 mge_watchdog(sc); 1494 1495 mii_tick(sc->mii); 1496 1497 /* Check for media type change */ 1498 if(sc->mge_media_status != sc->mii->mii_media.ifm_media) 1499 mge_ifmedia_upd(sc->ifp); 1500 | 1700 /* Check for TX timeout */ 1701 mge_watchdog(sc); 1702 1703 mii_tick(sc->mii); 1704 1705 /* Check for media type change */ 1706 if(sc->mge_media_status != sc->mii->mii_media.ifm_media) 1707 mge_ifmedia_upd(sc->ifp); 1708 |
1709 MGE_GLOBAL_UNLOCK(sc); 1710 |
|
1501 /* Schedule another timeout one second from now */ 1502 callout_reset(&sc->wd_callout, hz, mge_tick, sc); | 1711 /* Schedule another timeout one second from now */ 1712 callout_reset(&sc->wd_callout, hz, mge_tick, sc); |
1713 1714 return; |
|
1503} 1504 1505static void 1506mge_watchdog(struct mge_softc *sc) 1507{ 1508 struct ifnet *ifp; 1509 1510 ifp = sc->ifp; 1511 | 1715} 1716 1717static void 1718mge_watchdog(struct mge_softc *sc) 1719{ 1720 struct ifnet *ifp; 1721 1722 ifp = sc->ifp; 1723 |
1512 MGE_GLOBAL_LOCK(sc); 1513 | |
1514 if (sc->wd_timer == 0 || --sc->wd_timer) { | 1724 if (sc->wd_timer == 0 || --sc->wd_timer) { |
1515 MGE_GLOBAL_UNLOCK(sc); | |
1516 return; 1517 } 1518 1519 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1520 if_printf(ifp, "watchdog timeout\n"); 1521 1522 mge_stop(sc); 1523 mge_init_locked(sc); | 1725 return; 1726 } 1727 1728 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1729 if_printf(ifp, "watchdog timeout\n"); 1730 1731 mge_stop(sc); 1732 mge_init_locked(sc); |
1524 1525 MGE_GLOBAL_UNLOCK(sc); | |
1526} 1527 1528static void 1529mge_start(struct ifnet *ifp) 1530{ 1531 struct mge_softc *sc = ifp->if_softc; 1532 1533 MGE_TRANSMIT_LOCK(sc); --- 388 unchanged lines hidden (view full) --- 1922 1923 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_time", 1924 CTLTYPE_UINT | CTLFLAG_RW, sc, MGE_IC_RX, mge_sysctl_ic, 1925 "I", "IC RX time threshold"); 1926 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_time", 1927 CTLTYPE_UINT | CTLFLAG_RW, sc, MGE_IC_TX, mge_sysctl_ic, 1928 "I", "IC TX time threshold"); 1929} | 1733} 1734 1735static void 1736mge_start(struct ifnet *ifp) 1737{ 1738 struct mge_softc *sc = ifp->if_softc; 1739 1740 MGE_TRANSMIT_LOCK(sc); --- 388 unchanged lines hidden (view full) --- 2129 2130 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_time", 2131 CTLTYPE_UINT | CTLFLAG_RW, sc, MGE_IC_RX, mge_sysctl_ic, 2132 "I", "IC RX time threshold"); 2133 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_time", 2134 CTLTYPE_UINT | CTLFLAG_RW, sc, MGE_IC_TX, mge_sysctl_ic, 2135 "I", "IC TX time threshold"); 2136} |
2137 2138static int 2139mge_mdio_writereg(device_t dev, int phy, int reg, int value) 2140{ 2141 2142 mv_write_ge_smi(dev, phy, reg, value); 2143 2144 return (0); 2145} 2146 2147 2148static int 2149mge_mdio_readreg(device_t dev, int phy, int reg) 2150{ 2151 int ret; 2152 2153 ret = mv_read_ge_smi(dev, phy, reg); 2154 2155 return (ret); 2156} |
|