Deleted Added
full compact
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}