| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_cnmac.c,v 1.25 2021/05/27 01:43:32 simonb Exp $ */ | | 1 | /* $NetBSD: if_cnmac.c,v 1.26 2021/05/27 03:23:29 simonb Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2007 Internet Initiative Japan, Inc. | | 4 | * Copyright (c) 2007 Internet Initiative Japan, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -17,27 +17,27 @@ | | | @@ -17,27 +17,27 @@ |
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. | | 26 | * SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: if_cnmac.c,v 1.25 2021/05/27 01:43:32 simonb Exp $"); | | 30 | __KERNEL_RCSID(0, "$NetBSD: if_cnmac.c,v 1.26 2021/05/27 03:23:29 simonb Exp $"); |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * If no free send buffer is available, free all the sent buffers and bail out. | | 33 | * If no free send buffer is available, free all the sent buffers and bail out. |
34 | */ | | 34 | */ |
35 | #define CNMAC_SEND_QUEUE_CHECK | | 35 | #define CNMAC_SEND_QUEUE_CHECK |
36 | | | 36 | |
37 | /* XXX XXX XXX XXX XXX XXX */ | | 37 | /* XXX XXX XXX XXX XXX XXX */ |
38 | | | 38 | |
39 | #include <sys/param.h> | | 39 | #include <sys/param.h> |
40 | #include <sys/systm.h> | | 40 | #include <sys/systm.h> |
41 | #include <sys/pool.h> | | 41 | #include <sys/pool.h> |
42 | #include <sys/mbuf.h> | | 42 | #include <sys/mbuf.h> |
43 | #include <sys/malloc.h> | | 43 | #include <sys/malloc.h> |
| @@ -112,26 +112,27 @@ static void cnmac_pko_init(struct cnmac_ | | | @@ -112,26 +112,27 @@ static void cnmac_pko_init(struct cnmac_ |
112 | static void cnmac_board_mac_addr(uint8_t *, size_t, struct cnmac_softc *); | | 112 | static void cnmac_board_mac_addr(uint8_t *, size_t, struct cnmac_softc *); |
113 | | | 113 | |
114 | static int cnmac_mii_readreg(device_t, int, int, uint16_t *); | | 114 | static int cnmac_mii_readreg(device_t, int, int, uint16_t *); |
115 | static int cnmac_mii_writereg(device_t, int, int, uint16_t); | | 115 | static int cnmac_mii_writereg(device_t, int, int, uint16_t); |
116 | static void cnmac_mii_statchg(struct ifnet *); | | 116 | static void cnmac_mii_statchg(struct ifnet *); |
117 | | | 117 | |
118 | static int cnmac_mediainit(struct cnmac_softc *); | | 118 | static int cnmac_mediainit(struct cnmac_softc *); |
119 | static void cnmac_mediastatus(struct ifnet *, struct ifmediareq *); | | 119 | static void cnmac_mediastatus(struct ifnet *, struct ifmediareq *); |
120 | | | 120 | |
121 | static inline void cnmac_send_queue_flush_prefetch(struct cnmac_softc *); | | 121 | static inline void cnmac_send_queue_flush_prefetch(struct cnmac_softc *); |
122 | static inline void cnmac_send_queue_flush_fetch(struct cnmac_softc *); | | 122 | static inline void cnmac_send_queue_flush_fetch(struct cnmac_softc *); |
123 | static inline void cnmac_send_queue_flush(struct cnmac_softc *); | | 123 | static inline void cnmac_send_queue_flush(struct cnmac_softc *); |
124 | static inline void cnmac_send_queue_flush_sync(struct cnmac_softc *); | | 124 | static inline void cnmac_send_queue_flush_sync(struct cnmac_softc *); |
| | | 125 | static void cnmac_send_queue_check_and_flush(struct cnmac_softc *); |
125 | static inline int cnmac_send_queue_is_full(struct cnmac_softc *); | | 126 | static inline int cnmac_send_queue_is_full(struct cnmac_softc *); |
126 | static inline void cnmac_send_queue_add(struct cnmac_softc *, struct mbuf *, | | 127 | static inline void cnmac_send_queue_add(struct cnmac_softc *, struct mbuf *, |
127 | uint64_t *); | | 128 | uint64_t *); |
128 | static inline void cnmac_send_queue_del(struct cnmac_softc *, struct mbuf **, | | 129 | static inline void cnmac_send_queue_del(struct cnmac_softc *, struct mbuf **, |
129 | uint64_t **); | | 130 | uint64_t **); |
130 | static inline int cnmac_buf_free_work(struct cnmac_softc *, uint64_t *); | | 131 | static inline int cnmac_buf_free_work(struct cnmac_softc *, uint64_t *); |
131 | static inline void cnmac_buf_ext_free(struct mbuf *, void *, size_t, void *); | | 132 | static inline void cnmac_buf_ext_free(struct mbuf *, void *, size_t, void *); |
132 | | | 133 | |
133 | static int cnmac_ioctl(struct ifnet *, u_long, void *); | | 134 | static int cnmac_ioctl(struct ifnet *, u_long, void *); |
134 | static void cnmac_watchdog(struct ifnet *); | | 135 | static void cnmac_watchdog(struct ifnet *); |
135 | static int cnmac_init(struct ifnet *); | | 136 | static int cnmac_init(struct ifnet *); |
136 | static void cnmac_stop(struct ifnet *, int); | | 137 | static void cnmac_stop(struct ifnet *, int); |
137 | static void cnmac_start(struct ifnet *); | | 138 | static void cnmac_start(struct ifnet *); |
| @@ -594,26 +595,43 @@ cnmac_send_queue_is_full(struct cnmac_so | | | @@ -594,26 +595,43 @@ cnmac_send_queue_is_full(struct cnmac_so |
594 | | | 595 | |
595 | nofree_cnt = sc->sc_soft_req_cnt + sc->sc_hard_done_cnt; | | 596 | nofree_cnt = sc->sc_soft_req_cnt + sc->sc_hard_done_cnt; |
596 | | | 597 | |
597 | if (__predict_false(nofree_cnt == GATHER_QUEUE_SIZE - 1)) { | | 598 | if (__predict_false(nofree_cnt == GATHER_QUEUE_SIZE - 1)) { |
598 | cnmac_send_queue_flush(sc); | | 599 | cnmac_send_queue_flush(sc); |
599 | cnmac_send_queue_flush_sync(sc); | | 600 | cnmac_send_queue_flush_sync(sc); |
600 | return 1; | | 601 | return 1; |
601 | } | | 602 | } |
602 | | | 603 | |
603 | #endif | | 604 | #endif |
604 | return 0; | | 605 | return 0; |
605 | } | | 606 | } |
606 | | | 607 | |
| | | 608 | static void |
| | | 609 | cnmac_send_queue_check_and_flush(struct cnmac_softc *sc) |
| | | 610 | { |
| | | 611 | int s; |
| | | 612 | |
| | | 613 | /* XXX XXX XXX */ |
| | | 614 | s = splnet(); |
| | | 615 | if (sc->sc_soft_req_cnt > 0) { |
| | | 616 | cnmac_send_queue_flush_prefetch(sc); |
| | | 617 | cnmac_send_queue_flush_fetch(sc); |
| | | 618 | cnmac_send_queue_flush(sc); |
| | | 619 | cnmac_send_queue_flush_sync(sc); |
| | | 620 | } |
| | | 621 | splx(s); |
| | | 622 | /* XXX XXX XXX */ |
| | | 623 | } |
| | | 624 | |
607 | /* | | 625 | /* |
608 | * (Ab)use m_nextpkt and m_paddr to maintain mbuf chain and pointer to gather | | 626 | * (Ab)use m_nextpkt and m_paddr to maintain mbuf chain and pointer to gather |
609 | * buffer. Other mbuf members may be used by m_freem(), so don't touch them! | | 627 | * buffer. Other mbuf members may be used by m_freem(), so don't touch them! |
610 | */ | | 628 | */ |
611 | | | 629 | |
612 | struct _send_queue_entry { | | 630 | struct _send_queue_entry { |
613 | union { | | 631 | union { |
614 | struct mbuf _sqe_s_mbuf; | | 632 | struct mbuf _sqe_s_mbuf; |
615 | struct { | | 633 | struct { |
616 | char _sqe_s_entry_pad[offsetof(struct mbuf, m_nextpkt)]; | | 634 | char _sqe_s_entry_pad[offsetof(struct mbuf, m_nextpkt)]; |
617 | SIMPLEQ_ENTRY(_send_queue_entry) _sqe_s_entry_entry; | | 635 | SIMPLEQ_ENTRY(_send_queue_entry) _sqe_s_entry_entry; |
618 | } _sqe_s_entry; | | 636 | } _sqe_s_entry; |
619 | struct { | | 637 | struct { |
| @@ -1289,26 +1307,28 @@ cnmac_intr(void *arg) | | | @@ -1289,26 +1307,28 @@ cnmac_intr(void *arg) |
1289 | | | 1307 | |
1290 | octpow_tag_sw_wait(); | | 1308 | octpow_tag_sw_wait(); |
1291 | octpow_work_request_async(OCTEON_CVMSEG_OFFSET(csm_pow_intr), | | 1309 | octpow_work_request_async(OCTEON_CVMSEG_OFFSET(csm_pow_intr), |
1292 | POW_NO_WAIT); | | 1310 | POW_NO_WAIT); |
1293 | | | 1311 | |
1294 | port = __SHIFTOUT(work[1], PIP_WQE_WORD1_IPRT); | | 1312 | port = __SHIFTOUT(work[1], PIP_WQE_WORD1_IPRT); |
1295 | if (port != sc->sc_port) { | | 1313 | if (port != sc->sc_port) { |
1296 | printf("%s: unexpected wqe port %u, should be %u\n", | | 1314 | printf("%s: unexpected wqe port %u, should be %u\n", |
1297 | device_xname(sc->sc_dev), port, sc->sc_port); | | 1315 | device_xname(sc->sc_dev), port, sc->sc_port); |
1298 | goto wqe_error; | | 1316 | goto wqe_error; |
1299 | } | | 1317 | } |
1300 | | | 1318 | |
1301 | (void)cnmac_recv(sc, work); | | 1319 | (void)cnmac_recv(sc, work); |
| | | 1320 | |
| | | 1321 | cnmac_send_queue_check_and_flush(sc); |
1302 | } | | 1322 | } |
1303 | | | 1323 | |
1304 | _POW_WR8(sc->sc_pow, POW_WQ_INT_OFFSET, wqmask); | | 1324 | _POW_WR8(sc->sc_pow, POW_WQ_INT_OFFSET, wqmask); |
1305 | | | 1325 | |
1306 | return 1; | | 1326 | return 1; |
1307 | | | 1327 | |
1308 | wqe_error: | | 1328 | wqe_error: |
1309 | printf("word0: 0x%016" PRIx64 "\n", work[0]); | | 1329 | printf("word0: 0x%016" PRIx64 "\n", work[0]); |
1310 | printf("word1: 0x%016" PRIx64 "\n", work[1]); | | 1330 | printf("word1: 0x%016" PRIx64 "\n", work[1]); |
1311 | printf("word2: 0x%016" PRIx64 "\n", work[2]); | | 1331 | printf("word2: 0x%016" PRIx64 "\n", work[2]); |
1312 | printf("word3: 0x%016" PRIx64 "\n", work[3]); | | 1332 | printf("word3: 0x%016" PRIx64 "\n", work[3]); |
1313 | panic("wqe_error"); | | 1333 | panic("wqe_error"); |
1314 | } | | 1334 | } |
| @@ -1316,41 +1336,31 @@ wqe_error: | | | @@ -1316,41 +1336,31 @@ wqe_error: |
1316 | /* ---- tick */ | | 1336 | /* ---- tick */ |
1317 | | | 1337 | |
1318 | /* | | 1338 | /* |
1319 | * cnmac_tick_free | | 1339 | * cnmac_tick_free |
1320 | * | | 1340 | * |
1321 | * => garbage collect send gather buffer / mbuf | | 1341 | * => garbage collect send gather buffer / mbuf |
1322 | * => called at softclock | | 1342 | * => called at softclock |
1323 | */ | | 1343 | */ |
1324 | static void | | 1344 | static void |
1325 | cnmac_tick_free(void *arg) | | 1345 | cnmac_tick_free(void *arg) |
1326 | { | | 1346 | { |
1327 | struct cnmac_softc *sc = arg; | | 1347 | struct cnmac_softc *sc = arg; |
1328 | int timo; | | 1348 | int timo; |
1329 | int s; | | | |
1330 | | | 1349 | |
1331 | s = splnet(); | | 1350 | cnmac_send_queue_check_and_flush(sc); |
1332 | /* XXX XXX XXX */ | | | |
1333 | if (sc->sc_soft_req_cnt > 0) { | | | |
1334 | cnmac_send_queue_flush_prefetch(sc); | | | |
1335 | cnmac_send_queue_flush_fetch(sc); | | | |
1336 | cnmac_send_queue_flush(sc); | | | |
1337 | cnmac_send_queue_flush_sync(sc); | | | |
1338 | } | | | |
1339 | /* XXX XXX XXX */ | | | |
1340 | | | 1351 | |
1341 | timo = (sc->sc_ext_callback_cnt > 0) ? 1 : hz; | | 1352 | timo = (sc->sc_ext_callback_cnt > 0) ? 1 : hz; |
1342 | callout_schedule(&sc->sc_tick_free_ch, timo); | | 1353 | callout_schedule(&sc->sc_tick_free_ch, timo); |
1343 | splx(s); | | | |
1344 | } | | 1354 | } |
1345 | | | 1355 | |
1346 | /* | | 1356 | /* |
1347 | * cnmac_tick_misc | | 1357 | * cnmac_tick_misc |
1348 | * | | 1358 | * |
1349 | * => collect statistics | | 1359 | * => collect statistics |
1350 | * => check link status | | 1360 | * => check link status |
1351 | * => called at softclock | | 1361 | * => called at softclock |
1352 | */ | | 1362 | */ |
1353 | static void | | 1363 | static void |
1354 | cnmac_tick_misc(void *arg) | | 1364 | cnmac_tick_misc(void *arg) |
1355 | { | | 1365 | { |
1356 | struct cnmac_softc *sc = arg; | | 1366 | struct cnmac_softc *sc = arg; |