Sun Jan 24 05:22:22 2021 UTC ()
Add rnd(9) support.


(rin)
diff -r1.53 -r1.54 src/sys/arch/powerpc/ibm4xx/dev/if_emac.c

cvs diff -r1.53 -r1.54 src/sys/arch/powerpc/ibm4xx/dev/if_emac.c (expand / switch to unified diff)

--- src/sys/arch/powerpc/ibm4xx/dev/if_emac.c 2020/07/06 09:34:17 1.53
+++ src/sys/arch/powerpc/ibm4xx/dev/if_emac.c 2021/01/24 05:22:21 1.54
@@ -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 */
1251static int 1258static int
1252emac_txreap(struct emac_softc *sc) 1259emac_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
1340static void 1353static void
1341emac_soft_reset(struct emac_softc *sc) 1354emac_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
1578int 1591int
1579emac_rxeob_intr(void *arg) 1592emac_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
1692int 1711int
1693emac_txde_intr(void *arg) 1712emac_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