1 1.43 andvar /* $NetBSD: if_mvxpe.c,v 1.43 2025/05/19 06:16:25 andvar Exp $ */ 2 1.1 hsuenaga /* 3 1.1 hsuenaga * Copyright (c) 2015 Internet Initiative Japan Inc. 4 1.1 hsuenaga * All rights reserved. 5 1.1 hsuenaga * 6 1.1 hsuenaga * Redistribution and use in source and binary forms, with or without 7 1.1 hsuenaga * modification, are permitted provided that the following conditions 8 1.1 hsuenaga * are met: 9 1.1 hsuenaga * 1. Redistributions of source code must retain the above copyright 10 1.1 hsuenaga * notice, this list of conditions and the following disclaimer. 11 1.1 hsuenaga * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 hsuenaga * notice, this list of conditions and the following disclaimer in the 13 1.1 hsuenaga * documentation and/or other materials provided with the distribution. 14 1.1 hsuenaga * 15 1.1 hsuenaga * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 hsuenaga * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 hsuenaga * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 hsuenaga * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 1.1 hsuenaga * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 1.1 hsuenaga * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 hsuenaga * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 hsuenaga * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 1.1 hsuenaga * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 1.1 hsuenaga * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 1.1 hsuenaga * POSSIBILITY OF SUCH DAMAGE. 26 1.1 hsuenaga */ 27 1.1 hsuenaga #include <sys/cdefs.h> 28 1.43 andvar __KERNEL_RCSID(0, "$NetBSD: if_mvxpe.c,v 1.43 2025/05/19 06:16:25 andvar Exp $"); 29 1.1 hsuenaga 30 1.1 hsuenaga #include "opt_multiprocessor.h" 31 1.1 hsuenaga 32 1.1 hsuenaga #include <sys/param.h> 33 1.1 hsuenaga #include <sys/bus.h> 34 1.1 hsuenaga #include <sys/callout.h> 35 1.1 hsuenaga #include <sys/device.h> 36 1.1 hsuenaga #include <sys/endian.h> 37 1.1 hsuenaga #include <sys/errno.h> 38 1.1 hsuenaga #include <sys/evcnt.h> 39 1.1 hsuenaga #include <sys/kernel.h> 40 1.1 hsuenaga #include <sys/kmem.h> 41 1.1 hsuenaga #include <sys/mutex.h> 42 1.1 hsuenaga #include <sys/sockio.h> 43 1.1 hsuenaga #include <sys/sysctl.h> 44 1.1 hsuenaga #include <sys/syslog.h> 45 1.1 hsuenaga #include <sys/rndsource.h> 46 1.1 hsuenaga 47 1.1 hsuenaga #include <net/if.h> 48 1.1 hsuenaga #include <net/if_ether.h> 49 1.1 hsuenaga #include <net/if_media.h> 50 1.1 hsuenaga #include <net/bpf.h> 51 1.1 hsuenaga 52 1.1 hsuenaga #include <netinet/in.h> 53 1.1 hsuenaga #include <netinet/in_systm.h> 54 1.1 hsuenaga #include <netinet/ip.h> 55 1.1 hsuenaga 56 1.1 hsuenaga #include <dev/mii/mii.h> 57 1.1 hsuenaga #include <dev/mii/miivar.h> 58 1.1 hsuenaga 59 1.1 hsuenaga #include <dev/marvell/marvellreg.h> 60 1.1 hsuenaga #include <dev/marvell/marvellvar.h> 61 1.2 hsuenaga #include <dev/marvell/mvxpbmvar.h> 62 1.1 hsuenaga #include <dev/marvell/if_mvxpereg.h> 63 1.1 hsuenaga #include <dev/marvell/if_mvxpevar.h> 64 1.1 hsuenaga 65 1.1 hsuenaga #include "locators.h" 66 1.1 hsuenaga 67 1.1 hsuenaga #if BYTE_ORDER == BIG_ENDIAN 68 1.1 hsuenaga #error "BIG ENDIAN not supported" 69 1.1 hsuenaga #endif 70 1.1 hsuenaga 71 1.1 hsuenaga #ifdef MVXPE_DEBUG 72 1.1 hsuenaga #define STATIC /* nothing */ 73 1.1 hsuenaga #else 74 1.1 hsuenaga #define STATIC static 75 1.1 hsuenaga #endif 76 1.1 hsuenaga 77 1.1 hsuenaga /* autoconf(9) */ 78 1.1 hsuenaga STATIC int mvxpe_match(device_t, struct cfdata *, void *); 79 1.1 hsuenaga STATIC void mvxpe_attach(device_t, device_t, void *); 80 1.1 hsuenaga STATIC int mvxpe_evcnt_attach(struct mvxpe_softc *); 81 1.1 hsuenaga CFATTACH_DECL_NEW(mvxpe_mbus, sizeof(struct mvxpe_softc), 82 1.1 hsuenaga mvxpe_match, mvxpe_attach, NULL, NULL); 83 1.1 hsuenaga STATIC void mvxpe_sc_lock(struct mvxpe_softc *); 84 1.1 hsuenaga STATIC void mvxpe_sc_unlock(struct mvxpe_softc *); 85 1.1 hsuenaga 86 1.1 hsuenaga /* MII */ 87 1.21 msaitoh STATIC int mvxpe_miibus_readreg(device_t, int, int, uint16_t *); 88 1.21 msaitoh STATIC int mvxpe_miibus_writereg(device_t, int, int, uint16_t); 89 1.1 hsuenaga STATIC void mvxpe_miibus_statchg(struct ifnet *); 90 1.1 hsuenaga 91 1.34 andvar /* Address Decoding Window */ 92 1.1 hsuenaga STATIC void mvxpe_wininit(struct mvxpe_softc *, enum marvell_tags *); 93 1.1 hsuenaga 94 1.1 hsuenaga /* Device Register Initialization */ 95 1.1 hsuenaga STATIC int mvxpe_initreg(struct ifnet *); 96 1.1 hsuenaga 97 1.1 hsuenaga /* Descriptor Ring Control for each of queues */ 98 1.1 hsuenaga STATIC void *mvxpe_dma_memalloc(struct mvxpe_softc *, bus_dmamap_t *, size_t); 99 1.1 hsuenaga STATIC int mvxpe_ring_alloc_queue(struct mvxpe_softc *, int); 100 1.1 hsuenaga STATIC void mvxpe_ring_dealloc_queue(struct mvxpe_softc *, int); 101 1.1 hsuenaga STATIC void mvxpe_ring_init_queue(struct mvxpe_softc *, int); 102 1.1 hsuenaga STATIC void mvxpe_ring_flush_queue(struct mvxpe_softc *, int); 103 1.1 hsuenaga STATIC void mvxpe_ring_sync_rx(struct mvxpe_softc *, int, int, int, int); 104 1.1 hsuenaga STATIC void mvxpe_ring_sync_tx(struct mvxpe_softc *, int, int, int, int); 105 1.1 hsuenaga 106 1.1 hsuenaga /* Rx/Tx Queue Control */ 107 1.1 hsuenaga STATIC int mvxpe_rx_queue_init(struct ifnet *, int); 108 1.1 hsuenaga STATIC int mvxpe_tx_queue_init(struct ifnet *, int); 109 1.1 hsuenaga STATIC int mvxpe_rx_queue_enable(struct ifnet *, int); 110 1.1 hsuenaga STATIC int mvxpe_tx_queue_enable(struct ifnet *, int); 111 1.1 hsuenaga STATIC void mvxpe_rx_lockq(struct mvxpe_softc *, int); 112 1.1 hsuenaga STATIC void mvxpe_rx_unlockq(struct mvxpe_softc *, int); 113 1.1 hsuenaga STATIC void mvxpe_tx_lockq(struct mvxpe_softc *, int); 114 1.1 hsuenaga STATIC void mvxpe_tx_unlockq(struct mvxpe_softc *, int); 115 1.1 hsuenaga 116 1.1 hsuenaga /* Interrupt Handlers */ 117 1.1 hsuenaga STATIC void mvxpe_disable_intr(struct mvxpe_softc *); 118 1.1 hsuenaga STATIC void mvxpe_enable_intr(struct mvxpe_softc *); 119 1.1 hsuenaga STATIC int mvxpe_rxtxth_intr(void *); 120 1.1 hsuenaga STATIC int mvxpe_misc_intr(void *); 121 1.1 hsuenaga STATIC int mvxpe_rxtx_intr(void *); 122 1.1 hsuenaga STATIC void mvxpe_tick(void *); 123 1.1 hsuenaga 124 1.1 hsuenaga /* struct ifnet and mii callbacks*/ 125 1.1 hsuenaga STATIC void mvxpe_start(struct ifnet *); 126 1.1 hsuenaga STATIC int mvxpe_ioctl(struct ifnet *, u_long, void *); 127 1.1 hsuenaga STATIC int mvxpe_init(struct ifnet *); 128 1.1 hsuenaga STATIC void mvxpe_stop(struct ifnet *, int); 129 1.1 hsuenaga STATIC void mvxpe_watchdog(struct ifnet *); 130 1.1 hsuenaga STATIC int mvxpe_ifflags_cb(struct ethercom *); 131 1.1 hsuenaga STATIC int mvxpe_mediachange(struct ifnet *); 132 1.1 hsuenaga STATIC void mvxpe_mediastatus(struct ifnet *, struct ifmediareq *); 133 1.1 hsuenaga 134 1.1 hsuenaga /* Link State Notify */ 135 1.1 hsuenaga STATIC void mvxpe_linkupdate(struct mvxpe_softc *sc); 136 1.1 hsuenaga STATIC void mvxpe_linkup(struct mvxpe_softc *); 137 1.1 hsuenaga STATIC void mvxpe_linkdown(struct mvxpe_softc *); 138 1.1 hsuenaga STATIC void mvxpe_linkreset(struct mvxpe_softc *); 139 1.1 hsuenaga 140 1.1 hsuenaga /* Tx Subroutines */ 141 1.1 hsuenaga STATIC int mvxpe_tx_queue_select(struct mvxpe_softc *, struct mbuf *); 142 1.1 hsuenaga STATIC int mvxpe_tx_queue(struct mvxpe_softc *, struct mbuf *, int); 143 1.1 hsuenaga STATIC void mvxpe_tx_set_csumflag(struct ifnet *, 144 1.1 hsuenaga struct mvxpe_tx_desc *, struct mbuf *); 145 1.2 hsuenaga STATIC void mvxpe_tx_complete(struct mvxpe_softc *, uint32_t); 146 1.2 hsuenaga STATIC void mvxpe_tx_queue_complete(struct mvxpe_softc *, int); 147 1.1 hsuenaga 148 1.1 hsuenaga /* Rx Subroutines */ 149 1.2 hsuenaga STATIC void mvxpe_rx(struct mvxpe_softc *, uint32_t); 150 1.1 hsuenaga STATIC void mvxpe_rx_queue(struct mvxpe_softc *, int, int); 151 1.2 hsuenaga STATIC int mvxpe_rx_queue_select(struct mvxpe_softc *, uint32_t, int *); 152 1.2 hsuenaga STATIC void mvxpe_rx_refill(struct mvxpe_softc *, uint32_t); 153 1.2 hsuenaga STATIC void mvxpe_rx_queue_refill(struct mvxpe_softc *, int); 154 1.1 hsuenaga STATIC int mvxpe_rx_queue_add(struct mvxpe_softc *, int); 155 1.1 hsuenaga STATIC void mvxpe_rx_set_csumflag(struct ifnet *, 156 1.1 hsuenaga struct mvxpe_rx_desc *, struct mbuf *); 157 1.1 hsuenaga 158 1.1 hsuenaga /* MAC address filter */ 159 1.1 hsuenaga STATIC uint8_t mvxpe_crc8(const uint8_t *, size_t); 160 1.1 hsuenaga STATIC void mvxpe_filter_setup(struct mvxpe_softc *); 161 1.1 hsuenaga 162 1.1 hsuenaga /* sysctl(9) */ 163 1.1 hsuenaga STATIC int sysctl_read_mib(SYSCTLFN_PROTO); 164 1.1 hsuenaga STATIC int sysctl_clear_mib(SYSCTLFN_PROTO); 165 1.1 hsuenaga STATIC int sysctl_set_queue_length(SYSCTLFN_PROTO); 166 1.1 hsuenaga STATIC int sysctl_set_queue_rxthtime(SYSCTLFN_PROTO); 167 1.1 hsuenaga STATIC void sysctl_mvxpe_init(struct mvxpe_softc *); 168 1.1 hsuenaga 169 1.1 hsuenaga /* MIB */ 170 1.1 hsuenaga STATIC void mvxpe_clear_mib(struct mvxpe_softc *); 171 1.1 hsuenaga STATIC void mvxpe_update_mib(struct mvxpe_softc *); 172 1.1 hsuenaga 173 1.1 hsuenaga /* for Debug */ 174 1.1 hsuenaga STATIC void mvxpe_dump_txdesc(struct mvxpe_tx_desc *, int) __attribute__((__unused__)); 175 1.1 hsuenaga STATIC void mvxpe_dump_rxdesc(struct mvxpe_rx_desc *, int) __attribute__((__unused__)); 176 1.1 hsuenaga 177 1.1 hsuenaga STATIC int mvxpe_root_num; 178 1.1 hsuenaga STATIC kmutex_t mii_mutex; 179 1.1 hsuenaga STATIC int mii_init = 0; 180 1.1 hsuenaga #ifdef MVXPE_DEBUG 181 1.1 hsuenaga STATIC int mvxpe_debug = MVXPE_DEBUG; 182 1.1 hsuenaga #endif 183 1.1 hsuenaga 184 1.1 hsuenaga /* 185 1.1 hsuenaga * List of MIB register and names 186 1.1 hsuenaga */ 187 1.1 hsuenaga STATIC struct mvxpe_mib_def { 188 1.1 hsuenaga uint32_t regnum; 189 1.1 hsuenaga int reg64; 190 1.1 hsuenaga const char *sysctl_name; 191 1.1 hsuenaga const char *desc; 192 1.10 hikaru int ext; 193 1.10 hikaru #define MVXPE_MIBEXT_IF_OERRORS 1 194 1.10 hikaru #define MVXPE_MIBEXT_IF_IERRORS 2 195 1.10 hikaru #define MVXPE_MIBEXT_IF_COLLISIONS 3 196 1.1 hsuenaga } mvxpe_mib_list[] = { 197 1.1 hsuenaga {MVXPE_MIB_RX_GOOD_OCT, 1, "rx_good_oct", 198 1.10 hikaru "Good Octets Rx", 0}, 199 1.1 hsuenaga {MVXPE_MIB_RX_BAD_OCT, 0, "rx_bad_oct", 200 1.10 hikaru "Bad Octets Rx", 0}, 201 1.10 hikaru {MVXPE_MIB_TX_MAC_TRNS_ERR, 0, "tx_mac_err", 202 1.10 hikaru "MAC Transmit Error", MVXPE_MIBEXT_IF_OERRORS}, 203 1.1 hsuenaga {MVXPE_MIB_RX_GOOD_FRAME, 0, "rx_good_frame", 204 1.10 hikaru "Good Frames Rx", 0}, 205 1.1 hsuenaga {MVXPE_MIB_RX_BAD_FRAME, 0, "rx_bad_frame", 206 1.10 hikaru "Bad Frames Rx", 0}, 207 1.1 hsuenaga {MVXPE_MIB_RX_BCAST_FRAME, 0, "rx_bcast_frame", 208 1.10 hikaru "Broadcast Frames Rx", 0}, 209 1.1 hsuenaga {MVXPE_MIB_RX_MCAST_FRAME, 0, "rx_mcast_frame", 210 1.10 hikaru "Multicast Frames Rx", 0}, 211 1.1 hsuenaga {MVXPE_MIB_RX_FRAME64_OCT, 0, "rx_frame_1_64", 212 1.10 hikaru "Frame Size 1 - 64", 0}, 213 1.1 hsuenaga {MVXPE_MIB_RX_FRAME127_OCT, 0, "rx_frame_65_127", 214 1.10 hikaru "Frame Size 65 - 127", 0}, 215 1.1 hsuenaga {MVXPE_MIB_RX_FRAME255_OCT, 0, "rx_frame_128_255", 216 1.10 hikaru "Frame Size 128 - 255", 0}, 217 1.1 hsuenaga {MVXPE_MIB_RX_FRAME511_OCT, 0, "rx_frame_256_511", 218 1.1 hsuenaga "Frame Size 256 - 511"}, 219 1.1 hsuenaga {MVXPE_MIB_RX_FRAME1023_OCT, 0, "rx_frame_512_1023", 220 1.10 hikaru "Frame Size 512 - 1023", 0}, 221 1.35 andvar {MVXPE_MIB_RX_FRAMEMAX_OCT, 0, "rx_frame_1024_max", 222 1.10 hikaru "Frame Size 1024 - Max", 0}, 223 1.1 hsuenaga {MVXPE_MIB_TX_GOOD_OCT, 1, "tx_good_oct", 224 1.10 hikaru "Good Octets Tx", 0}, 225 1.1 hsuenaga {MVXPE_MIB_TX_GOOD_FRAME, 0, "tx_good_frame", 226 1.10 hikaru "Good Frames Tx", 0}, 227 1.1 hsuenaga {MVXPE_MIB_TX_EXCES_COL, 0, "tx_exces_collision", 228 1.10 hikaru "Excessive Collision", MVXPE_MIBEXT_IF_OERRORS}, 229 1.1 hsuenaga {MVXPE_MIB_TX_MCAST_FRAME, 0, "tx_mcast_frame", 230 1.1 hsuenaga "Multicast Frames Tx"}, 231 1.1 hsuenaga {MVXPE_MIB_TX_BCAST_FRAME, 0, "tx_bcast_frame", 232 1.1 hsuenaga "Broadcast Frames Tx"}, 233 1.1 hsuenaga {MVXPE_MIB_TX_MAC_CTL_ERR, 0, "tx_mac_err", 234 1.10 hikaru "Unknown MAC Control", 0}, 235 1.1 hsuenaga {MVXPE_MIB_FC_SENT, 0, "fc_tx", 236 1.10 hikaru "Flow Control Tx", 0}, 237 1.1 hsuenaga {MVXPE_MIB_FC_GOOD, 0, "fc_rx_good", 238 1.10 hikaru "Good Flow Control Rx", 0}, 239 1.1 hsuenaga {MVXPE_MIB_FC_BAD, 0, "fc_rx_bad", 240 1.10 hikaru "Bad Flow Control Rx", 0}, 241 1.1 hsuenaga {MVXPE_MIB_PKT_UNDERSIZE, 0, "pkt_undersize", 242 1.10 hikaru "Undersized Packets Rx", MVXPE_MIBEXT_IF_IERRORS}, 243 1.1 hsuenaga {MVXPE_MIB_PKT_FRAGMENT, 0, "pkt_fragment", 244 1.10 hikaru "Fragmented Packets Rx", MVXPE_MIBEXT_IF_IERRORS}, 245 1.1 hsuenaga {MVXPE_MIB_PKT_OVERSIZE, 0, "pkt_oversize", 246 1.10 hikaru "Oversized Packets Rx", MVXPE_MIBEXT_IF_IERRORS}, 247 1.1 hsuenaga {MVXPE_MIB_PKT_JABBER, 0, "pkt_jabber", 248 1.10 hikaru "Jabber Packets Rx", MVXPE_MIBEXT_IF_IERRORS}, 249 1.1 hsuenaga {MVXPE_MIB_MAC_RX_ERR, 0, "mac_rx_err", 250 1.10 hikaru "MAC Rx Errors", MVXPE_MIBEXT_IF_IERRORS}, 251 1.1 hsuenaga {MVXPE_MIB_MAC_CRC_ERR, 0, "mac_crc_err", 252 1.10 hikaru "MAC CRC Errors", MVXPE_MIBEXT_IF_IERRORS}, 253 1.1 hsuenaga {MVXPE_MIB_MAC_COL, 0, "mac_collision", 254 1.10 hikaru "MAC Collision", MVXPE_MIBEXT_IF_COLLISIONS}, 255 1.1 hsuenaga {MVXPE_MIB_MAC_LATE_COL, 0, "mac_late_collision", 256 1.10 hikaru "MAC Late Collision", MVXPE_MIBEXT_IF_OERRORS}, 257 1.1 hsuenaga }; 258 1.1 hsuenaga 259 1.1 hsuenaga /* 260 1.1 hsuenaga * autoconf(9) 261 1.1 hsuenaga */ 262 1.1 hsuenaga /* ARGSUSED */ 263 1.1 hsuenaga STATIC int 264 1.1 hsuenaga mvxpe_match(device_t parent, cfdata_t match, void *aux) 265 1.1 hsuenaga { 266 1.1 hsuenaga struct marvell_attach_args *mva = aux; 267 1.1 hsuenaga bus_size_t pv_off; 268 1.1 hsuenaga uint32_t pv; 269 1.1 hsuenaga 270 1.1 hsuenaga if (strcmp(mva->mva_name, match->cf_name) != 0) 271 1.1 hsuenaga return 0; 272 1.1 hsuenaga if (mva->mva_offset == MVA_OFFSET_DEFAULT) 273 1.1 hsuenaga return 0; 274 1.1 hsuenaga 275 1.1 hsuenaga /* check port version */ 276 1.1 hsuenaga pv_off = mva->mva_offset + MVXPE_PV; 277 1.1 hsuenaga pv = bus_space_read_4(mva->mva_iot, mva->mva_ioh, pv_off); 278 1.1 hsuenaga if (MVXPE_PV_GET_VERSION(pv) < 0x10) 279 1.1 hsuenaga return 0; /* old version is not supported */ 280 1.1 hsuenaga 281 1.1 hsuenaga return 1; 282 1.1 hsuenaga } 283 1.1 hsuenaga 284 1.1 hsuenaga /* ARGSUSED */ 285 1.1 hsuenaga STATIC void 286 1.1 hsuenaga mvxpe_attach(device_t parent, device_t self, void *aux) 287 1.1 hsuenaga { 288 1.1 hsuenaga struct mvxpe_softc *sc = device_private(self); 289 1.29 chs struct mii_softc *child; 290 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 291 1.24 msaitoh struct mii_data * const mii = &sc->sc_mii; 292 1.1 hsuenaga struct marvell_attach_args *mva = aux; 293 1.1 hsuenaga prop_dictionary_t dict; 294 1.1 hsuenaga prop_data_t enaddrp = NULL; 295 1.1 hsuenaga uint32_t phyaddr, maddrh, maddrl; 296 1.1 hsuenaga uint8_t enaddr[ETHER_ADDR_LEN]; 297 1.1 hsuenaga int q; 298 1.1 hsuenaga 299 1.1 hsuenaga aprint_naive("\n"); 300 1.1 hsuenaga aprint_normal(": Marvell ARMADA GbE Controller\n"); 301 1.1 hsuenaga memset(sc, 0, sizeof(*sc)); 302 1.1 hsuenaga sc->sc_dev = self; 303 1.1 hsuenaga sc->sc_port = mva->mva_unit; 304 1.1 hsuenaga sc->sc_iot = mva->mva_iot; 305 1.1 hsuenaga sc->sc_dmat = mva->mva_dmat; 306 1.1 hsuenaga mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NET); 307 1.1 hsuenaga callout_init(&sc->sc_tick_ch, 0); 308 1.1 hsuenaga callout_setfunc(&sc->sc_tick_ch, mvxpe_tick, sc); 309 1.1 hsuenaga 310 1.1 hsuenaga /* 311 1.1 hsuenaga * BUS space 312 1.1 hsuenaga */ 313 1.1 hsuenaga if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, 314 1.1 hsuenaga mva->mva_offset, mva->mva_size, &sc->sc_ioh)) { 315 1.1 hsuenaga aprint_error_dev(self, "Cannot map registers\n"); 316 1.1 hsuenaga goto fail; 317 1.1 hsuenaga } 318 1.1 hsuenaga if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, 319 1.1 hsuenaga mva->mva_offset + MVXPE_PORTMIB_BASE, MVXPE_PORTMIB_SIZE, 320 1.1 hsuenaga &sc->sc_mibh)) { 321 1.1 hsuenaga aprint_error_dev(self, 322 1.1 hsuenaga "Cannot map destination address filter registers\n"); 323 1.1 hsuenaga goto fail; 324 1.1 hsuenaga } 325 1.1 hsuenaga sc->sc_version = MVXPE_READ(sc, MVXPE_PV); 326 1.1 hsuenaga aprint_normal_dev(self, "Port Version %#x\n", sc->sc_version); 327 1.1 hsuenaga 328 1.1 hsuenaga /* 329 1.2 hsuenaga * Buffer Manager(BM) subsystem. 330 1.1 hsuenaga */ 331 1.2 hsuenaga sc->sc_bm = mvxpbm_device(mva); 332 1.2 hsuenaga if (sc->sc_bm == NULL) { 333 1.2 hsuenaga aprint_error_dev(self, "no Buffer Manager.\n"); 334 1.1 hsuenaga goto fail; 335 1.1 hsuenaga } 336 1.2 hsuenaga aprint_normal_dev(self, 337 1.24 msaitoh "Using Buffer Manager: %s\n", mvxpbm_xname(sc->sc_bm)); 338 1.2 hsuenaga aprint_normal_dev(sc->sc_dev, 339 1.2 hsuenaga "%zu kbytes managed buffer, %zu bytes * %u entries allocated.\n", 340 1.2 hsuenaga mvxpbm_buf_size(sc->sc_bm) / 1024, 341 1.2 hsuenaga mvxpbm_chunk_size(sc->sc_bm), mvxpbm_chunk_count(sc->sc_bm)); 342 1.1 hsuenaga 343 1.1 hsuenaga /* 344 1.1 hsuenaga * make sure DMA engines are in reset state 345 1.1 hsuenaga */ 346 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXINIT, 0x00000001); 347 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXINIT, 0x00000001); 348 1.1 hsuenaga 349 1.1 hsuenaga /* 350 1.1 hsuenaga * Address decoding window 351 1.1 hsuenaga */ 352 1.1 hsuenaga mvxpe_wininit(sc, mva->mva_tags); 353 1.1 hsuenaga 354 1.1 hsuenaga /* 355 1.1 hsuenaga * MAC address 356 1.1 hsuenaga */ 357 1.1 hsuenaga dict = device_properties(self); 358 1.1 hsuenaga if (dict) 359 1.1 hsuenaga enaddrp = prop_dictionary_get(dict, "mac-address"); 360 1.1 hsuenaga if (enaddrp) { 361 1.1 hsuenaga memcpy(enaddr, prop_data_data_nocopy(enaddrp), ETHER_ADDR_LEN); 362 1.1 hsuenaga maddrh = enaddr[0] << 24; 363 1.1 hsuenaga maddrh |= enaddr[1] << 16; 364 1.1 hsuenaga maddrh |= enaddr[2] << 8; 365 1.1 hsuenaga maddrh |= enaddr[3]; 366 1.1 hsuenaga maddrl = enaddr[4] << 8; 367 1.1 hsuenaga maddrl |= enaddr[5]; 368 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_MACAH, maddrh); 369 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_MACAL, maddrl); 370 1.1 hsuenaga } 371 1.1 hsuenaga else { 372 1.1 hsuenaga /* 373 1.1 hsuenaga * even if enaddr is not found in dictionary, 374 1.1 hsuenaga * the port may be initialized by IPL program such as U-BOOT. 375 1.1 hsuenaga */ 376 1.1 hsuenaga maddrh = MVXPE_READ(sc, MVXPE_MACAH); 377 1.1 hsuenaga maddrl = MVXPE_READ(sc, MVXPE_MACAL); 378 1.1 hsuenaga if ((maddrh | maddrl) == 0) { 379 1.1 hsuenaga aprint_error_dev(self, "No Ethernet address\n"); 380 1.1 hsuenaga return; 381 1.1 hsuenaga } 382 1.1 hsuenaga } 383 1.1 hsuenaga sc->sc_enaddr[0] = maddrh >> 24; 384 1.1 hsuenaga sc->sc_enaddr[1] = maddrh >> 16; 385 1.1 hsuenaga sc->sc_enaddr[2] = maddrh >> 8; 386 1.1 hsuenaga sc->sc_enaddr[3] = maddrh >> 0; 387 1.1 hsuenaga sc->sc_enaddr[4] = maddrl >> 8; 388 1.1 hsuenaga sc->sc_enaddr[5] = maddrl >> 0; 389 1.1 hsuenaga aprint_normal_dev(self, "Ethernet address %s\n", 390 1.1 hsuenaga ether_sprintf(sc->sc_enaddr)); 391 1.1 hsuenaga 392 1.1 hsuenaga /* 393 1.1 hsuenaga * Register interrupt handlers 394 1.1 hsuenaga * XXX: handle Ethernet unit intr. and Error intr. 395 1.1 hsuenaga */ 396 1.1 hsuenaga mvxpe_disable_intr(sc); 397 1.1 hsuenaga marvell_intr_establish(mva->mva_irq, IPL_NET, mvxpe_rxtxth_intr, sc); 398 1.1 hsuenaga 399 1.1 hsuenaga /* 400 1.1 hsuenaga * MIB buffer allocation 401 1.1 hsuenaga */ 402 1.1 hsuenaga sc->sc_sysctl_mib_size = 403 1.1 hsuenaga __arraycount(mvxpe_mib_list) * sizeof(struct mvxpe_sysctl_mib); 404 1.30 chs sc->sc_sysctl_mib = kmem_alloc(sc->sc_sysctl_mib_size, KM_SLEEP); 405 1.1 hsuenaga memset(sc->sc_sysctl_mib, 0, sc->sc_sysctl_mib_size); 406 1.1 hsuenaga 407 1.1 hsuenaga /* 408 1.1 hsuenaga * Device DMA Buffer allocation 409 1.1 hsuenaga */ 410 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 411 1.1 hsuenaga if (mvxpe_ring_alloc_queue(sc, q) != 0) 412 1.1 hsuenaga goto fail; 413 1.1 hsuenaga mvxpe_ring_init_queue(sc, q); 414 1.1 hsuenaga } 415 1.1 hsuenaga 416 1.1 hsuenaga /* 417 1.1 hsuenaga * We can support 802.1Q VLAN-sized frames and jumbo 418 1.1 hsuenaga * Ethernet frames. 419 1.1 hsuenaga */ 420 1.1 hsuenaga sc->sc_ethercom.ec_capabilities |= 421 1.1 hsuenaga ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU; 422 1.1 hsuenaga ifp->if_softc = sc; 423 1.1 hsuenaga ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 424 1.1 hsuenaga ifp->if_start = mvxpe_start; 425 1.1 hsuenaga ifp->if_ioctl = mvxpe_ioctl; 426 1.1 hsuenaga ifp->if_init = mvxpe_init; 427 1.1 hsuenaga ifp->if_stop = mvxpe_stop; 428 1.1 hsuenaga ifp->if_watchdog = mvxpe_watchdog; 429 1.1 hsuenaga 430 1.1 hsuenaga /* 431 1.1 hsuenaga * We can do IPv4/TCPv4/UDPv4/TCPv6/UDPv6 checksums in hardware. 432 1.1 hsuenaga */ 433 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_IPv4_Tx; 434 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_IPv4_Rx; 435 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Tx; 436 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_TCPv4_Rx; 437 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_UDPv4_Tx; 438 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_UDPv4_Rx; 439 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_TCPv6_Tx; 440 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_TCPv6_Rx; 441 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_UDPv6_Tx; 442 1.1 hsuenaga ifp->if_capabilities |= IFCAP_CSUM_UDPv6_Rx; 443 1.1 hsuenaga 444 1.1 hsuenaga /* 445 1.1 hsuenaga * Initialize struct ifnet 446 1.1 hsuenaga */ 447 1.20 riastrad IFQ_SET_MAXLEN(&ifp->if_snd, uimax(MVXPE_TX_RING_CNT - 1, IFQ_MAXLEN)); 448 1.1 hsuenaga IFQ_SET_READY(&ifp->if_snd); 449 1.1 hsuenaga strlcpy(ifp->if_xname, device_xname(sc->sc_dev), sizeof(ifp->if_xname)); 450 1.1 hsuenaga 451 1.1 hsuenaga /* 452 1.41 andvar * Enable DMA engines and Initialize Device Registers. 453 1.1 hsuenaga */ 454 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXINIT, 0x00000000); 455 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXINIT, 0x00000000); 456 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PACC, MVXPE_PACC_ACCELERATIONMODE_EDM); 457 1.1 hsuenaga mvxpe_sc_lock(sc); /* XXX */ 458 1.1 hsuenaga mvxpe_filter_setup(sc); 459 1.1 hsuenaga mvxpe_sc_unlock(sc); 460 1.1 hsuenaga mvxpe_initreg(ifp); 461 1.1 hsuenaga 462 1.1 hsuenaga /* 463 1.1 hsuenaga * Now MAC is working, setup MII. 464 1.1 hsuenaga */ 465 1.1 hsuenaga if (mii_init == 0) { 466 1.1 hsuenaga /* 467 1.1 hsuenaga * MII bus is shared by all MACs and all PHYs in SoC. 468 1.1 hsuenaga * serializing the bus access should be safe. 469 1.1 hsuenaga */ 470 1.1 hsuenaga mutex_init(&mii_mutex, MUTEX_DEFAULT, IPL_NET); 471 1.1 hsuenaga mii_init = 1; 472 1.1 hsuenaga } 473 1.24 msaitoh mii->mii_ifp = ifp; 474 1.24 msaitoh mii->mii_readreg = mvxpe_miibus_readreg; 475 1.24 msaitoh mii->mii_writereg = mvxpe_miibus_writereg; 476 1.24 msaitoh mii->mii_statchg = mvxpe_miibus_statchg; 477 1.24 msaitoh 478 1.24 msaitoh sc->sc_ethercom.ec_mii = mii; 479 1.24 msaitoh ifmedia_init(&mii->mii_media, 0, mvxpe_mediachange, mvxpe_mediastatus); 480 1.1 hsuenaga /* 481 1.1 hsuenaga * XXX: phy addressing highly depends on Board Design. 482 1.24 msaitoh * we assume phyaddress == MAC unit number here, 483 1.1 hsuenaga * but some boards may not. 484 1.1 hsuenaga */ 485 1.38 riastrad mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, device_unit(sc->sc_dev), 486 1.38 riastrad 0); 487 1.29 chs child = LIST_FIRST(&mii->mii_phys); 488 1.29 chs if (child == NULL) { 489 1.1 hsuenaga aprint_error_dev(self, "no PHY found!\n"); 490 1.24 msaitoh ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 491 1.24 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_MANUAL); 492 1.1 hsuenaga } else { 493 1.24 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 494 1.29 chs phyaddr = MVXPE_PHYADDR_PHYAD(child->mii_phy); 495 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PHYADDR, phyaddr); 496 1.1 hsuenaga DPRINTSC(sc, 1, "PHYADDR: %#x\n", MVXPE_READ(sc, MVXPE_PHYADDR)); 497 1.1 hsuenaga } 498 1.1 hsuenaga 499 1.1 hsuenaga /* 500 1.1 hsuenaga * Call MI attach routines. 501 1.1 hsuenaga */ 502 1.1 hsuenaga if_attach(ifp); 503 1.16 ozaki if_deferred_start_init(ifp, NULL); 504 1.1 hsuenaga 505 1.1 hsuenaga ether_ifattach(ifp, sc->sc_enaddr); 506 1.1 hsuenaga ether_set_ifflags_cb(&sc->sc_ethercom, mvxpe_ifflags_cb); 507 1.1 hsuenaga 508 1.1 hsuenaga sysctl_mvxpe_init(sc); 509 1.1 hsuenaga mvxpe_evcnt_attach(sc); 510 1.1 hsuenaga rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev), 511 1.1 hsuenaga RND_TYPE_NET, RND_FLAG_DEFAULT); 512 1.1 hsuenaga 513 1.1 hsuenaga return; 514 1.1 hsuenaga 515 1.1 hsuenaga fail: 516 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) 517 1.1 hsuenaga mvxpe_ring_dealloc_queue(sc, q); 518 1.1 hsuenaga if (sc->sc_sysctl_mib) 519 1.1 hsuenaga kmem_free(sc->sc_sysctl_mib, sc->sc_sysctl_mib_size); 520 1.1 hsuenaga 521 1.1 hsuenaga return; 522 1.1 hsuenaga } 523 1.1 hsuenaga 524 1.1 hsuenaga STATIC int 525 1.1 hsuenaga mvxpe_evcnt_attach(struct mvxpe_softc *sc) 526 1.1 hsuenaga { 527 1.2 hsuenaga #ifdef MVXPE_EVENT_COUNTERS 528 1.1 hsuenaga int q; 529 1.1 hsuenaga 530 1.1 hsuenaga /* Master Interrupt Handler */ 531 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_i_rxtxth, EVCNT_TYPE_INTR, 532 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "RxTxTH Intr."); 533 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_i_rxtx, EVCNT_TYPE_INTR, 534 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "RxTx Intr."); 535 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_i_misc, EVCNT_TYPE_INTR, 536 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC Intr."); 537 1.1 hsuenaga 538 1.1 hsuenaga /* RXTXTH Interrupt */ 539 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxtxth_txerr, EVCNT_TYPE_INTR, 540 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "RxTxTH Tx error summary"); 541 1.1 hsuenaga 542 1.1 hsuenaga /* MISC Interrupt */ 543 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_phystatuschng, EVCNT_TYPE_INTR, 544 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC phy status changed"); 545 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_linkchange, EVCNT_TYPE_INTR, 546 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC link status changed"); 547 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_iae, EVCNT_TYPE_INTR, 548 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC internal address error"); 549 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_rxoverrun, EVCNT_TYPE_INTR, 550 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC Rx FIFO overrun"); 551 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_rxcrc, EVCNT_TYPE_INTR, 552 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC Rx CRC error"); 553 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_rxlargepacket, EVCNT_TYPE_INTR, 554 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC Rx too large frame"); 555 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_txunderrun, EVCNT_TYPE_INTR, 556 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC Tx FIFO underrun"); 557 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_prbserr, EVCNT_TYPE_INTR, 558 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC SERDES loopback test err"); 559 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_srse, EVCNT_TYPE_INTR, 560 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "MISC SERDES sync error"); 561 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_misc_txreq, EVCNT_TYPE_INTR, 562 1.31 gutterid NULL, device_xname(sc->sc_dev), "MISC Tx resource error"); 563 1.1 hsuenaga 564 1.1 hsuenaga /* RxTx Interrupt */ 565 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_rreq, EVCNT_TYPE_INTR, 566 1.31 gutterid NULL, device_xname(sc->sc_dev), "RxTx Rx resource error"); 567 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_rpq, EVCNT_TYPE_INTR, 568 1.22 msaitoh NULL, device_xname(sc->sc_dev), "RxTx Rx packet"); 569 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_tbrq, EVCNT_TYPE_INTR, 570 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "RxTx Tx complete"); 571 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_rxtxth, EVCNT_TYPE_INTR, 572 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "RxTx RxTxTH summary"); 573 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_txerr, EVCNT_TYPE_INTR, 574 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "RxTx Tx error summary"); 575 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxtx_misc, EVCNT_TYPE_INTR, 576 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "RxTx MISC summary"); 577 1.1 hsuenaga 578 1.1 hsuenaga /* Link */ 579 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_link_up, EVCNT_TYPE_MISC, 580 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "link up"); 581 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_link_down, EVCNT_TYPE_MISC, 582 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "link down"); 583 1.1 hsuenaga 584 1.1 hsuenaga /* Rx Descriptor */ 585 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_ce, EVCNT_TYPE_MISC, 586 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Rx CRC error counter"); 587 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_or, EVCNT_TYPE_MISC, 588 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Rx FIFO overrun counter"); 589 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_mf, EVCNT_TYPE_MISC, 590 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Rx too large frame counter"); 591 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_re, EVCNT_TYPE_MISC, 592 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Rx resource error counter"); 593 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_rxd_scat, EVCNT_TYPE_MISC, 594 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Rx unexpected scatter bufs"); 595 1.1 hsuenaga 596 1.1 hsuenaga /* Tx Descriptor */ 597 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_txd_lc, EVCNT_TYPE_MISC, 598 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Tx late collision counter"); 599 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_txd_rl, EVCNT_TYPE_MISC, 600 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Tx excess. collision counter"); 601 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_txd_ur, EVCNT_TYPE_MISC, 602 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Tx FIFO underrun counter"); 603 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_txd_oth, EVCNT_TYPE_MISC, 604 1.31 gutterid NULL, device_xname(sc->sc_dev), "Tx unknown error counter"); 605 1.1 hsuenaga 606 1.1 hsuenaga /* Status Registers */ 607 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_reg_pdfc, EVCNT_TYPE_MISC, 608 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Rx discard counter"); 609 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_reg_pofc, EVCNT_TYPE_MISC, 610 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Rx overrun counter"); 611 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_reg_txbadfcs, EVCNT_TYPE_MISC, 612 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Tx bad FCS counter"); 613 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_reg_txdropped, EVCNT_TYPE_MISC, 614 1.31 gutterid NULL, device_xname(sc->sc_dev), "Tx dropped counter"); 615 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_reg_lpic, EVCNT_TYPE_MISC, 616 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "LP_IDLE counter"); 617 1.1 hsuenaga 618 1.1 hsuenaga /* Device Driver Errors */ 619 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_drv_wdogsoft, EVCNT_TYPE_MISC, 620 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "watchdog timer expired"); 621 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_drv_txerr, EVCNT_TYPE_MISC, 622 1.1 hsuenaga NULL, device_xname(sc->sc_dev), "Tx descriptor alloc failed"); 623 1.1 hsuenaga #define MVXPE_QUEUE_DESC(q) "Rx success in queue " # q 624 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 625 1.1 hsuenaga static const char *rxq_desc[] = { 626 1.1 hsuenaga MVXPE_QUEUE_DESC(0), MVXPE_QUEUE_DESC(1), 627 1.1 hsuenaga MVXPE_QUEUE_DESC(2), MVXPE_QUEUE_DESC(3), 628 1.1 hsuenaga MVXPE_QUEUE_DESC(4), MVXPE_QUEUE_DESC(5), 629 1.1 hsuenaga MVXPE_QUEUE_DESC(6), MVXPE_QUEUE_DESC(7), 630 1.1 hsuenaga }; 631 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_drv_rxq[q], EVCNT_TYPE_MISC, 632 1.1 hsuenaga NULL, device_xname(sc->sc_dev), rxq_desc[q]); 633 1.1 hsuenaga } 634 1.1 hsuenaga #undef MVXPE_QUEUE_DESC 635 1.1 hsuenaga #define MVXPE_QUEUE_DESC(q) "Tx success in queue " # q 636 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 637 1.1 hsuenaga static const char *txq_desc[] = { 638 1.1 hsuenaga MVXPE_QUEUE_DESC(0), MVXPE_QUEUE_DESC(1), 639 1.1 hsuenaga MVXPE_QUEUE_DESC(2), MVXPE_QUEUE_DESC(3), 640 1.1 hsuenaga MVXPE_QUEUE_DESC(4), MVXPE_QUEUE_DESC(5), 641 1.1 hsuenaga MVXPE_QUEUE_DESC(6), MVXPE_QUEUE_DESC(7), 642 1.1 hsuenaga }; 643 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_drv_txq[q], EVCNT_TYPE_MISC, 644 1.1 hsuenaga NULL, device_xname(sc->sc_dev), txq_desc[q]); 645 1.1 hsuenaga } 646 1.1 hsuenaga #undef MVXPE_QUEUE_DESC 647 1.1 hsuenaga #define MVXPE_QUEUE_DESC(q) "Rx error in queue " # q 648 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 649 1.1 hsuenaga static const char *rxqe_desc[] = { 650 1.1 hsuenaga MVXPE_QUEUE_DESC(0), MVXPE_QUEUE_DESC(1), 651 1.1 hsuenaga MVXPE_QUEUE_DESC(2), MVXPE_QUEUE_DESC(3), 652 1.1 hsuenaga MVXPE_QUEUE_DESC(4), MVXPE_QUEUE_DESC(5), 653 1.1 hsuenaga MVXPE_QUEUE_DESC(6), MVXPE_QUEUE_DESC(7), 654 1.1 hsuenaga }; 655 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_drv_rxqe[q], EVCNT_TYPE_MISC, 656 1.1 hsuenaga NULL, device_xname(sc->sc_dev), rxqe_desc[q]); 657 1.1 hsuenaga } 658 1.1 hsuenaga #undef MVXPE_QUEUE_DESC 659 1.1 hsuenaga #define MVXPE_QUEUE_DESC(q) "Tx error in queue " # q 660 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 661 1.1 hsuenaga static const char *txqe_desc[] = { 662 1.1 hsuenaga MVXPE_QUEUE_DESC(0), MVXPE_QUEUE_DESC(1), 663 1.1 hsuenaga MVXPE_QUEUE_DESC(2), MVXPE_QUEUE_DESC(3), 664 1.1 hsuenaga MVXPE_QUEUE_DESC(4), MVXPE_QUEUE_DESC(5), 665 1.1 hsuenaga MVXPE_QUEUE_DESC(6), MVXPE_QUEUE_DESC(7), 666 1.1 hsuenaga }; 667 1.1 hsuenaga evcnt_attach_dynamic(&sc->sc_ev.ev_drv_txqe[q], EVCNT_TYPE_MISC, 668 1.1 hsuenaga NULL, device_xname(sc->sc_dev), txqe_desc[q]); 669 1.1 hsuenaga } 670 1.1 hsuenaga #undef MVXPE_QUEUE_DESC 671 1.1 hsuenaga 672 1.1 hsuenaga #endif /* MVXPE_EVENT_COUNTERS */ 673 1.1 hsuenaga return 0; 674 1.1 hsuenaga } 675 1.1 hsuenaga 676 1.1 hsuenaga STATIC void 677 1.1 hsuenaga mvxpe_sc_lock(struct mvxpe_softc *sc) 678 1.1 hsuenaga { 679 1.1 hsuenaga mutex_enter(&sc->sc_mtx); 680 1.1 hsuenaga } 681 1.1 hsuenaga 682 1.1 hsuenaga STATIC void 683 1.1 hsuenaga mvxpe_sc_unlock(struct mvxpe_softc *sc) 684 1.1 hsuenaga { 685 1.1 hsuenaga mutex_exit(&sc->sc_mtx); 686 1.1 hsuenaga } 687 1.1 hsuenaga 688 1.1 hsuenaga /* 689 1.1 hsuenaga * MII 690 1.1 hsuenaga */ 691 1.1 hsuenaga STATIC int 692 1.21 msaitoh mvxpe_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val) 693 1.1 hsuenaga { 694 1.1 hsuenaga struct mvxpe_softc *sc = device_private(dev); 695 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 696 1.21 msaitoh uint32_t smi; 697 1.21 msaitoh int i, rv = 0; 698 1.1 hsuenaga 699 1.1 hsuenaga mutex_enter(&mii_mutex); 700 1.1 hsuenaga 701 1.1 hsuenaga for (i = 0; i < MVXPE_PHY_TIMEOUT; i++) { 702 1.1 hsuenaga DELAY(1); 703 1.1 hsuenaga if (!(MVXPE_READ(sc, MVXPE_SMI) & MVXPE_SMI_BUSY)) 704 1.1 hsuenaga break; 705 1.1 hsuenaga } 706 1.1 hsuenaga if (i == MVXPE_PHY_TIMEOUT) { 707 1.1 hsuenaga aprint_error_ifnet(ifp, "SMI busy timeout\n"); 708 1.21 msaitoh rv = ETIMEDOUT; 709 1.21 msaitoh goto out; 710 1.1 hsuenaga } 711 1.1 hsuenaga 712 1.1 hsuenaga smi = 713 1.1 hsuenaga MVXPE_SMI_PHYAD(phy) | MVXPE_SMI_REGAD(reg) | MVXPE_SMI_OPCODE_READ; 714 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_SMI, smi); 715 1.1 hsuenaga 716 1.1 hsuenaga for (i = 0; i < MVXPE_PHY_TIMEOUT; i++) { 717 1.1 hsuenaga DELAY(1); 718 1.1 hsuenaga smi = MVXPE_READ(sc, MVXPE_SMI); 719 1.21 msaitoh if (smi & MVXPE_SMI_READVALID) { 720 1.21 msaitoh *val = smi & MVXPE_SMI_DATA_MASK; 721 1.1 hsuenaga break; 722 1.21 msaitoh } 723 1.1 hsuenaga } 724 1.21 msaitoh DPRINTDEV(dev, 9, "i=%d, timeout=%d\n", i, MVXPE_PHY_TIMEOUT); 725 1.21 msaitoh if (i >= MVXPE_PHY_TIMEOUT) 726 1.21 msaitoh rv = ETIMEDOUT; 727 1.1 hsuenaga 728 1.21 msaitoh out: 729 1.1 hsuenaga mutex_exit(&mii_mutex); 730 1.1 hsuenaga 731 1.21 msaitoh DPRINTDEV(dev, 9, "phy=%d, reg=%#x, val=%#hx\n", phy, reg, *val); 732 1.1 hsuenaga 733 1.21 msaitoh return rv; 734 1.1 hsuenaga } 735 1.1 hsuenaga 736 1.21 msaitoh STATIC int 737 1.21 msaitoh mvxpe_miibus_writereg(device_t dev, int phy, int reg, uint16_t val) 738 1.1 hsuenaga { 739 1.1 hsuenaga struct mvxpe_softc *sc = device_private(dev); 740 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 741 1.1 hsuenaga uint32_t smi; 742 1.21 msaitoh int i, rv = 0; 743 1.1 hsuenaga 744 1.21 msaitoh DPRINTDEV(dev, 9, "phy=%d reg=%#x val=%#hx\n", phy, reg, val); 745 1.1 hsuenaga 746 1.1 hsuenaga mutex_enter(&mii_mutex); 747 1.1 hsuenaga 748 1.1 hsuenaga for (i = 0; i < MVXPE_PHY_TIMEOUT; i++) { 749 1.1 hsuenaga DELAY(1); 750 1.1 hsuenaga if (!(MVXPE_READ(sc, MVXPE_SMI) & MVXPE_SMI_BUSY)) 751 1.1 hsuenaga break; 752 1.1 hsuenaga } 753 1.1 hsuenaga if (i == MVXPE_PHY_TIMEOUT) { 754 1.1 hsuenaga aprint_error_ifnet(ifp, "SMI busy timeout\n"); 755 1.21 msaitoh rv = ETIMEDOUT; 756 1.21 msaitoh goto out; 757 1.1 hsuenaga } 758 1.1 hsuenaga 759 1.1 hsuenaga smi = MVXPE_SMI_PHYAD(phy) | MVXPE_SMI_REGAD(reg) | 760 1.1 hsuenaga MVXPE_SMI_OPCODE_WRITE | (val & MVXPE_SMI_DATA_MASK); 761 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_SMI, smi); 762 1.1 hsuenaga 763 1.1 hsuenaga for (i = 0; i < MVXPE_PHY_TIMEOUT; i++) { 764 1.1 hsuenaga DELAY(1); 765 1.1 hsuenaga if (!(MVXPE_READ(sc, MVXPE_SMI) & MVXPE_SMI_BUSY)) 766 1.1 hsuenaga break; 767 1.1 hsuenaga } 768 1.1 hsuenaga 769 1.21 msaitoh if (i == MVXPE_PHY_TIMEOUT) { 770 1.21 msaitoh aprint_error_ifnet(ifp, "phy write timed out\n"); 771 1.21 msaitoh rv = ETIMEDOUT; 772 1.21 msaitoh } 773 1.21 msaitoh 774 1.21 msaitoh out: 775 1.1 hsuenaga mutex_exit(&mii_mutex); 776 1.1 hsuenaga 777 1.21 msaitoh return rv; 778 1.1 hsuenaga } 779 1.1 hsuenaga 780 1.1 hsuenaga STATIC void 781 1.1 hsuenaga mvxpe_miibus_statchg(struct ifnet *ifp) 782 1.1 hsuenaga { 783 1.1 hsuenaga 784 1.1 hsuenaga /* nothing to do */ 785 1.1 hsuenaga } 786 1.1 hsuenaga 787 1.1 hsuenaga /* 788 1.1 hsuenaga * Address Decoding Window 789 1.1 hsuenaga */ 790 1.1 hsuenaga STATIC void 791 1.1 hsuenaga mvxpe_wininit(struct mvxpe_softc *sc, enum marvell_tags *tags) 792 1.1 hsuenaga { 793 1.1 hsuenaga device_t pdev = device_parent(sc->sc_dev); 794 1.1 hsuenaga uint64_t base; 795 1.1 hsuenaga uint32_t en, ac, size; 796 1.1 hsuenaga int window, target, attr, rv, i; 797 1.1 hsuenaga 798 1.1 hsuenaga /* First disable all address decode windows */ 799 1.1 hsuenaga en = MVXPE_BARE_EN_MASK; 800 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_BARE, en); 801 1.1 hsuenaga 802 1.1 hsuenaga ac = 0; 803 1.1 hsuenaga for (window = 0, i = 0; 804 1.1 hsuenaga tags[i] != MARVELL_TAG_UNDEFINED && window < MVXPE_NWINDOW; i++) { 805 1.1 hsuenaga rv = marvell_winparams_by_tag(pdev, tags[i], 806 1.1 hsuenaga &target, &attr, &base, &size); 807 1.1 hsuenaga if (rv != 0 || size == 0) 808 1.1 hsuenaga continue; 809 1.1 hsuenaga 810 1.1 hsuenaga if (base > 0xffffffffULL) { 811 1.1 hsuenaga if (window >= MVXPE_NREMAP) { 812 1.1 hsuenaga aprint_error_dev(sc->sc_dev, 813 1.1 hsuenaga "can't remap window %d\n", window); 814 1.1 hsuenaga continue; 815 1.1 hsuenaga } 816 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_HA(window), 817 1.1 hsuenaga (base >> 32) & 0xffffffff); 818 1.1 hsuenaga } 819 1.1 hsuenaga 820 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_BASEADDR(window), 821 1.1 hsuenaga MVXPE_BASEADDR_TARGET(target) | 822 1.1 hsuenaga MVXPE_BASEADDR_ATTR(attr) | 823 1.1 hsuenaga MVXPE_BASEADDR_BASE(base)); 824 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_S(window), MVXPE_S_SIZE(size)); 825 1.1 hsuenaga 826 1.1 hsuenaga DPRINTSC(sc, 1, "Window %d Base 0x%016llx: Size 0x%08x\n", 827 1.1 hsuenaga window, base, size); 828 1.1 hsuenaga 829 1.1 hsuenaga en &= ~(1 << window); 830 1.1 hsuenaga /* set full access (r/w) */ 831 1.1 hsuenaga ac |= MVXPE_EPAP_EPAR(window, MVXPE_EPAP_AC_FA); 832 1.1 hsuenaga window++; 833 1.1 hsuenaga } 834 1.1 hsuenaga /* allow to access decode window */ 835 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_EPAP, ac); 836 1.1 hsuenaga 837 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_BARE, en); 838 1.1 hsuenaga } 839 1.1 hsuenaga 840 1.1 hsuenaga /* 841 1.1 hsuenaga * Device Register Initialization 842 1.1 hsuenaga * reset device registers to device driver default value. 843 1.1 hsuenaga * the device is not enabled here. 844 1.1 hsuenaga */ 845 1.1 hsuenaga STATIC int 846 1.1 hsuenaga mvxpe_initreg(struct ifnet *ifp) 847 1.1 hsuenaga { 848 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 849 1.1 hsuenaga int serdes = 0; 850 1.1 hsuenaga uint32_t reg; 851 1.1 hsuenaga int q, i; 852 1.1 hsuenaga 853 1.1 hsuenaga DPRINTIFNET(ifp, 1, "initializing device register\n"); 854 1.1 hsuenaga 855 1.1 hsuenaga /* Init TX/RX Queue Registers */ 856 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 857 1.1 hsuenaga mvxpe_rx_lockq(sc, q); 858 1.1 hsuenaga if (mvxpe_rx_queue_init(ifp, q) != 0) { 859 1.1 hsuenaga aprint_error_ifnet(ifp, 860 1.1 hsuenaga "initialization failed: cannot initialize queue\n"); 861 1.1 hsuenaga mvxpe_rx_unlockq(sc, q); 862 1.1 hsuenaga return ENOBUFS; 863 1.1 hsuenaga } 864 1.1 hsuenaga mvxpe_rx_unlockq(sc, q); 865 1.1 hsuenaga 866 1.1 hsuenaga mvxpe_tx_lockq(sc, q); 867 1.1 hsuenaga if (mvxpe_tx_queue_init(ifp, q) != 0) { 868 1.1 hsuenaga aprint_error_ifnet(ifp, 869 1.1 hsuenaga "initialization failed: cannot initialize queue\n"); 870 1.1 hsuenaga mvxpe_tx_unlockq(sc, q); 871 1.1 hsuenaga return ENOBUFS; 872 1.1 hsuenaga } 873 1.1 hsuenaga mvxpe_tx_unlockq(sc, q); 874 1.1 hsuenaga } 875 1.1 hsuenaga 876 1.1 hsuenaga /* Tx MTU Limit */ 877 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_TXMTU, MVXPE_MTU); 878 1.1 hsuenaga 879 1.36 andvar /* Check SGMII or SERDES(assume IPL/U-BOOT initialize this) */ 880 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PMACC0); 881 1.1 hsuenaga if ((reg & MVXPE_PMACC0_PORTTYPE) != 0) 882 1.1 hsuenaga serdes = 1; 883 1.1 hsuenaga 884 1.1 hsuenaga /* Ethernet Unit Control */ 885 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_EUC); 886 1.1 hsuenaga reg |= MVXPE_EUC_POLLING; 887 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_EUC, reg); 888 1.1 hsuenaga 889 1.1 hsuenaga /* Auto Negotiation */ 890 1.1 hsuenaga reg = MVXPE_PANC_MUSTSET; /* must write 0x1 */ 891 1.1 hsuenaga reg |= MVXPE_PANC_FORCELINKFAIL;/* force link state down */ 892 1.1 hsuenaga reg |= MVXPE_PANC_ANSPEEDEN; /* interface speed negotiation */ 893 1.1 hsuenaga reg |= MVXPE_PANC_ANDUPLEXEN; /* negotiate duplex mode */ 894 1.1 hsuenaga if (serdes) { 895 1.1 hsuenaga reg |= MVXPE_PANC_INBANDANEN; /* In Band negotiation */ 896 1.1 hsuenaga reg |= MVXPE_PANC_INBANDANBYPASSEN; /* bypass negotiation */ 897 1.1 hsuenaga reg |= MVXPE_PANC_SETFULLDX; /* set full-duplex on failure */ 898 1.1 hsuenaga } 899 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PANC, reg); 900 1.1 hsuenaga 901 1.1 hsuenaga /* EEE: Low Power Idle */ 902 1.1 hsuenaga reg = MVXPE_LPIC0_LILIMIT(MVXPE_LPI_LI); 903 1.1 hsuenaga reg |= MVXPE_LPIC0_TSLIMIT(MVXPE_LPI_TS); 904 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_LPIC0, reg); 905 1.1 hsuenaga 906 1.1 hsuenaga reg = MVXPE_LPIC1_TWLIMIT(MVXPE_LPI_TS); 907 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_LPIC1, reg); 908 1.1 hsuenaga 909 1.1 hsuenaga reg = MVXPE_LPIC2_MUSTSET; 910 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_LPIC2, reg); 911 1.1 hsuenaga 912 1.1 hsuenaga /* Port MAC Control set 0 */ 913 1.1 hsuenaga reg = MVXPE_PMACC0_MUSTSET; /* must write 0x1 */ 914 1.1 hsuenaga reg &= ~MVXPE_PMACC0_PORTEN; /* port is still disabled */ 915 1.1 hsuenaga reg |= MVXPE_PMACC0_FRAMESIZELIMIT(MVXPE_MRU); 916 1.1 hsuenaga if (serdes) 917 1.1 hsuenaga reg |= MVXPE_PMACC0_PORTTYPE; 918 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PMACC0, reg); 919 1.1 hsuenaga 920 1.1 hsuenaga /* Port MAC Control set 1 is only used for loop-back test */ 921 1.1 hsuenaga 922 1.24 msaitoh /* Port MAC Control set 2 */ 923 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PMACC2); 924 1.1 hsuenaga reg &= (MVXPE_PMACC2_PCSEN | MVXPE_PMACC2_RGMIIEN); 925 1.1 hsuenaga reg |= MVXPE_PMACC2_MUSTSET; 926 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PMACC2, reg); 927 1.1 hsuenaga 928 1.1 hsuenaga /* Port MAC Control set 3 is used for IPG tune */ 929 1.1 hsuenaga 930 1.1 hsuenaga /* Port MAC Control set 4 is not used */ 931 1.1 hsuenaga 932 1.12 hikaru /* Port Configuration */ 933 1.12 hikaru /* Use queue 0 only */ 934 1.12 hikaru reg = MVXPE_READ(sc, MVXPE_PXC); 935 1.12 hikaru reg &= ~(MVXPE_PXC_RXQ_MASK | MVXPE_PXC_RXQARP_MASK | 936 1.12 hikaru MVXPE_PXC_TCPQ_MASK | MVXPE_PXC_UDPQ_MASK | MVXPE_PXC_BPDUQ_MASK); 937 1.12 hikaru MVXPE_WRITE(sc, MVXPE_PXC, reg); 938 1.12 hikaru 939 1.1 hsuenaga /* Port Configuration Extended: enable Tx CRC generation */ 940 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PXCX); 941 1.1 hsuenaga reg &= ~MVXPE_PXCX_TXCRCDIS; 942 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PXCX, reg); 943 1.1 hsuenaga 944 1.1 hsuenaga /* clear MIB counter registers(clear by read) */ 945 1.1 hsuenaga for (i = 0; i < __arraycount(mvxpe_mib_list); i++) 946 1.1 hsuenaga MVXPE_READ_MIB(sc, (mvxpe_mib_list[i].regnum)); 947 1.1 hsuenaga 948 1.1 hsuenaga /* Set SDC register except IPGINT bits */ 949 1.1 hsuenaga reg = MVXPE_SDC_RXBSZ_16_64BITWORDS; 950 1.1 hsuenaga reg |= MVXPE_SDC_TXBSZ_16_64BITWORDS; 951 1.1 hsuenaga reg |= MVXPE_SDC_BLMR; 952 1.1 hsuenaga reg |= MVXPE_SDC_BLMT; 953 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_SDC, reg); 954 1.1 hsuenaga 955 1.1 hsuenaga return 0; 956 1.1 hsuenaga } 957 1.1 hsuenaga 958 1.1 hsuenaga /* 959 1.1 hsuenaga * Descriptor Ring Controls for each of queues 960 1.1 hsuenaga */ 961 1.1 hsuenaga STATIC void * 962 1.1 hsuenaga mvxpe_dma_memalloc(struct mvxpe_softc *sc, bus_dmamap_t *map, size_t size) 963 1.1 hsuenaga { 964 1.1 hsuenaga bus_dma_segment_t segs; 965 1.1 hsuenaga void *kva = NULL; 966 1.1 hsuenaga int nsegs; 967 1.1 hsuenaga 968 1.1 hsuenaga /* 969 1.1 hsuenaga * Allocate the descriptor queues. 970 1.43 andvar * struct mvxpe_ring_data contains array of descriptors per queue. 971 1.1 hsuenaga */ 972 1.1 hsuenaga if (bus_dmamem_alloc(sc->sc_dmat, 973 1.1 hsuenaga size, PAGE_SIZE, 0, &segs, 1, &nsegs, BUS_DMA_NOWAIT)) { 974 1.1 hsuenaga aprint_error_dev(sc->sc_dev, 975 1.1 hsuenaga "can't alloc device memory (%zu bytes)\n", size); 976 1.1 hsuenaga return NULL; 977 1.1 hsuenaga } 978 1.1 hsuenaga if (bus_dmamem_map(sc->sc_dmat, 979 1.1 hsuenaga &segs, nsegs, size, &kva, BUS_DMA_NOWAIT)) { 980 1.1 hsuenaga aprint_error_dev(sc->sc_dev, 981 1.1 hsuenaga "can't map dma buffers (%zu bytes)\n", size); 982 1.1 hsuenaga goto fail1; 983 1.1 hsuenaga } 984 1.1 hsuenaga 985 1.1 hsuenaga if (bus_dmamap_create(sc->sc_dmat, 986 1.1 hsuenaga size, 1, size, 0, BUS_DMA_NOWAIT, map)) { 987 1.1 hsuenaga aprint_error_dev(sc->sc_dev, "can't create dma map\n"); 988 1.1 hsuenaga goto fail2; 989 1.1 hsuenaga } 990 1.1 hsuenaga if (bus_dmamap_load(sc->sc_dmat, 991 1.1 hsuenaga *map, kva, size, NULL, BUS_DMA_NOWAIT)) { 992 1.1 hsuenaga aprint_error_dev(sc->sc_dev, "can't load dma map\n"); 993 1.1 hsuenaga goto fail3; 994 1.1 hsuenaga } 995 1.1 hsuenaga memset(kva, 0, size); 996 1.1 hsuenaga return kva; 997 1.1 hsuenaga 998 1.1 hsuenaga fail3: 999 1.1 hsuenaga bus_dmamap_destroy(sc->sc_dmat, *map); 1000 1.1 hsuenaga memset(map, 0, sizeof(*map)); 1001 1.1 hsuenaga fail2: 1002 1.1 hsuenaga bus_dmamem_unmap(sc->sc_dmat, kva, size); 1003 1.1 hsuenaga fail1: 1004 1.1 hsuenaga bus_dmamem_free(sc->sc_dmat, &segs, nsegs); 1005 1.1 hsuenaga return NULL; 1006 1.1 hsuenaga } 1007 1.1 hsuenaga 1008 1.1 hsuenaga STATIC int 1009 1.1 hsuenaga mvxpe_ring_alloc_queue(struct mvxpe_softc *sc, int q) 1010 1.1 hsuenaga { 1011 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 1012 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 1013 1.1 hsuenaga 1014 1.1 hsuenaga /* 1015 1.1 hsuenaga * MVXPE_RX_RING_CNT and MVXPE_TX_RING_CNT is a hard limit of 1016 1.1 hsuenaga * queue length. real queue length is limited by 1017 1.1 hsuenaga * sc->sc_rx_ring[q].rx_queue_len and sc->sc_tx_ring[q].tx_queue_len. 1018 1.1 hsuenaga * 1019 1.1 hsuenaga * because descriptor ring reallocation needs reprogramming of 1020 1.1 hsuenaga * DMA registers, we allocate enough descriptor for hard limit 1021 1.1 hsuenaga * of queue length. 1022 1.1 hsuenaga */ 1023 1.1 hsuenaga rx->rx_descriptors = 1024 1.1 hsuenaga mvxpe_dma_memalloc(sc, &rx->rx_descriptors_map, 1025 1.1 hsuenaga (sizeof(struct mvxpe_rx_desc) * MVXPE_RX_RING_CNT)); 1026 1.1 hsuenaga if (rx->rx_descriptors == NULL) 1027 1.1 hsuenaga goto fail; 1028 1.1 hsuenaga 1029 1.1 hsuenaga tx->tx_descriptors = 1030 1.1 hsuenaga mvxpe_dma_memalloc(sc, &tx->tx_descriptors_map, 1031 1.1 hsuenaga (sizeof(struct mvxpe_tx_desc) * MVXPE_TX_RING_CNT)); 1032 1.1 hsuenaga if (tx->tx_descriptors == NULL) 1033 1.1 hsuenaga goto fail; 1034 1.1 hsuenaga 1035 1.1 hsuenaga return 0; 1036 1.1 hsuenaga fail: 1037 1.1 hsuenaga mvxpe_ring_dealloc_queue(sc, q); 1038 1.1 hsuenaga aprint_error_dev(sc->sc_dev, "DMA Ring buffer allocation failure.\n"); 1039 1.1 hsuenaga return ENOMEM; 1040 1.1 hsuenaga } 1041 1.1 hsuenaga 1042 1.1 hsuenaga STATIC void 1043 1.1 hsuenaga mvxpe_ring_dealloc_queue(struct mvxpe_softc *sc, int q) 1044 1.1 hsuenaga { 1045 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 1046 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 1047 1.1 hsuenaga bus_dma_segment_t *segs; 1048 1.1 hsuenaga bus_size_t size; 1049 1.1 hsuenaga void *kva; 1050 1.1 hsuenaga int nsegs; 1051 1.1 hsuenaga 1052 1.1 hsuenaga /* Rx */ 1053 1.1 hsuenaga kva = (void *)MVXPE_RX_RING_MEM_VA(sc, q); 1054 1.1 hsuenaga if (kva) { 1055 1.1 hsuenaga segs = MVXPE_RX_RING_MEM_MAP(sc, q)->dm_segs; 1056 1.1 hsuenaga nsegs = MVXPE_RX_RING_MEM_MAP(sc, q)->dm_nsegs; 1057 1.1 hsuenaga size = MVXPE_RX_RING_MEM_MAP(sc, q)->dm_mapsize; 1058 1.1 hsuenaga 1059 1.1 hsuenaga bus_dmamap_unload(sc->sc_dmat, MVXPE_RX_RING_MEM_MAP(sc, q)); 1060 1.1 hsuenaga bus_dmamap_destroy(sc->sc_dmat, MVXPE_RX_RING_MEM_MAP(sc, q)); 1061 1.1 hsuenaga bus_dmamem_unmap(sc->sc_dmat, kva, size); 1062 1.1 hsuenaga bus_dmamem_free(sc->sc_dmat, segs, nsegs); 1063 1.1 hsuenaga } 1064 1.1 hsuenaga 1065 1.1 hsuenaga /* Tx */ 1066 1.1 hsuenaga kva = (void *)MVXPE_TX_RING_MEM_VA(sc, q); 1067 1.1 hsuenaga if (kva) { 1068 1.1 hsuenaga segs = MVXPE_TX_RING_MEM_MAP(sc, q)->dm_segs; 1069 1.1 hsuenaga nsegs = MVXPE_TX_RING_MEM_MAP(sc, q)->dm_nsegs; 1070 1.1 hsuenaga size = MVXPE_TX_RING_MEM_MAP(sc, q)->dm_mapsize; 1071 1.1 hsuenaga 1072 1.1 hsuenaga bus_dmamap_unload(sc->sc_dmat, MVXPE_TX_RING_MEM_MAP(sc, q)); 1073 1.1 hsuenaga bus_dmamap_destroy(sc->sc_dmat, MVXPE_TX_RING_MEM_MAP(sc, q)); 1074 1.1 hsuenaga bus_dmamem_unmap(sc->sc_dmat, kva, size); 1075 1.1 hsuenaga bus_dmamem_free(sc->sc_dmat, segs, nsegs); 1076 1.1 hsuenaga } 1077 1.1 hsuenaga 1078 1.1 hsuenaga /* Clear doungling pointers all */ 1079 1.1 hsuenaga memset(rx, 0, sizeof(*rx)); 1080 1.1 hsuenaga memset(tx, 0, sizeof(*tx)); 1081 1.1 hsuenaga } 1082 1.1 hsuenaga 1083 1.1 hsuenaga STATIC void 1084 1.1 hsuenaga mvxpe_ring_init_queue(struct mvxpe_softc *sc, int q) 1085 1.1 hsuenaga { 1086 1.1 hsuenaga struct mvxpe_rx_desc *rxd = MVXPE_RX_RING_MEM_VA(sc, q); 1087 1.1 hsuenaga struct mvxpe_tx_desc *txd = MVXPE_TX_RING_MEM_VA(sc, q); 1088 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 1089 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 1090 1.1 hsuenaga static const int rx_default_queue_len[] = { 1091 1.1 hsuenaga MVXPE_RX_QUEUE_LIMIT_0, MVXPE_RX_QUEUE_LIMIT_1, 1092 1.1 hsuenaga MVXPE_RX_QUEUE_LIMIT_2, MVXPE_RX_QUEUE_LIMIT_3, 1093 1.1 hsuenaga MVXPE_RX_QUEUE_LIMIT_4, MVXPE_RX_QUEUE_LIMIT_5, 1094 1.1 hsuenaga MVXPE_RX_QUEUE_LIMIT_6, MVXPE_RX_QUEUE_LIMIT_7, 1095 1.1 hsuenaga }; 1096 1.1 hsuenaga static const int tx_default_queue_len[] = { 1097 1.1 hsuenaga MVXPE_TX_QUEUE_LIMIT_0, MVXPE_TX_QUEUE_LIMIT_1, 1098 1.1 hsuenaga MVXPE_TX_QUEUE_LIMIT_2, MVXPE_TX_QUEUE_LIMIT_3, 1099 1.1 hsuenaga MVXPE_TX_QUEUE_LIMIT_4, MVXPE_TX_QUEUE_LIMIT_5, 1100 1.1 hsuenaga MVXPE_TX_QUEUE_LIMIT_6, MVXPE_TX_QUEUE_LIMIT_7, 1101 1.1 hsuenaga }; 1102 1.1 hsuenaga extern uint32_t mvTclk; 1103 1.1 hsuenaga int i; 1104 1.1 hsuenaga 1105 1.1 hsuenaga /* Rx handle */ 1106 1.1 hsuenaga for (i = 0; i < MVXPE_RX_RING_CNT; i++) { 1107 1.1 hsuenaga MVXPE_RX_DESC(sc, q, i) = &rxd[i]; 1108 1.1 hsuenaga MVXPE_RX_DESC_OFF(sc, q, i) = sizeof(struct mvxpe_rx_desc) * i; 1109 1.1 hsuenaga MVXPE_RX_PKTBUF(sc, q, i) = NULL; 1110 1.1 hsuenaga } 1111 1.1 hsuenaga mutex_init(&rx->rx_ring_mtx, MUTEX_DEFAULT, IPL_NET); 1112 1.1 hsuenaga rx->rx_dma = rx->rx_cpu = 0; 1113 1.1 hsuenaga rx->rx_queue_len = rx_default_queue_len[q]; 1114 1.1 hsuenaga if (rx->rx_queue_len > MVXPE_RX_RING_CNT) 1115 1.1 hsuenaga rx->rx_queue_len = MVXPE_RX_RING_CNT; 1116 1.2 hsuenaga rx->rx_queue_th_received = rx->rx_queue_len / MVXPE_RXTH_RATIO; 1117 1.2 hsuenaga rx->rx_queue_th_free = rx->rx_queue_len / MVXPE_RXTH_REFILL_RATIO; 1118 1.1 hsuenaga rx->rx_queue_th_time = (mvTclk / 1000) / 2; /* 0.5 [ms] */ 1119 1.1 hsuenaga 1120 1.1 hsuenaga /* Tx handle */ 1121 1.1 hsuenaga for (i = 0; i < MVXPE_TX_RING_CNT; i++) { 1122 1.1 hsuenaga MVXPE_TX_DESC(sc, q, i) = &txd[i]; 1123 1.1 hsuenaga MVXPE_TX_DESC_OFF(sc, q, i) = sizeof(struct mvxpe_tx_desc) * i; 1124 1.1 hsuenaga MVXPE_TX_MBUF(sc, q, i) = NULL; 1125 1.1 hsuenaga /* Tx handle needs DMA map for busdma_load_mbuf() */ 1126 1.2 hsuenaga if (bus_dmamap_create(sc->sc_dmat, 1127 1.2 hsuenaga mvxpbm_chunk_size(sc->sc_bm), 1128 1.2 hsuenaga MVXPE_TX_SEGLIMIT, mvxpbm_chunk_size(sc->sc_bm), 0, 1129 1.24 msaitoh BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 1130 1.1 hsuenaga &MVXPE_TX_MAP(sc, q, i))) { 1131 1.1 hsuenaga aprint_error_dev(sc->sc_dev, 1132 1.1 hsuenaga "can't create dma map (tx ring %d)\n", i); 1133 1.1 hsuenaga } 1134 1.1 hsuenaga } 1135 1.1 hsuenaga mutex_init(&tx->tx_ring_mtx, MUTEX_DEFAULT, IPL_NET); 1136 1.1 hsuenaga tx->tx_dma = tx->tx_cpu = 0; 1137 1.1 hsuenaga tx->tx_queue_len = tx_default_queue_len[q]; 1138 1.1 hsuenaga if (tx->tx_queue_len > MVXPE_TX_RING_CNT) 1139 1.1 hsuenaga tx->tx_queue_len = MVXPE_TX_RING_CNT; 1140 1.25 msaitoh tx->tx_used = 0; 1141 1.2 hsuenaga tx->tx_queue_th_free = tx->tx_queue_len / MVXPE_TXTH_RATIO; 1142 1.1 hsuenaga } 1143 1.1 hsuenaga 1144 1.1 hsuenaga STATIC void 1145 1.1 hsuenaga mvxpe_ring_flush_queue(struct mvxpe_softc *sc, int q) 1146 1.1 hsuenaga { 1147 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 1148 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 1149 1.14 kiyohara struct mbuf *m; 1150 1.1 hsuenaga int i; 1151 1.1 hsuenaga 1152 1.1 hsuenaga KASSERT_RX_MTX(sc, q); 1153 1.1 hsuenaga KASSERT_TX_MTX(sc, q); 1154 1.1 hsuenaga 1155 1.1 hsuenaga /* Rx handle */ 1156 1.1 hsuenaga for (i = 0; i < MVXPE_RX_RING_CNT; i++) { 1157 1.1 hsuenaga if (MVXPE_RX_PKTBUF(sc, q, i) == NULL) 1158 1.1 hsuenaga continue; 1159 1.2 hsuenaga mvxpbm_free_chunk(MVXPE_RX_PKTBUF(sc, q, i)); 1160 1.1 hsuenaga MVXPE_RX_PKTBUF(sc, q, i) = NULL; 1161 1.1 hsuenaga } 1162 1.1 hsuenaga rx->rx_dma = rx->rx_cpu = 0; 1163 1.1 hsuenaga 1164 1.1 hsuenaga /* Tx handle */ 1165 1.1 hsuenaga for (i = 0; i < MVXPE_TX_RING_CNT; i++) { 1166 1.14 kiyohara m = MVXPE_TX_MBUF(sc, q, i); 1167 1.14 kiyohara if (m == NULL) 1168 1.1 hsuenaga continue; 1169 1.14 kiyohara MVXPE_TX_MBUF(sc, q, i) = NULL; 1170 1.14 kiyohara bus_dmamap_sync(sc->sc_dmat, 1171 1.14 kiyohara MVXPE_TX_MAP(sc, q, i), 0, m->m_pkthdr.len, 1172 1.14 kiyohara BUS_DMASYNC_POSTWRITE); 1173 1.1 hsuenaga bus_dmamap_unload(sc->sc_dmat, MVXPE_TX_MAP(sc, q, i)); 1174 1.14 kiyohara m_freem(m); 1175 1.1 hsuenaga } 1176 1.1 hsuenaga tx->tx_dma = tx->tx_cpu = 0; 1177 1.25 msaitoh tx->tx_used = 0; 1178 1.1 hsuenaga } 1179 1.1 hsuenaga 1180 1.1 hsuenaga STATIC void 1181 1.1 hsuenaga mvxpe_ring_sync_rx(struct mvxpe_softc *sc, int q, int idx, int count, int ops) 1182 1.1 hsuenaga { 1183 1.1 hsuenaga int wrap; 1184 1.1 hsuenaga 1185 1.1 hsuenaga KASSERT_RX_MTX(sc, q); 1186 1.1 hsuenaga KASSERT(count > 0 && count <= MVXPE_RX_RING_CNT); 1187 1.1 hsuenaga KASSERT(idx >= 0 && idx < MVXPE_RX_RING_CNT); 1188 1.1 hsuenaga 1189 1.1 hsuenaga wrap = (idx + count) - MVXPE_RX_RING_CNT; 1190 1.1 hsuenaga if (wrap > 0) { 1191 1.1 hsuenaga count -= wrap; 1192 1.1 hsuenaga KASSERT(count > 0); 1193 1.1 hsuenaga bus_dmamap_sync(sc->sc_dmat, MVXPE_RX_RING_MEM_MAP(sc, q), 1194 1.1 hsuenaga 0, sizeof(struct mvxpe_rx_desc) * wrap, ops); 1195 1.1 hsuenaga } 1196 1.1 hsuenaga bus_dmamap_sync(sc->sc_dmat, MVXPE_RX_RING_MEM_MAP(sc, q), 1197 1.1 hsuenaga MVXPE_RX_DESC_OFF(sc, q, idx), 1198 1.1 hsuenaga sizeof(struct mvxpe_rx_desc) * count, ops); 1199 1.1 hsuenaga } 1200 1.1 hsuenaga 1201 1.1 hsuenaga STATIC void 1202 1.1 hsuenaga mvxpe_ring_sync_tx(struct mvxpe_softc *sc, int q, int idx, int count, int ops) 1203 1.1 hsuenaga { 1204 1.1 hsuenaga int wrap = 0; 1205 1.1 hsuenaga 1206 1.1 hsuenaga KASSERT_TX_MTX(sc, q); 1207 1.1 hsuenaga KASSERT(count > 0 && count <= MVXPE_TX_RING_CNT); 1208 1.1 hsuenaga KASSERT(idx >= 0 && idx < MVXPE_TX_RING_CNT); 1209 1.1 hsuenaga 1210 1.1 hsuenaga wrap = (idx + count) - MVXPE_TX_RING_CNT; 1211 1.26 msaitoh if (wrap > 0) { 1212 1.1 hsuenaga count -= wrap; 1213 1.1 hsuenaga bus_dmamap_sync(sc->sc_dmat, MVXPE_TX_RING_MEM_MAP(sc, q), 1214 1.1 hsuenaga 0, sizeof(struct mvxpe_tx_desc) * wrap, ops); 1215 1.1 hsuenaga } 1216 1.1 hsuenaga bus_dmamap_sync(sc->sc_dmat, MVXPE_TX_RING_MEM_MAP(sc, q), 1217 1.1 hsuenaga MVXPE_TX_DESC_OFF(sc, q, idx), 1218 1.1 hsuenaga sizeof(struct mvxpe_tx_desc) * count, ops); 1219 1.1 hsuenaga } 1220 1.1 hsuenaga 1221 1.1 hsuenaga /* 1222 1.1 hsuenaga * Rx/Tx Queue Control 1223 1.1 hsuenaga */ 1224 1.1 hsuenaga STATIC int 1225 1.1 hsuenaga mvxpe_rx_queue_init(struct ifnet *ifp, int q) 1226 1.1 hsuenaga { 1227 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1228 1.1 hsuenaga uint32_t reg; 1229 1.1 hsuenaga 1230 1.1 hsuenaga KASSERT_RX_MTX(sc, q); 1231 1.1 hsuenaga KASSERT(MVXPE_RX_RING_MEM_PA(sc, q) != 0); 1232 1.1 hsuenaga 1233 1.1 hsuenaga /* descriptor address */ 1234 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXDQA(q), MVXPE_RX_RING_MEM_PA(sc, q)); 1235 1.1 hsuenaga 1236 1.1 hsuenaga /* Rx buffer size and descriptor ring size */ 1237 1.2 hsuenaga reg = MVXPE_PRXDQS_BUFFERSIZE(mvxpbm_chunk_size(sc->sc_bm) >> 3); 1238 1.1 hsuenaga reg |= MVXPE_PRXDQS_DESCRIPTORSQUEUESIZE(MVXPE_RX_RING_CNT); 1239 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXDQS(q), reg); 1240 1.1 hsuenaga DPRINTIFNET(ifp, 1, "PRXDQS(%d): %#x\n", 1241 1.1 hsuenaga q, MVXPE_READ(sc, MVXPE_PRXDQS(q))); 1242 1.1 hsuenaga 1243 1.1 hsuenaga /* Rx packet offset address */ 1244 1.2 hsuenaga reg = MVXPE_PRXC_PACKETOFFSET(mvxpbm_packet_offset(sc->sc_bm) >> 3); 1245 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXC(q), reg); 1246 1.1 hsuenaga DPRINTIFNET(ifp, 1, "PRXC(%d): %#x\n", 1247 1.1 hsuenaga q, MVXPE_READ(sc, MVXPE_PRXC(q))); 1248 1.1 hsuenaga 1249 1.2 hsuenaga /* Rx DMA SNOOP */ 1250 1.2 hsuenaga reg = MVXPE_PRXSNP_SNOOPNOOFBYTES(MVXPE_MRU); 1251 1.2 hsuenaga reg |= MVXPE_PRXSNP_L2DEPOSITNOOFBYTES(MVXPE_MRU); 1252 1.2 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXSNP(q), reg); 1253 1.2 hsuenaga 1254 1.1 hsuenaga /* if DMA is not working, register is not updated */ 1255 1.1 hsuenaga KASSERT(MVXPE_READ(sc, MVXPE_PRXDQA(q)) == MVXPE_RX_RING_MEM_PA(sc, q)); 1256 1.1 hsuenaga return 0; 1257 1.1 hsuenaga } 1258 1.1 hsuenaga 1259 1.1 hsuenaga STATIC int 1260 1.1 hsuenaga mvxpe_tx_queue_init(struct ifnet *ifp, int q) 1261 1.1 hsuenaga { 1262 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1263 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 1264 1.1 hsuenaga uint32_t reg; 1265 1.1 hsuenaga 1266 1.1 hsuenaga KASSERT_TX_MTX(sc, q); 1267 1.1 hsuenaga KASSERT(MVXPE_TX_RING_MEM_PA(sc, q) != 0); 1268 1.1 hsuenaga 1269 1.1 hsuenaga /* descriptor address */ 1270 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXDQA(q), MVXPE_TX_RING_MEM_PA(sc, q)); 1271 1.1 hsuenaga 1272 1.1 hsuenaga /* Tx threshold, and descriptor ring size */ 1273 1.1 hsuenaga reg = MVXPE_PTXDQS_TBT(tx->tx_queue_th_free); 1274 1.1 hsuenaga reg |= MVXPE_PTXDQS_DQS(MVXPE_TX_RING_CNT); 1275 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXDQS(q), reg); 1276 1.1 hsuenaga DPRINTIFNET(ifp, 1, "PTXDQS(%d): %#x\n", 1277 1.1 hsuenaga q, MVXPE_READ(sc, MVXPE_PTXDQS(q))); 1278 1.1 hsuenaga 1279 1.1 hsuenaga /* if DMA is not working, register is not updated */ 1280 1.1 hsuenaga KASSERT(MVXPE_READ(sc, MVXPE_PTXDQA(q)) == MVXPE_TX_RING_MEM_PA(sc, q)); 1281 1.1 hsuenaga return 0; 1282 1.1 hsuenaga } 1283 1.1 hsuenaga 1284 1.1 hsuenaga STATIC int 1285 1.1 hsuenaga mvxpe_rx_queue_enable(struct ifnet *ifp, int q) 1286 1.1 hsuenaga { 1287 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1288 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 1289 1.1 hsuenaga uint32_t reg; 1290 1.1 hsuenaga 1291 1.1 hsuenaga KASSERT_RX_MTX(sc, q); 1292 1.1 hsuenaga 1293 1.1 hsuenaga /* Set Rx interrupt threshold */ 1294 1.1 hsuenaga reg = MVXPE_PRXDQTH_ODT(rx->rx_queue_th_received); 1295 1.1 hsuenaga reg |= MVXPE_PRXDQTH_NODT(rx->rx_queue_th_free); 1296 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXDQTH(q), reg); 1297 1.1 hsuenaga 1298 1.1 hsuenaga reg = MVXPE_PRXITTH_RITT(rx->rx_queue_th_time); 1299 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXITTH(q), reg); 1300 1.1 hsuenaga 1301 1.1 hsuenaga /* Unmask RXTX_TH Intr. */ 1302 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PRXTXTIM); 1303 1.43 andvar reg |= MVXPE_PRXTXTI_RBICTAPQ(q); /* Rx Buffer Interrupt Coalesce */ 1304 1.43 andvar reg |= MVXPE_PRXTXTI_RDTAQ(q); /* Rx Descriptor Alert */ 1305 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg); 1306 1.1 hsuenaga 1307 1.1 hsuenaga /* Enable Rx queue */ 1308 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_RQC) & MVXPE_RQC_EN_MASK; 1309 1.1 hsuenaga reg |= MVXPE_RQC_ENQ(q); 1310 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_RQC, reg); 1311 1.1 hsuenaga 1312 1.1 hsuenaga return 0; 1313 1.1 hsuenaga } 1314 1.1 hsuenaga 1315 1.1 hsuenaga STATIC int 1316 1.1 hsuenaga mvxpe_tx_queue_enable(struct ifnet *ifp, int q) 1317 1.1 hsuenaga { 1318 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1319 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 1320 1.1 hsuenaga uint32_t reg; 1321 1.1 hsuenaga 1322 1.1 hsuenaga KASSERT_TX_MTX(sc, q); 1323 1.1 hsuenaga 1324 1.1 hsuenaga /* Set Tx interrupt threshold */ 1325 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PTXDQS(q)); 1326 1.1 hsuenaga reg &= ~MVXPE_PTXDQS_TBT_MASK; /* keep queue size */ 1327 1.1 hsuenaga reg |= MVXPE_PTXDQS_TBT(tx->tx_queue_th_free); 1328 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXDQS(q), reg); 1329 1.1 hsuenaga 1330 1.1 hsuenaga /* Unmask RXTX_TH Intr. */ 1331 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PRXTXTIM); 1332 1.1 hsuenaga reg |= MVXPE_PRXTXTI_TBTCQ(q); /* Tx Threshold cross */ 1333 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg); 1334 1.1 hsuenaga 1335 1.1 hsuenaga /* Don't update MVXPE_TQC here, there is no packet yet. */ 1336 1.1 hsuenaga return 0; 1337 1.1 hsuenaga } 1338 1.1 hsuenaga 1339 1.1 hsuenaga STATIC void 1340 1.1 hsuenaga mvxpe_rx_lockq(struct mvxpe_softc *sc, int q) 1341 1.1 hsuenaga { 1342 1.1 hsuenaga KASSERT(q >= 0); 1343 1.1 hsuenaga KASSERT(q < MVXPE_QUEUE_SIZE); 1344 1.1 hsuenaga mutex_enter(&sc->sc_rx_ring[q].rx_ring_mtx); 1345 1.1 hsuenaga } 1346 1.1 hsuenaga 1347 1.1 hsuenaga STATIC void 1348 1.1 hsuenaga mvxpe_rx_unlockq(struct mvxpe_softc *sc, int q) 1349 1.1 hsuenaga { 1350 1.1 hsuenaga KASSERT(q >= 0); 1351 1.1 hsuenaga KASSERT(q < MVXPE_QUEUE_SIZE); 1352 1.1 hsuenaga mutex_exit(&sc->sc_rx_ring[q].rx_ring_mtx); 1353 1.1 hsuenaga } 1354 1.1 hsuenaga 1355 1.1 hsuenaga STATIC void 1356 1.1 hsuenaga mvxpe_tx_lockq(struct mvxpe_softc *sc, int q) 1357 1.1 hsuenaga { 1358 1.1 hsuenaga KASSERT(q >= 0); 1359 1.1 hsuenaga KASSERT(q < MVXPE_QUEUE_SIZE); 1360 1.1 hsuenaga mutex_enter(&sc->sc_tx_ring[q].tx_ring_mtx); 1361 1.1 hsuenaga } 1362 1.1 hsuenaga 1363 1.1 hsuenaga STATIC void 1364 1.1 hsuenaga mvxpe_tx_unlockq(struct mvxpe_softc *sc, int q) 1365 1.1 hsuenaga { 1366 1.1 hsuenaga KASSERT(q >= 0); 1367 1.1 hsuenaga KASSERT(q < MVXPE_QUEUE_SIZE); 1368 1.1 hsuenaga mutex_exit(&sc->sc_tx_ring[q].tx_ring_mtx); 1369 1.1 hsuenaga } 1370 1.1 hsuenaga 1371 1.1 hsuenaga /* 1372 1.1 hsuenaga * Interrupt Handlers 1373 1.1 hsuenaga */ 1374 1.1 hsuenaga STATIC void 1375 1.1 hsuenaga mvxpe_disable_intr(struct mvxpe_softc *sc) 1376 1.1 hsuenaga { 1377 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_EUIM, 0); 1378 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_EUIC, 0); 1379 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXTIM, 0); 1380 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXTIC, 0); 1381 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXIM, 0); 1382 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXIC, 0); 1383 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PMIM, 0); 1384 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PMIC, 0); 1385 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PIE, 0); 1386 1.1 hsuenaga } 1387 1.1 hsuenaga 1388 1.1 hsuenaga STATIC void 1389 1.1 hsuenaga mvxpe_enable_intr(struct mvxpe_softc *sc) 1390 1.1 hsuenaga { 1391 1.1 hsuenaga uint32_t reg; 1392 1.1 hsuenaga 1393 1.1 hsuenaga /* Enable Port MISC Intr. (via RXTX_TH_Summary bit) */ 1394 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PMIM); 1395 1.1 hsuenaga reg |= MVXPE_PMI_PHYSTATUSCHNG; 1396 1.1 hsuenaga reg |= MVXPE_PMI_LINKCHANGE; 1397 1.1 hsuenaga reg |= MVXPE_PMI_IAE; 1398 1.1 hsuenaga reg |= MVXPE_PMI_RXOVERRUN; 1399 1.1 hsuenaga reg |= MVXPE_PMI_RXCRCERROR; 1400 1.1 hsuenaga reg |= MVXPE_PMI_RXLARGEPACKET; 1401 1.1 hsuenaga reg |= MVXPE_PMI_TXUNDRN; 1402 1.6 hikaru #if 0 1403 1.6 hikaru /* 1404 1.6 hikaru * The device may raise false interrupts for SERDES even if the device 1405 1.6 hikaru * is not configured to use SERDES connection. 1406 1.6 hikaru */ 1407 1.6 hikaru reg |= MVXPE_PMI_PRBSERROR; 1408 1.6 hikaru reg |= MVXPE_PMI_SRSE; 1409 1.6 hikaru #else 1410 1.6 hikaru reg &= ~MVXPE_PMI_PRBSERROR; 1411 1.6 hikaru reg &= ~MVXPE_PMI_SRSE; 1412 1.6 hikaru #endif 1413 1.1 hsuenaga reg |= MVXPE_PMI_TREQ_MASK; 1414 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PMIM, reg); 1415 1.1 hsuenaga 1416 1.1 hsuenaga /* Enable Summary Bit to check all interrupt cause. */ 1417 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PRXTXTIM); 1418 1.1 hsuenaga reg |= MVXPE_PRXTXTI_PMISCICSUMMARY; 1419 1.1 hsuenaga reg |= MVXPE_PRXTXTI_PTXERRORSUMMARY; 1420 1.1 hsuenaga reg |= MVXPE_PRXTXTI_PRXTXICSUMMARY; 1421 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg); 1422 1.1 hsuenaga 1423 1.1 hsuenaga /* Enable All Queue Interrupt */ 1424 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PIE); 1425 1.1 hsuenaga reg |= MVXPE_PIE_RXPKTINTRPTENB_MASK; 1426 1.1 hsuenaga reg |= MVXPE_PIE_TXPKTINTRPTENB_MASK; 1427 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PIE, reg); 1428 1.1 hsuenaga } 1429 1.1 hsuenaga 1430 1.1 hsuenaga STATIC int 1431 1.1 hsuenaga mvxpe_rxtxth_intr(void *arg) 1432 1.1 hsuenaga { 1433 1.1 hsuenaga struct mvxpe_softc *sc = arg; 1434 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1435 1.2 hsuenaga uint32_t ic, queues, datum = 0; 1436 1.1 hsuenaga 1437 1.1 hsuenaga DPRINTSC(sc, 2, "got RXTX_TH_Intr\n"); 1438 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_i_rxtxth); 1439 1.1 hsuenaga 1440 1.1 hsuenaga mvxpe_sc_lock(sc); 1441 1.2 hsuenaga ic = MVXPE_READ(sc, MVXPE_PRXTXTIC); 1442 1.4 hikaru if (ic == 0) { 1443 1.4 hikaru mvxpe_sc_unlock(sc); 1444 1.2 hsuenaga return 0; 1445 1.4 hikaru } 1446 1.2 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXTIC, ~ic); 1447 1.2 hsuenaga datum = datum ^ ic; 1448 1.1 hsuenaga 1449 1.2 hsuenaga DPRINTIFNET(ifp, 2, "PRXTXTIC: %#x\n", ic); 1450 1.1 hsuenaga 1451 1.40 andvar /* ack maintenance interrupt first */ 1452 1.2 hsuenaga if (ic & MVXPE_PRXTXTI_PTXERRORSUMMARY) { 1453 1.2 hsuenaga DPRINTIFNET(ifp, 1, "PRXTXTIC: +PTXERRORSUMMARY\n"); 1454 1.2 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtxth_txerr); 1455 1.2 hsuenaga } 1456 1.2 hsuenaga if ((ic & MVXPE_PRXTXTI_PMISCICSUMMARY)) { 1457 1.2 hsuenaga DPRINTIFNET(ifp, 2, "PTXTXTIC: +PMISCICSUMMARY\n"); 1458 1.2 hsuenaga mvxpe_misc_intr(sc); 1459 1.2 hsuenaga } 1460 1.2 hsuenaga if (ic & MVXPE_PRXTXTI_PRXTXICSUMMARY) { 1461 1.2 hsuenaga DPRINTIFNET(ifp, 2, "PTXTXTIC: +PRXTXICSUMMARY\n"); 1462 1.2 hsuenaga mvxpe_rxtx_intr(sc); 1463 1.2 hsuenaga } 1464 1.4 hikaru if (!(ifp->if_flags & IFF_RUNNING)) { 1465 1.4 hikaru mvxpe_sc_unlock(sc); 1466 1.2 hsuenaga return 1; 1467 1.4 hikaru } 1468 1.2 hsuenaga 1469 1.2 hsuenaga /* RxTxTH interrupt */ 1470 1.2 hsuenaga queues = MVXPE_PRXTXTI_GET_RBICTAPQ(ic); 1471 1.2 hsuenaga if (queues) { 1472 1.2 hsuenaga DPRINTIFNET(ifp, 2, "PRXTXTIC: +RXEOF\n"); 1473 1.2 hsuenaga mvxpe_rx(sc, queues); 1474 1.2 hsuenaga } 1475 1.2 hsuenaga queues = MVXPE_PRXTXTI_GET_TBTCQ(ic); 1476 1.2 hsuenaga if (queues) { 1477 1.2 hsuenaga DPRINTIFNET(ifp, 2, "PRXTXTIC: +TBTCQ\n"); 1478 1.2 hsuenaga mvxpe_tx_complete(sc, queues); 1479 1.2 hsuenaga } 1480 1.2 hsuenaga queues = MVXPE_PRXTXTI_GET_RDTAQ(ic); 1481 1.2 hsuenaga if (queues) { 1482 1.2 hsuenaga DPRINTIFNET(ifp, 2, "PRXTXTIC: +RDTAQ\n"); 1483 1.2 hsuenaga mvxpe_rx_refill(sc, queues); 1484 1.1 hsuenaga } 1485 1.1 hsuenaga mvxpe_sc_unlock(sc); 1486 1.1 hsuenaga 1487 1.16 ozaki if_schedule_deferred_start(ifp); 1488 1.1 hsuenaga 1489 1.1 hsuenaga rnd_add_uint32(&sc->sc_rnd_source, datum); 1490 1.1 hsuenaga 1491 1.2 hsuenaga return 1; 1492 1.1 hsuenaga } 1493 1.1 hsuenaga 1494 1.1 hsuenaga STATIC int 1495 1.1 hsuenaga mvxpe_misc_intr(void *arg) 1496 1.1 hsuenaga { 1497 1.1 hsuenaga struct mvxpe_softc *sc = arg; 1498 1.1 hsuenaga #ifdef MVXPE_DEBUG 1499 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1500 1.1 hsuenaga #endif 1501 1.1 hsuenaga uint32_t ic; 1502 1.1 hsuenaga uint32_t datum = 0; 1503 1.1 hsuenaga int claimed = 0; 1504 1.1 hsuenaga 1505 1.1 hsuenaga DPRINTSC(sc, 2, "got MISC_INTR\n"); 1506 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_i_misc); 1507 1.1 hsuenaga 1508 1.1 hsuenaga KASSERT_SC_MTX(sc); 1509 1.1 hsuenaga 1510 1.1 hsuenaga for (;;) { 1511 1.1 hsuenaga ic = MVXPE_READ(sc, MVXPE_PMIC); 1512 1.1 hsuenaga ic &= MVXPE_READ(sc, MVXPE_PMIM); 1513 1.1 hsuenaga if (ic == 0) 1514 1.1 hsuenaga break; 1515 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PMIC, ~ic); 1516 1.1 hsuenaga datum = datum ^ ic; 1517 1.1 hsuenaga claimed = 1; 1518 1.1 hsuenaga 1519 1.1 hsuenaga DPRINTIFNET(ifp, 2, "PMIC=%#x\n", ic); 1520 1.1 hsuenaga if (ic & MVXPE_PMI_PHYSTATUSCHNG) { 1521 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+PHYSTATUSCHNG\n"); 1522 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_phystatuschng); 1523 1.1 hsuenaga } 1524 1.1 hsuenaga if (ic & MVXPE_PMI_LINKCHANGE) { 1525 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+LINKCHANGE\n"); 1526 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_linkchange); 1527 1.1 hsuenaga mvxpe_linkupdate(sc); 1528 1.1 hsuenaga } 1529 1.1 hsuenaga if (ic & MVXPE_PMI_IAE) { 1530 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+IAE\n"); 1531 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_iae); 1532 1.1 hsuenaga } 1533 1.1 hsuenaga if (ic & MVXPE_PMI_RXOVERRUN) { 1534 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+RXOVERRUN\n"); 1535 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_rxoverrun); 1536 1.1 hsuenaga } 1537 1.1 hsuenaga if (ic & MVXPE_PMI_RXCRCERROR) { 1538 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+RXCRCERROR\n"); 1539 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_rxcrc); 1540 1.1 hsuenaga } 1541 1.1 hsuenaga if (ic & MVXPE_PMI_RXLARGEPACKET) { 1542 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+RXLARGEPACKET\n"); 1543 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_rxlargepacket); 1544 1.1 hsuenaga } 1545 1.1 hsuenaga if (ic & MVXPE_PMI_TXUNDRN) { 1546 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+TXUNDRN\n"); 1547 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_txunderrun); 1548 1.1 hsuenaga } 1549 1.1 hsuenaga if (ic & MVXPE_PMI_PRBSERROR) { 1550 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+PRBSERROR\n"); 1551 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_prbserr); 1552 1.1 hsuenaga } 1553 1.1 hsuenaga if (ic & MVXPE_PMI_TREQ_MASK) { 1554 1.1 hsuenaga DPRINTIFNET(ifp, 2, "+TREQ\n"); 1555 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_misc_txreq); 1556 1.1 hsuenaga } 1557 1.1 hsuenaga } 1558 1.1 hsuenaga if (datum) 1559 1.1 hsuenaga rnd_add_uint32(&sc->sc_rnd_source, datum); 1560 1.1 hsuenaga 1561 1.1 hsuenaga return claimed; 1562 1.1 hsuenaga } 1563 1.1 hsuenaga 1564 1.1 hsuenaga STATIC int 1565 1.1 hsuenaga mvxpe_rxtx_intr(void *arg) 1566 1.1 hsuenaga { 1567 1.1 hsuenaga struct mvxpe_softc *sc = arg; 1568 1.1 hsuenaga #ifdef MVXPE_DEBUG 1569 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1570 1.1 hsuenaga #endif 1571 1.1 hsuenaga uint32_t datum = 0; 1572 1.1 hsuenaga uint32_t prxtxic; 1573 1.1 hsuenaga int claimed = 0; 1574 1.1 hsuenaga 1575 1.1 hsuenaga DPRINTSC(sc, 2, "got RXTX_Intr\n"); 1576 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_i_rxtx); 1577 1.1 hsuenaga 1578 1.1 hsuenaga KASSERT_SC_MTX(sc); 1579 1.1 hsuenaga 1580 1.1 hsuenaga for (;;) { 1581 1.1 hsuenaga prxtxic = MVXPE_READ(sc, MVXPE_PRXTXIC); 1582 1.1 hsuenaga prxtxic &= MVXPE_READ(sc, MVXPE_PRXTXIM); 1583 1.1 hsuenaga if (prxtxic == 0) 1584 1.1 hsuenaga break; 1585 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXIC, ~prxtxic); 1586 1.1 hsuenaga datum = datum ^ prxtxic; 1587 1.1 hsuenaga claimed = 1; 1588 1.1 hsuenaga 1589 1.1 hsuenaga DPRINTSC(sc, 2, "PRXTXIC: %#x\n", prxtxic); 1590 1.1 hsuenaga 1591 1.1 hsuenaga if (prxtxic & MVXPE_PRXTXI_RREQ_MASK) { 1592 1.1 hsuenaga DPRINTIFNET(ifp, 1, "Rx Resource Error.\n"); 1593 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_rreq); 1594 1.1 hsuenaga } 1595 1.1 hsuenaga if (prxtxic & MVXPE_PRXTXI_RPQ_MASK) { 1596 1.1 hsuenaga DPRINTIFNET(ifp, 1, "Rx Packet in Queue.\n"); 1597 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_rpq); 1598 1.1 hsuenaga } 1599 1.1 hsuenaga if (prxtxic & MVXPE_PRXTXI_TBRQ_MASK) { 1600 1.1 hsuenaga DPRINTIFNET(ifp, 1, "Tx Buffer Return.\n"); 1601 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_tbrq); 1602 1.1 hsuenaga } 1603 1.1 hsuenaga if (prxtxic & MVXPE_PRXTXI_PRXTXTHICSUMMARY) { 1604 1.37 msaitoh DPRINTIFNET(ifp, 1, "PRXTXTHIC Summary\n"); 1605 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_rxtxth); 1606 1.1 hsuenaga } 1607 1.1 hsuenaga if (prxtxic & MVXPE_PRXTXI_PTXERRORSUMMARY) { 1608 1.37 msaitoh DPRINTIFNET(ifp, 1, "PTXERROR Summary\n"); 1609 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_txerr); 1610 1.1 hsuenaga } 1611 1.1 hsuenaga if (prxtxic & MVXPE_PRXTXI_PMISCICSUMMARY) { 1612 1.37 msaitoh DPRINTIFNET(ifp, 1, "PMISCIC Summary\n"); 1613 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxtx_misc); 1614 1.1 hsuenaga } 1615 1.1 hsuenaga } 1616 1.1 hsuenaga if (datum) 1617 1.1 hsuenaga rnd_add_uint32(&sc->sc_rnd_source, datum); 1618 1.1 hsuenaga 1619 1.1 hsuenaga return claimed; 1620 1.1 hsuenaga } 1621 1.1 hsuenaga 1622 1.1 hsuenaga STATIC void 1623 1.1 hsuenaga mvxpe_tick(void *arg) 1624 1.1 hsuenaga { 1625 1.1 hsuenaga struct mvxpe_softc *sc = arg; 1626 1.1 hsuenaga struct mii_data *mii = &sc->sc_mii; 1627 1.1 hsuenaga 1628 1.1 hsuenaga mvxpe_sc_lock(sc); 1629 1.1 hsuenaga 1630 1.1 hsuenaga mii_tick(mii); 1631 1.1 hsuenaga mii_pollstat(&sc->sc_mii); 1632 1.1 hsuenaga 1633 1.15 skrll /* read mib registers(clear by read) */ 1634 1.1 hsuenaga mvxpe_update_mib(sc); 1635 1.1 hsuenaga 1636 1.1 hsuenaga /* read counter registers(clear by read) */ 1637 1.1 hsuenaga MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_pdfc, 1638 1.1 hsuenaga MVXPE_READ(sc, MVXPE_PDFC)); 1639 1.1 hsuenaga MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_pofc, 1640 1.1 hsuenaga MVXPE_READ(sc, MVXPE_POFC)); 1641 1.1 hsuenaga MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_txbadfcs, 1642 1.1 hsuenaga MVXPE_READ(sc, MVXPE_TXBADFCS)); 1643 1.1 hsuenaga MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_txdropped, 1644 1.1 hsuenaga MVXPE_READ(sc, MVXPE_TXDROPPED)); 1645 1.1 hsuenaga MVXPE_EVCNT_ADD(&sc->sc_ev.ev_reg_lpic, 1646 1.1 hsuenaga MVXPE_READ(sc, MVXPE_LPIC)); 1647 1.1 hsuenaga 1648 1.1 hsuenaga mvxpe_sc_unlock(sc); 1649 1.1 hsuenaga 1650 1.1 hsuenaga callout_schedule(&sc->sc_tick_ch, hz); 1651 1.1 hsuenaga } 1652 1.1 hsuenaga 1653 1.1 hsuenaga 1654 1.1 hsuenaga /* 1655 1.1 hsuenaga * struct ifnet and mii callbacks 1656 1.1 hsuenaga */ 1657 1.1 hsuenaga STATIC void 1658 1.1 hsuenaga mvxpe_start(struct ifnet *ifp) 1659 1.1 hsuenaga { 1660 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1661 1.1 hsuenaga struct mbuf *m; 1662 1.1 hsuenaga int q; 1663 1.1 hsuenaga 1664 1.24 msaitoh if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) { 1665 1.1 hsuenaga DPRINTIFNET(ifp, 1, "not running\n"); 1666 1.1 hsuenaga return; 1667 1.1 hsuenaga } 1668 1.1 hsuenaga 1669 1.1 hsuenaga mvxpe_sc_lock(sc); 1670 1.1 hsuenaga if (!MVXPE_IS_LINKUP(sc)) { 1671 1.1 hsuenaga /* If Link is DOWN, can't start TX */ 1672 1.1 hsuenaga DPRINTIFNET(ifp, 1, "link fail\n"); 1673 1.1 hsuenaga for (;;) { 1674 1.1 hsuenaga /* 1675 1.1 hsuenaga * discard stale packets all. 1676 1.1 hsuenaga * these may confuse DAD, ARP or timer based protocols. 1677 1.1 hsuenaga */ 1678 1.1 hsuenaga IFQ_DEQUEUE(&ifp->if_snd, m); 1679 1.1 hsuenaga if (m == NULL) 1680 1.1 hsuenaga break; 1681 1.1 hsuenaga m_freem(m); 1682 1.1 hsuenaga } 1683 1.1 hsuenaga mvxpe_sc_unlock(sc); 1684 1.1 hsuenaga return; 1685 1.1 hsuenaga } 1686 1.1 hsuenaga for (;;) { 1687 1.1 hsuenaga /* 1688 1.1 hsuenaga * don't use IFQ_POLL(). 1689 1.1 hsuenaga * there is lock problem between IFQ_POLL and IFQ_DEQUEUE 1690 1.1 hsuenaga * on SMP enabled networking stack. 1691 1.24 msaitoh */ 1692 1.1 hsuenaga IFQ_DEQUEUE(&ifp->if_snd, m); 1693 1.1 hsuenaga if (m == NULL) 1694 1.1 hsuenaga break; 1695 1.1 hsuenaga 1696 1.1 hsuenaga q = mvxpe_tx_queue_select(sc, m); 1697 1.1 hsuenaga if (q < 0) 1698 1.1 hsuenaga break; 1699 1.1 hsuenaga /* mutex is held in mvxpe_tx_queue_select() */ 1700 1.1 hsuenaga 1701 1.1 hsuenaga if (mvxpe_tx_queue(sc, m, q) != 0) { 1702 1.1 hsuenaga DPRINTIFNET(ifp, 1, "cannot add packet to tx ring\n"); 1703 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_txerr); 1704 1.1 hsuenaga mvxpe_tx_unlockq(sc, q); 1705 1.1 hsuenaga break; 1706 1.1 hsuenaga } 1707 1.1 hsuenaga mvxpe_tx_unlockq(sc, q); 1708 1.2 hsuenaga KASSERT(sc->sc_tx_ring[q].tx_used >= 0); 1709 1.2 hsuenaga KASSERT(sc->sc_tx_ring[q].tx_used <= 1710 1.1 hsuenaga sc->sc_tx_ring[q].tx_queue_len); 1711 1.1 hsuenaga DPRINTIFNET(ifp, 1, "a packet is added to tx ring\n"); 1712 1.1 hsuenaga sc->sc_tx_pending++; 1713 1.32 skrll if_statinc(ifp, if_opackets); 1714 1.1 hsuenaga ifp->if_timer = 1; 1715 1.1 hsuenaga sc->sc_wdogsoft = 1; 1716 1.19 msaitoh bpf_mtap(ifp, m, BPF_D_OUT); 1717 1.1 hsuenaga } 1718 1.1 hsuenaga mvxpe_sc_unlock(sc); 1719 1.1 hsuenaga 1720 1.1 hsuenaga return; 1721 1.1 hsuenaga } 1722 1.1 hsuenaga 1723 1.1 hsuenaga STATIC int 1724 1.1 hsuenaga mvxpe_ioctl(struct ifnet *ifp, u_long cmd, void *data) 1725 1.1 hsuenaga { 1726 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1727 1.1 hsuenaga int error = 0; 1728 1.1 hsuenaga 1729 1.1 hsuenaga switch (cmd) { 1730 1.1 hsuenaga default: 1731 1.1 hsuenaga DPRINTIFNET(ifp, 2, "mvxpe_ioctl ETHER\n"); 1732 1.1 hsuenaga error = ether_ioctl(ifp, cmd, data); 1733 1.1 hsuenaga if (error == ENETRESET) { 1734 1.1 hsuenaga if (ifp->if_flags & IFF_RUNNING) { 1735 1.1 hsuenaga mvxpe_sc_lock(sc); 1736 1.1 hsuenaga mvxpe_filter_setup(sc); 1737 1.1 hsuenaga mvxpe_sc_unlock(sc); 1738 1.1 hsuenaga } 1739 1.1 hsuenaga error = 0; 1740 1.1 hsuenaga } 1741 1.1 hsuenaga break; 1742 1.1 hsuenaga } 1743 1.1 hsuenaga 1744 1.1 hsuenaga return error; 1745 1.1 hsuenaga } 1746 1.1 hsuenaga 1747 1.1 hsuenaga STATIC int 1748 1.1 hsuenaga mvxpe_init(struct ifnet *ifp) 1749 1.1 hsuenaga { 1750 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1751 1.1 hsuenaga struct mii_data *mii = &sc->sc_mii; 1752 1.1 hsuenaga uint32_t reg; 1753 1.1 hsuenaga int q; 1754 1.1 hsuenaga 1755 1.1 hsuenaga mvxpe_sc_lock(sc); 1756 1.1 hsuenaga 1757 1.1 hsuenaga /* Start DMA Engine */ 1758 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXINIT, 0x00000000); 1759 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXINIT, 0x00000000); 1760 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PACC, MVXPE_PACC_ACCELERATIONMODE_EDM); 1761 1.1 hsuenaga 1762 1.1 hsuenaga /* Enable port */ 1763 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PMACC0); 1764 1.1 hsuenaga reg |= MVXPE_PMACC0_PORTEN; 1765 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PMACC0, reg); 1766 1.1 hsuenaga 1767 1.1 hsuenaga /* Link up */ 1768 1.1 hsuenaga mvxpe_linkup(sc); 1769 1.1 hsuenaga 1770 1.1 hsuenaga /* Enable All Queue and interrupt of each Queue */ 1771 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 1772 1.1 hsuenaga mvxpe_rx_lockq(sc, q); 1773 1.1 hsuenaga mvxpe_rx_queue_enable(ifp, q); 1774 1.2 hsuenaga mvxpe_rx_queue_refill(sc, q); 1775 1.1 hsuenaga mvxpe_rx_unlockq(sc, q); 1776 1.1 hsuenaga 1777 1.1 hsuenaga mvxpe_tx_lockq(sc, q); 1778 1.1 hsuenaga mvxpe_tx_queue_enable(ifp, q); 1779 1.1 hsuenaga mvxpe_tx_unlockq(sc, q); 1780 1.1 hsuenaga } 1781 1.1 hsuenaga 1782 1.1 hsuenaga /* Enable interrupt */ 1783 1.1 hsuenaga mvxpe_enable_intr(sc); 1784 1.1 hsuenaga 1785 1.1 hsuenaga /* Set Counter */ 1786 1.1 hsuenaga callout_schedule(&sc->sc_tick_ch, hz); 1787 1.1 hsuenaga 1788 1.1 hsuenaga /* Media check */ 1789 1.1 hsuenaga mii_mediachg(mii); 1790 1.1 hsuenaga 1791 1.1 hsuenaga ifp->if_flags |= IFF_RUNNING; 1792 1.1 hsuenaga ifp->if_flags &= ~IFF_OACTIVE; 1793 1.1 hsuenaga 1794 1.1 hsuenaga mvxpe_sc_unlock(sc); 1795 1.1 hsuenaga return 0; 1796 1.1 hsuenaga } 1797 1.1 hsuenaga 1798 1.1 hsuenaga /* ARGSUSED */ 1799 1.1 hsuenaga STATIC void 1800 1.1 hsuenaga mvxpe_stop(struct ifnet *ifp, int disable) 1801 1.1 hsuenaga { 1802 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1803 1.1 hsuenaga uint32_t reg; 1804 1.1 hsuenaga int q, cnt; 1805 1.1 hsuenaga 1806 1.1 hsuenaga DPRINTIFNET(ifp, 1, "stop device dma and interrupts.\n"); 1807 1.1 hsuenaga 1808 1.1 hsuenaga mvxpe_sc_lock(sc); 1809 1.1 hsuenaga 1810 1.1 hsuenaga callout_stop(&sc->sc_tick_ch); 1811 1.1 hsuenaga 1812 1.1 hsuenaga /* Link down */ 1813 1.1 hsuenaga mvxpe_linkdown(sc); 1814 1.1 hsuenaga 1815 1.1 hsuenaga /* Disable Rx interrupt */ 1816 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PIE); 1817 1.1 hsuenaga reg &= ~MVXPE_PIE_RXPKTINTRPTENB_MASK; 1818 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PIE, reg); 1819 1.1 hsuenaga 1820 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PRXTXTIM); 1821 1.1 hsuenaga reg &= ~MVXPE_PRXTXTI_RBICTAPQ_MASK; 1822 1.1 hsuenaga reg &= ~MVXPE_PRXTXTI_RDTAQ_MASK; 1823 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg); 1824 1.1 hsuenaga 1825 1.1 hsuenaga /* Wait for all Rx activity to terminate. */ 1826 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_RQC) & MVXPE_RQC_EN_MASK; 1827 1.1 hsuenaga reg = MVXPE_RQC_DIS(reg); 1828 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_RQC, reg); 1829 1.1 hsuenaga cnt = 0; 1830 1.1 hsuenaga do { 1831 1.1 hsuenaga if (cnt >= RX_DISABLE_TIMEOUT) { 1832 1.1 hsuenaga aprint_error_ifnet(ifp, 1833 1.1 hsuenaga "timeout for RX stopped. rqc 0x%x\n", reg); 1834 1.1 hsuenaga break; 1835 1.1 hsuenaga } 1836 1.1 hsuenaga cnt++; 1837 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_RQC); 1838 1.1 hsuenaga } while (reg & MVXPE_RQC_EN_MASK); 1839 1.1 hsuenaga 1840 1.42 andvar /* Wait for all Tx activity to terminate. */ 1841 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PIE); 1842 1.1 hsuenaga reg &= ~MVXPE_PIE_TXPKTINTRPTENB_MASK; 1843 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PIE, reg); 1844 1.1 hsuenaga 1845 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PRXTXTIM); 1846 1.1 hsuenaga reg &= ~MVXPE_PRXTXTI_TBTCQ_MASK; 1847 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXTXTIM, reg); 1848 1.1 hsuenaga 1849 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_TQC) & MVXPE_TQC_EN_MASK; 1850 1.1 hsuenaga reg = MVXPE_TQC_DIS(reg); 1851 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_TQC, reg); 1852 1.1 hsuenaga cnt = 0; 1853 1.1 hsuenaga do { 1854 1.1 hsuenaga if (cnt >= TX_DISABLE_TIMEOUT) { 1855 1.1 hsuenaga aprint_error_ifnet(ifp, 1856 1.1 hsuenaga "timeout for TX stopped. tqc 0x%x\n", reg); 1857 1.1 hsuenaga break; 1858 1.1 hsuenaga } 1859 1.1 hsuenaga cnt++; 1860 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_TQC); 1861 1.1 hsuenaga } while (reg & MVXPE_TQC_EN_MASK); 1862 1.1 hsuenaga 1863 1.1 hsuenaga /* Wait for all Tx FIFO is empty */ 1864 1.1 hsuenaga cnt = 0; 1865 1.1 hsuenaga do { 1866 1.1 hsuenaga if (cnt >= TX_FIFO_EMPTY_TIMEOUT) { 1867 1.1 hsuenaga aprint_error_ifnet(ifp, 1868 1.1 hsuenaga "timeout for TX FIFO drained. ps0 0x%x\n", reg); 1869 1.1 hsuenaga break; 1870 1.1 hsuenaga } 1871 1.1 hsuenaga cnt++; 1872 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PS0); 1873 1.1 hsuenaga } while (!(reg & MVXPE_PS0_TXFIFOEMP) && (reg & MVXPE_PS0_TXINPROG)); 1874 1.1 hsuenaga 1875 1.1 hsuenaga /* Reset the MAC Port Enable bit */ 1876 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PMACC0); 1877 1.1 hsuenaga reg &= ~MVXPE_PMACC0_PORTEN; 1878 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PMACC0, reg); 1879 1.1 hsuenaga 1880 1.1 hsuenaga /* Disable each of queue */ 1881 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 1882 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 1883 1.1 hsuenaga 1884 1.1 hsuenaga mvxpe_rx_lockq(sc, q); 1885 1.1 hsuenaga mvxpe_tx_lockq(sc, q); 1886 1.1 hsuenaga 1887 1.2 hsuenaga /* Disable Rx packet buffer refill request */ 1888 1.1 hsuenaga reg = MVXPE_PRXDQTH_ODT(rx->rx_queue_th_received); 1889 1.1 hsuenaga reg |= MVXPE_PRXDQTH_NODT(0); 1890 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXITTH(q), reg); 1891 1.1 hsuenaga 1892 1.1 hsuenaga if (disable) { 1893 1.1 hsuenaga /* 1894 1.24 msaitoh * Hold Reset state of DMA Engine 1895 1.1 hsuenaga * (must write 0x0 to restart it) 1896 1.1 hsuenaga */ 1897 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXINIT, 0x00000001); 1898 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXINIT, 0x00000001); 1899 1.1 hsuenaga mvxpe_ring_flush_queue(sc, q); 1900 1.1 hsuenaga } 1901 1.1 hsuenaga 1902 1.1 hsuenaga mvxpe_tx_unlockq(sc, q); 1903 1.1 hsuenaga mvxpe_rx_unlockq(sc, q); 1904 1.1 hsuenaga } 1905 1.1 hsuenaga 1906 1.1 hsuenaga ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1907 1.1 hsuenaga 1908 1.1 hsuenaga mvxpe_sc_unlock(sc); 1909 1.1 hsuenaga } 1910 1.1 hsuenaga 1911 1.1 hsuenaga STATIC void 1912 1.1 hsuenaga mvxpe_watchdog(struct ifnet *ifp) 1913 1.1 hsuenaga { 1914 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1915 1.1 hsuenaga int q; 1916 1.1 hsuenaga 1917 1.1 hsuenaga mvxpe_sc_lock(sc); 1918 1.1 hsuenaga 1919 1.1 hsuenaga /* 1920 1.1 hsuenaga * Reclaim first as there is a possibility of losing Tx completion 1921 1.1 hsuenaga * interrupts. 1922 1.1 hsuenaga */ 1923 1.2 hsuenaga mvxpe_tx_complete(sc, 0xff); 1924 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 1925 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 1926 1.1 hsuenaga 1927 1.1 hsuenaga if (tx->tx_dma != tx->tx_cpu) { 1928 1.1 hsuenaga if (sc->sc_wdogsoft) { 1929 1.1 hsuenaga /* 1930 1.1 hsuenaga * There is race condition between CPU and DMA 1931 1.1 hsuenaga * engine. When DMA engine encounters queue end, 1932 1.1 hsuenaga * it clears MVXPE_TQC_ENQ bit. 1933 1.1 hsuenaga * XXX: how about enhanced mode? 1934 1.1 hsuenaga */ 1935 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_TQC, MVXPE_TQC_ENQ(q)); 1936 1.1 hsuenaga ifp->if_timer = 5; 1937 1.1 hsuenaga sc->sc_wdogsoft = 0; 1938 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_wdogsoft); 1939 1.1 hsuenaga } else { 1940 1.1 hsuenaga aprint_error_ifnet(ifp, "watchdog timeout\n"); 1941 1.32 skrll if_statinc(ifp, if_oerrors); 1942 1.1 hsuenaga mvxpe_linkreset(sc); 1943 1.1 hsuenaga mvxpe_sc_unlock(sc); 1944 1.1 hsuenaga 1945 1.1 hsuenaga /* trigger reinitialize sequence */ 1946 1.1 hsuenaga mvxpe_stop(ifp, 1); 1947 1.1 hsuenaga mvxpe_init(ifp); 1948 1.1 hsuenaga 1949 1.1 hsuenaga mvxpe_sc_lock(sc); 1950 1.1 hsuenaga } 1951 1.1 hsuenaga } 1952 1.1 hsuenaga } 1953 1.1 hsuenaga mvxpe_sc_unlock(sc); 1954 1.1 hsuenaga } 1955 1.1 hsuenaga 1956 1.1 hsuenaga STATIC int 1957 1.1 hsuenaga mvxpe_ifflags_cb(struct ethercom *ec) 1958 1.1 hsuenaga { 1959 1.1 hsuenaga struct ifnet *ifp = &ec->ec_if; 1960 1.1 hsuenaga struct mvxpe_softc *sc = ifp->if_softc; 1961 1.28 msaitoh u_short change = ifp->if_flags ^ sc->sc_if_flags; 1962 1.1 hsuenaga 1963 1.1 hsuenaga mvxpe_sc_lock(sc); 1964 1.1 hsuenaga 1965 1.1 hsuenaga if (change != 0) 1966 1.1 hsuenaga sc->sc_if_flags = ifp->if_flags; 1967 1.1 hsuenaga 1968 1.24 msaitoh if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) { 1969 1.1 hsuenaga mvxpe_sc_unlock(sc); 1970 1.1 hsuenaga return ENETRESET; 1971 1.1 hsuenaga } 1972 1.1 hsuenaga 1973 1.1 hsuenaga if ((change & IFF_PROMISC) != 0) 1974 1.1 hsuenaga mvxpe_filter_setup(sc); 1975 1.1 hsuenaga 1976 1.1 hsuenaga if ((change & IFF_UP) != 0) 1977 1.1 hsuenaga mvxpe_linkreset(sc); 1978 1.1 hsuenaga 1979 1.1 hsuenaga mvxpe_sc_unlock(sc); 1980 1.1 hsuenaga return 0; 1981 1.1 hsuenaga } 1982 1.1 hsuenaga 1983 1.1 hsuenaga STATIC int 1984 1.1 hsuenaga mvxpe_mediachange(struct ifnet *ifp) 1985 1.1 hsuenaga { 1986 1.1 hsuenaga return ether_mediachange(ifp); 1987 1.1 hsuenaga } 1988 1.1 hsuenaga 1989 1.1 hsuenaga STATIC void 1990 1.1 hsuenaga mvxpe_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1991 1.1 hsuenaga { 1992 1.1 hsuenaga ether_mediastatus(ifp, ifmr); 1993 1.1 hsuenaga } 1994 1.1 hsuenaga 1995 1.1 hsuenaga /* 1996 1.1 hsuenaga * Link State Notify 1997 1.1 hsuenaga */ 1998 1.1 hsuenaga STATIC void mvxpe_linkupdate(struct mvxpe_softc *sc) 1999 1.1 hsuenaga { 2000 1.1 hsuenaga int linkup; /* bool */ 2001 1.1 hsuenaga 2002 1.1 hsuenaga KASSERT_SC_MTX(sc); 2003 1.1 hsuenaga 2004 1.1 hsuenaga /* tell miibus */ 2005 1.1 hsuenaga mii_pollstat(&sc->sc_mii); 2006 1.1 hsuenaga 2007 1.1 hsuenaga /* syslog */ 2008 1.1 hsuenaga linkup = MVXPE_IS_LINKUP(sc); 2009 1.1 hsuenaga if (sc->sc_linkstate == linkup) 2010 1.1 hsuenaga return; 2011 1.1 hsuenaga 2012 1.2 hsuenaga #ifdef DEBUG 2013 1.2 hsuenaga log(LOG_DEBUG, 2014 1.2 hsuenaga "%s: link %s\n", device_xname(sc->sc_dev), linkup ? "up" : "down"); 2015 1.2 hsuenaga #endif 2016 1.1 hsuenaga if (linkup) 2017 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_link_up); 2018 1.1 hsuenaga else 2019 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_link_down); 2020 1.1 hsuenaga 2021 1.1 hsuenaga sc->sc_linkstate = linkup; 2022 1.1 hsuenaga } 2023 1.1 hsuenaga 2024 1.1 hsuenaga STATIC void 2025 1.1 hsuenaga mvxpe_linkup(struct mvxpe_softc *sc) 2026 1.1 hsuenaga { 2027 1.1 hsuenaga uint32_t reg; 2028 1.1 hsuenaga 2029 1.1 hsuenaga KASSERT_SC_MTX(sc); 2030 1.1 hsuenaga 2031 1.1 hsuenaga /* set EEE parameters */ 2032 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_LPIC1); 2033 1.1 hsuenaga if (sc->sc_cf.cf_lpi) 2034 1.1 hsuenaga reg |= MVXPE_LPIC1_LPIRE; 2035 1.1 hsuenaga else 2036 1.1 hsuenaga reg &= ~MVXPE_LPIC1_LPIRE; 2037 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_LPIC1, reg); 2038 1.1 hsuenaga 2039 1.1 hsuenaga /* set auto-negotiation parameters */ 2040 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PANC); 2041 1.1 hsuenaga if (sc->sc_cf.cf_fc) { 2042 1.1 hsuenaga /* flow control negotiation */ 2043 1.1 hsuenaga reg |= MVXPE_PANC_PAUSEADV; 2044 1.1 hsuenaga reg |= MVXPE_PANC_ANFCEN; 2045 1.1 hsuenaga } 2046 1.1 hsuenaga else { 2047 1.1 hsuenaga reg &= ~MVXPE_PANC_PAUSEADV; 2048 1.1 hsuenaga reg &= ~MVXPE_PANC_ANFCEN; 2049 1.1 hsuenaga } 2050 1.1 hsuenaga reg &= ~MVXPE_PANC_FORCELINKFAIL; 2051 1.1 hsuenaga reg &= ~MVXPE_PANC_FORCELINKPASS; 2052 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PANC, reg); 2053 1.1 hsuenaga 2054 1.1 hsuenaga mii_mediachg(&sc->sc_mii); 2055 1.1 hsuenaga } 2056 1.1 hsuenaga 2057 1.1 hsuenaga STATIC void 2058 1.1 hsuenaga mvxpe_linkdown(struct mvxpe_softc *sc) 2059 1.1 hsuenaga { 2060 1.1 hsuenaga struct mii_softc *mii; 2061 1.1 hsuenaga uint32_t reg; 2062 1.1 hsuenaga 2063 1.1 hsuenaga KASSERT_SC_MTX(sc); 2064 1.1 hsuenaga return; 2065 1.1 hsuenaga 2066 1.1 hsuenaga reg = MVXPE_READ(sc, MVXPE_PANC); 2067 1.1 hsuenaga reg |= MVXPE_PANC_FORCELINKFAIL; 2068 1.1 hsuenaga reg &= MVXPE_PANC_FORCELINKPASS; 2069 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PANC, reg); 2070 1.1 hsuenaga 2071 1.1 hsuenaga mii = LIST_FIRST(&sc->sc_mii.mii_phys); 2072 1.1 hsuenaga if (mii) 2073 1.1 hsuenaga mii_phy_down(mii); 2074 1.1 hsuenaga } 2075 1.1 hsuenaga 2076 1.1 hsuenaga STATIC void 2077 1.1 hsuenaga mvxpe_linkreset(struct mvxpe_softc *sc) 2078 1.1 hsuenaga { 2079 1.1 hsuenaga struct mii_softc *mii; 2080 1.1 hsuenaga 2081 1.1 hsuenaga KASSERT_SC_MTX(sc); 2082 1.1 hsuenaga 2083 1.1 hsuenaga /* force reset PHY first */ 2084 1.1 hsuenaga mii = LIST_FIRST(&sc->sc_mii.mii_phys); 2085 1.1 hsuenaga if (mii) 2086 1.1 hsuenaga mii_phy_reset(mii); 2087 1.1 hsuenaga 2088 1.1 hsuenaga /* reinit MAC and PHY */ 2089 1.1 hsuenaga mvxpe_linkdown(sc); 2090 1.1 hsuenaga if ((sc->sc_if_flags & IFF_UP) != 0) 2091 1.1 hsuenaga mvxpe_linkup(sc); 2092 1.1 hsuenaga } 2093 1.1 hsuenaga 2094 1.1 hsuenaga /* 2095 1.1 hsuenaga * Tx Subroutines 2096 1.1 hsuenaga */ 2097 1.1 hsuenaga STATIC int 2098 1.1 hsuenaga mvxpe_tx_queue_select(struct mvxpe_softc *sc, struct mbuf *m) 2099 1.1 hsuenaga { 2100 1.1 hsuenaga int q = 0; 2101 1.1 hsuenaga 2102 1.1 hsuenaga /* XXX: get attribute from ALTQ framework? */ 2103 1.1 hsuenaga mvxpe_tx_lockq(sc, q); 2104 1.1 hsuenaga return 0; 2105 1.1 hsuenaga } 2106 1.1 hsuenaga 2107 1.1 hsuenaga STATIC int 2108 1.1 hsuenaga mvxpe_tx_queue(struct mvxpe_softc *sc, struct mbuf *m, int q) 2109 1.1 hsuenaga { 2110 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 2111 1.1 hsuenaga bus_dma_segment_t *txsegs; 2112 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 2113 1.1 hsuenaga struct mvxpe_tx_desc *t = NULL; 2114 1.1 hsuenaga uint32_t ptxsu; 2115 1.1 hsuenaga int txnsegs; 2116 1.1 hsuenaga int start, used; 2117 1.1 hsuenaga int i; 2118 1.1 hsuenaga 2119 1.2 hsuenaga KASSERT_TX_MTX(sc, q); 2120 1.2 hsuenaga KASSERT(tx->tx_used >= 0); 2121 1.2 hsuenaga KASSERT(tx->tx_used <= tx->tx_queue_len); 2122 1.1 hsuenaga 2123 1.1 hsuenaga /* load mbuf using dmamap of 1st descriptor */ 2124 1.1 hsuenaga if (bus_dmamap_load_mbuf(sc->sc_dmat, 2125 1.1 hsuenaga MVXPE_TX_MAP(sc, q, tx->tx_cpu), m, BUS_DMA_NOWAIT) != 0) { 2126 1.1 hsuenaga m_freem(m); 2127 1.1 hsuenaga return ENOBUFS; 2128 1.1 hsuenaga } 2129 1.1 hsuenaga txsegs = MVXPE_TX_MAP(sc, q, tx->tx_cpu)->dm_segs; 2130 1.1 hsuenaga txnsegs = MVXPE_TX_MAP(sc, q, tx->tx_cpu)->dm_nsegs; 2131 1.2 hsuenaga if (txnsegs <= 0 || (txnsegs + tx->tx_used) > tx->tx_queue_len) { 2132 1.1 hsuenaga /* we have no enough descriptors or mbuf is broken */ 2133 1.1 hsuenaga bus_dmamap_unload(sc->sc_dmat, MVXPE_TX_MAP(sc, q, tx->tx_cpu)); 2134 1.1 hsuenaga m_freem(m); 2135 1.1 hsuenaga return ENOBUFS; 2136 1.1 hsuenaga } 2137 1.1 hsuenaga DPRINTSC(sc, 2, "send packet %p descriptor %d\n", m, tx->tx_cpu); 2138 1.1 hsuenaga KASSERT(MVXPE_TX_MBUF(sc, q, tx->tx_cpu) == NULL); 2139 1.1 hsuenaga 2140 1.1 hsuenaga /* remember mbuf using 1st descriptor */ 2141 1.1 hsuenaga MVXPE_TX_MBUF(sc, q, tx->tx_cpu) = m; 2142 1.1 hsuenaga bus_dmamap_sync(sc->sc_dmat, 2143 1.1 hsuenaga MVXPE_TX_MAP(sc, q, tx->tx_cpu), 0, m->m_pkthdr.len, 2144 1.14 kiyohara BUS_DMASYNC_PREWRITE); 2145 1.1 hsuenaga 2146 1.1 hsuenaga /* load to tx descriptors */ 2147 1.1 hsuenaga start = tx->tx_cpu; 2148 1.1 hsuenaga used = 0; 2149 1.1 hsuenaga for (i = 0; i < txnsegs; i++) { 2150 1.1 hsuenaga if (__predict_false(txsegs[i].ds_len == 0)) 2151 1.1 hsuenaga continue; 2152 1.1 hsuenaga t = MVXPE_TX_DESC(sc, q, tx->tx_cpu); 2153 1.1 hsuenaga t->command = 0; 2154 1.1 hsuenaga t->l4ichk = 0; 2155 1.1 hsuenaga t->flags = 0; 2156 1.1 hsuenaga if (i == 0) { 2157 1.1 hsuenaga /* 1st descriptor */ 2158 1.1 hsuenaga t->command |= MVXPE_TX_CMD_W_PACKET_OFFSET(0); 2159 1.1 hsuenaga t->command |= MVXPE_TX_CMD_PADDING; 2160 1.1 hsuenaga t->command |= MVXPE_TX_CMD_F; 2161 1.1 hsuenaga mvxpe_tx_set_csumflag(ifp, t, m); 2162 1.1 hsuenaga } 2163 1.1 hsuenaga t->bufptr = txsegs[i].ds_addr; 2164 1.1 hsuenaga t->bytecnt = txsegs[i].ds_len; 2165 1.1 hsuenaga tx->tx_cpu = tx_counter_adv(tx->tx_cpu, 1); 2166 1.2 hsuenaga tx->tx_used++; 2167 1.1 hsuenaga used++; 2168 1.1 hsuenaga } 2169 1.1 hsuenaga /* t is last descriptor here */ 2170 1.1 hsuenaga KASSERT(t != NULL); 2171 1.1 hsuenaga t->command |= MVXPE_TX_CMD_L; 2172 1.1 hsuenaga 2173 1.1 hsuenaga DPRINTSC(sc, 2, "queue %d, %d descriptors used\n", q, used); 2174 1.1 hsuenaga #ifdef MVXPE_DEBUG 2175 1.1 hsuenaga if (mvxpe_debug > 2) 2176 1.1 hsuenaga for (i = start; i <= tx->tx_cpu; i++) { 2177 1.1 hsuenaga t = MVXPE_TX_DESC(sc, q, i); 2178 1.1 hsuenaga mvxpe_dump_txdesc(t, i); 2179 1.1 hsuenaga } 2180 1.1 hsuenaga #endif 2181 1.1 hsuenaga mvxpe_ring_sync_tx(sc, q, start, used, 2182 1.24 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2183 1.1 hsuenaga 2184 1.1 hsuenaga while (used > 255) { 2185 1.1 hsuenaga ptxsu = MVXPE_PTXSU_NOWD(255); 2186 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu); 2187 1.1 hsuenaga used -= 255; 2188 1.1 hsuenaga } 2189 1.1 hsuenaga if (used > 0) { 2190 1.1 hsuenaga ptxsu = MVXPE_PTXSU_NOWD(used); 2191 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu); 2192 1.1 hsuenaga } 2193 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_TQC, MVXPE_TQC_ENQ(q)); 2194 1.1 hsuenaga 2195 1.1 hsuenaga DPRINTSC(sc, 2, 2196 1.1 hsuenaga "PTXDQA: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PTXDQA(q))); 2197 1.1 hsuenaga DPRINTSC(sc, 2, 2198 1.1 hsuenaga "PTXDQS: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PTXDQS(q))); 2199 1.1 hsuenaga DPRINTSC(sc, 2, 2200 1.1 hsuenaga "PTXS: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PTXS(q))); 2201 1.1 hsuenaga DPRINTSC(sc, 2, 2202 1.1 hsuenaga "PTXDI: queue %d, %d\n", q, MVXPE_READ(sc, MVXPE_PTXDI(q))); 2203 1.1 hsuenaga DPRINTSC(sc, 2, "TQC: %#x\n", MVXPE_READ(sc, MVXPE_TQC)); 2204 1.1 hsuenaga DPRINTIFNET(ifp, 2, 2205 1.2 hsuenaga "Tx: tx_cpu = %d, tx_dma = %d, tx_used = %d\n", 2206 1.2 hsuenaga tx->tx_cpu, tx->tx_dma, tx->tx_used); 2207 1.1 hsuenaga return 0; 2208 1.1 hsuenaga } 2209 1.1 hsuenaga 2210 1.1 hsuenaga STATIC void 2211 1.1 hsuenaga mvxpe_tx_set_csumflag(struct ifnet *ifp, 2212 1.1 hsuenaga struct mvxpe_tx_desc *t, struct mbuf *m) 2213 1.1 hsuenaga { 2214 1.2 hsuenaga struct ether_header *eh; 2215 1.1 hsuenaga int csum_flags; 2216 1.1 hsuenaga uint32_t iphl = 0, ipoff = 0; 2217 1.1 hsuenaga 2218 1.25 msaitoh csum_flags = ifp->if_csum_flags_tx & m->m_pkthdr.csum_flags; 2219 1.1 hsuenaga 2220 1.2 hsuenaga eh = mtod(m, struct ether_header *); 2221 1.2 hsuenaga switch (htons(eh->ether_type)) { 2222 1.2 hsuenaga case ETHERTYPE_IP: 2223 1.2 hsuenaga case ETHERTYPE_IPV6: 2224 1.2 hsuenaga ipoff = ETHER_HDR_LEN; 2225 1.2 hsuenaga break; 2226 1.2 hsuenaga case ETHERTYPE_VLAN: 2227 1.2 hsuenaga ipoff = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 2228 1.2 hsuenaga break; 2229 1.2 hsuenaga } 2230 1.2 hsuenaga 2231 1.24 msaitoh if (csum_flags & (M_CSUM_IPv4 | M_CSUM_TCPv4 | M_CSUM_UDPv4)) { 2232 1.1 hsuenaga iphl = M_CSUM_DATA_IPv4_IPHL(m->m_pkthdr.csum_data); 2233 1.2 hsuenaga t->command |= MVXPE_TX_CMD_L3_IP4; 2234 1.1 hsuenaga } 2235 1.24 msaitoh else if (csum_flags & (M_CSUM_TCPv6 | M_CSUM_UDPv6)) { 2236 1.18 maxv iphl = M_CSUM_DATA_IPv6_IPHL(m->m_pkthdr.csum_data); 2237 1.2 hsuenaga t->command |= MVXPE_TX_CMD_L3_IP6; 2238 1.1 hsuenaga } 2239 1.1 hsuenaga else { 2240 1.1 hsuenaga t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NONE; 2241 1.1 hsuenaga return; 2242 1.1 hsuenaga } 2243 1.1 hsuenaga 2244 1.2 hsuenaga 2245 1.1 hsuenaga /* L3 */ 2246 1.1 hsuenaga if (csum_flags & M_CSUM_IPv4) { 2247 1.1 hsuenaga t->command |= MVXPE_TX_CMD_IP4_CHECKSUM; 2248 1.1 hsuenaga } 2249 1.1 hsuenaga 2250 1.1 hsuenaga /* L4 */ 2251 1.24 msaitoh if ((csum_flags & 2252 1.24 msaitoh (M_CSUM_TCPv4 | M_CSUM_UDPv4 | M_CSUM_TCPv6 | M_CSUM_UDPv6)) == 0) { 2253 1.2 hsuenaga t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NONE; 2254 1.2 hsuenaga } 2255 1.2 hsuenaga else if (csum_flags & M_CSUM_TCPv4) { 2256 1.2 hsuenaga t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG; 2257 1.1 hsuenaga t->command |= MVXPE_TX_CMD_L4_TCP; 2258 1.1 hsuenaga } 2259 1.1 hsuenaga else if (csum_flags & M_CSUM_UDPv4) { 2260 1.2 hsuenaga t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG; 2261 1.1 hsuenaga t->command |= MVXPE_TX_CMD_L4_UDP; 2262 1.1 hsuenaga } 2263 1.1 hsuenaga else if (csum_flags & M_CSUM_TCPv6) { 2264 1.2 hsuenaga t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG; 2265 1.1 hsuenaga t->command |= MVXPE_TX_CMD_L4_TCP; 2266 1.1 hsuenaga } 2267 1.1 hsuenaga else if (csum_flags & M_CSUM_UDPv6) { 2268 1.2 hsuenaga t->command |= MVXPE_TX_CMD_L4_CHECKSUM_NOFRAG; 2269 1.1 hsuenaga t->command |= MVXPE_TX_CMD_L4_UDP; 2270 1.1 hsuenaga } 2271 1.1 hsuenaga 2272 1.1 hsuenaga t->l4ichk = 0; 2273 1.2 hsuenaga t->command |= MVXPE_TX_CMD_IP_HEADER_LEN(iphl >> 2); 2274 1.2 hsuenaga t->command |= MVXPE_TX_CMD_L3_OFFSET(ipoff); 2275 1.1 hsuenaga } 2276 1.1 hsuenaga 2277 1.1 hsuenaga STATIC void 2278 1.2 hsuenaga mvxpe_tx_complete(struct mvxpe_softc *sc, uint32_t queues) 2279 1.1 hsuenaga { 2280 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 2281 1.1 hsuenaga int q; 2282 1.1 hsuenaga 2283 1.1 hsuenaga DPRINTSC(sc, 2, "tx completed.\n"); 2284 1.1 hsuenaga 2285 1.1 hsuenaga KASSERT_SC_MTX(sc); 2286 1.1 hsuenaga 2287 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 2288 1.2 hsuenaga if (!MVXPE_IS_QUEUE_BUSY(queues, q)) 2289 1.2 hsuenaga continue; 2290 1.1 hsuenaga mvxpe_tx_lockq(sc, q); 2291 1.2 hsuenaga mvxpe_tx_queue_complete(sc, q); 2292 1.1 hsuenaga mvxpe_tx_unlockq(sc, q); 2293 1.1 hsuenaga } 2294 1.1 hsuenaga KASSERT(sc->sc_tx_pending >= 0); 2295 1.1 hsuenaga if (sc->sc_tx_pending == 0) 2296 1.1 hsuenaga ifp->if_timer = 0; 2297 1.1 hsuenaga } 2298 1.1 hsuenaga 2299 1.1 hsuenaga STATIC void 2300 1.2 hsuenaga mvxpe_tx_queue_complete(struct mvxpe_softc *sc, int q) 2301 1.1 hsuenaga { 2302 1.1 hsuenaga struct mvxpe_tx_ring *tx = MVXPE_TX_RING(sc, q); 2303 1.1 hsuenaga struct mvxpe_tx_desc *t; 2304 1.14 kiyohara struct mbuf *m; 2305 1.1 hsuenaga uint32_t ptxs, ptxsu, ndesc; 2306 1.1 hsuenaga int i; 2307 1.1 hsuenaga 2308 1.1 hsuenaga KASSERT_TX_MTX(sc, q); 2309 1.1 hsuenaga 2310 1.1 hsuenaga ptxs = MVXPE_READ(sc, MVXPE_PTXS(q)); 2311 1.1 hsuenaga ndesc = MVXPE_PTXS_GET_TBC(ptxs); 2312 1.1 hsuenaga if (ndesc == 0) 2313 1.1 hsuenaga return; 2314 1.1 hsuenaga 2315 1.1 hsuenaga DPRINTSC(sc, 2, 2316 1.1 hsuenaga "tx complete queue %d, %d descriptors.\n", q, ndesc); 2317 1.1 hsuenaga 2318 1.1 hsuenaga mvxpe_ring_sync_tx(sc, q, tx->tx_dma, ndesc, 2319 1.24 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2320 1.1 hsuenaga 2321 1.1 hsuenaga for (i = 0; i < ndesc; i++) { 2322 1.1 hsuenaga int error = 0; 2323 1.1 hsuenaga 2324 1.1 hsuenaga t = MVXPE_TX_DESC(sc, q, tx->tx_dma); 2325 1.1 hsuenaga if (t->flags & MVXPE_TX_F_ES) { 2326 1.1 hsuenaga DPRINTSC(sc, 1, 2327 1.1 hsuenaga "tx error queue %d desc %d\n", 2328 1.1 hsuenaga q, tx->tx_dma); 2329 1.1 hsuenaga switch (t->flags & MVXPE_TX_F_EC_MASK) { 2330 1.1 hsuenaga case MVXPE_TX_F_EC_LC: 2331 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_txd_lc); 2332 1.4 hikaru break; 2333 1.1 hsuenaga case MVXPE_TX_F_EC_UR: 2334 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_txd_ur); 2335 1.4 hikaru break; 2336 1.1 hsuenaga case MVXPE_TX_F_EC_RL: 2337 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_txd_rl); 2338 1.4 hikaru break; 2339 1.1 hsuenaga default: 2340 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_txd_oth); 2341 1.4 hikaru break; 2342 1.1 hsuenaga } 2343 1.1 hsuenaga error = 1; 2344 1.1 hsuenaga } 2345 1.14 kiyohara m = MVXPE_TX_MBUF(sc, q, tx->tx_dma); 2346 1.14 kiyohara if (m != NULL) { 2347 1.1 hsuenaga KASSERT((t->command & MVXPE_TX_CMD_F) != 0); 2348 1.14 kiyohara MVXPE_TX_MBUF(sc, q, tx->tx_dma) = NULL; 2349 1.14 kiyohara bus_dmamap_sync(sc->sc_dmat, 2350 1.14 kiyohara MVXPE_TX_MAP(sc, q, tx->tx_dma), 0, m->m_pkthdr.len, 2351 1.14 kiyohara BUS_DMASYNC_POSTWRITE); 2352 1.1 hsuenaga bus_dmamap_unload(sc->sc_dmat, 2353 1.1 hsuenaga MVXPE_TX_MAP(sc, q, tx->tx_dma)); 2354 1.14 kiyohara m_freem(m); 2355 1.1 hsuenaga sc->sc_tx_pending--; 2356 1.1 hsuenaga } 2357 1.1 hsuenaga else 2358 1.1 hsuenaga KASSERT((t->flags & MVXPE_TX_CMD_F) == 0); 2359 1.1 hsuenaga tx->tx_dma = tx_counter_adv(tx->tx_dma, 1); 2360 1.2 hsuenaga tx->tx_used--; 2361 1.1 hsuenaga if (error) 2362 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_txqe[q]); 2363 1.1 hsuenaga else 2364 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_txq[q]); 2365 1.1 hsuenaga } 2366 1.2 hsuenaga KASSERT(tx->tx_used >= 0); 2367 1.2 hsuenaga KASSERT(tx->tx_used <= tx->tx_queue_len); 2368 1.1 hsuenaga while (ndesc > 255) { 2369 1.1 hsuenaga ptxsu = MVXPE_PTXSU_NORB(255); 2370 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu); 2371 1.1 hsuenaga ndesc -= 255; 2372 1.1 hsuenaga } 2373 1.1 hsuenaga if (ndesc > 0) { 2374 1.1 hsuenaga ptxsu = MVXPE_PTXSU_NORB(ndesc); 2375 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXSU(q), ptxsu); 2376 1.1 hsuenaga } 2377 1.1 hsuenaga DPRINTSC(sc, 2, 2378 1.2 hsuenaga "Tx complete q %d, tx_cpu = %d, tx_dma = %d, tx_used = %d\n", 2379 1.2 hsuenaga q, tx->tx_cpu, tx->tx_dma, tx->tx_used); 2380 1.1 hsuenaga } 2381 1.1 hsuenaga 2382 1.1 hsuenaga /* 2383 1.1 hsuenaga * Rx Subroutines 2384 1.1 hsuenaga */ 2385 1.1 hsuenaga STATIC void 2386 1.2 hsuenaga mvxpe_rx(struct mvxpe_softc *sc, uint32_t queues) 2387 1.1 hsuenaga { 2388 1.1 hsuenaga int q, npkt; 2389 1.1 hsuenaga 2390 1.1 hsuenaga KASSERT_SC_MTX(sc); 2391 1.1 hsuenaga 2392 1.2 hsuenaga while ( (npkt = mvxpe_rx_queue_select(sc, queues, &q))) { 2393 1.2 hsuenaga /* mutex is held by rx_queue_select */ 2394 1.1 hsuenaga mvxpe_rx_queue(sc, q, npkt); 2395 1.1 hsuenaga mvxpe_rx_unlockq(sc, q); 2396 1.1 hsuenaga } 2397 1.1 hsuenaga } 2398 1.1 hsuenaga 2399 1.1 hsuenaga STATIC void 2400 1.1 hsuenaga mvxpe_rx_queue(struct mvxpe_softc *sc, int q, int npkt) 2401 1.1 hsuenaga { 2402 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 2403 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 2404 1.1 hsuenaga struct mvxpe_rx_desc *r; 2405 1.2 hsuenaga struct mvxpbm_chunk *chunk; 2406 1.1 hsuenaga struct mbuf *m; 2407 1.1 hsuenaga uint32_t prxsu; 2408 1.1 hsuenaga int error = 0; 2409 1.1 hsuenaga int i; 2410 1.1 hsuenaga 2411 1.1 hsuenaga KASSERT_RX_MTX(sc, q); 2412 1.1 hsuenaga 2413 1.1 hsuenaga mvxpe_ring_sync_rx(sc, q, rx->rx_dma, npkt, 2414 1.24 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2415 1.1 hsuenaga 2416 1.1 hsuenaga for (i = 0; i < npkt; i++) { 2417 1.1 hsuenaga /* get descriptor and packet */ 2418 1.1 hsuenaga chunk = MVXPE_RX_PKTBUF(sc, q, rx->rx_dma); 2419 1.1 hsuenaga MVXPE_RX_PKTBUF(sc, q, rx->rx_dma) = NULL; 2420 1.1 hsuenaga r = MVXPE_RX_DESC(sc, q, rx->rx_dma); 2421 1.2 hsuenaga mvxpbm_dmamap_sync(chunk, r->bytecnt, BUS_DMASYNC_POSTREAD); 2422 1.1 hsuenaga 2423 1.1 hsuenaga /* check errors */ 2424 1.1 hsuenaga if (r->status & MVXPE_RX_ES) { 2425 1.1 hsuenaga switch (r->status & MVXPE_RX_EC_MASK) { 2426 1.1 hsuenaga case MVXPE_RX_EC_CE: 2427 1.1 hsuenaga DPRINTIFNET(ifp, 1, "CRC error\n"); 2428 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_ce); 2429 1.1 hsuenaga break; 2430 1.1 hsuenaga case MVXPE_RX_EC_OR: 2431 1.1 hsuenaga DPRINTIFNET(ifp, 1, "Rx FIFO overrun\n"); 2432 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_or); 2433 1.1 hsuenaga break; 2434 1.1 hsuenaga case MVXPE_RX_EC_MF: 2435 1.1 hsuenaga DPRINTIFNET(ifp, 1, "Rx too large frame\n"); 2436 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_mf); 2437 1.1 hsuenaga break; 2438 1.1 hsuenaga case MVXPE_RX_EC_RE: 2439 1.1 hsuenaga DPRINTIFNET(ifp, 1, "Rx resource error\n"); 2440 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_re); 2441 1.1 hsuenaga break; 2442 1.1 hsuenaga } 2443 1.1 hsuenaga error = 1; 2444 1.1 hsuenaga goto rx_done; 2445 1.1 hsuenaga } 2446 1.1 hsuenaga if (!(r->status & MVXPE_RX_F) || !(r->status & MVXPE_RX_L)) { 2447 1.1 hsuenaga DPRINTIFNET(ifp, 1, "not support scatter buf\n"); 2448 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_rxd_scat); 2449 1.1 hsuenaga error = 1; 2450 1.1 hsuenaga goto rx_done; 2451 1.1 hsuenaga } 2452 1.1 hsuenaga 2453 1.1 hsuenaga if (chunk == NULL) { 2454 1.1 hsuenaga device_printf(sc->sc_dev, 2455 1.1 hsuenaga "got rx interrupt, but no chunk\n"); 2456 1.1 hsuenaga error = 1; 2457 1.1 hsuenaga goto rx_done; 2458 1.1 hsuenaga } 2459 1.1 hsuenaga 2460 1.1 hsuenaga /* extract packet buffer */ 2461 1.2 hsuenaga if (mvxpbm_init_mbuf_hdr(chunk) != 0) { 2462 1.2 hsuenaga error = 1; 2463 1.2 hsuenaga goto rx_done; 2464 1.2 hsuenaga } 2465 1.1 hsuenaga m = chunk->m; 2466 1.13 ozaki m_set_rcvif(m, ifp); 2467 1.1 hsuenaga m->m_pkthdr.len = m->m_len = r->bytecnt - ETHER_CRC_LEN; 2468 1.1 hsuenaga m_adj(m, MVXPE_HWHEADER_SIZE); /* strip MH */ 2469 1.1 hsuenaga mvxpe_rx_set_csumflag(ifp, r, m); 2470 1.3 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 2471 1.1 hsuenaga chunk = NULL; /* the BM chunk goes to networking stack now */ 2472 1.1 hsuenaga rx_done: 2473 1.1 hsuenaga if (chunk) { 2474 1.1 hsuenaga /* rx error. just return the chunk to BM. */ 2475 1.2 hsuenaga mvxpbm_free_chunk(chunk); 2476 1.1 hsuenaga } 2477 1.1 hsuenaga if (error) 2478 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_rxqe[q]); 2479 1.1 hsuenaga else 2480 1.1 hsuenaga MVXPE_EVCNT_INCR(&sc->sc_ev.ev_drv_rxq[q]); 2481 1.1 hsuenaga rx->rx_dma = rx_counter_adv(rx->rx_dma, 1); 2482 1.1 hsuenaga } 2483 1.1 hsuenaga /* DMA status update */ 2484 1.1 hsuenaga DPRINTSC(sc, 2, "%d packets received from queue %d\n", npkt, q); 2485 1.1 hsuenaga while (npkt > 255) { 2486 1.1 hsuenaga prxsu = MVXPE_PRXSU_NOOFPROCESSEDDESCRIPTORS(255); 2487 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXSU(q), prxsu); 2488 1.1 hsuenaga npkt -= 255; 2489 1.1 hsuenaga } 2490 1.1 hsuenaga if (npkt > 0) { 2491 1.1 hsuenaga prxsu = MVXPE_PRXSU_NOOFPROCESSEDDESCRIPTORS(npkt); 2492 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXSU(q), prxsu); 2493 1.1 hsuenaga } 2494 1.1 hsuenaga 2495 1.1 hsuenaga DPRINTSC(sc, 2, 2496 1.1 hsuenaga "PRXDQA: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PRXDQA(q))); 2497 1.1 hsuenaga DPRINTSC(sc, 2, 2498 1.1 hsuenaga "PRXDQS: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PRXDQS(q))); 2499 1.1 hsuenaga DPRINTSC(sc, 2, 2500 1.1 hsuenaga "PRXS: queue %d, %#x\n", q, MVXPE_READ(sc, MVXPE_PRXS(q))); 2501 1.1 hsuenaga DPRINTSC(sc, 2, 2502 1.1 hsuenaga "PRXDI: queue %d, %d\n", q, MVXPE_READ(sc, MVXPE_PRXDI(q))); 2503 1.1 hsuenaga DPRINTSC(sc, 2, "RQC: %#x\n", MVXPE_READ(sc, MVXPE_RQC)); 2504 1.1 hsuenaga DPRINTIFNET(ifp, 2, "Rx: rx_cpu = %d, rx_dma = %d\n", 2505 1.1 hsuenaga rx->rx_cpu, rx->rx_dma); 2506 1.1 hsuenaga } 2507 1.1 hsuenaga 2508 1.1 hsuenaga STATIC int 2509 1.2 hsuenaga mvxpe_rx_queue_select(struct mvxpe_softc *sc, uint32_t queues, int *queue) 2510 1.1 hsuenaga { 2511 1.1 hsuenaga uint32_t prxs, npkt; 2512 1.1 hsuenaga int q; 2513 1.1 hsuenaga 2514 1.1 hsuenaga KASSERT_SC_MTX(sc); 2515 1.1 hsuenaga KASSERT(queue != NULL); 2516 1.1 hsuenaga DPRINTSC(sc, 2, "selecting rx queue\n"); 2517 1.1 hsuenaga 2518 1.1 hsuenaga for (q = MVXPE_QUEUE_SIZE - 1; q >= 0; q--) { 2519 1.2 hsuenaga if (!MVXPE_IS_QUEUE_BUSY(queues, q)) 2520 1.2 hsuenaga continue; 2521 1.2 hsuenaga 2522 1.1 hsuenaga prxs = MVXPE_READ(sc, MVXPE_PRXS(q)); 2523 1.1 hsuenaga npkt = MVXPE_PRXS_GET_ODC(prxs); 2524 1.1 hsuenaga if (npkt == 0) 2525 1.1 hsuenaga continue; 2526 1.1 hsuenaga 2527 1.24 msaitoh DPRINTSC(sc, 2, 2528 1.22 msaitoh "queue %d selected: prxs=%#x, %u packet received.\n", 2529 1.1 hsuenaga q, prxs, npkt); 2530 1.1 hsuenaga *queue = q; 2531 1.1 hsuenaga mvxpe_rx_lockq(sc, q); 2532 1.1 hsuenaga return npkt; 2533 1.1 hsuenaga } 2534 1.1 hsuenaga 2535 1.1 hsuenaga return 0; 2536 1.1 hsuenaga } 2537 1.1 hsuenaga 2538 1.1 hsuenaga STATIC void 2539 1.2 hsuenaga mvxpe_rx_refill(struct mvxpe_softc *sc, uint32_t queues) 2540 1.1 hsuenaga { 2541 1.1 hsuenaga int q; 2542 1.1 hsuenaga 2543 1.1 hsuenaga KASSERT_SC_MTX(sc); 2544 1.1 hsuenaga 2545 1.1 hsuenaga /* XXX: check rx bit array */ 2546 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 2547 1.2 hsuenaga if (!MVXPE_IS_QUEUE_BUSY(queues, q)) 2548 1.2 hsuenaga continue; 2549 1.2 hsuenaga 2550 1.1 hsuenaga mvxpe_rx_lockq(sc, q); 2551 1.2 hsuenaga mvxpe_rx_queue_refill(sc, q); 2552 1.1 hsuenaga mvxpe_rx_unlockq(sc, q); 2553 1.1 hsuenaga } 2554 1.1 hsuenaga } 2555 1.1 hsuenaga 2556 1.1 hsuenaga STATIC void 2557 1.2 hsuenaga mvxpe_rx_queue_refill(struct mvxpe_softc *sc, int q) 2558 1.1 hsuenaga { 2559 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 2560 1.1 hsuenaga uint32_t prxs, prxsu, ndesc; 2561 1.2 hsuenaga int idx, refill = 0; 2562 1.1 hsuenaga int npkt; 2563 1.1 hsuenaga 2564 1.1 hsuenaga KASSERT_RX_MTX(sc, q); 2565 1.1 hsuenaga 2566 1.1 hsuenaga prxs = MVXPE_READ(sc, MVXPE_PRXS(q)); 2567 1.1 hsuenaga ndesc = MVXPE_PRXS_GET_NODC(prxs) + MVXPE_PRXS_GET_ODC(prxs); 2568 1.2 hsuenaga refill = rx->rx_queue_len - ndesc; 2569 1.2 hsuenaga if (refill <= 0) 2570 1.1 hsuenaga return; 2571 1.1 hsuenaga DPRINTPRXS(2, q); 2572 1.2 hsuenaga DPRINTSC(sc, 2, "%d buffers to refill.\n", refill); 2573 1.1 hsuenaga 2574 1.1 hsuenaga idx = rx->rx_cpu; 2575 1.2 hsuenaga for (npkt = 0; npkt < refill; npkt++) 2576 1.1 hsuenaga if (mvxpe_rx_queue_add(sc, q) != 0) 2577 1.1 hsuenaga break; 2578 1.2 hsuenaga DPRINTSC(sc, 2, "queue %d, %d buffer refilled.\n", q, npkt); 2579 1.1 hsuenaga if (npkt == 0) 2580 1.1 hsuenaga return; 2581 1.1 hsuenaga 2582 1.1 hsuenaga mvxpe_ring_sync_rx(sc, q, idx, npkt, 2583 1.1 hsuenaga BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2584 1.1 hsuenaga 2585 1.1 hsuenaga while (npkt > 255) { 2586 1.1 hsuenaga prxsu = MVXPE_PRXSU_NOOFNEWDESCRIPTORS(255); 2587 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXSU(q), prxsu); 2588 1.1 hsuenaga npkt -= 255; 2589 1.1 hsuenaga } 2590 1.1 hsuenaga if (npkt > 0) { 2591 1.1 hsuenaga prxsu = MVXPE_PRXSU_NOOFNEWDESCRIPTORS(npkt); 2592 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXSU(q), prxsu); 2593 1.1 hsuenaga } 2594 1.1 hsuenaga DPRINTPRXS(2, q); 2595 1.1 hsuenaga return; 2596 1.1 hsuenaga } 2597 1.1 hsuenaga 2598 1.1 hsuenaga STATIC int 2599 1.1 hsuenaga mvxpe_rx_queue_add(struct mvxpe_softc *sc, int q) 2600 1.1 hsuenaga { 2601 1.1 hsuenaga struct mvxpe_rx_ring *rx = MVXPE_RX_RING(sc, q); 2602 1.1 hsuenaga struct mvxpe_rx_desc *r; 2603 1.2 hsuenaga struct mvxpbm_chunk *chunk = NULL; 2604 1.1 hsuenaga 2605 1.1 hsuenaga KASSERT_RX_MTX(sc, q); 2606 1.1 hsuenaga 2607 1.1 hsuenaga /* Allocate the packet buffer */ 2608 1.2 hsuenaga chunk = mvxpbm_alloc(sc->sc_bm); 2609 1.1 hsuenaga if (chunk == NULL) { 2610 1.1 hsuenaga DPRINTSC(sc, 1, "BM chunk allocation failed.\n"); 2611 1.1 hsuenaga return ENOBUFS; 2612 1.1 hsuenaga } 2613 1.1 hsuenaga 2614 1.39 andvar /* Add the packet to descriptor */ 2615 1.1 hsuenaga KASSERT(MVXPE_RX_PKTBUF(sc, q, rx->rx_cpu) == NULL); 2616 1.1 hsuenaga MVXPE_RX_PKTBUF(sc, q, rx->rx_cpu) = chunk; 2617 1.2 hsuenaga mvxpbm_dmamap_sync(chunk, BM_SYNC_ALL, BUS_DMASYNC_PREREAD); 2618 1.1 hsuenaga 2619 1.1 hsuenaga r = MVXPE_RX_DESC(sc, q, rx->rx_cpu); 2620 1.1 hsuenaga r->bufptr = chunk->buf_pa; 2621 1.1 hsuenaga DPRINTSC(sc, 9, "chunk added to index %d\n", rx->rx_cpu); 2622 1.1 hsuenaga rx->rx_cpu = rx_counter_adv(rx->rx_cpu, 1); 2623 1.1 hsuenaga return 0; 2624 1.1 hsuenaga } 2625 1.1 hsuenaga 2626 1.1 hsuenaga STATIC void 2627 1.1 hsuenaga mvxpe_rx_set_csumflag(struct ifnet *ifp, 2628 1.1 hsuenaga struct mvxpe_rx_desc *r, struct mbuf *m0) 2629 1.1 hsuenaga { 2630 1.1 hsuenaga uint32_t csum_flags = 0; 2631 1.1 hsuenaga 2632 1.24 msaitoh if ((r->status & (MVXPE_RX_IP_HEADER_OK | MVXPE_RX_L3_IP)) == 0) 2633 1.1 hsuenaga return; /* not a IP packet */ 2634 1.1 hsuenaga 2635 1.1 hsuenaga /* L3 */ 2636 1.1 hsuenaga if (r->status & MVXPE_RX_L3_IP) { 2637 1.8 hikaru csum_flags |= M_CSUM_IPv4 & ifp->if_csum_flags_rx; 2638 1.8 hikaru if ((r->status & MVXPE_RX_IP_HEADER_OK) == 0 && 2639 1.9 hikaru (csum_flags & M_CSUM_IPv4) != 0) { 2640 1.1 hsuenaga csum_flags |= M_CSUM_IPv4_BAD; 2641 1.1 hsuenaga goto finish; 2642 1.1 hsuenaga } 2643 1.1 hsuenaga else if (r->status & MVXPE_RX_IPV4_FRAGMENT) { 2644 1.1 hsuenaga /* 2645 1.43 andvar * r->l4chk has partial checksum of each fragment. 2646 1.1 hsuenaga * but there is no way to use it in NetBSD. 2647 1.1 hsuenaga */ 2648 1.1 hsuenaga return; 2649 1.1 hsuenaga } 2650 1.1 hsuenaga } 2651 1.1 hsuenaga 2652 1.1 hsuenaga /* L4 */ 2653 1.1 hsuenaga switch (r->status & MVXPE_RX_L4_MASK) { 2654 1.1 hsuenaga case MVXPE_RX_L4_TCP: 2655 1.1 hsuenaga if (r->status & MVXPE_RX_L3_IP) 2656 1.8 hikaru csum_flags |= M_CSUM_TCPv4 & ifp->if_csum_flags_rx; 2657 1.1 hsuenaga else 2658 1.8 hikaru csum_flags |= M_CSUM_TCPv6 & ifp->if_csum_flags_rx; 2659 1.1 hsuenaga break; 2660 1.1 hsuenaga case MVXPE_RX_L4_UDP: 2661 1.1 hsuenaga if (r->status & MVXPE_RX_L3_IP) 2662 1.8 hikaru csum_flags |= M_CSUM_UDPv4 & ifp->if_csum_flags_rx; 2663 1.1 hsuenaga else 2664 1.8 hikaru csum_flags |= M_CSUM_UDPv6 & ifp->if_csum_flags_rx; 2665 1.1 hsuenaga break; 2666 1.1 hsuenaga case MVXPE_RX_L4_OTH: 2667 1.1 hsuenaga default: 2668 1.1 hsuenaga break; 2669 1.1 hsuenaga } 2670 1.8 hikaru if ((r->status & MVXPE_RX_L4_CHECKSUM_OK) == 0 && (csum_flags & 2671 1.9 hikaru (M_CSUM_TCPv4 | M_CSUM_TCPv6 | M_CSUM_UDPv4 | M_CSUM_UDPv6)) != 0) 2672 1.8 hikaru csum_flags |= M_CSUM_TCP_UDP_BAD; 2673 1.1 hsuenaga finish: 2674 1.8 hikaru m0->m_pkthdr.csum_flags = csum_flags; 2675 1.1 hsuenaga } 2676 1.1 hsuenaga 2677 1.1 hsuenaga /* 2678 1.1 hsuenaga * MAC address filter 2679 1.1 hsuenaga */ 2680 1.1 hsuenaga STATIC uint8_t 2681 1.1 hsuenaga mvxpe_crc8(const uint8_t *data, size_t size) 2682 1.1 hsuenaga { 2683 1.1 hsuenaga int bit; 2684 1.1 hsuenaga uint8_t byte; 2685 1.1 hsuenaga uint8_t crc = 0; 2686 1.1 hsuenaga const uint8_t poly = 0x07; 2687 1.1 hsuenaga 2688 1.24 msaitoh while (size--) 2689 1.1 hsuenaga for (byte = *data++, bit = NBBY-1; bit >= 0; bit--) 2690 1.1 hsuenaga crc = (crc << 1) ^ ((((crc >> 7) ^ (byte >> bit)) & 1) ? poly : 0); 2691 1.1 hsuenaga 2692 1.1 hsuenaga return crc; 2693 1.1 hsuenaga } 2694 1.1 hsuenaga 2695 1.1 hsuenaga CTASSERT(MVXPE_NDFSMT == MVXPE_NDFOMT); 2696 1.1 hsuenaga 2697 1.1 hsuenaga STATIC void 2698 1.1 hsuenaga mvxpe_filter_setup(struct mvxpe_softc *sc) 2699 1.1 hsuenaga { 2700 1.1 hsuenaga struct ethercom *ec = &sc->sc_ethercom; 2701 1.1 hsuenaga struct ifnet *ifp= &sc->sc_ethercom.ec_if; 2702 1.1 hsuenaga struct ether_multi *enm; 2703 1.1 hsuenaga struct ether_multistep step; 2704 1.1 hsuenaga uint32_t dfut[MVXPE_NDFUT], dfsmt[MVXPE_NDFSMT], dfomt[MVXPE_NDFOMT]; 2705 1.1 hsuenaga uint32_t pxc; 2706 1.1 hsuenaga int i; 2707 1.1 hsuenaga const uint8_t special[ETHER_ADDR_LEN] = {0x01,0x00,0x5e,0x00,0x00,0x00}; 2708 1.1 hsuenaga 2709 1.1 hsuenaga KASSERT_SC_MTX(sc); 2710 1.1 hsuenaga 2711 1.1 hsuenaga memset(dfut, 0, sizeof(dfut)); 2712 1.1 hsuenaga memset(dfsmt, 0, sizeof(dfsmt)); 2713 1.1 hsuenaga memset(dfomt, 0, sizeof(dfomt)); 2714 1.1 hsuenaga 2715 1.24 msaitoh if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) { 2716 1.1 hsuenaga goto allmulti; 2717 1.1 hsuenaga } 2718 1.1 hsuenaga 2719 1.27 msaitoh ETHER_LOCK(ec); 2720 1.1 hsuenaga ETHER_FIRST_MULTI(step, ec, enm); 2721 1.1 hsuenaga while (enm != NULL) { 2722 1.1 hsuenaga if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 2723 1.1 hsuenaga /* ranges are complex and somewhat rare */ 2724 1.27 msaitoh ETHER_UNLOCK(ec); 2725 1.1 hsuenaga goto allmulti; 2726 1.1 hsuenaga } 2727 1.1 hsuenaga /* chip handles some IPv4 multicast specially */ 2728 1.1 hsuenaga if (memcmp(enm->enm_addrlo, special, 5) == 0) { 2729 1.1 hsuenaga i = enm->enm_addrlo[5]; 2730 1.1 hsuenaga dfsmt[i>>2] |= 2731 1.12 hikaru MVXPE_DF(i&3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS); 2732 1.1 hsuenaga } else { 2733 1.1 hsuenaga i = mvxpe_crc8(enm->enm_addrlo, ETHER_ADDR_LEN); 2734 1.1 hsuenaga dfomt[i>>2] |= 2735 1.12 hikaru MVXPE_DF(i&3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS); 2736 1.1 hsuenaga } 2737 1.1 hsuenaga 2738 1.1 hsuenaga ETHER_NEXT_MULTI(step, enm); 2739 1.1 hsuenaga } 2740 1.27 msaitoh ETHER_UNLOCK(ec); 2741 1.1 hsuenaga goto set; 2742 1.1 hsuenaga 2743 1.1 hsuenaga allmulti: 2744 1.24 msaitoh if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) { 2745 1.1 hsuenaga for (i = 0; i < MVXPE_NDFSMT; i++) { 2746 1.24 msaitoh dfsmt[i] = dfomt[i] = 2747 1.12 hikaru MVXPE_DF(0, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) | 2748 1.12 hikaru MVXPE_DF(1, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) | 2749 1.12 hikaru MVXPE_DF(2, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) | 2750 1.12 hikaru MVXPE_DF(3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS); 2751 1.1 hsuenaga } 2752 1.1 hsuenaga } 2753 1.1 hsuenaga 2754 1.1 hsuenaga set: 2755 1.1 hsuenaga pxc = MVXPE_READ(sc, MVXPE_PXC); 2756 1.1 hsuenaga pxc &= ~MVXPE_PXC_UPM; 2757 1.1 hsuenaga pxc |= MVXPE_PXC_RB | MVXPE_PXC_RBIP | MVXPE_PXC_RBARP; 2758 1.1 hsuenaga if (ifp->if_flags & IFF_BROADCAST) { 2759 1.1 hsuenaga pxc &= ~(MVXPE_PXC_RB | MVXPE_PXC_RBIP | MVXPE_PXC_RBARP); 2760 1.1 hsuenaga } 2761 1.1 hsuenaga if (ifp->if_flags & IFF_PROMISC) { 2762 1.1 hsuenaga pxc |= MVXPE_PXC_UPM; 2763 1.1 hsuenaga } 2764 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PXC, pxc); 2765 1.1 hsuenaga 2766 1.1 hsuenaga /* Set Destination Address Filter Unicast Table */ 2767 1.12 hikaru if (ifp->if_flags & IFF_PROMISC) { 2768 1.12 hikaru /* pass all unicast addresses */ 2769 1.12 hikaru for (i = 0; i < MVXPE_NDFUT; i++) { 2770 1.12 hikaru dfut[i] = 2771 1.12 hikaru MVXPE_DF(0, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) | 2772 1.12 hikaru MVXPE_DF(1, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) | 2773 1.12 hikaru MVXPE_DF(2, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS) | 2774 1.12 hikaru MVXPE_DF(3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS); 2775 1.12 hikaru } 2776 1.12 hikaru } 2777 1.12 hikaru else { 2778 1.25 msaitoh i = sc->sc_enaddr[5] & 0xf; /* last nibble */ 2779 1.12 hikaru dfut[i>>2] = MVXPE_DF(i&3, MVXPE_DF_QUEUE(0) | MVXPE_DF_PASS); 2780 1.12 hikaru } 2781 1.1 hsuenaga MVXPE_WRITE_REGION(sc, MVXPE_DFUT(0), dfut, MVXPE_NDFUT); 2782 1.1 hsuenaga 2783 1.1 hsuenaga /* Set Destination Address Filter Multicast Tables */ 2784 1.1 hsuenaga MVXPE_WRITE_REGION(sc, MVXPE_DFSMT(0), dfsmt, MVXPE_NDFSMT); 2785 1.1 hsuenaga MVXPE_WRITE_REGION(sc, MVXPE_DFOMT(0), dfomt, MVXPE_NDFOMT); 2786 1.1 hsuenaga } 2787 1.1 hsuenaga 2788 1.1 hsuenaga /* 2789 1.1 hsuenaga * sysctl(9) 2790 1.1 hsuenaga */ 2791 1.1 hsuenaga SYSCTL_SETUP(sysctl_mvxpe, "sysctl mvxpe subtree setup") 2792 1.1 hsuenaga { 2793 1.1 hsuenaga int rc; 2794 1.1 hsuenaga const struct sysctlnode *node; 2795 1.1 hsuenaga 2796 1.1 hsuenaga if ((rc = sysctl_createv(clog, 0, NULL, &node, 2797 1.1 hsuenaga 0, CTLTYPE_NODE, "mvxpe", 2798 1.1 hsuenaga SYSCTL_DESCR("mvxpe interface controls"), 2799 1.1 hsuenaga NULL, 0, NULL, 0, 2800 1.1 hsuenaga CTL_HW, CTL_CREATE, CTL_EOL)) != 0) { 2801 1.1 hsuenaga goto err; 2802 1.1 hsuenaga } 2803 1.1 hsuenaga 2804 1.1 hsuenaga mvxpe_root_num = node->sysctl_num; 2805 1.1 hsuenaga return; 2806 1.1 hsuenaga 2807 1.1 hsuenaga err: 2808 1.1 hsuenaga aprint_error("%s: syctl_createv failed (rc = %d)\n", __func__, rc); 2809 1.1 hsuenaga } 2810 1.1 hsuenaga 2811 1.1 hsuenaga STATIC int 2812 1.1 hsuenaga sysctl_read_mib(SYSCTLFN_ARGS) 2813 1.1 hsuenaga { 2814 1.1 hsuenaga struct mvxpe_sysctl_mib *arg; 2815 1.1 hsuenaga struct mvxpe_softc *sc; 2816 1.1 hsuenaga struct sysctlnode node; 2817 1.1 hsuenaga uint64_t val; 2818 1.1 hsuenaga int err; 2819 1.1 hsuenaga 2820 1.1 hsuenaga node = *rnode; 2821 1.1 hsuenaga arg = (struct mvxpe_sysctl_mib *)rnode->sysctl_data; 2822 1.1 hsuenaga if (arg == NULL) 2823 1.1 hsuenaga return EINVAL; 2824 1.1 hsuenaga 2825 1.1 hsuenaga sc = arg->sc; 2826 1.1 hsuenaga if (sc == NULL) 2827 1.1 hsuenaga return EINVAL; 2828 1.1 hsuenaga if (arg->index < 0 || arg->index > __arraycount(mvxpe_mib_list)) 2829 1.1 hsuenaga return EINVAL; 2830 1.24 msaitoh 2831 1.1 hsuenaga mvxpe_sc_lock(sc); 2832 1.1 hsuenaga val = arg->counter; 2833 1.1 hsuenaga mvxpe_sc_unlock(sc); 2834 1.1 hsuenaga 2835 1.1 hsuenaga node.sysctl_data = &val; 2836 1.1 hsuenaga err = sysctl_lookup(SYSCTLFN_CALL(&node)); 2837 1.1 hsuenaga if (err) 2838 1.1 hsuenaga return err; 2839 1.1 hsuenaga if (newp) 2840 1.1 hsuenaga return EINVAL; 2841 1.1 hsuenaga 2842 1.1 hsuenaga return 0; 2843 1.1 hsuenaga } 2844 1.1 hsuenaga 2845 1.1 hsuenaga 2846 1.1 hsuenaga STATIC int 2847 1.1 hsuenaga sysctl_clear_mib(SYSCTLFN_ARGS) 2848 1.1 hsuenaga { 2849 1.1 hsuenaga struct mvxpe_softc *sc; 2850 1.1 hsuenaga struct sysctlnode node; 2851 1.1 hsuenaga int val; 2852 1.1 hsuenaga int err; 2853 1.1 hsuenaga 2854 1.1 hsuenaga node = *rnode; 2855 1.1 hsuenaga sc = (struct mvxpe_softc *)rnode->sysctl_data; 2856 1.1 hsuenaga if (sc == NULL) 2857 1.1 hsuenaga return EINVAL; 2858 1.1 hsuenaga 2859 1.1 hsuenaga val = 0; 2860 1.1 hsuenaga node.sysctl_data = &val; 2861 1.1 hsuenaga err = sysctl_lookup(SYSCTLFN_CALL(&node)); 2862 1.1 hsuenaga if (err || newp == NULL) 2863 1.1 hsuenaga return err; 2864 1.1 hsuenaga if (val < 0 || val > 1) 2865 1.1 hsuenaga return EINVAL; 2866 1.1 hsuenaga if (val == 1) { 2867 1.1 hsuenaga mvxpe_sc_lock(sc); 2868 1.1 hsuenaga mvxpe_clear_mib(sc); 2869 1.1 hsuenaga mvxpe_sc_unlock(sc); 2870 1.1 hsuenaga } 2871 1.1 hsuenaga 2872 1.1 hsuenaga return 0; 2873 1.1 hsuenaga } 2874 1.1 hsuenaga 2875 1.1 hsuenaga STATIC int 2876 1.1 hsuenaga sysctl_set_queue_length(SYSCTLFN_ARGS) 2877 1.1 hsuenaga { 2878 1.1 hsuenaga struct mvxpe_sysctl_queue *arg; 2879 1.1 hsuenaga struct mvxpe_rx_ring *rx = NULL; 2880 1.1 hsuenaga struct mvxpe_tx_ring *tx = NULL; 2881 1.1 hsuenaga struct mvxpe_softc *sc; 2882 1.1 hsuenaga struct sysctlnode node; 2883 1.1 hsuenaga uint32_t reg; 2884 1.1 hsuenaga int val; 2885 1.1 hsuenaga int err; 2886 1.1 hsuenaga 2887 1.1 hsuenaga node = *rnode; 2888 1.1 hsuenaga 2889 1.1 hsuenaga arg = (struct mvxpe_sysctl_queue *)rnode->sysctl_data; 2890 1.1 hsuenaga if (arg == NULL) 2891 1.1 hsuenaga return EINVAL; 2892 1.1 hsuenaga if (arg->queue < 0 || arg->queue > MVXPE_RX_RING_CNT) 2893 1.1 hsuenaga return EINVAL; 2894 1.1 hsuenaga if (arg->rxtx != MVXPE_SYSCTL_RX && arg->rxtx != MVXPE_SYSCTL_TX) 2895 1.1 hsuenaga return EINVAL; 2896 1.1 hsuenaga 2897 1.1 hsuenaga sc = arg->sc; 2898 1.1 hsuenaga if (sc == NULL) 2899 1.1 hsuenaga return EINVAL; 2900 1.1 hsuenaga 2901 1.1 hsuenaga /* read queue length */ 2902 1.1 hsuenaga mvxpe_sc_lock(sc); 2903 1.1 hsuenaga switch (arg->rxtx) { 2904 1.1 hsuenaga case MVXPE_SYSCTL_RX: 2905 1.1 hsuenaga mvxpe_rx_lockq(sc, arg->queue); 2906 1.1 hsuenaga rx = MVXPE_RX_RING(sc, arg->queue); 2907 1.1 hsuenaga val = rx->rx_queue_len; 2908 1.1 hsuenaga mvxpe_rx_unlockq(sc, arg->queue); 2909 1.1 hsuenaga break; 2910 1.1 hsuenaga case MVXPE_SYSCTL_TX: 2911 1.1 hsuenaga mvxpe_tx_lockq(sc, arg->queue); 2912 1.1 hsuenaga tx = MVXPE_TX_RING(sc, arg->queue); 2913 1.1 hsuenaga val = tx->tx_queue_len; 2914 1.1 hsuenaga mvxpe_tx_unlockq(sc, arg->queue); 2915 1.1 hsuenaga break; 2916 1.1 hsuenaga } 2917 1.1 hsuenaga 2918 1.1 hsuenaga node.sysctl_data = &val; 2919 1.1 hsuenaga err = sysctl_lookup(SYSCTLFN_CALL(&node)); 2920 1.1 hsuenaga if (err || newp == NULL) { 2921 1.1 hsuenaga mvxpe_sc_unlock(sc); 2922 1.1 hsuenaga return err; 2923 1.1 hsuenaga } 2924 1.1 hsuenaga 2925 1.1 hsuenaga /* update queue length */ 2926 1.1 hsuenaga if (val < 8 || val > MVXPE_RX_RING_CNT) { 2927 1.1 hsuenaga mvxpe_sc_unlock(sc); 2928 1.1 hsuenaga return EINVAL; 2929 1.1 hsuenaga } 2930 1.1 hsuenaga switch (arg->rxtx) { 2931 1.1 hsuenaga case MVXPE_SYSCTL_RX: 2932 1.1 hsuenaga mvxpe_rx_lockq(sc, arg->queue); 2933 1.1 hsuenaga rx->rx_queue_len = val; 2934 1.24 msaitoh rx->rx_queue_th_received = 2935 1.2 hsuenaga rx->rx_queue_len / MVXPE_RXTH_RATIO; 2936 1.24 msaitoh rx->rx_queue_th_free = 2937 1.2 hsuenaga rx->rx_queue_len / MVXPE_RXTH_REFILL_RATIO; 2938 1.1 hsuenaga 2939 1.1 hsuenaga reg = MVXPE_PRXDQTH_ODT(rx->rx_queue_th_received); 2940 1.1 hsuenaga reg |= MVXPE_PRXDQTH_NODT(rx->rx_queue_th_free); 2941 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXDQTH(arg->queue), reg); 2942 1.1 hsuenaga 2943 1.1 hsuenaga mvxpe_rx_unlockq(sc, arg->queue); 2944 1.1 hsuenaga break; 2945 1.1 hsuenaga case MVXPE_SYSCTL_TX: 2946 1.1 hsuenaga mvxpe_tx_lockq(sc, arg->queue); 2947 1.1 hsuenaga tx->tx_queue_len = val; 2948 1.2 hsuenaga tx->tx_queue_th_free = 2949 1.2 hsuenaga tx->tx_queue_len / MVXPE_TXTH_RATIO; 2950 1.1 hsuenaga 2951 1.1 hsuenaga reg = MVXPE_PTXDQS_TBT(tx->tx_queue_th_free); 2952 1.1 hsuenaga reg |= MVXPE_PTXDQS_DQS(MVXPE_TX_RING_CNT); 2953 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PTXDQS(arg->queue), reg); 2954 1.1 hsuenaga 2955 1.1 hsuenaga mvxpe_tx_unlockq(sc, arg->queue); 2956 1.1 hsuenaga break; 2957 1.1 hsuenaga } 2958 1.1 hsuenaga mvxpe_sc_unlock(sc); 2959 1.1 hsuenaga 2960 1.1 hsuenaga return 0; 2961 1.1 hsuenaga } 2962 1.1 hsuenaga 2963 1.1 hsuenaga STATIC int 2964 1.1 hsuenaga sysctl_set_queue_rxthtime(SYSCTLFN_ARGS) 2965 1.1 hsuenaga { 2966 1.1 hsuenaga struct mvxpe_sysctl_queue *arg; 2967 1.1 hsuenaga struct mvxpe_rx_ring *rx = NULL; 2968 1.1 hsuenaga struct mvxpe_softc *sc; 2969 1.1 hsuenaga struct sysctlnode node; 2970 1.1 hsuenaga extern uint32_t mvTclk; 2971 1.1 hsuenaga uint32_t reg, time_mvtclk; 2972 1.1 hsuenaga int time_us; 2973 1.1 hsuenaga int err; 2974 1.1 hsuenaga 2975 1.1 hsuenaga node = *rnode; 2976 1.1 hsuenaga 2977 1.1 hsuenaga arg = (struct mvxpe_sysctl_queue *)rnode->sysctl_data; 2978 1.1 hsuenaga if (arg == NULL) 2979 1.1 hsuenaga return EINVAL; 2980 1.1 hsuenaga if (arg->queue < 0 || arg->queue > MVXPE_RX_RING_CNT) 2981 1.1 hsuenaga return EINVAL; 2982 1.1 hsuenaga if (arg->rxtx != MVXPE_SYSCTL_RX) 2983 1.1 hsuenaga return EINVAL; 2984 1.1 hsuenaga 2985 1.1 hsuenaga sc = arg->sc; 2986 1.1 hsuenaga if (sc == NULL) 2987 1.1 hsuenaga return EINVAL; 2988 1.1 hsuenaga 2989 1.1 hsuenaga /* read queue length */ 2990 1.1 hsuenaga mvxpe_sc_lock(sc); 2991 1.1 hsuenaga mvxpe_rx_lockq(sc, arg->queue); 2992 1.1 hsuenaga rx = MVXPE_RX_RING(sc, arg->queue); 2993 1.1 hsuenaga time_mvtclk = rx->rx_queue_th_time; 2994 1.1 hsuenaga time_us = ((uint64_t)time_mvtclk * 1000ULL * 1000ULL) / mvTclk; 2995 1.1 hsuenaga node.sysctl_data = &time_us; 2996 1.1 hsuenaga DPRINTSC(sc, 1, "RXITTH(%d) => %#x\n", 2997 1.1 hsuenaga arg->queue, MVXPE_READ(sc, MVXPE_PRXITTH(arg->queue))); 2998 1.1 hsuenaga err = sysctl_lookup(SYSCTLFN_CALL(&node)); 2999 1.1 hsuenaga if (err || newp == NULL) { 3000 1.1 hsuenaga mvxpe_rx_unlockq(sc, arg->queue); 3001 1.1 hsuenaga mvxpe_sc_unlock(sc); 3002 1.1 hsuenaga return err; 3003 1.1 hsuenaga } 3004 1.1 hsuenaga 3005 1.1 hsuenaga /* update queue length (0[sec] - 1[sec]) */ 3006 1.1 hsuenaga if (time_us < 0 || time_us > (1000 * 1000)) { 3007 1.1 hsuenaga mvxpe_rx_unlockq(sc, arg->queue); 3008 1.1 hsuenaga mvxpe_sc_unlock(sc); 3009 1.1 hsuenaga return EINVAL; 3010 1.1 hsuenaga } 3011 1.1 hsuenaga time_mvtclk = 3012 1.1 hsuenaga (uint64_t)mvTclk * (uint64_t)time_us / (1000ULL * 1000ULL); 3013 1.1 hsuenaga rx->rx_queue_th_time = time_mvtclk; 3014 1.1 hsuenaga reg = MVXPE_PRXITTH_RITT(rx->rx_queue_th_time); 3015 1.1 hsuenaga MVXPE_WRITE(sc, MVXPE_PRXITTH(arg->queue), reg); 3016 1.1 hsuenaga DPRINTSC(sc, 1, "RXITTH(%d) => %#x\n", arg->queue, reg); 3017 1.1 hsuenaga mvxpe_rx_unlockq(sc, arg->queue); 3018 1.1 hsuenaga mvxpe_sc_unlock(sc); 3019 1.1 hsuenaga 3020 1.1 hsuenaga return 0; 3021 1.1 hsuenaga } 3022 1.1 hsuenaga 3023 1.1 hsuenaga 3024 1.1 hsuenaga STATIC void 3025 1.1 hsuenaga sysctl_mvxpe_init(struct mvxpe_softc *sc) 3026 1.1 hsuenaga { 3027 1.1 hsuenaga struct ifnet *ifp = &sc->sc_ethercom.ec_if; 3028 1.1 hsuenaga const struct sysctlnode *node; 3029 1.1 hsuenaga int mvxpe_nodenum; 3030 1.1 hsuenaga int mvxpe_mibnum; 3031 1.1 hsuenaga int mvxpe_rxqueuenum; 3032 1.1 hsuenaga int mvxpe_txqueuenum; 3033 1.1 hsuenaga int q, i; 3034 1.1 hsuenaga 3035 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit] */ 3036 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3037 1.1 hsuenaga 0, CTLTYPE_NODE, ifp->if_xname, 3038 1.1 hsuenaga SYSCTL_DESCR("mvxpe per-controller controls"), 3039 1.1 hsuenaga NULL, 0, NULL, 0, 3040 1.1 hsuenaga CTL_HW, mvxpe_root_num, CTL_CREATE, 3041 1.1 hsuenaga CTL_EOL) != 0) { 3042 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n"); 3043 1.1 hsuenaga return; 3044 1.1 hsuenaga } 3045 1.1 hsuenaga mvxpe_nodenum = node->sysctl_num; 3046 1.1 hsuenaga 3047 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].mib */ 3048 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3049 1.1 hsuenaga 0, CTLTYPE_NODE, "mib", 3050 1.1 hsuenaga SYSCTL_DESCR("mvxpe per-controller MIB counters"), 3051 1.1 hsuenaga NULL, 0, NULL, 0, 3052 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, CTL_CREATE, 3053 1.1 hsuenaga CTL_EOL) != 0) { 3054 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n"); 3055 1.1 hsuenaga return; 3056 1.1 hsuenaga } 3057 1.1 hsuenaga mvxpe_mibnum = node->sysctl_num; 3058 1.1 hsuenaga 3059 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].rx */ 3060 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3061 1.1 hsuenaga 0, CTLTYPE_NODE, "rx", 3062 1.1 hsuenaga SYSCTL_DESCR("Rx Queues"), 3063 1.1 hsuenaga NULL, 0, NULL, 0, 3064 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, CTL_CREATE, CTL_EOL) != 0) { 3065 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n"); 3066 1.1 hsuenaga return; 3067 1.1 hsuenaga } 3068 1.1 hsuenaga mvxpe_rxqueuenum = node->sysctl_num; 3069 1.1 hsuenaga 3070 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].tx */ 3071 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3072 1.1 hsuenaga 0, CTLTYPE_NODE, "tx", 3073 1.1 hsuenaga SYSCTL_DESCR("Tx Queues"), 3074 1.1 hsuenaga NULL, 0, NULL, 0, 3075 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, CTL_CREATE, CTL_EOL) != 0) { 3076 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n"); 3077 1.1 hsuenaga return; 3078 1.1 hsuenaga } 3079 1.1 hsuenaga mvxpe_txqueuenum = node->sysctl_num; 3080 1.1 hsuenaga 3081 1.1 hsuenaga #ifdef MVXPE_DEBUG 3082 1.1 hsuenaga /* hw.mvxpe.debug */ 3083 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3084 1.1 hsuenaga CTLFLAG_READWRITE, CTLTYPE_INT, "debug", 3085 1.11 hikaru SYSCTL_DESCR("mvxpe device driver debug control"), 3086 1.1 hsuenaga NULL, 0, &mvxpe_debug, 0, 3087 1.1 hsuenaga CTL_HW, mvxpe_root_num, CTL_CREATE, CTL_EOL) != 0) { 3088 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n"); 3089 1.1 hsuenaga return; 3090 1.1 hsuenaga } 3091 1.1 hsuenaga #endif 3092 1.1 hsuenaga /* 3093 1.1 hsuenaga * MIB access 3094 1.1 hsuenaga */ 3095 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].mib.<mibs> */ 3096 1.1 hsuenaga for (i = 0; i < __arraycount(mvxpe_mib_list); i++) { 3097 1.1 hsuenaga const char *name = mvxpe_mib_list[i].sysctl_name; 3098 1.1 hsuenaga const char *desc = mvxpe_mib_list[i].desc; 3099 1.1 hsuenaga struct mvxpe_sysctl_mib *mib_arg = &sc->sc_sysctl_mib[i]; 3100 1.1 hsuenaga 3101 1.1 hsuenaga mib_arg->sc = sc; 3102 1.24 msaitoh mib_arg->index = i; 3103 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3104 1.1 hsuenaga CTLFLAG_READONLY, CTLTYPE_QUAD, name, desc, 3105 1.1 hsuenaga sysctl_read_mib, 0, (void *)mib_arg, 0, 3106 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_mibnum, 3107 1.1 hsuenaga CTL_CREATE, CTL_EOL) != 0) { 3108 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, 3109 1.1 hsuenaga "couldn't create sysctl node\n"); 3110 1.1 hsuenaga break; 3111 1.1 hsuenaga } 3112 1.1 hsuenaga } 3113 1.1 hsuenaga 3114 1.1 hsuenaga for (q = 0; q < MVXPE_QUEUE_SIZE; q++) { 3115 1.1 hsuenaga struct mvxpe_sysctl_queue *rxarg = &sc->sc_sysctl_rx_queue[q]; 3116 1.1 hsuenaga struct mvxpe_sysctl_queue *txarg = &sc->sc_sysctl_tx_queue[q]; 3117 1.1 hsuenaga #define MVXPE_SYSCTL_NAME(num) "queue" # num 3118 1.1 hsuenaga static const char *sysctl_queue_names[] = { 3119 1.1 hsuenaga MVXPE_SYSCTL_NAME(0), MVXPE_SYSCTL_NAME(1), 3120 1.1 hsuenaga MVXPE_SYSCTL_NAME(2), MVXPE_SYSCTL_NAME(3), 3121 1.1 hsuenaga MVXPE_SYSCTL_NAME(4), MVXPE_SYSCTL_NAME(5), 3122 1.1 hsuenaga MVXPE_SYSCTL_NAME(6), MVXPE_SYSCTL_NAME(7), 3123 1.1 hsuenaga }; 3124 1.1 hsuenaga #undef MVXPE_SYSCTL_NAME 3125 1.1 hsuenaga #ifdef SYSCTL_INCLUDE_DESCR 3126 1.1 hsuenaga #define MVXPE_SYSCTL_DESCR(num) "configuration parameters for queue " # num 3127 1.1 hsuenaga static const char *sysctl_queue_descrs[] = { 3128 1.11 hikaru MVXPE_SYSCTL_DESCR(0), MVXPE_SYSCTL_DESCR(1), 3129 1.11 hikaru MVXPE_SYSCTL_DESCR(2), MVXPE_SYSCTL_DESCR(3), 3130 1.11 hikaru MVXPE_SYSCTL_DESCR(4), MVXPE_SYSCTL_DESCR(5), 3131 1.11 hikaru MVXPE_SYSCTL_DESCR(6), MVXPE_SYSCTL_DESCR(7), 3132 1.1 hsuenaga }; 3133 1.1 hsuenaga #undef MVXPE_SYSCTL_DESCR 3134 1.1 hsuenaga #endif /* SYSCTL_INCLUDE_DESCR */ 3135 1.1 hsuenaga int mvxpe_curnum; 3136 1.1 hsuenaga 3137 1.1 hsuenaga rxarg->sc = txarg->sc = sc; 3138 1.1 hsuenaga rxarg->queue = txarg->queue = q; 3139 1.1 hsuenaga rxarg->rxtx = MVXPE_SYSCTL_RX; 3140 1.1 hsuenaga txarg->rxtx = MVXPE_SYSCTL_TX; 3141 1.1 hsuenaga 3142 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].rx.[queue] */ 3143 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3144 1.1 hsuenaga 0, CTLTYPE_NODE, 3145 1.1 hsuenaga sysctl_queue_names[q], SYSCTL_DESCR(sysctl_queue_descrs[q]), 3146 1.1 hsuenaga NULL, 0, NULL, 0, 3147 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_rxqueuenum, 3148 1.1 hsuenaga CTL_CREATE, CTL_EOL) != 0) { 3149 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, 3150 1.1 hsuenaga "couldn't create sysctl node\n"); 3151 1.1 hsuenaga break; 3152 1.1 hsuenaga } 3153 1.1 hsuenaga mvxpe_curnum = node->sysctl_num; 3154 1.1 hsuenaga 3155 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].rx.[queue].length */ 3156 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3157 1.1 hsuenaga CTLFLAG_READWRITE, CTLTYPE_INT, "length", 3158 1.1 hsuenaga SYSCTL_DESCR("maximum length of the queue"), 3159 1.1 hsuenaga sysctl_set_queue_length, 0, (void *)rxarg, 0, 3160 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_rxqueuenum, 3161 1.1 hsuenaga mvxpe_curnum, CTL_CREATE, CTL_EOL) != 0) { 3162 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, 3163 1.1 hsuenaga "couldn't create sysctl node\n"); 3164 1.1 hsuenaga break; 3165 1.1 hsuenaga } 3166 1.1 hsuenaga 3167 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].rx.[queue].threshold_timer_us */ 3168 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3169 1.1 hsuenaga CTLFLAG_READWRITE, CTLTYPE_INT, "threshold_timer_us", 3170 1.1 hsuenaga SYSCTL_DESCR("interrupt coalescing threshold timer [us]"), 3171 1.1 hsuenaga sysctl_set_queue_rxthtime, 0, (void *)rxarg, 0, 3172 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_rxqueuenum, 3173 1.1 hsuenaga mvxpe_curnum, CTL_CREATE, CTL_EOL) != 0) { 3174 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, 3175 1.1 hsuenaga "couldn't create sysctl node\n"); 3176 1.1 hsuenaga break; 3177 1.1 hsuenaga } 3178 1.1 hsuenaga 3179 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].tx.[queue] */ 3180 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3181 1.1 hsuenaga 0, CTLTYPE_NODE, 3182 1.1 hsuenaga sysctl_queue_names[q], SYSCTL_DESCR(sysctl_queue_descs[q]), 3183 1.1 hsuenaga NULL, 0, NULL, 0, 3184 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_txqueuenum, 3185 1.1 hsuenaga CTL_CREATE, CTL_EOL) != 0) { 3186 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, 3187 1.1 hsuenaga "couldn't create sysctl node\n"); 3188 1.1 hsuenaga break; 3189 1.1 hsuenaga } 3190 1.1 hsuenaga mvxpe_curnum = node->sysctl_num; 3191 1.1 hsuenaga 3192 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].tx.length[queue] */ 3193 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3194 1.1 hsuenaga CTLFLAG_READWRITE, CTLTYPE_INT, "length", 3195 1.1 hsuenaga SYSCTL_DESCR("maximum length of the queue"), 3196 1.1 hsuenaga sysctl_set_queue_length, 0, (void *)txarg, 0, 3197 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, mvxpe_txqueuenum, 3198 1.1 hsuenaga mvxpe_curnum, CTL_CREATE, CTL_EOL) != 0) { 3199 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, 3200 1.1 hsuenaga "couldn't create sysctl node\n"); 3201 1.1 hsuenaga break; 3202 1.1 hsuenaga } 3203 1.1 hsuenaga } 3204 1.1 hsuenaga 3205 1.1 hsuenaga /* hw.mvxpe.mvxpe[unit].clear_mib */ 3206 1.1 hsuenaga if (sysctl_createv(&sc->sc_mvxpe_clog, 0, NULL, &node, 3207 1.1 hsuenaga CTLFLAG_READWRITE, CTLTYPE_INT, "clear_mib", 3208 1.11 hikaru SYSCTL_DESCR("mvxpe device driver debug control"), 3209 1.1 hsuenaga sysctl_clear_mib, 0, (void *)sc, 0, 3210 1.1 hsuenaga CTL_HW, mvxpe_root_num, mvxpe_nodenum, CTL_CREATE, 3211 1.1 hsuenaga CTL_EOL) != 0) { 3212 1.1 hsuenaga aprint_normal_dev(sc->sc_dev, "couldn't create sysctl node\n"); 3213 1.1 hsuenaga return; 3214 1.1 hsuenaga } 3215 1.1 hsuenaga 3216 1.1 hsuenaga } 3217 1.1 hsuenaga 3218 1.1 hsuenaga /* 3219 1.1 hsuenaga * MIB 3220 1.1 hsuenaga */ 3221 1.1 hsuenaga STATIC void 3222 1.1 hsuenaga mvxpe_clear_mib(struct mvxpe_softc *sc) 3223 1.1 hsuenaga { 3224 1.1 hsuenaga int i; 3225 1.1 hsuenaga 3226 1.1 hsuenaga KASSERT_SC_MTX(sc); 3227 1.1 hsuenaga 3228 1.1 hsuenaga for (i = 0; i < __arraycount(mvxpe_mib_list); i++) { 3229 1.1 hsuenaga if (mvxpe_mib_list[i].reg64) 3230 1.1 hsuenaga MVXPE_READ_MIB(sc, (mvxpe_mib_list[i].regnum + 4)); 3231 1.1 hsuenaga MVXPE_READ_MIB(sc, mvxpe_mib_list[i].regnum); 3232 1.1 hsuenaga sc->sc_sysctl_mib[i].counter = 0; 3233 1.1 hsuenaga } 3234 1.1 hsuenaga } 3235 1.1 hsuenaga 3236 1.1 hsuenaga STATIC void 3237 1.1 hsuenaga mvxpe_update_mib(struct mvxpe_softc *sc) 3238 1.1 hsuenaga { 3239 1.10 hikaru struct ifnet *ifp = &sc->sc_ethercom.ec_if; 3240 1.1 hsuenaga int i; 3241 1.1 hsuenaga 3242 1.1 hsuenaga KASSERT_SC_MTX(sc); 3243 1.1 hsuenaga 3244 1.1 hsuenaga for (i = 0; i < __arraycount(mvxpe_mib_list); i++) { 3245 1.1 hsuenaga uint32_t val_hi; 3246 1.1 hsuenaga uint32_t val_lo; 3247 1.10 hikaru uint64_t val; 3248 1.1 hsuenaga 3249 1.1 hsuenaga if (mvxpe_mib_list[i].reg64) { 3250 1.1 hsuenaga /* XXX: implement bus_space_read_8() */ 3251 1.1 hsuenaga val_lo = MVXPE_READ_MIB(sc, 3252 1.1 hsuenaga (mvxpe_mib_list[i].regnum + 4)); 3253 1.1 hsuenaga val_hi = MVXPE_READ_MIB(sc, mvxpe_mib_list[i].regnum); 3254 1.1 hsuenaga } 3255 1.1 hsuenaga else { 3256 1.1 hsuenaga val_lo = MVXPE_READ_MIB(sc, mvxpe_mib_list[i].regnum); 3257 1.1 hsuenaga val_hi = 0; 3258 1.1 hsuenaga } 3259 1.1 hsuenaga 3260 1.1 hsuenaga if ((val_lo | val_hi) == 0) 3261 1.1 hsuenaga continue; 3262 1.1 hsuenaga 3263 1.10 hikaru val = ((uint64_t)val_hi << 32) | (uint64_t)val_lo; 3264 1.10 hikaru sc->sc_sysctl_mib[i].counter += val; 3265 1.10 hikaru 3266 1.10 hikaru switch (mvxpe_mib_list[i].ext) { 3267 1.10 hikaru case MVXPE_MIBEXT_IF_OERRORS: 3268 1.33 skrll if_statadd(ifp, if_oerrors, val); 3269 1.10 hikaru break; 3270 1.10 hikaru case MVXPE_MIBEXT_IF_IERRORS: 3271 1.33 skrll if_statadd(ifp, if_ierrors, val); 3272 1.10 hikaru break; 3273 1.10 hikaru case MVXPE_MIBEXT_IF_COLLISIONS: 3274 1.32 skrll if_statadd(ifp, if_collisions, val); 3275 1.10 hikaru break; 3276 1.10 hikaru default: 3277 1.10 hikaru break; 3278 1.10 hikaru } 3279 1.10 hikaru 3280 1.1 hsuenaga } 3281 1.1 hsuenaga } 3282 1.1 hsuenaga 3283 1.1 hsuenaga /* 3284 1.1 hsuenaga * for Debug 3285 1.1 hsuenaga */ 3286 1.1 hsuenaga STATIC void 3287 1.1 hsuenaga mvxpe_dump_txdesc(struct mvxpe_tx_desc *desc, int idx) 3288 1.1 hsuenaga { 3289 1.1 hsuenaga #define DESC_PRINT(X) \ 3290 1.1 hsuenaga if (X) \ 3291 1.1 hsuenaga printf("txdesc[%d]." #X "=%#x\n", idx, X); 3292 1.1 hsuenaga 3293 1.1 hsuenaga DESC_PRINT(desc->command); 3294 1.1 hsuenaga DESC_PRINT(desc->l4ichk); 3295 1.1 hsuenaga DESC_PRINT(desc->bytecnt); 3296 1.1 hsuenaga DESC_PRINT(desc->bufptr); 3297 1.1 hsuenaga DESC_PRINT(desc->flags); 3298 1.1 hsuenaga #undef DESC_PRINT 3299 1.1 hsuenaga } 3300 1.1 hsuenaga 3301 1.1 hsuenaga STATIC void 3302 1.1 hsuenaga mvxpe_dump_rxdesc(struct mvxpe_rx_desc *desc, int idx) 3303 1.1 hsuenaga { 3304 1.1 hsuenaga #define DESC_PRINT(X) \ 3305 1.1 hsuenaga if (X) \ 3306 1.1 hsuenaga printf("rxdesc[%d]." #X "=%#x\n", idx, X); 3307 1.1 hsuenaga 3308 1.1 hsuenaga DESC_PRINT(desc->status); 3309 1.1 hsuenaga DESC_PRINT(desc->bytecnt); 3310 1.1 hsuenaga DESC_PRINT(desc->bufptr); 3311 1.1 hsuenaga DESC_PRINT(desc->l4chk); 3312 1.1 hsuenaga #undef DESC_PRINT 3313 1.1 hsuenaga } 3314