| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_emac.c,v 1.53 2020/07/06 09:34:17 rin Exp $ */ | | 1 | /* $NetBSD: if_emac.c,v 1.54 2021/01/24 05:22:21 rin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright 2001, 2002 Wasabi Systems, Inc. | | 4 | * Copyright 2001, 2002 Wasabi Systems, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Written by Simon Burge and Jason Thorpe for Wasabi Systems, Inc. | | 7 | * Written by Simon Burge and Jason Thorpe for Wasabi Systems, Inc. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -42,41 +42,43 @@ | | | @@ -42,41 +42,43 @@ |
42 | * tested | | 42 | * tested |
43 | * ------ | | 43 | * ------ |
44 | * 405EP - 10/100 x2 | | 44 | * 405EP - 10/100 x2 |
45 | * 405EX/EXr o 10/100/1000 x2 (EXr x1), STA v2, 256bit hash-Table, RGMII | | 45 | * 405EX/EXr o 10/100/1000 x2 (EXr x1), STA v2, 256bit hash-Table, RGMII |
46 | * 405GP/GPr o 10/100 | | 46 | * 405GP/GPr o 10/100 |
47 | * 440EP - 10/100 x2, ZMII | | 47 | * 440EP - 10/100 x2, ZMII |
48 | * 440GP - 10/100 x2, ZMII | | 48 | * 440GP - 10/100 x2, ZMII |
49 | * 440GX - 10/100/1000 x4, ZMII/RGMII(ch 2, 3), TAH(ch 2, 3) | | 49 | * 440GX - 10/100/1000 x4, ZMII/RGMII(ch 2, 3), TAH(ch 2, 3) |
50 | * 440SP - 10/100/1000 | | 50 | * 440SP - 10/100/1000 |
51 | * 440SPe - 10/100/1000, STA v2 | | 51 | * 440SPe - 10/100/1000, STA v2 |
52 | */ | | 52 | */ |
53 | | | 53 | |
54 | #include <sys/cdefs.h> | | 54 | #include <sys/cdefs.h> |
55 | __KERNEL_RCSID(0, "$NetBSD: if_emac.c,v 1.53 2020/07/06 09:34:17 rin Exp $"); | | 55 | __KERNEL_RCSID(0, "$NetBSD: if_emac.c,v 1.54 2021/01/24 05:22:21 rin Exp $"); |
56 | | | 56 | |
57 | #ifdef _KERNEL_OPT | | 57 | #ifdef _KERNEL_OPT |
58 | #include "opt_emac.h" | | 58 | #include "opt_emac.h" |
59 | #endif | | 59 | #endif |
60 | | | 60 | |
61 | #include <sys/param.h> | | 61 | #include <sys/param.h> |
62 | #include <sys/systm.h> | | 62 | #include <sys/systm.h> |
63 | #include <sys/mbuf.h> | | 63 | #include <sys/mbuf.h> |
64 | #include <sys/kernel.h> | | 64 | #include <sys/kernel.h> |
65 | #include <sys/socket.h> | | 65 | #include <sys/socket.h> |
66 | #include <sys/ioctl.h> | | 66 | #include <sys/ioctl.h> |
67 | #include <sys/cpu.h> | | 67 | #include <sys/cpu.h> |
68 | #include <sys/device.h> | | 68 | #include <sys/device.h> |
69 | | | 69 | |
| | | 70 | #include <sys/rndsource.h> |
| | | 71 | |
70 | #include <uvm/uvm_extern.h> /* for PAGE_SIZE */ | | 72 | #include <uvm/uvm_extern.h> /* for PAGE_SIZE */ |
71 | | | 73 | |
72 | #include <net/if.h> | | 74 | #include <net/if.h> |
73 | #include <net/if_dl.h> | | 75 | #include <net/if_dl.h> |
74 | #include <net/if_media.h> | | 76 | #include <net/if_media.h> |
75 | #include <net/if_ether.h> | | 77 | #include <net/if_ether.h> |
76 | | | 78 | |
77 | #include <net/bpf.h> | | 79 | #include <net/bpf.h> |
78 | | | 80 | |
79 | #include <powerpc/ibm4xx/cpu.h> | | 81 | #include <powerpc/ibm4xx/cpu.h> |
80 | #include <powerpc/ibm4xx/dcr4xx.h> | | 82 | #include <powerpc/ibm4xx/dcr4xx.h> |
81 | #include <powerpc/ibm4xx/mal405gp.h> | | 83 | #include <powerpc/ibm4xx/mal405gp.h> |
82 | #include <powerpc/ibm4xx/dev/emacreg.h> | | 84 | #include <powerpc/ibm4xx/dev/emacreg.h> |
| @@ -200,26 +202,28 @@ struct emac_softc { | | | @@ -200,26 +202,28 @@ struct emac_softc { |
200 | struct evcnt sc_ev_txdrop; /* Tx packets dropped (too many segs) */ | | 202 | struct evcnt sc_ev_txdrop; /* Tx packets dropped (too many segs) */ |
201 | struct evcnt sc_ev_tu; /* Tx underrun */ | | 203 | struct evcnt sc_ev_tu; /* Tx underrun */ |
202 | #endif /* EMAC_EVENT_COUNTERS */ | | 204 | #endif /* EMAC_EVENT_COUNTERS */ |
203 | | | 205 | |
204 | int sc_txfree; /* number of free Tx descriptors */ | | 206 | int sc_txfree; /* number of free Tx descriptors */ |
205 | int sc_txnext; /* next ready Tx descriptor */ | | 207 | int sc_txnext; /* next ready Tx descriptor */ |
206 | | | 208 | |
207 | int sc_txsfree; /* number of free Tx jobs */ | | 209 | int sc_txsfree; /* number of free Tx jobs */ |
208 | int sc_txsnext; /* next ready Tx job */ | | 210 | int sc_txsnext; /* next ready Tx job */ |
209 | int sc_txsdirty; /* dirty Tx jobs */ | | 211 | int sc_txsdirty; /* dirty Tx jobs */ |
210 | | | 212 | |
211 | int sc_rxptr; /* next ready RX descriptor/descsoft */ | | 213 | int sc_rxptr; /* next ready RX descriptor/descsoft */ |
212 | | | 214 | |
| | | 215 | krndsource_t rnd_source; /* random source */ |
| | | 216 | |
213 | void (*sc_rmii_enable)(device_t, int); /* reduced MII enable */ | | 217 | void (*sc_rmii_enable)(device_t, int); /* reduced MII enable */ |
214 | void (*sc_rmii_disable)(device_t, int); /* reduced MII disable*/ | | 218 | void (*sc_rmii_disable)(device_t, int); /* reduced MII disable*/ |
215 | void (*sc_rmii_speed)(device_t, int, int); /* reduced MII speed */ | | 219 | void (*sc_rmii_speed)(device_t, int, int); /* reduced MII speed */ |
216 | }; | | 220 | }; |
217 | | | 221 | |
218 | #ifdef EMAC_EVENT_COUNTERS | | 222 | #ifdef EMAC_EVENT_COUNTERS |
219 | #define EMAC_EVCNT_INCR(ev) (ev)->ev_count++ | | 223 | #define EMAC_EVCNT_INCR(ev) (ev)->ev_count++ |
220 | #else | | 224 | #else |
221 | #define EMAC_EVCNT_INCR(ev) /* nothing */ | | 225 | #define EMAC_EVCNT_INCR(ev) /* nothing */ |
222 | #endif | | 226 | #endif |
223 | | | 227 | |
224 | #define EMAC_CDTXADDR(sc, x) ((sc)->sc_cddma + EMAC_CDTXOFF((x))) | | 228 | #define EMAC_CDTXADDR(sc, x) ((sc)->sc_cddma + EMAC_CDTXOFF((x))) |
225 | #define EMAC_CDRXADDR(sc, x) ((sc)->sc_cddma + EMAC_CDRXOFF((x))) | | 229 | #define EMAC_CDRXADDR(sc, x) ((sc)->sc_cddma + EMAC_CDRXOFF((x))) |
| @@ -545,26 +549,29 @@ emac_attach(device_t parent, device_t se | | | @@ -545,26 +549,29 @@ emac_attach(device_t parent, device_t se |
545 | | | 549 | |
546 | /* | | 550 | /* |
547 | * We can support 802.1Q VLAN-sized frames. | | 551 | * We can support 802.1Q VLAN-sized frames. |
548 | */ | | 552 | */ |
549 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; | | 553 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; |
550 | | | 554 | |
551 | /* | | 555 | /* |
552 | * Attach the interface. | | 556 | * Attach the interface. |
553 | */ | | 557 | */ |
554 | if_attach(ifp); | | 558 | if_attach(ifp); |
555 | if_deferred_start_init(ifp, NULL); | | 559 | if_deferred_start_init(ifp, NULL); |
556 | ether_ifattach(ifp, enaddr); | | 560 | ether_ifattach(ifp, enaddr); |
557 | | | 561 | |
| | | 562 | rnd_attach_source(&sc->rnd_source, xname, RND_TYPE_NET, |
| | | 563 | RND_FLAG_DEFAULT); |
| | | 564 | |
558 | #ifdef EMAC_EVENT_COUNTERS | | 565 | #ifdef EMAC_EVENT_COUNTERS |
559 | /* | | 566 | /* |
560 | * Attach the event counters. | | 567 | * Attach the event counters. |
561 | */ | | 568 | */ |
562 | evcnt_attach_dynamic(&sc->sc_ev_txintr, EVCNT_TYPE_INTR, | | 569 | evcnt_attach_dynamic(&sc->sc_ev_txintr, EVCNT_TYPE_INTR, |
563 | NULL, xname, "txintr"); | | 570 | NULL, xname, "txintr"); |
564 | evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_INTR, | | 571 | evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_INTR, |
565 | NULL, xname, "rxintr"); | | 572 | NULL, xname, "rxintr"); |
566 | evcnt_attach_dynamic(&sc->sc_ev_txde, EVCNT_TYPE_INTR, | | 573 | evcnt_attach_dynamic(&sc->sc_ev_txde, EVCNT_TYPE_INTR, |
567 | NULL, xname, "txde"); | | 574 | NULL, xname, "txde"); |
568 | evcnt_attach_dynamic(&sc->sc_ev_rxde, EVCNT_TYPE_INTR, | | 575 | evcnt_attach_dynamic(&sc->sc_ev_rxde, EVCNT_TYPE_INTR, |
569 | NULL, xname, "rxde"); | | 576 | NULL, xname, "rxde"); |
570 | evcnt_attach_dynamic(&sc->sc_ev_intr, EVCNT_TYPE_INTR, | | 577 | evcnt_attach_dynamic(&sc->sc_ev_intr, EVCNT_TYPE_INTR, |
| @@ -1244,33 +1251,34 @@ emac_set_filter(struct emac_softc *sc) | | | @@ -1244,33 +1251,34 @@ emac_set_filter(struct emac_softc *sc) |
1244 | | | 1251 | |
1245 | return 0; | | 1252 | return 0; |
1246 | } | | 1253 | } |
1247 | | | 1254 | |
1248 | /* | | 1255 | /* |
1249 | * Reap completed Tx descriptors. | | 1256 | * Reap completed Tx descriptors. |
1250 | */ | | 1257 | */ |
1251 | static int | | 1258 | static int |
1252 | emac_txreap(struct emac_softc *sc) | | 1259 | emac_txreap(struct emac_softc *sc) |
1253 | { | | 1260 | { |
1254 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 1261 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
1255 | struct emac_txsoft *txs; | | 1262 | struct emac_txsoft *txs; |
1256 | int handled, i; | | 1263 | int handled, i; |
1257 | uint32_t txstat; | | 1264 | uint32_t txstat, count; |
1258 | | | 1265 | |
1259 | EMAC_EVCNT_INCR(&sc->sc_ev_txreap); | | 1266 | EMAC_EVCNT_INCR(&sc->sc_ev_txreap); |
1260 | handled = 0; | | 1267 | handled = 0; |
1261 | | | 1268 | |
1262 | ifp->if_flags &= ~IFF_OACTIVE; | | 1269 | ifp->if_flags &= ~IFF_OACTIVE; |
1263 | | | 1270 | |
| | | 1271 | count = 0; |
1264 | /* | | 1272 | /* |
1265 | * Go through our Tx list and free mbufs for those | | 1273 | * Go through our Tx list and free mbufs for those |
1266 | * frames that have been transmitted. | | 1274 | * frames that have been transmitted. |
1267 | */ | | 1275 | */ |
1268 | for (i = sc->sc_txsdirty; sc->sc_txsfree != EMAC_TXQUEUELEN; | | 1276 | for (i = sc->sc_txsdirty; sc->sc_txsfree != EMAC_TXQUEUELEN; |
1269 | i = EMAC_NEXTTXS(i), sc->sc_txsfree++) { | | 1277 | i = EMAC_NEXTTXS(i), sc->sc_txsfree++) { |
1270 | txs = &sc->sc_txsoft[i]; | | 1278 | txs = &sc->sc_txsoft[i]; |
1271 | | | 1279 | |
1272 | EMAC_CDTXSYNC(sc, txs->txs_lastdesc, | | 1280 | EMAC_CDTXSYNC(sc, txs->txs_lastdesc, |
1273 | txs->txs_dmamap->dm_nsegs, | | 1281 | txs->txs_dmamap->dm_nsegs, |
1274 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); | | 1282 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
1275 | | | 1283 | |
1276 | txstat = sc->sc_txdescs[txs->txs_lastdesc].md_stat_ctrl; | | 1284 | txstat = sc->sc_txdescs[txs->txs_lastdesc].md_stat_ctrl; |
| @@ -1307,38 +1315,43 @@ emac_txreap(struct emac_softc *sc) | | | @@ -1307,38 +1315,43 @@ emac_txreap(struct emac_softc *sc) |
1307 | if (txstat & EMAC_TXS_ED) | | 1315 | if (txstat & EMAC_TXS_ED) |
1308 | aprint_error_ifnet(ifp, "excessive deferral\n"); | | 1316 | aprint_error_ifnet(ifp, "excessive deferral\n"); |
1309 | if (txstat & EMAC_TXS_EC) | | 1317 | if (txstat & EMAC_TXS_EC) |
1310 | aprint_error_ifnet(ifp, | | 1318 | aprint_error_ifnet(ifp, |
1311 | "excessive collisions\n"); | | 1319 | "excessive collisions\n"); |
1312 | } | | 1320 | } |
1313 | | | 1321 | |
1314 | sc->sc_txfree += txs->txs_ndesc; | | 1322 | sc->sc_txfree += txs->txs_ndesc; |
1315 | bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap, | | 1323 | bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap, |
1316 | 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); | | 1324 | 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
1317 | bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); | | 1325 | bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); |
1318 | m_freem(txs->txs_mbuf); | | 1326 | m_freem(txs->txs_mbuf); |
1319 | txs->txs_mbuf = NULL; | | 1327 | txs->txs_mbuf = NULL; |
| | | 1328 | |
| | | 1329 | count++; |
1320 | } | | 1330 | } |
1321 | | | 1331 | |
1322 | /* Update the dirty transmit buffer pointer. */ | | 1332 | /* Update the dirty transmit buffer pointer. */ |
1323 | sc->sc_txsdirty = i; | | 1333 | sc->sc_txsdirty = i; |
1324 | | | 1334 | |
1325 | /* | | 1335 | /* |
1326 | * If there are no more pending transmissions, cancel the watchdog | | 1336 | * If there are no more pending transmissions, cancel the watchdog |
1327 | * timer. | | 1337 | * timer. |
1328 | */ | | 1338 | */ |
1329 | if (sc->sc_txsfree == EMAC_TXQUEUELEN) | | 1339 | if (sc->sc_txsfree == EMAC_TXQUEUELEN) |
1330 | ifp->if_timer = 0; | | 1340 | ifp->if_timer = 0; |
1331 | | | 1341 | |
| | | 1342 | if (count != 0) |
| | | 1343 | rnd_add_uint32(&sc->rnd_source, count); |
| | | 1344 | |
1332 | return handled; | | 1345 | return handled; |
1333 | } | | 1346 | } |
1334 | | | 1347 | |
1335 | | | 1348 | |
1336 | /* | | 1349 | /* |
1337 | * Reset functions | | 1350 | * Reset functions |
1338 | */ | | 1351 | */ |
1339 | | | 1352 | |
1340 | static void | | 1353 | static void |
1341 | emac_soft_reset(struct emac_softc *sc) | | 1354 | emac_soft_reset(struct emac_softc *sc) |
1342 | { | | 1355 | { |
1343 | uint32_t sdr; | | 1356 | uint32_t sdr; |
1344 | int t = 0; | | 1357 | int t = 0; |
| @@ -1572,31 +1585,32 @@ emac_txeob_intr(void *arg) | | | @@ -1572,31 +1585,32 @@ emac_txeob_intr(void *arg) |
1572 | /* try to get more packets going */ | | 1585 | /* try to get more packets going */ |
1573 | if_schedule_deferred_start(&sc->sc_ethercom.ec_if); | | 1586 | if_schedule_deferred_start(&sc->sc_ethercom.ec_if); |
1574 | | | 1587 | |
1575 | return handled; | | 1588 | return handled; |
1576 | } | | 1589 | } |
1577 | | | 1590 | |
1578 | int | | 1591 | int |
1579 | emac_rxeob_intr(void *arg) | | 1592 | emac_rxeob_intr(void *arg) |
1580 | { | | 1593 | { |
1581 | struct emac_softc *sc = arg; | | 1594 | struct emac_softc *sc = arg; |
1582 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 1595 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
1583 | struct emac_rxsoft *rxs; | | 1596 | struct emac_rxsoft *rxs; |
1584 | struct mbuf *m; | | 1597 | struct mbuf *m; |
1585 | uint32_t rxstat; | | 1598 | uint32_t rxstat, count; |
1586 | int i, len; | | 1599 | int i, len; |
1587 | | | 1600 | |
1588 | EMAC_EVCNT_INCR(&sc->sc_ev_rxintr); | | 1601 | EMAC_EVCNT_INCR(&sc->sc_ev_rxintr); |
1589 | | | 1602 | |
| | | 1603 | count = 0; |
1590 | for (i = sc->sc_rxptr; ; i = EMAC_NEXTRX(i)) { | | 1604 | for (i = sc->sc_rxptr; ; i = EMAC_NEXTRX(i)) { |
1591 | rxs = &sc->sc_rxsoft[i]; | | 1605 | rxs = &sc->sc_rxsoft[i]; |
1592 | | | 1606 | |
1593 | EMAC_CDRXSYNC(sc, i, | | 1607 | EMAC_CDRXSYNC(sc, i, |
1594 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); | | 1608 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
1595 | | | 1609 | |
1596 | rxstat = sc->sc_rxdescs[i].md_stat_ctrl; | | 1610 | rxstat = sc->sc_rxdescs[i].md_stat_ctrl; |
1597 | | | 1611 | |
1598 | if (rxstat & MAL_RX_EMPTY) { | | 1612 | if (rxstat & MAL_RX_EMPTY) { |
1599 | /* | | 1613 | /* |
1600 | * We have processed all of the receive buffers. | | 1614 | * We have processed all of the receive buffers. |
1601 | */ | | 1615 | */ |
1602 | /* Flush current empty descriptor */ | | 1616 | /* Flush current empty descriptor */ |
| @@ -1671,31 +1685,36 @@ emac_rxeob_intr(void *arg) | | | @@ -1671,31 +1685,36 @@ emac_rxeob_intr(void *arg) |
1671 | bus_dmamap_sync(sc->sc_dmat, | | 1685 | bus_dmamap_sync(sc->sc_dmat, |
1672 | rxs->rxs_dmamap, 0, | | 1686 | rxs->rxs_dmamap, 0, |
1673 | rxs->rxs_dmamap->dm_mapsize, | | 1687 | rxs->rxs_dmamap->dm_mapsize, |
1674 | BUS_DMASYNC_PREREAD); | | 1688 | BUS_DMASYNC_PREREAD); |
1675 | continue; | | 1689 | continue; |
1676 | } | | 1690 | } |
1677 | } | | 1691 | } |
1678 | | | 1692 | |
1679 | m_set_rcvif(m, ifp); | | 1693 | m_set_rcvif(m, ifp); |
1680 | m->m_pkthdr.len = m->m_len = len; | | 1694 | m->m_pkthdr.len = m->m_len = len; |
1681 | | | 1695 | |
1682 | /* Pass it on. */ | | 1696 | /* Pass it on. */ |
1683 | if_percpuq_enqueue(ifp->if_percpuq, m); | | 1697 | if_percpuq_enqueue(ifp->if_percpuq, m); |
| | | 1698 | |
| | | 1699 | count++; |
1684 | } | | 1700 | } |
1685 | | | 1701 | |
1686 | /* Update the receive pointer. */ | | 1702 | /* Update the receive pointer. */ |
1687 | sc->sc_rxptr = i; | | 1703 | sc->sc_rxptr = i; |
1688 | | | 1704 | |
| | | 1705 | if (count != 0) |
| | | 1706 | rnd_add_uint32(&sc->rnd_source, count); |
| | | 1707 | |
1689 | return 1; | | 1708 | return 1; |
1690 | } | | 1709 | } |
1691 | | | 1710 | |
1692 | int | | 1711 | int |
1693 | emac_txde_intr(void *arg) | | 1712 | emac_txde_intr(void *arg) |
1694 | { | | 1713 | { |
1695 | struct emac_softc *sc = arg; | | 1714 | struct emac_softc *sc = arg; |
1696 | | | 1715 | |
1697 | EMAC_EVCNT_INCR(&sc->sc_ev_txde); | | 1716 | EMAC_EVCNT_INCR(&sc->sc_ev_txde); |
1698 | aprint_error_dev(sc->sc_dev, "emac_txde_intr\n"); | | 1717 | aprint_error_dev(sc->sc_dev, "emac_txde_intr\n"); |
1699 | return 1; | | 1718 | return 1; |
1700 | } | | 1719 | } |
1701 | | | 1720 | |