| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: tulip.c,v 1.200 2019/11/10 21:16:35 chs Exp $ */ | | 1 | /* $NetBSD: tulip.c,v 1.201 2020/01/29 14:18:54 thorpej Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 1999, 2000, 2002 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 1999, 2000, 2002 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
9 | * NASA Ames Research Center; and by Charles M. Hannum. | | 9 | * NASA Ames Research Center; and by Charles M. Hannum. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -26,27 +26,27 @@ | | | @@ -26,27 +26,27 @@ |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * Device driver for the Digital Semiconductor ``Tulip'' (21x4x) | | 34 | * Device driver for the Digital Semiconductor ``Tulip'' (21x4x) |
35 | * Ethernet controller family, and a variety of clone chips. | | 35 | * Ethernet controller family, and a variety of clone chips. |
36 | */ | | 36 | */ |
37 | | | 37 | |
38 | #include <sys/cdefs.h> | | 38 | #include <sys/cdefs.h> |
39 | __KERNEL_RCSID(0, "$NetBSD: tulip.c,v 1.200 2019/11/10 21:16:35 chs Exp $"); | | 39 | __KERNEL_RCSID(0, "$NetBSD: tulip.c,v 1.201 2020/01/29 14:18:54 thorpej Exp $"); |
40 | | | 40 | |
41 | | | 41 | |
42 | #include <sys/param.h> | | 42 | #include <sys/param.h> |
43 | #include <sys/systm.h> | | 43 | #include <sys/systm.h> |
44 | #include <sys/callout.h> | | 44 | #include <sys/callout.h> |
45 | #include <sys/mbuf.h> | | 45 | #include <sys/mbuf.h> |
46 | #include <sys/malloc.h> | | 46 | #include <sys/malloc.h> |
47 | #include <sys/kernel.h> | | 47 | #include <sys/kernel.h> |
48 | #include <sys/socket.h> | | 48 | #include <sys/socket.h> |
49 | #include <sys/ioctl.h> | | 49 | #include <sys/ioctl.h> |
50 | #include <sys/errno.h> | | 50 | #include <sys/errno.h> |
51 | #include <sys/device.h> | | 51 | #include <sys/device.h> |
52 | | | 52 | |
| @@ -930,30 +930,30 @@ tlp_start(struct ifnet *ifp) | | | @@ -930,30 +930,30 @@ tlp_start(struct ifnet *ifp) |
930 | */ | | 930 | */ |
931 | static void | | 931 | static void |
932 | tlp_watchdog(struct ifnet *ifp) | | 932 | tlp_watchdog(struct ifnet *ifp) |
933 | { | | 933 | { |
934 | struct tulip_softc *sc = ifp->if_softc; | | 934 | struct tulip_softc *sc = ifp->if_softc; |
935 | int doing_setup, doing_transmit; | | 935 | int doing_setup, doing_transmit; |
936 | | | 936 | |
937 | doing_setup = (sc->sc_flags & TULIPF_DOING_SETUP); | | 937 | doing_setup = (sc->sc_flags & TULIPF_DOING_SETUP); |
938 | doing_transmit = (! SIMPLEQ_EMPTY(&sc->sc_txdirtyq)); | | 938 | doing_transmit = (! SIMPLEQ_EMPTY(&sc->sc_txdirtyq)); |
939 | | | 939 | |
940 | if (doing_setup && doing_transmit) { | | 940 | if (doing_setup && doing_transmit) { |
941 | printf("%s: filter setup and transmit timeout\n", | | 941 | printf("%s: filter setup and transmit timeout\n", |
942 | device_xname(sc->sc_dev)); | | 942 | device_xname(sc->sc_dev)); |
943 | ifp->if_oerrors++; | | 943 | if_statinc(ifp, if_oerrors); |
944 | } else if (doing_transmit) { | | 944 | } else if (doing_transmit) { |
945 | printf("%s: transmit timeout\n", device_xname(sc->sc_dev)); | | 945 | printf("%s: transmit timeout\n", device_xname(sc->sc_dev)); |
946 | ifp->if_oerrors++; | | 946 | if_statinc(ifp, if_oerrors); |
947 | } else if (doing_setup) | | 947 | } else if (doing_setup) |
948 | printf("%s: filter setup timeout\n", device_xname(sc->sc_dev)); | | 948 | printf("%s: filter setup timeout\n", device_xname(sc->sc_dev)); |
949 | else | | 949 | else |
950 | printf("%s: spurious watchdog timeout\n", | | 950 | printf("%s: spurious watchdog timeout\n", |
951 | device_xname(sc->sc_dev)); | | 951 | device_xname(sc->sc_dev)); |
952 | | | 952 | |
953 | (void) tlp_init(ifp); | | 953 | (void) tlp_init(ifp); |
954 | | | 954 | |
955 | /* Try to get more packets going. */ | | 955 | /* Try to get more packets going. */ |
956 | tlp_start(ifp); | | 956 | tlp_start(ifp); |
957 | } | | 957 | } |
958 | | | 958 | |
959 | /* If the interface is up and running, only modify the receive | | 959 | /* If the interface is up and running, only modify the receive |
| @@ -1241,27 +1241,27 @@ tlp_rxintr(struct tulip_softc *sc) | | | @@ -1241,27 +1241,27 @@ tlp_rxintr(struct tulip_softc *sc) |
1241 | */ | | 1241 | */ |
1242 | if ((rxstat & (TDSTAT_Rx_FS | TDSTAT_Rx_LS)) != | | 1242 | if ((rxstat & (TDSTAT_Rx_FS | TDSTAT_Rx_LS)) != |
1243 | (TDSTAT_Rx_FS | TDSTAT_Rx_LS)) { | | 1243 | (TDSTAT_Rx_FS | TDSTAT_Rx_LS)) { |
1244 | printf("%s: incoming packet spilled, resetting\n", | | 1244 | printf("%s: incoming packet spilled, resetting\n", |
1245 | device_xname(sc->sc_dev)); | | 1245 | device_xname(sc->sc_dev)); |
1246 | (void) tlp_init(ifp); | | 1246 | (void) tlp_init(ifp); |
1247 | return; | | 1247 | return; |
1248 | } | | 1248 | } |
1249 | | | 1249 | |
1250 | /* | | 1250 | /* |
1251 | * If any collisions were seen on the wire, count one. | | 1251 | * If any collisions were seen on the wire, count one. |
1252 | */ | | 1252 | */ |
1253 | if (rxstat & TDSTAT_Rx_CS) | | 1253 | if (rxstat & TDSTAT_Rx_CS) |
1254 | ifp->if_collisions++; | | 1254 | if_statinc(ifp, if_collisions); |
1255 | | | 1255 | |
1256 | /* | | 1256 | /* |
1257 | * If an error occurred, update stats, clear the status | | 1257 | * If an error occurred, update stats, clear the status |
1258 | * word, and leave the packet buffer in place. It will | | 1258 | * word, and leave the packet buffer in place. It will |
1259 | * simply be reused the next time the ring comes around. | | 1259 | * simply be reused the next time the ring comes around. |
1260 | */ | | 1260 | */ |
1261 | errors = TDSTAT_Rx_DE | TDSTAT_Rx_RF | TDSTAT_Rx_TL | | | 1261 | errors = TDSTAT_Rx_DE | TDSTAT_Rx_RF | TDSTAT_Rx_TL | |
1262 | TDSTAT_Rx_CS | TDSTAT_Rx_RE | TDSTAT_Rx_DB | TDSTAT_Rx_CE; | | 1262 | TDSTAT_Rx_CS | TDSTAT_Rx_RE | TDSTAT_Rx_DB | TDSTAT_Rx_CE; |
1263 | /* | | 1263 | /* |
1264 | * If 802.1Q VLAN MTU is enabled, ignore the Frame Too Long | | 1264 | * If 802.1Q VLAN MTU is enabled, ignore the Frame Too Long |
1265 | * error. | | 1265 | * error. |
1266 | */ | | 1266 | */ |
1267 | if ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) != 0) | | 1267 | if ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) != 0) |
| @@ -1269,27 +1269,27 @@ tlp_rxintr(struct tulip_softc *sc) | | | @@ -1269,27 +1269,27 @@ tlp_rxintr(struct tulip_softc *sc) |
1269 | /* | | 1269 | /* |
1270 | * If chip doesn't have MII, ignore the MII error bit. | | 1270 | * If chip doesn't have MII, ignore the MII error bit. |
1271 | */ | | 1271 | */ |
1272 | if ((sc->sc_flags & TULIPF_HAS_MII) == 0) | | 1272 | if ((sc->sc_flags & TULIPF_HAS_MII) == 0) |
1273 | errors &= ~TDSTAT_Rx_RE; | | 1273 | errors &= ~TDSTAT_Rx_RE; |
1274 | | | 1274 | |
1275 | if ((rxstat & TDSTAT_ES) != 0 && | | 1275 | if ((rxstat & TDSTAT_ES) != 0 && |
1276 | (rxstat & errors) != 0) { | | 1276 | (rxstat & errors) != 0) { |
1277 | rxstat &= errors; | | 1277 | rxstat &= errors; |
1278 | #define PRINTERR(bit, str) \ | | 1278 | #define PRINTERR(bit, str) \ |
1279 | if (rxstat & (bit)) \ | | 1279 | if (rxstat & (bit)) \ |
1280 | aprint_error_dev(sc->sc_dev, \ | | 1280 | aprint_error_dev(sc->sc_dev, \ |
1281 | "receive error: %s\n", str) | | 1281 | "receive error: %s\n", str) |
1282 | ifp->if_ierrors++; | | 1282 | if_statinc(ifp, if_ierrors); |
1283 | PRINTERR(TDSTAT_Rx_DE, "descriptor error"); | | 1283 | PRINTERR(TDSTAT_Rx_DE, "descriptor error"); |
1284 | PRINTERR(TDSTAT_Rx_RF, "runt frame"); | | 1284 | PRINTERR(TDSTAT_Rx_RF, "runt frame"); |
1285 | PRINTERR(TDSTAT_Rx_TL, "frame too long"); | | 1285 | PRINTERR(TDSTAT_Rx_TL, "frame too long"); |
1286 | PRINTERR(TDSTAT_Rx_RE, "MII error"); | | 1286 | PRINTERR(TDSTAT_Rx_RE, "MII error"); |
1287 | PRINTERR(TDSTAT_Rx_DB, "dribbling bit"); | | 1287 | PRINTERR(TDSTAT_Rx_DB, "dribbling bit"); |
1288 | PRINTERR(TDSTAT_Rx_CE, "CRC error"); | | 1288 | PRINTERR(TDSTAT_Rx_CE, "CRC error"); |
1289 | #undef PRINTERR | | 1289 | #undef PRINTERR |
1290 | TULIP_INIT_RXDESC(sc, i); | | 1290 | TULIP_INIT_RXDESC(sc, i); |
1291 | continue; | | 1291 | continue; |
1292 | } | | 1292 | } |
1293 | | | 1293 | |
1294 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, | | 1294 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, |
1295 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); | | 1295 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); |
| @@ -1298,43 +1298,43 @@ tlp_rxintr(struct tulip_softc *sc) | | | @@ -1298,43 +1298,43 @@ tlp_rxintr(struct tulip_softc *sc) |
1298 | * No errors; receive the packet. Note the Tulip | | 1298 | * No errors; receive the packet. Note the Tulip |
1299 | * includes the CRC with every packet. | | 1299 | * includes the CRC with every packet. |
1300 | */ | | 1300 | */ |
1301 | len = TDSTAT_Rx_LENGTH(rxstat) - ETHER_CRC_LEN; | | 1301 | len = TDSTAT_Rx_LENGTH(rxstat) - ETHER_CRC_LEN; |
1302 | | | 1302 | |
1303 | #ifdef __NO_STRICT_ALIGNMENT | | 1303 | #ifdef __NO_STRICT_ALIGNMENT |
1304 | /* | | 1304 | /* |
1305 | * Allocate a new mbuf cluster. If that fails, we are | | 1305 | * Allocate a new mbuf cluster. If that fails, we are |
1306 | * out of memory, and must drop the packet and recycle | | 1306 | * out of memory, and must drop the packet and recycle |
1307 | * the buffer that's already attached to this descriptor. | | 1307 | * the buffer that's already attached to this descriptor. |
1308 | */ | | 1308 | */ |
1309 | m = rxs->rxs_mbuf; | | 1309 | m = rxs->rxs_mbuf; |
1310 | if (tlp_add_rxbuf(sc, i) != 0) { | | 1310 | if (tlp_add_rxbuf(sc, i) != 0) { |
1311 | ifp->if_ierrors++; | | 1311 | if_statinc(ifp, if_ierrors); |
1312 | TULIP_INIT_RXDESC(sc, i); | | 1312 | TULIP_INIT_RXDESC(sc, i); |
1313 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, | | 1313 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, |
1314 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); | | 1314 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); |
1315 | continue; | | 1315 | continue; |
1316 | } | | 1316 | } |
1317 | #else | | 1317 | #else |
1318 | /* | | 1318 | /* |
1319 | * The Tulip's receive buffers must be 4-byte aligned. | | 1319 | * The Tulip's receive buffers must be 4-byte aligned. |
1320 | * But this means that the data after the Ethernet header | | 1320 | * But this means that the data after the Ethernet header |
1321 | * is misaligned. We must allocate a new buffer and | | 1321 | * is misaligned. We must allocate a new buffer and |
1322 | * copy the data, shifted forward 2 bytes. | | 1322 | * copy the data, shifted forward 2 bytes. |
1323 | */ | | 1323 | */ |
1324 | MGETHDR(m, M_DONTWAIT, MT_DATA); | | 1324 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
1325 | if (m == NULL) { | | 1325 | if (m == NULL) { |
1326 | dropit: | | 1326 | dropit: |
1327 | ifp->if_ierrors++; | | 1327 | if_statinc(ifp, if_ierrors); |
1328 | TULIP_INIT_RXDESC(sc, i); | | 1328 | TULIP_INIT_RXDESC(sc, i); |
1329 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, | | 1329 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, |
1330 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); | | 1330 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); |
1331 | continue; | | 1331 | continue; |
1332 | } | | 1332 | } |
1333 | MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); | | 1333 | MCLAIM(m, &sc->sc_ethercom.ec_rx_mowner); |
1334 | if (len > (MHLEN - 2)) { | | 1334 | if (len > (MHLEN - 2)) { |
1335 | MCLGET(m, M_DONTWAIT); | | 1335 | MCLGET(m, M_DONTWAIT); |
1336 | if ((m->m_flags & M_EXT) == 0) { | | 1336 | if ((m->m_flags & M_EXT) == 0) { |
1337 | m_freem(m); | | 1337 | m_freem(m); |
1338 | goto dropit; | | 1338 | goto dropit; |
1339 | } | | 1339 | } |
1340 | } | | 1340 | } |
| @@ -1481,38 +1481,40 @@ tlp_txintr(struct tulip_softc *sc) | | | @@ -1481,38 +1481,40 @@ tlp_txintr(struct tulip_softc *sc) |
1481 | /* | | 1481 | /* |
1482 | * Check for errors and collisions. | | 1482 | * Check for errors and collisions. |
1483 | */ | | 1483 | */ |
1484 | #ifdef TLP_STATS | | 1484 | #ifdef TLP_STATS |
1485 | if (txstat & TDSTAT_Tx_UF) | | 1485 | if (txstat & TDSTAT_Tx_UF) |
1486 | sc->sc_stats.ts_tx_uf++; | | 1486 | sc->sc_stats.ts_tx_uf++; |
1487 | if (txstat & TDSTAT_Tx_TO) | | 1487 | if (txstat & TDSTAT_Tx_TO) |
1488 | sc->sc_stats.ts_tx_to++; | | 1488 | sc->sc_stats.ts_tx_to++; |
1489 | if (txstat & TDSTAT_Tx_EC) | | 1489 | if (txstat & TDSTAT_Tx_EC) |
1490 | sc->sc_stats.ts_tx_ec++; | | 1490 | sc->sc_stats.ts_tx_ec++; |
1491 | if (txstat & TDSTAT_Tx_LC) | | 1491 | if (txstat & TDSTAT_Tx_LC) |
1492 | sc->sc_stats.ts_tx_lc++; | | 1492 | sc->sc_stats.ts_tx_lc++; |
1493 | #endif | | 1493 | #endif |
1494 | | | 1494 | net_stat_ref_t nsr = IF_STAT_GETREF(ifp); |
1495 | if (txstat & (TDSTAT_Tx_UF | TDSTAT_Tx_TO)) | | 1495 | if (txstat & (TDSTAT_Tx_UF | TDSTAT_Tx_TO)) |
1496 | ifp->if_oerrors++; | | 1496 | if_statinc_ref(nsr, if_oerrors); |
1497 | | | 1497 | |
1498 | if (txstat & TDSTAT_Tx_EC) | | 1498 | if (txstat & TDSTAT_Tx_EC) |
1499 | ifp->if_collisions += 16; | | 1499 | if_statadd_ref(nsr, if_collisions, 16); |
1500 | else | | 1500 | else |
1501 | ifp->if_collisions += TDSTAT_Tx_COLLISIONS(txstat); | | 1501 | if_statadd_ref(nsr, if_collisions, |
| | | 1502 | TDSTAT_Tx_COLLISIONS(txstat)); |
1502 | if (txstat & TDSTAT_Tx_LC) | | 1503 | if (txstat & TDSTAT_Tx_LC) |
1503 | ifp->if_collisions++; | | 1504 | if_statinc_ref(nsr, if_collisions); |
1504 | | | 1505 | |
1505 | ifp->if_opackets++; | | 1506 | if_statinc_ref(nsr, if_opackets); |
| | | 1507 | IF_STAT_PUTREF(ifp); |
1506 | } | | 1508 | } |
1507 | | | 1509 | |
1508 | /* | | 1510 | /* |
1509 | * If there are no more pending transmissions, cancel the watchdog | | 1511 | * If there are no more pending transmissions, cancel the watchdog |
1510 | * timer. | | 1512 | * timer. |
1511 | */ | | 1513 | */ |
1512 | if (txs == NULL && (sc->sc_flags & TULIPF_DOING_SETUP) == 0) | | 1514 | if (txs == NULL && (sc->sc_flags & TULIPF_DOING_SETUP) == 0) |
1513 | ifp->if_timer = 0; | | 1515 | ifp->if_timer = 0; |
1514 | | | 1516 | |
1515 | /* | | 1517 | /* |
1516 | * If we have a receive filter setup pending, do it now. | | 1518 | * If we have a receive filter setup pending, do it now. |
1517 | */ | | 1519 | */ |
1518 | if (sc->sc_flags & TULIPF_WANT_SETUP) | | 1520 | if (sc->sc_flags & TULIPF_WANT_SETUP) |