Thu May 27 01:43:32 2021 UTC ()
Schedule the send cleanup function for next tick in cnmac_start().  In
the send cleanup function, schedule for the next tick instead of waiting
for HZ ticks if there are still send requests outstanding.  Greatly
increases NFS throughput, perhaps other types of network traffic.

Use callout_setfunc() after callout_init() instead of callout_reset().


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

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

--- src/sys/arch/mips/cavium/dev/if_cnmac.c 2020/06/23 05:17:13 1.24
+++ src/sys/arch/mips/cavium/dev/if_cnmac.c 2021/05/27 01:43:32 1.25
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_cnmac.c,v 1.24 2020/06/23 05:17:13 simonb Exp $ */ 1/* $NetBSD: if_cnmac.c,v 1.25 2021/05/27 01:43:32 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.24 2020/06/23 05:17:13 simonb Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: if_cnmac.c,v 1.25 2021/05/27 01:43:32 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>
@@ -268,27 +268,30 @@ cnmac_attach(device_t parent, device_t s @@ -268,27 +268,30 @@ cnmac_attach(device_t parent, device_t s
268 } 268 }
269 269
270 cnmac_board_mac_addr(enaddr, sizeof(enaddr), sc); 270 cnmac_board_mac_addr(enaddr, sizeof(enaddr), sc);
271 printf("%s: Ethernet address %s\n", device_xname(self), 271 printf("%s: Ethernet address %s\n", device_xname(self),
272 ether_sprintf(enaddr)); 272 ether_sprintf(enaddr));
273 273
274 SIMPLEQ_INIT(&sc->sc_sendq); 274 SIMPLEQ_INIT(&sc->sc_sendq);
275 sc->sc_soft_req_thresh = 15/* XXX */; 275 sc->sc_soft_req_thresh = 15/* XXX */;
276 sc->sc_ext_callback_cnt = 0; 276 sc->sc_ext_callback_cnt = 0;
277 277
278 octgmx_stats_init(sc->sc_gmx_port); 278 octgmx_stats_init(sc->sc_gmx_port);
279 279
280 callout_init(&sc->sc_tick_misc_ch, 0); 280 callout_init(&sc->sc_tick_misc_ch, 0);
 281 callout_setfunc(&sc->sc_tick_misc_ch, cnmac_tick_misc, sc);
 282
281 callout_init(&sc->sc_tick_free_ch, 0); 283 callout_init(&sc->sc_tick_free_ch, 0);
 284 callout_setfunc(&sc->sc_tick_free_ch, cnmac_tick_free, sc);
282 285
283 const int dv_unit = device_unit(self); 286 const int dv_unit = device_unit(self);
284 octfau_op_init(&sc->sc_fau_done, 287 octfau_op_init(&sc->sc_fau_done,
285 OCTEON_CVMSEG_ETHER_OFFSET(dv_unit, csm_ether_fau_done), 288 OCTEON_CVMSEG_ETHER_OFFSET(dv_unit, csm_ether_fau_done),
286 OCT_FAU_REG_ADDR_END - (8 * (dv_unit + 1))/* XXX */); 289 OCT_FAU_REG_ADDR_END - (8 * (dv_unit + 1))/* XXX */);
287 octfau_op_set_8(&sc->sc_fau_done, 0); 290 octfau_op_set_8(&sc->sc_fau_done, 0);
288 291
289 cnmac_pip_init(sc); 292 cnmac_pip_init(sc);
290 cnmac_ipd_init(sc); 293 cnmac_ipd_init(sc);
291 cnmac_pko_init(sc); 294 cnmac_pko_init(sc);
292 295
293 cnmac_configure_common(sc); 296 cnmac_configure_common(sc);
294 297
@@ -988,26 +991,27 @@ cnmac_start(struct ifnet *ifp) @@ -988,26 +991,27 @@ cnmac_start(struct ifnet *ifp)
988 991
989 /* XXX XXX XXX */ 992 /* XXX XXX XXX */
990 cnmac_send_queue_flush_fetch(sc); 993 cnmac_send_queue_flush_fetch(sc);
991 994
992 /* 995 /*
993 * If no free send buffer is available, free all the sent 996 * If no free send buffer is available, free all the sent
994 * buffers and bail out. 997 * buffers and bail out.
995 */ 998 */
996 if (cnmac_send_queue_is_full(sc)) { 999 if (cnmac_send_queue_is_full(sc)) {
997 SET(ifp->if_flags, IFF_OACTIVE); 1000 SET(ifp->if_flags, IFF_OACTIVE);
998 if (wdc > 0) 1001 if (wdc > 0)
999 octpko_op_doorbell_write(sc->sc_port, 1002 octpko_op_doorbell_write(sc->sc_port,
1000 sc->sc_port, wdc); 1003 sc->sc_port, wdc);
 1004 callout_schedule(&sc->sc_tick_free_ch, 1);
1001 return; 1005 return;
1002 } 1006 }
1003 /* XXX XXX XXX */ 1007 /* XXX XXX XXX */
1004 1008
1005 IFQ_DEQUEUE(&ifp->if_snd, m); 1009 IFQ_DEQUEUE(&ifp->if_snd, m);
1006 1010
1007 bpf_mtap(ifp, m, BPF_D_OUT); 1011 bpf_mtap(ifp, m, BPF_D_OUT);
1008 1012
1009 /* XXX XXX XXX */ 1013 /* XXX XXX XXX */
1010 if (sc->sc_soft_req_cnt > sc->sc_soft_req_thresh) 1014 if (sc->sc_soft_req_cnt > sc->sc_soft_req_thresh)
1011 cnmac_send_queue_flush(sc); 1015 cnmac_send_queue_flush(sc);
1012 if (cnmac_send(sc, m, &wdc)) { 1016 if (cnmac_send(sc, m, &wdc)) {
1013 IF_DROP(&ifp->if_snd); 1017 IF_DROP(&ifp->if_snd);
@@ -1021,26 +1025,27 @@ cnmac_start(struct ifnet *ifp) @@ -1021,26 +1025,27 @@ cnmac_start(struct ifnet *ifp)
1021 if (sc->sc_flush) 1025 if (sc->sc_flush)
1022 cnmac_send_queue_flush_sync(sc); 1026 cnmac_send_queue_flush_sync(sc);
1023 /* XXX XXX XXX */ 1027 /* XXX XXX XXX */
1024 1028
1025 /* Send next iobdma request */ 1029 /* Send next iobdma request */
1026 cnmac_send_queue_flush_prefetch(sc); 1030 cnmac_send_queue_flush_prefetch(sc);
1027 } 1031 }
1028 1032
1029 if (wdc > 0) 1033 if (wdc > 0)
1030 octpko_op_doorbell_write(sc->sc_port, sc->sc_port, wdc); 1034 octpko_op_doorbell_write(sc->sc_port, sc->sc_port, wdc);
1031 1035
1032last: 1036last:
1033 cnmac_send_queue_flush_fetch(sc); 1037 cnmac_send_queue_flush_fetch(sc);
 1038 callout_schedule(&sc->sc_tick_free_ch, 1);
1034} 1039}
1035 1040
1036static void 1041static void
1037cnmac_watchdog(struct ifnet *ifp) 1042cnmac_watchdog(struct ifnet *ifp)
1038{ 1043{
1039 struct cnmac_softc *sc = ifp->if_softc; 1044 struct cnmac_softc *sc = ifp->if_softc;
1040 1045
1041 printf("%s: device timeout\n", device_xname(sc->sc_dev)); 1046 printf("%s: device timeout\n", device_xname(sc->sc_dev));
1042 1047
1043 cnmac_configure(sc); 1048 cnmac_configure(sc);
1044 1049
1045 SET(ifp->if_flags, IFF_RUNNING); 1050 SET(ifp->if_flags, IFF_RUNNING);
1046 CLR(ifp->if_flags, IFF_OACTIVE); 1051 CLR(ifp->if_flags, IFF_OACTIVE);
@@ -1063,51 +1068,50 @@ cnmac_init(struct ifnet *ifp) @@ -1063,51 +1068,50 @@ cnmac_init(struct ifnet *ifp)
1063 cnmac_configure(sc); 1068 cnmac_configure(sc);
1064 1069
1065 octpko_enable(sc->sc_pko); 1070 octpko_enable(sc->sc_pko);
1066 octipd_enable(sc->sc_ipd); 1071 octipd_enable(sc->sc_ipd);
1067 1072
1068 sc->sc_init_flag = 1; 1073 sc->sc_init_flag = 1;
1069 } else { 1074 } else {
1070 octgmx_port_enable(sc->sc_gmx_port, 1); 1075 octgmx_port_enable(sc->sc_gmx_port, 1);
1071 } 1076 }
1072 mii_ifmedia_change(&sc->sc_mii); 1077 mii_ifmedia_change(&sc->sc_mii);
1073 1078
1074 octgmx_set_filter(sc->sc_gmx_port); 1079 octgmx_set_filter(sc->sc_gmx_port);
1075 1080
1076 callout_reset(&sc->sc_tick_misc_ch, hz, cnmac_tick_misc, sc); 1081 callout_schedule(&sc->sc_tick_misc_ch, hz);
1077 callout_reset(&sc->sc_tick_free_ch, hz, cnmac_tick_free, sc); 1082 callout_schedule(&sc->sc_tick_free_ch, hz);
1078 1083
1079 SET(ifp->if_flags, IFF_RUNNING); 1084 SET(ifp->if_flags, IFF_RUNNING);
1080 CLR(ifp->if_flags, IFF_OACTIVE); 1085 CLR(ifp->if_flags, IFF_OACTIVE);
1081 1086
1082 return 0; 1087 return 0;
1083} 1088}
1084 1089
1085static void 1090static void
1086cnmac_stop(struct ifnet *ifp, int disable) 1091cnmac_stop(struct ifnet *ifp, int disable)
1087{ 1092{
1088 struct cnmac_softc *sc = ifp->if_softc; 1093 struct cnmac_softc *sc = ifp->if_softc;
1089 1094
1090 callout_stop(&sc->sc_tick_misc_ch); 1095 callout_stop(&sc->sc_tick_misc_ch);
1091 callout_stop(&sc->sc_tick_free_ch); 1096 callout_stop(&sc->sc_tick_free_ch);
1092 1097
1093 mii_down(&sc->sc_mii); 1098 mii_down(&sc->sc_mii);
1094 1099
1095 octgmx_port_enable(sc->sc_gmx_port, 0); 1100 octgmx_port_enable(sc->sc_gmx_port, 0);
1096 1101
1097 /* Mark the interface as down and cancel the watchdog timer. */ 1102 /* Mark the interface as down and cancel the watchdog timer. */
1098 CLR(ifp->if_flags, IFF_RUNNING | IFF_OACTIVE); 1103 CLR(ifp->if_flags, IFF_RUNNING | IFF_OACTIVE);
1099 ifp->if_timer = 0; 1104 ifp->if_timer = 0;
1100 
1101} 1105}
1102 1106
1103/* ---- misc */ 1107/* ---- misc */
1104 1108
1105static int 1109static int
1106cnmac_reset(struct cnmac_softc *sc) 1110cnmac_reset(struct cnmac_softc *sc)
1107{ 1111{
1108 octgmx_reset_speed(sc->sc_gmx_port); 1112 octgmx_reset_speed(sc->sc_gmx_port);
1109 octgmx_reset_flowctl(sc->sc_gmx_port); 1113 octgmx_reset_flowctl(sc->sc_gmx_port);
1110 octgmx_reset_timing(sc->sc_gmx_port); 1114 octgmx_reset_timing(sc->sc_gmx_port);
1111 1115
1112 return 0; 1116 return 0;
1113} 1117}
@@ -1324,33 +1328,28 @@ cnmac_tick_free(void *arg) @@ -1324,33 +1328,28 @@ cnmac_tick_free(void *arg)
1324 int timo; 1328 int timo;
1325 int s; 1329 int s;
1326 1330
1327 s = splnet(); 1331 s = splnet();
1328 /* XXX XXX XXX */ 1332 /* XXX XXX XXX */
1329 if (sc->sc_soft_req_cnt > 0) { 1333 if (sc->sc_soft_req_cnt > 0) {
1330 cnmac_send_queue_flush_prefetch(sc); 1334 cnmac_send_queue_flush_prefetch(sc);
1331 cnmac_send_queue_flush_fetch(sc); 1335 cnmac_send_queue_flush_fetch(sc);
1332 cnmac_send_queue_flush(sc); 1336 cnmac_send_queue_flush(sc);
1333 cnmac_send_queue_flush_sync(sc); 1337 cnmac_send_queue_flush_sync(sc);
1334 } 1338 }
1335 /* XXX XXX XXX */ 1339 /* XXX XXX XXX */
1336 1340
1337 /* XXX XXX XXX */ 1341 timo = (sc->sc_ext_callback_cnt > 0) ? 1 : hz;
1338 /* ??? */ 
1339 timo = hz - (100 * sc->sc_ext_callback_cnt); 
1340 if (timo < 10) 
1341 timo = 10; 
1342 callout_schedule(&sc->sc_tick_free_ch, timo); 1342 callout_schedule(&sc->sc_tick_free_ch, timo);
1343 /* XXX XXX XXX */ 
1344 splx(s); 1343 splx(s);
1345} 1344}
1346 1345
1347/* 1346/*
1348 * cnmac_tick_misc 1347 * cnmac_tick_misc
1349 * 1348 *
1350 * => collect statistics 1349 * => collect statistics
1351 * => check link status 1350 * => check link status
1352 * => called at softclock 1351 * => called at softclock
1353 */ 1352 */
1354static void 1353static void
1355cnmac_tick_misc(void *arg) 1354cnmac_tick_misc(void *arg)
1356{ 1355{