Thu May 27 03:23:29 2021 UTC ()
Move the send queue checking to a new function, and also call this
in the rx interrupt path.  Measureable improvement on a NFS "create
small files" test.


(simonb)
diff -r1.25 -r1.26 src/sys/arch/mips/cavium/dev/if_cnmac.c

cvs diff -r1.25 -r1.26 src/sys/arch/mips/cavium/dev/if_cnmac.c (expand / switch to unified diff)

--- src/sys/arch/mips/cavium/dev/if_cnmac.c 2021/05/27 01:43:32 1.25
+++ src/sys/arch/mips/cavium/dev/if_cnmac.c 2021/05/27 03:23:29 1.26
@@ -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_
112static void cnmac_board_mac_addr(uint8_t *, size_t, struct cnmac_softc *); 112static void cnmac_board_mac_addr(uint8_t *, size_t, struct cnmac_softc *);
113 113
114static int cnmac_mii_readreg(device_t, int, int, uint16_t *); 114static int cnmac_mii_readreg(device_t, int, int, uint16_t *);
115static int cnmac_mii_writereg(device_t, int, int, uint16_t); 115static int cnmac_mii_writereg(device_t, int, int, uint16_t);
116static void cnmac_mii_statchg(struct ifnet *); 116static void cnmac_mii_statchg(struct ifnet *);
117 117
118static int cnmac_mediainit(struct cnmac_softc *); 118static int cnmac_mediainit(struct cnmac_softc *);
119static void cnmac_mediastatus(struct ifnet *, struct ifmediareq *); 119static void cnmac_mediastatus(struct ifnet *, struct ifmediareq *);
120 120
121static inline void cnmac_send_queue_flush_prefetch(struct cnmac_softc *); 121static inline void cnmac_send_queue_flush_prefetch(struct cnmac_softc *);
122static inline void cnmac_send_queue_flush_fetch(struct cnmac_softc *); 122static inline void cnmac_send_queue_flush_fetch(struct cnmac_softc *);
123static inline void cnmac_send_queue_flush(struct cnmac_softc *); 123static inline void cnmac_send_queue_flush(struct cnmac_softc *);
124static inline void cnmac_send_queue_flush_sync(struct cnmac_softc *); 124static inline void cnmac_send_queue_flush_sync(struct cnmac_softc *);
 125static void cnmac_send_queue_check_and_flush(struct cnmac_softc *);
125static inline int cnmac_send_queue_is_full(struct cnmac_softc *); 126static inline int cnmac_send_queue_is_full(struct cnmac_softc *);
126static inline void cnmac_send_queue_add(struct cnmac_softc *, struct mbuf *, 127static inline void cnmac_send_queue_add(struct cnmac_softc *, struct mbuf *,
127 uint64_t *); 128 uint64_t *);
128static inline void cnmac_send_queue_del(struct cnmac_softc *, struct mbuf **, 129static inline void cnmac_send_queue_del(struct cnmac_softc *, struct mbuf **,
129 uint64_t **); 130 uint64_t **);
130static inline int cnmac_buf_free_work(struct cnmac_softc *, uint64_t *); 131static inline int cnmac_buf_free_work(struct cnmac_softc *, uint64_t *);
131static inline void cnmac_buf_ext_free(struct mbuf *, void *, size_t, void *); 132static inline void cnmac_buf_ext_free(struct mbuf *, void *, size_t, void *);
132 133
133static int cnmac_ioctl(struct ifnet *, u_long, void *); 134static int cnmac_ioctl(struct ifnet *, u_long, void *);
134static void cnmac_watchdog(struct ifnet *); 135static void cnmac_watchdog(struct ifnet *);
135static int cnmac_init(struct ifnet *); 136static int cnmac_init(struct ifnet *);
136static void cnmac_stop(struct ifnet *, int); 137static void cnmac_stop(struct ifnet *, int);
137static void cnmac_start(struct ifnet *); 138static 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
 608static void
 609cnmac_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
612struct _send_queue_entry { 630struct _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
1308wqe_error: 1328wqe_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 */
1324static void 1344static void
1325cnmac_tick_free(void *arg) 1345cnmac_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 */
1353static void 1363static void
1354cnmac_tick_misc(void *arg) 1364cnmac_tick_misc(void *arg)
1355{ 1365{
1356 struct cnmac_softc *sc = arg; 1366 struct cnmac_softc *sc = arg;