1ae813fd8SSepherosa Ziehau /* $OpenBSD: if_nfe.c,v 1.63 2006/06/17 18:00:43 brad Exp $ */ 2*8b712a27SSepherosa Ziehau /* $DragonFly: src/sys/dev/netif/nfe/if_nfe.c,v 1.15 2007/08/10 15:29:25 sephe Exp $ */ 3ae813fd8SSepherosa Ziehau 4ae813fd8SSepherosa Ziehau /* 5ae813fd8SSepherosa Ziehau * Copyright (c) 2006 The DragonFly Project. All rights reserved. 6ae813fd8SSepherosa Ziehau * 7ae813fd8SSepherosa Ziehau * This code is derived from software contributed to The DragonFly Project 8ae813fd8SSepherosa Ziehau * by Sepherosa Ziehau <sepherosa@gmail.com> and 9ae813fd8SSepherosa Ziehau * Matthew Dillon <dillon@apollo.backplane.com> 10ae813fd8SSepherosa Ziehau * 11ae813fd8SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 12ae813fd8SSepherosa Ziehau * modification, are permitted provided that the following conditions 13ae813fd8SSepherosa Ziehau * are met: 14ae813fd8SSepherosa Ziehau * 15ae813fd8SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 16ae813fd8SSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 17ae813fd8SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 18ae813fd8SSepherosa Ziehau * notice, this list of conditions and the following disclaimer in 19ae813fd8SSepherosa Ziehau * the documentation and/or other materials provided with the 20ae813fd8SSepherosa Ziehau * distribution. 21ae813fd8SSepherosa Ziehau * 3. Neither the name of The DragonFly Project nor the names of its 22ae813fd8SSepherosa Ziehau * contributors may be used to endorse or promote products derived 23ae813fd8SSepherosa Ziehau * from this software without specific, prior written permission. 24ae813fd8SSepherosa Ziehau * 25ae813fd8SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26ae813fd8SSepherosa Ziehau * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27ae813fd8SSepherosa Ziehau * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28ae813fd8SSepherosa Ziehau * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29ae813fd8SSepherosa Ziehau * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30ae813fd8SSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 31ae813fd8SSepherosa Ziehau * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32ae813fd8SSepherosa Ziehau * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 33ae813fd8SSepherosa Ziehau * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 34ae813fd8SSepherosa Ziehau * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 35ae813fd8SSepherosa Ziehau * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36ae813fd8SSepherosa Ziehau * SUCH DAMAGE. 37ae813fd8SSepherosa Ziehau */ 38ae813fd8SSepherosa Ziehau 39ae813fd8SSepherosa Ziehau /* 40ae813fd8SSepherosa Ziehau * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> 41ae813fd8SSepherosa Ziehau * Copyright (c) 2005, 2006 Jonathan Gray <jsg@openbsd.org> 42ae813fd8SSepherosa Ziehau * 43ae813fd8SSepherosa Ziehau * Permission to use, copy, modify, and distribute this software for any 44ae813fd8SSepherosa Ziehau * purpose with or without fee is hereby granted, provided that the above 45ae813fd8SSepherosa Ziehau * copyright notice and this permission notice appear in all copies. 46ae813fd8SSepherosa Ziehau * 47ae813fd8SSepherosa Ziehau * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 48ae813fd8SSepherosa Ziehau * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 49ae813fd8SSepherosa Ziehau * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 50ae813fd8SSepherosa Ziehau * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 51ae813fd8SSepherosa Ziehau * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 52ae813fd8SSepherosa Ziehau * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 53ae813fd8SSepherosa Ziehau * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 54ae813fd8SSepherosa Ziehau */ 55ae813fd8SSepherosa Ziehau 56ae813fd8SSepherosa Ziehau /* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */ 57ae813fd8SSepherosa Ziehau 58ae813fd8SSepherosa Ziehau #include "opt_polling.h" 59ae813fd8SSepherosa Ziehau 60ae813fd8SSepherosa Ziehau #include <sys/param.h> 61ae813fd8SSepherosa Ziehau #include <sys/endian.h> 62ae813fd8SSepherosa Ziehau #include <sys/kernel.h> 63ae813fd8SSepherosa Ziehau #include <sys/bus.h> 64ae813fd8SSepherosa Ziehau #include <sys/proc.h> 65ae813fd8SSepherosa Ziehau #include <sys/rman.h> 66ae813fd8SSepherosa Ziehau #include <sys/serialize.h> 67ae813fd8SSepherosa Ziehau #include <sys/socket.h> 68ae813fd8SSepherosa Ziehau #include <sys/sockio.h> 69ae813fd8SSepherosa Ziehau #include <sys/sysctl.h> 70ae813fd8SSepherosa Ziehau 71ae813fd8SSepherosa Ziehau #include <net/ethernet.h> 72ae813fd8SSepherosa Ziehau #include <net/if.h> 73ae813fd8SSepherosa Ziehau #include <net/bpf.h> 74ae813fd8SSepherosa Ziehau #include <net/if_arp.h> 75ae813fd8SSepherosa Ziehau #include <net/if_dl.h> 76ae813fd8SSepherosa Ziehau #include <net/if_media.h> 77ae813fd8SSepherosa Ziehau #include <net/ifq_var.h> 78ae813fd8SSepherosa Ziehau #include <net/if_types.h> 79ae813fd8SSepherosa Ziehau #include <net/if_var.h> 80ae813fd8SSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 81ae813fd8SSepherosa Ziehau 82ae813fd8SSepherosa Ziehau #include <bus/pci/pcireg.h> 83ae813fd8SSepherosa Ziehau #include <bus/pci/pcivar.h> 84ae813fd8SSepherosa Ziehau #include <bus/pci/pcidevs.h> 85ae813fd8SSepherosa Ziehau 86ae813fd8SSepherosa Ziehau #include <dev/netif/mii_layer/mii.h> 87ae813fd8SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 88ae813fd8SSepherosa Ziehau 89ae813fd8SSepherosa Ziehau #include "miibus_if.h" 90ae813fd8SSepherosa Ziehau 9111db6c57SSepherosa Ziehau #include <dev/netif/nfe/if_nfereg.h> 9211db6c57SSepherosa Ziehau #include <dev/netif/nfe/if_nfevar.h> 9311db6c57SSepherosa Ziehau 9411db6c57SSepherosa Ziehau #define NFE_CSUM 9511db6c57SSepherosa Ziehau #define NFE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 96ae813fd8SSepherosa Ziehau 97ae813fd8SSepherosa Ziehau static int nfe_probe(device_t); 98ae813fd8SSepherosa Ziehau static int nfe_attach(device_t); 99ae813fd8SSepherosa Ziehau static int nfe_detach(device_t); 100ae813fd8SSepherosa Ziehau static void nfe_shutdown(device_t); 101ae813fd8SSepherosa Ziehau static int nfe_resume(device_t); 102ae813fd8SSepherosa Ziehau static int nfe_suspend(device_t); 103ae813fd8SSepherosa Ziehau 104ae813fd8SSepherosa Ziehau static int nfe_miibus_readreg(device_t, int, int); 105ae813fd8SSepherosa Ziehau static void nfe_miibus_writereg(device_t, int, int, int); 106ae813fd8SSepherosa Ziehau static void nfe_miibus_statchg(device_t); 107ae813fd8SSepherosa Ziehau 108ae813fd8SSepherosa Ziehau #ifdef DEVICE_POLLING 109ae813fd8SSepherosa Ziehau static void nfe_poll(struct ifnet *, enum poll_cmd, int); 110ae813fd8SSepherosa Ziehau #endif 111ae813fd8SSepherosa Ziehau static void nfe_intr(void *); 112ae813fd8SSepherosa Ziehau static int nfe_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 113ae813fd8SSepherosa Ziehau static void nfe_rxeof(struct nfe_softc *); 114ae813fd8SSepherosa Ziehau static void nfe_txeof(struct nfe_softc *); 115ae813fd8SSepherosa Ziehau static int nfe_encap(struct nfe_softc *, struct nfe_tx_ring *, 116ae813fd8SSepherosa Ziehau struct mbuf *); 117ae813fd8SSepherosa Ziehau static void nfe_start(struct ifnet *); 118ae813fd8SSepherosa Ziehau static void nfe_watchdog(struct ifnet *); 119ae813fd8SSepherosa Ziehau static void nfe_init(void *); 120ae813fd8SSepherosa Ziehau static void nfe_stop(struct nfe_softc *); 121ae813fd8SSepherosa Ziehau static struct nfe_jbuf *nfe_jalloc(struct nfe_softc *); 122ae813fd8SSepherosa Ziehau static void nfe_jfree(void *); 123ae813fd8SSepherosa Ziehau static void nfe_jref(void *); 124ae813fd8SSepherosa Ziehau static int nfe_jpool_alloc(struct nfe_softc *, struct nfe_rx_ring *); 125ae813fd8SSepherosa Ziehau static void nfe_jpool_free(struct nfe_softc *, struct nfe_rx_ring *); 126ae813fd8SSepherosa Ziehau static int nfe_alloc_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 127ae813fd8SSepherosa Ziehau static void nfe_reset_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 128ae813fd8SSepherosa Ziehau static int nfe_init_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 129ae813fd8SSepherosa Ziehau static void nfe_free_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 130ae813fd8SSepherosa Ziehau static int nfe_alloc_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 131ae813fd8SSepherosa Ziehau static void nfe_reset_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 132ae813fd8SSepherosa Ziehau static int nfe_init_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 133ae813fd8SSepherosa Ziehau static void nfe_free_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 134ae813fd8SSepherosa Ziehau static int nfe_ifmedia_upd(struct ifnet *); 135ae813fd8SSepherosa Ziehau static void nfe_ifmedia_sts(struct ifnet *, struct ifmediareq *); 136ae813fd8SSepherosa Ziehau static void nfe_setmulti(struct nfe_softc *); 137ae813fd8SSepherosa Ziehau static void nfe_get_macaddr(struct nfe_softc *, uint8_t *); 138ae813fd8SSepherosa Ziehau static void nfe_set_macaddr(struct nfe_softc *, const uint8_t *); 139ae813fd8SSepherosa Ziehau static void nfe_tick(void *); 140ae813fd8SSepherosa Ziehau static void nfe_ring_dma_addr(void *, bus_dma_segment_t *, int, int); 141ae813fd8SSepherosa Ziehau static void nfe_buf_dma_addr(void *, bus_dma_segment_t *, int, bus_size_t, 142ae813fd8SSepherosa Ziehau int); 143ae813fd8SSepherosa Ziehau static void nfe_set_paddr_rxdesc(struct nfe_softc *, struct nfe_rx_ring *, 144ae813fd8SSepherosa Ziehau int, bus_addr_t); 145ae813fd8SSepherosa Ziehau static void nfe_set_ready_rxdesc(struct nfe_softc *, struct nfe_rx_ring *, 146ae813fd8SSepherosa Ziehau int); 147ae813fd8SSepherosa Ziehau static int nfe_newbuf_std(struct nfe_softc *, struct nfe_rx_ring *, int, 148ae813fd8SSepherosa Ziehau int); 149ae813fd8SSepherosa Ziehau static int nfe_newbuf_jumbo(struct nfe_softc *, struct nfe_rx_ring *, int, 150ae813fd8SSepherosa Ziehau int); 151ae813fd8SSepherosa Ziehau 152ae813fd8SSepherosa Ziehau #define NFE_DEBUG 153ae813fd8SSepherosa Ziehau #ifdef NFE_DEBUG 154ae813fd8SSepherosa Ziehau 155ae813fd8SSepherosa Ziehau static int nfe_debug = 0; 156a455c52eSSepherosa Ziehau static int nfe_rx_ring_count = NFE_RX_RING_DEF_COUNT; 157a455c52eSSepherosa Ziehau 158a455c52eSSepherosa Ziehau TUNABLE_INT("hw.nfe.rx_ring_count", &nfe_rx_ring_count); 159ae813fd8SSepherosa Ziehau 160ae813fd8SSepherosa Ziehau SYSCTL_NODE(_hw, OID_AUTO, nfe, CTLFLAG_RD, 0, "nVidia GigE parameters"); 161a455c52eSSepherosa Ziehau SYSCTL_INT(_hw_nfe, OID_AUTO, rx_ring_count, CTLFLAG_RD, &nfe_rx_ring_count, 162a455c52eSSepherosa Ziehau NFE_RX_RING_DEF_COUNT, "rx ring count"); 163ae813fd8SSepherosa Ziehau SYSCTL_INT(_hw_nfe, OID_AUTO, debug, CTLFLAG_RW, &nfe_debug, 0, 164ae813fd8SSepherosa Ziehau "control debugging printfs"); 165ae813fd8SSepherosa Ziehau 166ae813fd8SSepherosa Ziehau #define DPRINTF(sc, fmt, ...) do { \ 167ae813fd8SSepherosa Ziehau if (nfe_debug) { \ 168ae813fd8SSepherosa Ziehau if_printf(&(sc)->arpcom.ac_if, \ 169ae813fd8SSepherosa Ziehau fmt, __VA_ARGS__); \ 170ae813fd8SSepherosa Ziehau } \ 171ae813fd8SSepherosa Ziehau } while (0) 172ae813fd8SSepherosa Ziehau 173ae813fd8SSepherosa Ziehau #define DPRINTFN(sc, lv, fmt, ...) do { \ 174ae813fd8SSepherosa Ziehau if (nfe_debug >= (lv)) { \ 175ae813fd8SSepherosa Ziehau if_printf(&(sc)->arpcom.ac_if, \ 176ae813fd8SSepherosa Ziehau fmt, __VA_ARGS__); \ 177ae813fd8SSepherosa Ziehau } \ 178ae813fd8SSepherosa Ziehau } while (0) 179ae813fd8SSepherosa Ziehau 180ae813fd8SSepherosa Ziehau #else /* !NFE_DEBUG */ 181ae813fd8SSepherosa Ziehau 182ae813fd8SSepherosa Ziehau #define DPRINTF(sc, fmt, ...) 183ae813fd8SSepherosa Ziehau #define DPRINTFN(sc, lv, fmt, ...) 184ae813fd8SSepherosa Ziehau 185ae813fd8SSepherosa Ziehau #endif /* NFE_DEBUG */ 186ae813fd8SSepherosa Ziehau 187ae813fd8SSepherosa Ziehau struct nfe_dma_ctx { 188ae813fd8SSepherosa Ziehau int nsegs; 189ae813fd8SSepherosa Ziehau bus_dma_segment_t *segs; 190ae813fd8SSepherosa Ziehau }; 191ae813fd8SSepherosa Ziehau 192ae813fd8SSepherosa Ziehau static const struct nfe_dev { 193ae813fd8SSepherosa Ziehau uint16_t vid; 194ae813fd8SSepherosa Ziehau uint16_t did; 195ae813fd8SSepherosa Ziehau const char *desc; 196ae813fd8SSepherosa Ziehau } nfe_devices[] = { 197ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN, 19887e3db44SThomas E. Spanjaard "NVIDIA nForce Fast Ethernet" }, 199ae813fd8SSepherosa Ziehau 200ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN, 20187e3db44SThomas E. Spanjaard "NVIDIA nForce2 Fast Ethernet" }, 202ae813fd8SSepherosa Ziehau 203ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1, 204ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 205ae813fd8SSepherosa Ziehau 20687e3db44SThomas E. Spanjaard /* XXX TGEN the next chip can also be found in the nForce2 Ultra 400Gb 20787e3db44SThomas E. Spanjaard chipset, and possibly also the 400R; it might be both nForce2- and 20887e3db44SThomas E. Spanjaard nForce3-based boards can use the same MCPs (= southbridges) */ 209ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN2, 210ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 211ae813fd8SSepherosa Ziehau 212ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN3, 213ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 214ae813fd8SSepherosa Ziehau 215ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4, 216ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 217ae813fd8SSepherosa Ziehau 218ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN5, 219ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 220ae813fd8SSepherosa Ziehau 221ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_CK804_LAN1, 222ae813fd8SSepherosa Ziehau "NVIDIA CK804 Gigabit Ethernet" }, 223ae813fd8SSepherosa Ziehau 224ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_CK804_LAN2, 225ae813fd8SSepherosa Ziehau "NVIDIA CK804 Gigabit Ethernet" }, 226ae813fd8SSepherosa Ziehau 227ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1, 228ae813fd8SSepherosa Ziehau "NVIDIA MCP04 Gigabit Ethernet" }, 229ae813fd8SSepherosa Ziehau 230ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2, 231ae813fd8SSepherosa Ziehau "NVIDIA MCP04 Gigabit Ethernet" }, 232ae813fd8SSepherosa Ziehau 233ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_LAN1, 234ae813fd8SSepherosa Ziehau "NVIDIA MCP51 Gigabit Ethernet" }, 235ae813fd8SSepherosa Ziehau 236ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_LAN2, 237ae813fd8SSepherosa Ziehau "NVIDIA MCP51 Gigabit Ethernet" }, 238ae813fd8SSepherosa Ziehau 239ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1, 240ae813fd8SSepherosa Ziehau "NVIDIA MCP55 Gigabit Ethernet" }, 241ae813fd8SSepherosa Ziehau 242ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2, 2439d1ecb21SSepherosa Ziehau "NVIDIA MCP55 Gigabit Ethernet" }, 2449d1ecb21SSepherosa Ziehau 2459d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1, 2469d1ecb21SSepherosa Ziehau "NVIDIA MCP61 Gigabit Ethernet" }, 2479d1ecb21SSepherosa Ziehau 2489d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, 2499d1ecb21SSepherosa Ziehau "NVIDIA MCP61 Gigabit Ethernet" }, 2509d1ecb21SSepherosa Ziehau 2519d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3, 2529d1ecb21SSepherosa Ziehau "NVIDIA MCP61 Gigabit Ethernet" }, 2539d1ecb21SSepherosa Ziehau 2549d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN4, 2559d1ecb21SSepherosa Ziehau "NVIDIA MCP61 Gigabit Ethernet" }, 2569d1ecb21SSepherosa Ziehau 2579d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1, 2589d1ecb21SSepherosa Ziehau "NVIDIA MCP65 Gigabit Ethernet" }, 2599d1ecb21SSepherosa Ziehau 2609d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, 2619d1ecb21SSepherosa Ziehau "NVIDIA MCP65 Gigabit Ethernet" }, 2629d1ecb21SSepherosa Ziehau 2639d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3, 2649d1ecb21SSepherosa Ziehau "NVIDIA MCP65 Gigabit Ethernet" }, 2659d1ecb21SSepherosa Ziehau 2669d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN4, 267df290cacSSepherosa Ziehau "NVIDIA MCP65 Gigabit Ethernet" }, 268df290cacSSepherosa Ziehau 269df290cacSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN1, 270df290cacSSepherosa Ziehau "NVIDIA MCP67 Gigabit Ethernet" }, 271df290cacSSepherosa Ziehau 272df290cacSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN2, 273df290cacSSepherosa Ziehau "NVIDIA MCP67 Gigabit Ethernet" }, 274df290cacSSepherosa Ziehau 275df290cacSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN3, 276df290cacSSepherosa Ziehau "NVIDIA MCP67 Gigabit Ethernet" }, 277df290cacSSepherosa Ziehau 278df290cacSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN4, 279df290cacSSepherosa Ziehau "NVIDIA MCP67 Gigabit Ethernet" } 280ae813fd8SSepherosa Ziehau }; 281ae813fd8SSepherosa Ziehau 282ae813fd8SSepherosa Ziehau static device_method_t nfe_methods[] = { 283ae813fd8SSepherosa Ziehau /* Device interface */ 284ae813fd8SSepherosa Ziehau DEVMETHOD(device_probe, nfe_probe), 285ae813fd8SSepherosa Ziehau DEVMETHOD(device_attach, nfe_attach), 286ae813fd8SSepherosa Ziehau DEVMETHOD(device_detach, nfe_detach), 287ae813fd8SSepherosa Ziehau DEVMETHOD(device_suspend, nfe_suspend), 288ae813fd8SSepherosa Ziehau DEVMETHOD(device_resume, nfe_resume), 289ae813fd8SSepherosa Ziehau DEVMETHOD(device_shutdown, nfe_shutdown), 290ae813fd8SSepherosa Ziehau 291ae813fd8SSepherosa Ziehau /* Bus interface */ 292ae813fd8SSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 293ae813fd8SSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 294ae813fd8SSepherosa Ziehau 295ae813fd8SSepherosa Ziehau /* MII interface */ 296ae813fd8SSepherosa Ziehau DEVMETHOD(miibus_readreg, nfe_miibus_readreg), 297ae813fd8SSepherosa Ziehau DEVMETHOD(miibus_writereg, nfe_miibus_writereg), 298ae813fd8SSepherosa Ziehau DEVMETHOD(miibus_statchg, nfe_miibus_statchg), 299ae813fd8SSepherosa Ziehau 300ae813fd8SSepherosa Ziehau { 0, 0 } 301ae813fd8SSepherosa Ziehau }; 302ae813fd8SSepherosa Ziehau 303ae813fd8SSepherosa Ziehau static driver_t nfe_driver = { 304ae813fd8SSepherosa Ziehau "nfe", 305ae813fd8SSepherosa Ziehau nfe_methods, 306ae813fd8SSepherosa Ziehau sizeof(struct nfe_softc) 307ae813fd8SSepherosa Ziehau }; 308ae813fd8SSepherosa Ziehau 309ae813fd8SSepherosa Ziehau static devclass_t nfe_devclass; 310ae813fd8SSepherosa Ziehau 311ae813fd8SSepherosa Ziehau DECLARE_DUMMY_MODULE(if_nfe); 312ae813fd8SSepherosa Ziehau MODULE_DEPEND(if_nfe, miibus, 1, 1, 1); 313ae813fd8SSepherosa Ziehau DRIVER_MODULE(if_nfe, pci, nfe_driver, nfe_devclass, 0, 0); 314ae813fd8SSepherosa Ziehau DRIVER_MODULE(miibus, nfe, miibus_driver, miibus_devclass, 0, 0); 315ae813fd8SSepherosa Ziehau 316ae813fd8SSepherosa Ziehau static int 317ae813fd8SSepherosa Ziehau nfe_probe(device_t dev) 318ae813fd8SSepherosa Ziehau { 319ae813fd8SSepherosa Ziehau const struct nfe_dev *n; 320ae813fd8SSepherosa Ziehau uint16_t vid, did; 321ae813fd8SSepherosa Ziehau 322ae813fd8SSepherosa Ziehau vid = pci_get_vendor(dev); 323ae813fd8SSepherosa Ziehau did = pci_get_device(dev); 324ae813fd8SSepherosa Ziehau for (n = nfe_devices; n->desc != NULL; ++n) { 325ae813fd8SSepherosa Ziehau if (vid == n->vid && did == n->did) { 326ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 327ae813fd8SSepherosa Ziehau 328ae813fd8SSepherosa Ziehau switch (did) { 329ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2: 330ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3: 331ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4: 332ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5: 333ae813fd8SSepherosa Ziehau sc->sc_flags = NFE_JUMBO_SUP | 334ae813fd8SSepherosa Ziehau NFE_HW_CSUM; 335ae813fd8SSepherosa Ziehau break; 336ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP51_LAN1: 337ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP51_LAN2: 3389d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP61_LAN1: 3399d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP61_LAN2: 3409d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP61_LAN3: 3419d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP61_LAN4: 342df290cacSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP67_LAN1: 343df290cacSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP67_LAN2: 344df290cacSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP67_LAN3: 345df290cacSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP67_LAN4: 346ae813fd8SSepherosa Ziehau sc->sc_flags = NFE_40BIT_ADDR; 347ae813fd8SSepherosa Ziehau break; 348ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_CK804_LAN1: 349ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_CK804_LAN2: 350ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP04_LAN1: 351ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP04_LAN2: 3529d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP65_LAN1: 3539d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP65_LAN2: 3549d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP65_LAN3: 3559d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP65_LAN4: 356ae813fd8SSepherosa Ziehau sc->sc_flags = NFE_JUMBO_SUP | 357ae813fd8SSepherosa Ziehau NFE_40BIT_ADDR | 358ae813fd8SSepherosa Ziehau NFE_HW_CSUM; 359ae813fd8SSepherosa Ziehau break; 360ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP55_LAN1: 361ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP55_LAN2: 362ae813fd8SSepherosa Ziehau sc->sc_flags = NFE_JUMBO_SUP | 363ae813fd8SSepherosa Ziehau NFE_40BIT_ADDR | 364ae813fd8SSepherosa Ziehau NFE_HW_CSUM | 365ae813fd8SSepherosa Ziehau NFE_HW_VLAN; 366ae813fd8SSepherosa Ziehau break; 367ae813fd8SSepherosa Ziehau } 368ae813fd8SSepherosa Ziehau 369ae813fd8SSepherosa Ziehau device_set_desc(dev, n->desc); 370dbcd0c9bSMatthew Dillon device_set_async_attach(dev, TRUE); 371ae813fd8SSepherosa Ziehau return 0; 372ae813fd8SSepherosa Ziehau } 373ae813fd8SSepherosa Ziehau } 374ae813fd8SSepherosa Ziehau return ENXIO; 375ae813fd8SSepherosa Ziehau } 376ae813fd8SSepherosa Ziehau 377ae813fd8SSepherosa Ziehau static int 378ae813fd8SSepherosa Ziehau nfe_attach(device_t dev) 379ae813fd8SSepherosa Ziehau { 380ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 381ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 382ae813fd8SSepherosa Ziehau uint8_t eaddr[ETHER_ADDR_LEN]; 383ae813fd8SSepherosa Ziehau int error; 384ae813fd8SSepherosa Ziehau 385ae813fd8SSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 386ae813fd8SSepherosa Ziehau lwkt_serialize_init(&sc->sc_jbuf_serializer); 387ae813fd8SSepherosa Ziehau 388ae813fd8SSepherosa Ziehau sc->sc_mem_rid = PCIR_BAR(0); 389ae813fd8SSepherosa Ziehau 390ae813fd8SSepherosa Ziehau #ifndef BURN_BRIDGES 391ae813fd8SSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 392ae813fd8SSepherosa Ziehau uint32_t mem, irq; 393ae813fd8SSepherosa Ziehau 394ae813fd8SSepherosa Ziehau mem = pci_read_config(dev, sc->sc_mem_rid, 4); 395ae813fd8SSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 396ae813fd8SSepherosa Ziehau 397ae813fd8SSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 398ae813fd8SSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 399ae813fd8SSepherosa Ziehau 400ae813fd8SSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 401ae813fd8SSepherosa Ziehau 402ae813fd8SSepherosa Ziehau pci_write_config(dev, sc->sc_mem_rid, mem, 4); 403ae813fd8SSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 404ae813fd8SSepherosa Ziehau } 405ae813fd8SSepherosa Ziehau #endif /* !BURN_BRIDGE */ 406ae813fd8SSepherosa Ziehau 407ae813fd8SSepherosa Ziehau /* Enable bus mastering */ 408ae813fd8SSepherosa Ziehau pci_enable_busmaster(dev); 409ae813fd8SSepherosa Ziehau 410ae813fd8SSepherosa Ziehau /* Allocate IO memory */ 411ae813fd8SSepherosa Ziehau sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 412ae813fd8SSepherosa Ziehau &sc->sc_mem_rid, RF_ACTIVE); 413ae813fd8SSepherosa Ziehau if (sc->sc_mem_res == NULL) { 414ae813fd8SSepherosa Ziehau device_printf(dev, "cound not allocate io memory\n"); 415ae813fd8SSepherosa Ziehau return ENXIO; 416ae813fd8SSepherosa Ziehau } 417ae813fd8SSepherosa Ziehau sc->sc_memh = rman_get_bushandle(sc->sc_mem_res); 418ae813fd8SSepherosa Ziehau sc->sc_memt = rman_get_bustag(sc->sc_mem_res); 419ae813fd8SSepherosa Ziehau 420ae813fd8SSepherosa Ziehau /* Allocate IRQ */ 421ae813fd8SSepherosa Ziehau sc->sc_irq_rid = 0; 422ae813fd8SSepherosa Ziehau sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 423ae813fd8SSepherosa Ziehau &sc->sc_irq_rid, 424ae813fd8SSepherosa Ziehau RF_SHAREABLE | RF_ACTIVE); 425ae813fd8SSepherosa Ziehau if (sc->sc_irq_res == NULL) { 426ae813fd8SSepherosa Ziehau device_printf(dev, "could not allocate irq\n"); 427ae813fd8SSepherosa Ziehau error = ENXIO; 428ae813fd8SSepherosa Ziehau goto fail; 429ae813fd8SSepherosa Ziehau } 430ae813fd8SSepherosa Ziehau 431ae813fd8SSepherosa Ziehau nfe_get_macaddr(sc, eaddr); 432ae813fd8SSepherosa Ziehau 433ae813fd8SSepherosa Ziehau /* 434ae813fd8SSepherosa Ziehau * Allocate Tx and Rx rings. 435ae813fd8SSepherosa Ziehau */ 436ae813fd8SSepherosa Ziehau error = nfe_alloc_tx_ring(sc, &sc->txq); 437ae813fd8SSepherosa Ziehau if (error) { 438ae813fd8SSepherosa Ziehau device_printf(dev, "could not allocate Tx ring\n"); 439ae813fd8SSepherosa Ziehau goto fail; 440ae813fd8SSepherosa Ziehau } 441ae813fd8SSepherosa Ziehau 442ae813fd8SSepherosa Ziehau error = nfe_alloc_rx_ring(sc, &sc->rxq); 443ae813fd8SSepherosa Ziehau if (error) { 444ae813fd8SSepherosa Ziehau device_printf(dev, "could not allocate Rx ring\n"); 445ae813fd8SSepherosa Ziehau goto fail; 446ae813fd8SSepherosa Ziehau } 447ae813fd8SSepherosa Ziehau 448ae813fd8SSepherosa Ziehau error = mii_phy_probe(dev, &sc->sc_miibus, nfe_ifmedia_upd, 449ae813fd8SSepherosa Ziehau nfe_ifmedia_sts); 450ae813fd8SSepherosa Ziehau if (error) { 451ae813fd8SSepherosa Ziehau device_printf(dev, "MII without any phy\n"); 452ae813fd8SSepherosa Ziehau goto fail; 453ae813fd8SSepherosa Ziehau } 454ae813fd8SSepherosa Ziehau 455ae813fd8SSepherosa Ziehau ifp->if_softc = sc; 456ae813fd8SSepherosa Ziehau ifp->if_mtu = ETHERMTU; 457ae813fd8SSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 458ae813fd8SSepherosa Ziehau ifp->if_ioctl = nfe_ioctl; 459ae813fd8SSepherosa Ziehau ifp->if_start = nfe_start; 460ae813fd8SSepherosa Ziehau #ifdef DEVICE_POLLING 461ae813fd8SSepherosa Ziehau ifp->if_poll = nfe_poll; 462ae813fd8SSepherosa Ziehau #endif 463ae813fd8SSepherosa Ziehau ifp->if_watchdog = nfe_watchdog; 464ae813fd8SSepherosa Ziehau ifp->if_init = nfe_init; 465ae813fd8SSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, NFE_IFQ_MAXLEN); 466ae813fd8SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 467ae813fd8SSepherosa Ziehau 468ae813fd8SSepherosa Ziehau ifp->if_capabilities = IFCAP_VLAN_MTU; 469ae813fd8SSepherosa Ziehau 470ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_HW_VLAN) 471ae813fd8SSepherosa Ziehau ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 472ae813fd8SSepherosa Ziehau 473ae813fd8SSepherosa Ziehau #ifdef NFE_CSUM 474ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_HW_CSUM) { 47511db6c57SSepherosa Ziehau ifp->if_capabilities |= IFCAP_HWCSUM; 47611db6c57SSepherosa Ziehau ifp->if_hwassist = NFE_CSUM_FEATURES; 477ae813fd8SSepherosa Ziehau } 47811db6c57SSepherosa Ziehau #else 47911db6c57SSepherosa Ziehau sc->sc_flags &= ~NFE_HW_CSUM; 480ae813fd8SSepherosa Ziehau #endif 481ae813fd8SSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 482ae813fd8SSepherosa Ziehau 483ae813fd8SSepherosa Ziehau callout_init(&sc->sc_tick_ch); 484ae813fd8SSepherosa Ziehau 485ae813fd8SSepherosa Ziehau ether_ifattach(ifp, eaddr, NULL); 486ae813fd8SSepherosa Ziehau 487ae813fd8SSepherosa Ziehau error = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE, nfe_intr, sc, 488ae813fd8SSepherosa Ziehau &sc->sc_ih, ifp->if_serializer); 489ae813fd8SSepherosa Ziehau if (error) { 490ae813fd8SSepherosa Ziehau device_printf(dev, "could not setup intr\n"); 491ae813fd8SSepherosa Ziehau ether_ifdetach(ifp); 492ae813fd8SSepherosa Ziehau goto fail; 493ae813fd8SSepherosa Ziehau } 494ae813fd8SSepherosa Ziehau 495ae813fd8SSepherosa Ziehau return 0; 496ae813fd8SSepherosa Ziehau fail: 497ae813fd8SSepherosa Ziehau nfe_detach(dev); 498ae813fd8SSepherosa Ziehau return error; 499ae813fd8SSepherosa Ziehau } 500ae813fd8SSepherosa Ziehau 501ae813fd8SSepherosa Ziehau static int 502ae813fd8SSepherosa Ziehau nfe_detach(device_t dev) 503ae813fd8SSepherosa Ziehau { 504ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 505ae813fd8SSepherosa Ziehau 506ae813fd8SSepherosa Ziehau if (device_is_attached(dev)) { 507ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 508ae813fd8SSepherosa Ziehau 509ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 510ae813fd8SSepherosa Ziehau nfe_stop(sc); 511ae813fd8SSepherosa Ziehau bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_ih); 512ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 513ae813fd8SSepherosa Ziehau 514ae813fd8SSepherosa Ziehau ether_ifdetach(ifp); 515ae813fd8SSepherosa Ziehau } 516ae813fd8SSepherosa Ziehau 517ae813fd8SSepherosa Ziehau if (sc->sc_miibus != NULL) 518ae813fd8SSepherosa Ziehau device_delete_child(dev, sc->sc_miibus); 519ae813fd8SSepherosa Ziehau bus_generic_detach(dev); 520ae813fd8SSepherosa Ziehau 521ae813fd8SSepherosa Ziehau if (sc->sc_irq_res != NULL) { 522ae813fd8SSepherosa Ziehau bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, 523ae813fd8SSepherosa Ziehau sc->sc_irq_res); 524ae813fd8SSepherosa Ziehau } 525ae813fd8SSepherosa Ziehau 526ae813fd8SSepherosa Ziehau if (sc->sc_mem_res != NULL) { 527ae813fd8SSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, 528ae813fd8SSepherosa Ziehau sc->sc_mem_res); 529ae813fd8SSepherosa Ziehau } 530ae813fd8SSepherosa Ziehau 531ae813fd8SSepherosa Ziehau nfe_free_tx_ring(sc, &sc->txq); 532ae813fd8SSepherosa Ziehau nfe_free_rx_ring(sc, &sc->rxq); 533ae813fd8SSepherosa Ziehau 534ae813fd8SSepherosa Ziehau return 0; 535ae813fd8SSepherosa Ziehau } 536ae813fd8SSepherosa Ziehau 537ae813fd8SSepherosa Ziehau static void 538ae813fd8SSepherosa Ziehau nfe_shutdown(device_t dev) 539ae813fd8SSepherosa Ziehau { 540ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 541ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 542ae813fd8SSepherosa Ziehau 543ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 544ae813fd8SSepherosa Ziehau nfe_stop(sc); 545ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 546ae813fd8SSepherosa Ziehau } 547ae813fd8SSepherosa Ziehau 548ae813fd8SSepherosa Ziehau static int 549ae813fd8SSepherosa Ziehau nfe_suspend(device_t dev) 550ae813fd8SSepherosa Ziehau { 551ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 552ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 553ae813fd8SSepherosa Ziehau 554ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 555ae813fd8SSepherosa Ziehau nfe_stop(sc); 556ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 557ae813fd8SSepherosa Ziehau 558ae813fd8SSepherosa Ziehau return 0; 559ae813fd8SSepherosa Ziehau } 560ae813fd8SSepherosa Ziehau 561ae813fd8SSepherosa Ziehau static int 562ae813fd8SSepherosa Ziehau nfe_resume(device_t dev) 563ae813fd8SSepherosa Ziehau { 564ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 565ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 566ae813fd8SSepherosa Ziehau 567ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 568751890abSMatthew Dillon if (ifp->if_flags & IFF_UP) 5693ffca68aSSepherosa Ziehau nfe_init(sc); 570ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 571ae813fd8SSepherosa Ziehau 572ae813fd8SSepherosa Ziehau return 0; 573ae813fd8SSepherosa Ziehau } 574ae813fd8SSepherosa Ziehau 575ae813fd8SSepherosa Ziehau static void 576ae813fd8SSepherosa Ziehau nfe_miibus_statchg(device_t dev) 577ae813fd8SSepherosa Ziehau { 578ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 579ae813fd8SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 580ae813fd8SSepherosa Ziehau uint32_t phy, seed, misc = NFE_MISC1_MAGIC, link = NFE_MEDIA_SET; 581ae813fd8SSepherosa Ziehau 582ae813fd8SSepherosa Ziehau phy = NFE_READ(sc, NFE_PHY_IFACE); 583ae813fd8SSepherosa Ziehau phy &= ~(NFE_PHY_HDX | NFE_PHY_100TX | NFE_PHY_1000T); 584ae813fd8SSepherosa Ziehau 585ae813fd8SSepherosa Ziehau seed = NFE_READ(sc, NFE_RNDSEED); 586ae813fd8SSepherosa Ziehau seed &= ~NFE_SEED_MASK; 587ae813fd8SSepherosa Ziehau 588ae813fd8SSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) { 589ae813fd8SSepherosa Ziehau phy |= NFE_PHY_HDX; /* half-duplex */ 590ae813fd8SSepherosa Ziehau misc |= NFE_MISC1_HDX; 591ae813fd8SSepherosa Ziehau } 592ae813fd8SSepherosa Ziehau 593ae813fd8SSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 594ae813fd8SSepherosa Ziehau case IFM_1000_T: /* full-duplex only */ 595ae813fd8SSepherosa Ziehau link |= NFE_MEDIA_1000T; 596ae813fd8SSepherosa Ziehau seed |= NFE_SEED_1000T; 597ae813fd8SSepherosa Ziehau phy |= NFE_PHY_1000T; 598ae813fd8SSepherosa Ziehau break; 599ae813fd8SSepherosa Ziehau case IFM_100_TX: 600ae813fd8SSepherosa Ziehau link |= NFE_MEDIA_100TX; 601ae813fd8SSepherosa Ziehau seed |= NFE_SEED_100TX; 602ae813fd8SSepherosa Ziehau phy |= NFE_PHY_100TX; 603ae813fd8SSepherosa Ziehau break; 604ae813fd8SSepherosa Ziehau case IFM_10_T: 605ae813fd8SSepherosa Ziehau link |= NFE_MEDIA_10T; 606ae813fd8SSepherosa Ziehau seed |= NFE_SEED_10T; 607ae813fd8SSepherosa Ziehau break; 608ae813fd8SSepherosa Ziehau } 609ae813fd8SSepherosa Ziehau 610ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RNDSEED, seed); /* XXX: gigabit NICs only? */ 611ae813fd8SSepherosa Ziehau 612ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_IFACE, phy); 613ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MISC1, misc); 614ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_LINKSPEED, link); 615ae813fd8SSepherosa Ziehau } 616ae813fd8SSepherosa Ziehau 617ae813fd8SSepherosa Ziehau static int 618ae813fd8SSepherosa Ziehau nfe_miibus_readreg(device_t dev, int phy, int reg) 619ae813fd8SSepherosa Ziehau { 620ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 621ae813fd8SSepherosa Ziehau uint32_t val; 622ae813fd8SSepherosa Ziehau int ntries; 623ae813fd8SSepherosa Ziehau 624ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 625ae813fd8SSepherosa Ziehau 626ae813fd8SSepherosa Ziehau if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 627ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 628ae813fd8SSepherosa Ziehau DELAY(100); 629ae813fd8SSepherosa Ziehau } 630ae813fd8SSepherosa Ziehau 631ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_CTL, (phy << NFE_PHYADD_SHIFT) | reg); 632ae813fd8SSepherosa Ziehau 633ae813fd8SSepherosa Ziehau for (ntries = 0; ntries < 1000; ntries++) { 634ae813fd8SSepherosa Ziehau DELAY(100); 635ae813fd8SSepherosa Ziehau if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 636ae813fd8SSepherosa Ziehau break; 637ae813fd8SSepherosa Ziehau } 638ae813fd8SSepherosa Ziehau if (ntries == 1000) { 639ae813fd8SSepherosa Ziehau DPRINTFN(sc, 2, "timeout waiting for PHY %s\n", ""); 640ae813fd8SSepherosa Ziehau return 0; 641ae813fd8SSepherosa Ziehau } 642ae813fd8SSepherosa Ziehau 643ae813fd8SSepherosa Ziehau if (NFE_READ(sc, NFE_PHY_STATUS) & NFE_PHY_ERROR) { 644ae813fd8SSepherosa Ziehau DPRINTFN(sc, 2, "could not read PHY %s\n", ""); 645ae813fd8SSepherosa Ziehau return 0; 646ae813fd8SSepherosa Ziehau } 647ae813fd8SSepherosa Ziehau 648ae813fd8SSepherosa Ziehau val = NFE_READ(sc, NFE_PHY_DATA); 649ae813fd8SSepherosa Ziehau if (val != 0xffffffff && val != 0) 650ae813fd8SSepherosa Ziehau sc->mii_phyaddr = phy; 651ae813fd8SSepherosa Ziehau 652ae813fd8SSepherosa Ziehau DPRINTFN(sc, 2, "mii read phy %d reg 0x%x ret 0x%x\n", phy, reg, val); 653ae813fd8SSepherosa Ziehau 654ae813fd8SSepherosa Ziehau return val; 655ae813fd8SSepherosa Ziehau } 656ae813fd8SSepherosa Ziehau 657ae813fd8SSepherosa Ziehau static void 658ae813fd8SSepherosa Ziehau nfe_miibus_writereg(device_t dev, int phy, int reg, int val) 659ae813fd8SSepherosa Ziehau { 660ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 661ae813fd8SSepherosa Ziehau uint32_t ctl; 662ae813fd8SSepherosa Ziehau int ntries; 663ae813fd8SSepherosa Ziehau 664ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 665ae813fd8SSepherosa Ziehau 666ae813fd8SSepherosa Ziehau if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 667ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 668ae813fd8SSepherosa Ziehau DELAY(100); 669ae813fd8SSepherosa Ziehau } 670ae813fd8SSepherosa Ziehau 671ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_DATA, val); 672ae813fd8SSepherosa Ziehau ctl = NFE_PHY_WRITE | (phy << NFE_PHYADD_SHIFT) | reg; 673ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_CTL, ctl); 674ae813fd8SSepherosa Ziehau 675ae813fd8SSepherosa Ziehau for (ntries = 0; ntries < 1000; ntries++) { 676ae813fd8SSepherosa Ziehau DELAY(100); 677ae813fd8SSepherosa Ziehau if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 678ae813fd8SSepherosa Ziehau break; 679ae813fd8SSepherosa Ziehau } 680ae813fd8SSepherosa Ziehau 681ae813fd8SSepherosa Ziehau #ifdef NFE_DEBUG 682ae813fd8SSepherosa Ziehau if (ntries == 1000) 683ae813fd8SSepherosa Ziehau DPRINTFN(sc, 2, "could not write to PHY %s\n", ""); 684ae813fd8SSepherosa Ziehau #endif 685ae813fd8SSepherosa Ziehau } 686ae813fd8SSepherosa Ziehau 687ae813fd8SSepherosa Ziehau #ifdef DEVICE_POLLING 688ae813fd8SSepherosa Ziehau 689ae813fd8SSepherosa Ziehau static void 690ae813fd8SSepherosa Ziehau nfe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 691ae813fd8SSepherosa Ziehau { 692ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 693ae813fd8SSepherosa Ziehau 694ae813fd8SSepherosa Ziehau switch(cmd) { 695ae813fd8SSepherosa Ziehau case POLL_REGISTER: 696ae813fd8SSepherosa Ziehau /* Disable interrupts */ 697ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, 0); 698ae813fd8SSepherosa Ziehau break; 699ae813fd8SSepherosa Ziehau case POLL_DEREGISTER: 700ae813fd8SSepherosa Ziehau /* enable interrupts */ 701ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); 702ae813fd8SSepherosa Ziehau break; 703ae813fd8SSepherosa Ziehau case POLL_AND_CHECK_STATUS: 704ae813fd8SSepherosa Ziehau /* fall through */ 705ae813fd8SSepherosa Ziehau case POLL_ONLY: 706ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 707ae813fd8SSepherosa Ziehau nfe_rxeof(sc); 708ae813fd8SSepherosa Ziehau nfe_txeof(sc); 709ae813fd8SSepherosa Ziehau } 710ae813fd8SSepherosa Ziehau break; 711ae813fd8SSepherosa Ziehau } 712ae813fd8SSepherosa Ziehau } 713ae813fd8SSepherosa Ziehau 714ae813fd8SSepherosa Ziehau #endif 715ae813fd8SSepherosa Ziehau 716ae813fd8SSepherosa Ziehau static void 717ae813fd8SSepherosa Ziehau nfe_intr(void *arg) 718ae813fd8SSepherosa Ziehau { 719ae813fd8SSepherosa Ziehau struct nfe_softc *sc = arg; 720ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 721ae813fd8SSepherosa Ziehau uint32_t r; 722ae813fd8SSepherosa Ziehau 723ae813fd8SSepherosa Ziehau r = NFE_READ(sc, NFE_IRQ_STATUS); 724ae813fd8SSepherosa Ziehau if (r == 0) 725ae813fd8SSepherosa Ziehau return; /* not for us */ 726ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_STATUS, r); 727ae813fd8SSepherosa Ziehau 728ae813fd8SSepherosa Ziehau DPRINTFN(sc, 5, "%s: interrupt register %x\n", __func__, r); 729ae813fd8SSepherosa Ziehau 730ae813fd8SSepherosa Ziehau if (r & NFE_IRQ_LINK) { 731ae813fd8SSepherosa Ziehau NFE_READ(sc, NFE_PHY_STATUS); 732ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 733ae813fd8SSepherosa Ziehau DPRINTF(sc, "link state changed %s\n", ""); 734ae813fd8SSepherosa Ziehau } 735ae813fd8SSepherosa Ziehau 736ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 737ae813fd8SSepherosa Ziehau /* check Rx ring */ 738ae813fd8SSepherosa Ziehau nfe_rxeof(sc); 739ae813fd8SSepherosa Ziehau 740ae813fd8SSepherosa Ziehau /* check Tx ring */ 741ae813fd8SSepherosa Ziehau nfe_txeof(sc); 742ae813fd8SSepherosa Ziehau } 743ae813fd8SSepherosa Ziehau } 744ae813fd8SSepherosa Ziehau 745ae813fd8SSepherosa Ziehau static int 746ae813fd8SSepherosa Ziehau nfe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 747ae813fd8SSepherosa Ziehau { 748ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 749ae813fd8SSepherosa Ziehau struct ifreq *ifr = (struct ifreq *)data; 750ae813fd8SSepherosa Ziehau struct mii_data *mii; 751ae813fd8SSepherosa Ziehau int error = 0, mask; 752ae813fd8SSepherosa Ziehau 753ae813fd8SSepherosa Ziehau switch (cmd) { 754ae813fd8SSepherosa Ziehau case SIOCSIFMTU: 755a455c52eSSepherosa Ziehau if (((sc->sc_flags & NFE_JUMBO_SUP) && 756a455c52eSSepherosa Ziehau ifr->ifr_mtu > NFE_JUMBO_MTU) || 757a455c52eSSepherosa Ziehau ((sc->sc_flags & NFE_JUMBO_SUP) == 0 && 758a455c52eSSepherosa Ziehau ifr->ifr_mtu > ETHERMTU)) { 759a455c52eSSepherosa Ziehau return EINVAL; 760a455c52eSSepherosa Ziehau } else if (ifp->if_mtu != ifr->ifr_mtu) { 761a455c52eSSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 762a455c52eSSepherosa Ziehau nfe_init(sc); 763a455c52eSSepherosa Ziehau } 764ae813fd8SSepherosa Ziehau break; 765ae813fd8SSepherosa Ziehau case SIOCSIFFLAGS: 766ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 767ae813fd8SSepherosa Ziehau /* 768ae813fd8SSepherosa Ziehau * If only the PROMISC or ALLMULTI flag changes, then 769ae813fd8SSepherosa Ziehau * don't do a full re-init of the chip, just update 770ae813fd8SSepherosa Ziehau * the Rx filter. 771ae813fd8SSepherosa Ziehau */ 772ae813fd8SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) && 773ae813fd8SSepherosa Ziehau ((ifp->if_flags ^ sc->sc_if_flags) & 774ae813fd8SSepherosa Ziehau (IFF_ALLMULTI | IFF_PROMISC)) != 0) { 775ae813fd8SSepherosa Ziehau nfe_setmulti(sc); 776ae813fd8SSepherosa Ziehau } else { 777ae813fd8SSepherosa Ziehau if (!(ifp->if_flags & IFF_RUNNING)) 778ae813fd8SSepherosa Ziehau nfe_init(sc); 779ae813fd8SSepherosa Ziehau } 780ae813fd8SSepherosa Ziehau } else { 781ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 782ae813fd8SSepherosa Ziehau nfe_stop(sc); 783ae813fd8SSepherosa Ziehau } 784ae813fd8SSepherosa Ziehau sc->sc_if_flags = ifp->if_flags; 785ae813fd8SSepherosa Ziehau break; 786ae813fd8SSepherosa Ziehau case SIOCADDMULTI: 787ae813fd8SSepherosa Ziehau case SIOCDELMULTI: 788ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 789ae813fd8SSepherosa Ziehau nfe_setmulti(sc); 790ae813fd8SSepherosa Ziehau break; 791ae813fd8SSepherosa Ziehau case SIOCSIFMEDIA: 792ae813fd8SSepherosa Ziehau case SIOCGIFMEDIA: 793ae813fd8SSepherosa Ziehau mii = device_get_softc(sc->sc_miibus); 794ae813fd8SSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 795ae813fd8SSepherosa Ziehau break; 796ae813fd8SSepherosa Ziehau case SIOCSIFCAP: 797bf2a5992SSepherosa Ziehau mask = (ifr->ifr_reqcap ^ ifp->if_capenable) & IFCAP_HWCSUM; 798bf2a5992SSepherosa Ziehau if (mask && (ifp->if_capabilities & IFCAP_HWCSUM)) { 799bf2a5992SSepherosa Ziehau ifp->if_capenable ^= mask; 800bf2a5992SSepherosa Ziehau if (IFCAP_TXCSUM & ifp->if_capenable) 80111db6c57SSepherosa Ziehau ifp->if_hwassist = NFE_CSUM_FEATURES; 802bf2a5992SSepherosa Ziehau else 803bf2a5992SSepherosa Ziehau ifp->if_hwassist = 0; 80411db6c57SSepherosa Ziehau 80511db6c57SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 80611db6c57SSepherosa Ziehau nfe_init(sc); 807ae813fd8SSepherosa Ziehau } 808ae813fd8SSepherosa Ziehau break; 809ae813fd8SSepherosa Ziehau default: 810ae813fd8SSepherosa Ziehau error = ether_ioctl(ifp, cmd, data); 811ae813fd8SSepherosa Ziehau break; 812ae813fd8SSepherosa Ziehau } 813ae813fd8SSepherosa Ziehau return error; 814ae813fd8SSepherosa Ziehau } 815ae813fd8SSepherosa Ziehau 816ae813fd8SSepherosa Ziehau static void 817ae813fd8SSepherosa Ziehau nfe_rxeof(struct nfe_softc *sc) 818ae813fd8SSepherosa Ziehau { 819ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 820ae813fd8SSepherosa Ziehau struct nfe_rx_ring *ring = &sc->rxq; 821ae813fd8SSepherosa Ziehau int reap; 822ae813fd8SSepherosa Ziehau 823ae813fd8SSepherosa Ziehau reap = 0; 824ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_POSTREAD); 825ae813fd8SSepherosa Ziehau 826ae813fd8SSepherosa Ziehau for (;;) { 827ae813fd8SSepherosa Ziehau struct nfe_rx_data *data = &ring->data[ring->cur]; 828ae813fd8SSepherosa Ziehau struct mbuf *m; 829ae813fd8SSepherosa Ziehau uint16_t flags; 830ae813fd8SSepherosa Ziehau int len, error; 831ae813fd8SSepherosa Ziehau 832ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) { 833ae813fd8SSepherosa Ziehau struct nfe_desc64 *desc64 = &ring->desc64[ring->cur]; 834ae813fd8SSepherosa Ziehau 835ae813fd8SSepherosa Ziehau flags = le16toh(desc64->flags); 836ae813fd8SSepherosa Ziehau len = le16toh(desc64->length) & 0x3fff; 837ae813fd8SSepherosa Ziehau } else { 838ae813fd8SSepherosa Ziehau struct nfe_desc32 *desc32 = &ring->desc32[ring->cur]; 839ae813fd8SSepherosa Ziehau 840ae813fd8SSepherosa Ziehau flags = le16toh(desc32->flags); 841ae813fd8SSepherosa Ziehau len = le16toh(desc32->length) & 0x3fff; 842ae813fd8SSepherosa Ziehau } 843ae813fd8SSepherosa Ziehau 844ae813fd8SSepherosa Ziehau if (flags & NFE_RX_READY) 845ae813fd8SSepherosa Ziehau break; 846ae813fd8SSepherosa Ziehau 847ae813fd8SSepherosa Ziehau reap = 1; 848ae813fd8SSepherosa Ziehau 849ae813fd8SSepherosa Ziehau if ((sc->sc_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 850ae813fd8SSepherosa Ziehau if (!(flags & NFE_RX_VALID_V1)) 851ae813fd8SSepherosa Ziehau goto skip; 852ae813fd8SSepherosa Ziehau 853ae813fd8SSepherosa Ziehau if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { 854ae813fd8SSepherosa Ziehau flags &= ~NFE_RX_ERROR; 855ae813fd8SSepherosa Ziehau len--; /* fix buffer length */ 856ae813fd8SSepherosa Ziehau } 857ae813fd8SSepherosa Ziehau } else { 858ae813fd8SSepherosa Ziehau if (!(flags & NFE_RX_VALID_V2)) 859ae813fd8SSepherosa Ziehau goto skip; 860ae813fd8SSepherosa Ziehau 861ae813fd8SSepherosa Ziehau if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) { 862ae813fd8SSepherosa Ziehau flags &= ~NFE_RX_ERROR; 863ae813fd8SSepherosa Ziehau len--; /* fix buffer length */ 864ae813fd8SSepherosa Ziehau } 865ae813fd8SSepherosa Ziehau } 866ae813fd8SSepherosa Ziehau 867ae813fd8SSepherosa Ziehau if (flags & NFE_RX_ERROR) { 868ae813fd8SSepherosa Ziehau ifp->if_ierrors++; 869ae813fd8SSepherosa Ziehau goto skip; 870ae813fd8SSepherosa Ziehau } 871ae813fd8SSepherosa Ziehau 872ae813fd8SSepherosa Ziehau m = data->m; 873ae813fd8SSepherosa Ziehau 874ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_USE_JUMBO) 875ae813fd8SSepherosa Ziehau error = nfe_newbuf_jumbo(sc, ring, ring->cur, 0); 876ae813fd8SSepherosa Ziehau else 877ae813fd8SSepherosa Ziehau error = nfe_newbuf_std(sc, ring, ring->cur, 0); 878ae813fd8SSepherosa Ziehau if (error) { 879ae813fd8SSepherosa Ziehau ifp->if_ierrors++; 880ae813fd8SSepherosa Ziehau goto skip; 881ae813fd8SSepherosa Ziehau } 882ae813fd8SSepherosa Ziehau 883ae813fd8SSepherosa Ziehau /* finalize mbuf */ 884ae813fd8SSepherosa Ziehau m->m_pkthdr.len = m->m_len = len; 885ae813fd8SSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 886ae813fd8SSepherosa Ziehau 887bf2a5992SSepherosa Ziehau if ((ifp->if_capenable & IFCAP_RXCSUM) && 88811db6c57SSepherosa Ziehau (flags & NFE_RX_CSUMOK)) { 889*8b712a27SSepherosa Ziehau if (flags & NFE_RX_IP_CSUMOK_V2) { 890*8b712a27SSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED | 891*8b712a27SSepherosa Ziehau CSUM_IP_VALID; 892*8b712a27SSepherosa Ziehau } 89311db6c57SSepherosa Ziehau 89411db6c57SSepherosa Ziehau if (flags & 89511db6c57SSepherosa Ziehau (NFE_RX_UDP_CSUMOK_V2 | NFE_RX_TCP_CSUMOK_V2)) { 89611db6c57SSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | 89711db6c57SSepherosa Ziehau CSUM_PSEUDO_HDR; 89811db6c57SSepherosa Ziehau m->m_pkthdr.csum_data = 0xffff; 899ae813fd8SSepherosa Ziehau } 90011db6c57SSepherosa Ziehau } 901ae813fd8SSepherosa Ziehau 902ae813fd8SSepherosa Ziehau ifp->if_ipackets++; 903ae813fd8SSepherosa Ziehau ifp->if_input(ifp, m); 904ae813fd8SSepherosa Ziehau skip: 905ae813fd8SSepherosa Ziehau nfe_set_ready_rxdesc(sc, ring, ring->cur); 906a455c52eSSepherosa Ziehau sc->rxq.cur = (sc->rxq.cur + 1) % nfe_rx_ring_count; 907ae813fd8SSepherosa Ziehau } 908ae813fd8SSepherosa Ziehau 909ae813fd8SSepherosa Ziehau if (reap) 910ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 911ae813fd8SSepherosa Ziehau } 912ae813fd8SSepherosa Ziehau 913ae813fd8SSepherosa Ziehau static void 914ae813fd8SSepherosa Ziehau nfe_txeof(struct nfe_softc *sc) 915ae813fd8SSepherosa Ziehau { 916ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 917ae813fd8SSepherosa Ziehau struct nfe_tx_ring *ring = &sc->txq; 918ae813fd8SSepherosa Ziehau struct nfe_tx_data *data = NULL; 919ae813fd8SSepherosa Ziehau 920ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_POSTREAD); 921ae813fd8SSepherosa Ziehau while (ring->next != ring->cur) { 922ae813fd8SSepherosa Ziehau uint16_t flags; 923ae813fd8SSepherosa Ziehau 924ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) 925ae813fd8SSepherosa Ziehau flags = le16toh(ring->desc64[ring->next].flags); 926ae813fd8SSepherosa Ziehau else 927ae813fd8SSepherosa Ziehau flags = le16toh(ring->desc32[ring->next].flags); 928ae813fd8SSepherosa Ziehau 929ae813fd8SSepherosa Ziehau if (flags & NFE_TX_VALID) 930ae813fd8SSepherosa Ziehau break; 931ae813fd8SSepherosa Ziehau 932ae813fd8SSepherosa Ziehau data = &ring->data[ring->next]; 933ae813fd8SSepherosa Ziehau 934ae813fd8SSepherosa Ziehau if ((sc->sc_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 935ae813fd8SSepherosa Ziehau if (!(flags & NFE_TX_LASTFRAG_V1) && data->m == NULL) 936ae813fd8SSepherosa Ziehau goto skip; 937ae813fd8SSepherosa Ziehau 938ae813fd8SSepherosa Ziehau if ((flags & NFE_TX_ERROR_V1) != 0) { 939ae813fd8SSepherosa Ziehau if_printf(ifp, "tx v1 error 0x%4b\n", flags, 940ae813fd8SSepherosa Ziehau NFE_V1_TXERR); 941ae813fd8SSepherosa Ziehau ifp->if_oerrors++; 942ae813fd8SSepherosa Ziehau } else { 943ae813fd8SSepherosa Ziehau ifp->if_opackets++; 944ae813fd8SSepherosa Ziehau } 945ae813fd8SSepherosa Ziehau } else { 946ae813fd8SSepherosa Ziehau if (!(flags & NFE_TX_LASTFRAG_V2) && data->m == NULL) 947ae813fd8SSepherosa Ziehau goto skip; 948ae813fd8SSepherosa Ziehau 949ae813fd8SSepherosa Ziehau if ((flags & NFE_TX_ERROR_V2) != 0) { 950ae813fd8SSepherosa Ziehau if_printf(ifp, "tx v2 error 0x%4b\n", flags, 951ae813fd8SSepherosa Ziehau NFE_V2_TXERR); 952ae813fd8SSepherosa Ziehau ifp->if_oerrors++; 953ae813fd8SSepherosa Ziehau } else { 954ae813fd8SSepherosa Ziehau ifp->if_opackets++; 955ae813fd8SSepherosa Ziehau } 956ae813fd8SSepherosa Ziehau } 957ae813fd8SSepherosa Ziehau 958ae813fd8SSepherosa Ziehau if (data->m == NULL) { /* should not get there */ 959ae813fd8SSepherosa Ziehau if_printf(ifp, 960ae813fd8SSepherosa Ziehau "last fragment bit w/o associated mbuf!\n"); 961ae813fd8SSepherosa Ziehau goto skip; 962ae813fd8SSepherosa Ziehau } 963ae813fd8SSepherosa Ziehau 964ae813fd8SSepherosa Ziehau /* last fragment of the mbuf chain transmitted */ 965ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->data_tag, data->map, 966ae813fd8SSepherosa Ziehau BUS_DMASYNC_POSTWRITE); 967ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 968ae813fd8SSepherosa Ziehau m_freem(data->m); 969ae813fd8SSepherosa Ziehau data->m = NULL; 970ae813fd8SSepherosa Ziehau 971ae813fd8SSepherosa Ziehau ifp->if_timer = 0; 972ae813fd8SSepherosa Ziehau skip: 973ae813fd8SSepherosa Ziehau ring->queued--; 974ae813fd8SSepherosa Ziehau KKASSERT(ring->queued >= 0); 975ae813fd8SSepherosa Ziehau ring->next = (ring->next + 1) % NFE_TX_RING_COUNT; 976ae813fd8SSepherosa Ziehau } 977ae813fd8SSepherosa Ziehau 978ae813fd8SSepherosa Ziehau if (data != NULL) { /* at least one slot freed */ 979ae813fd8SSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 980ae813fd8SSepherosa Ziehau ifp->if_start(ifp); 981ae813fd8SSepherosa Ziehau } 982ae813fd8SSepherosa Ziehau } 983ae813fd8SSepherosa Ziehau 984ae813fd8SSepherosa Ziehau static int 985ae813fd8SSepherosa Ziehau nfe_encap(struct nfe_softc *sc, struct nfe_tx_ring *ring, struct mbuf *m0) 986ae813fd8SSepherosa Ziehau { 987ae813fd8SSepherosa Ziehau struct nfe_dma_ctx ctx; 988ae813fd8SSepherosa Ziehau bus_dma_segment_t segs[NFE_MAX_SCATTER]; 989ae813fd8SSepherosa Ziehau struct nfe_tx_data *data, *data_map; 990ae813fd8SSepherosa Ziehau bus_dmamap_t map; 991ae813fd8SSepherosa Ziehau struct nfe_desc64 *desc64 = NULL; 992ae813fd8SSepherosa Ziehau struct nfe_desc32 *desc32 = NULL; 993ae813fd8SSepherosa Ziehau uint16_t flags = 0; 994ae813fd8SSepherosa Ziehau uint32_t vtag = 0; 995ae813fd8SSepherosa Ziehau int error, i, j; 996ae813fd8SSepherosa Ziehau 997ae813fd8SSepherosa Ziehau data = &ring->data[ring->cur]; 998ae813fd8SSepherosa Ziehau map = data->map; 999ae813fd8SSepherosa Ziehau data_map = data; /* Remember who owns the DMA map */ 1000ae813fd8SSepherosa Ziehau 1001ae813fd8SSepherosa Ziehau ctx.nsegs = NFE_MAX_SCATTER; 1002ae813fd8SSepherosa Ziehau ctx.segs = segs; 1003ae813fd8SSepherosa Ziehau error = bus_dmamap_load_mbuf(ring->data_tag, map, m0, 1004ae813fd8SSepherosa Ziehau nfe_buf_dma_addr, &ctx, BUS_DMA_NOWAIT); 1005ae813fd8SSepherosa Ziehau if (error && error != EFBIG) { 1006ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "could not map TX mbuf\n"); 1007ae813fd8SSepherosa Ziehau goto back; 1008ae813fd8SSepherosa Ziehau } 1009ae813fd8SSepherosa Ziehau 1010ae813fd8SSepherosa Ziehau if (error) { /* error == EFBIG */ 1011ae813fd8SSepherosa Ziehau struct mbuf *m_new; 1012ae813fd8SSepherosa Ziehau 1013ae813fd8SSepherosa Ziehau m_new = m_defrag(m0, MB_DONTWAIT); 1014ae813fd8SSepherosa Ziehau if (m_new == NULL) { 1015ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1016ae813fd8SSepherosa Ziehau "could not defrag TX mbuf\n"); 1017ae813fd8SSepherosa Ziehau error = ENOBUFS; 1018ae813fd8SSepherosa Ziehau goto back; 1019ae813fd8SSepherosa Ziehau } else { 1020ae813fd8SSepherosa Ziehau m0 = m_new; 1021ae813fd8SSepherosa Ziehau } 1022ae813fd8SSepherosa Ziehau 1023ae813fd8SSepherosa Ziehau ctx.nsegs = NFE_MAX_SCATTER; 1024ae813fd8SSepherosa Ziehau ctx.segs = segs; 1025ae813fd8SSepherosa Ziehau error = bus_dmamap_load_mbuf(ring->data_tag, map, m0, 1026ae813fd8SSepherosa Ziehau nfe_buf_dma_addr, &ctx, 1027ae813fd8SSepherosa Ziehau BUS_DMA_NOWAIT); 1028ae813fd8SSepherosa Ziehau if (error) { 1029ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1030ae813fd8SSepherosa Ziehau "could not map defraged TX mbuf\n"); 1031ae813fd8SSepherosa Ziehau goto back; 1032ae813fd8SSepherosa Ziehau } 1033ae813fd8SSepherosa Ziehau } 1034ae813fd8SSepherosa Ziehau 1035ae813fd8SSepherosa Ziehau error = 0; 1036ae813fd8SSepherosa Ziehau 1037ae813fd8SSepherosa Ziehau if (ring->queued + ctx.nsegs >= NFE_TX_RING_COUNT - 1) { 1038ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, map); 1039ae813fd8SSepherosa Ziehau error = ENOBUFS; 1040ae813fd8SSepherosa Ziehau goto back; 1041ae813fd8SSepherosa Ziehau } 1042ae813fd8SSepherosa Ziehau 1043ae813fd8SSepherosa Ziehau /* setup h/w VLAN tagging */ 1044ae813fd8SSepherosa Ziehau if ((m0->m_flags & (M_PROTO1 | M_PKTHDR)) == (M_PROTO1 | M_PKTHDR) && 1045ae813fd8SSepherosa Ziehau m0->m_pkthdr.rcvif != NULL && 1046ae813fd8SSepherosa Ziehau m0->m_pkthdr.rcvif->if_type == IFT_L2VLAN) { 1047ae813fd8SSepherosa Ziehau struct ifvlan *ifv = m0->m_pkthdr.rcvif->if_softc; 1048ae813fd8SSepherosa Ziehau 1049ae813fd8SSepherosa Ziehau if (ifv != NULL) 1050ae813fd8SSepherosa Ziehau vtag = NFE_TX_VTAG | htons(ifv->ifv_tag); 1051ae813fd8SSepherosa Ziehau } 1052ae813fd8SSepherosa Ziehau 1053bf2a5992SSepherosa Ziehau if (sc->arpcom.ac_if.if_capenable & IFCAP_TXCSUM) { 105411db6c57SSepherosa Ziehau if (m0->m_pkthdr.csum_flags & CSUM_IP) 1055ae813fd8SSepherosa Ziehau flags |= NFE_TX_IP_CSUM; 105611db6c57SSepherosa Ziehau if (m0->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 1057ae813fd8SSepherosa Ziehau flags |= NFE_TX_TCP_CSUM; 105811db6c57SSepherosa Ziehau } 1059ae813fd8SSepherosa Ziehau 1060ae813fd8SSepherosa Ziehau /* 1061ae813fd8SSepherosa Ziehau * XXX urm. somebody is unaware of how hardware works. You 1062ae813fd8SSepherosa Ziehau * absolutely CANNOT set NFE_TX_VALID on the next descriptor in 1063ae813fd8SSepherosa Ziehau * the ring until the entire chain is actually *VALID*. Otherwise 1064ae813fd8SSepherosa Ziehau * the hardware may encounter a partially initialized chain that 1065ae813fd8SSepherosa Ziehau * is marked as being ready to go when it in fact is not ready to 1066ae813fd8SSepherosa Ziehau * go. 1067ae813fd8SSepherosa Ziehau */ 1068ae813fd8SSepherosa Ziehau 1069ae813fd8SSepherosa Ziehau for (i = 0; i < ctx.nsegs; i++) { 1070ae813fd8SSepherosa Ziehau j = (ring->cur + i) % NFE_TX_RING_COUNT; 1071ae813fd8SSepherosa Ziehau data = &ring->data[j]; 1072ae813fd8SSepherosa Ziehau 1073ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) { 1074ae813fd8SSepherosa Ziehau desc64 = &ring->desc64[j]; 1075ae813fd8SSepherosa Ziehau #if defined(__LP64__) 1076ae813fd8SSepherosa Ziehau desc64->physaddr[0] = 1077ae813fd8SSepherosa Ziehau htole32(segs[i].ds_addr >> 32); 1078ae813fd8SSepherosa Ziehau #endif 1079ae813fd8SSepherosa Ziehau desc64->physaddr[1] = 1080ae813fd8SSepherosa Ziehau htole32(segs[i].ds_addr & 0xffffffff); 1081ae813fd8SSepherosa Ziehau desc64->length = htole16(segs[i].ds_len - 1); 1082ae813fd8SSepherosa Ziehau desc64->vtag = htole32(vtag); 1083ae813fd8SSepherosa Ziehau desc64->flags = htole16(flags); 1084ae813fd8SSepherosa Ziehau } else { 1085ae813fd8SSepherosa Ziehau desc32 = &ring->desc32[j]; 1086ae813fd8SSepherosa Ziehau desc32->physaddr = htole32(segs[i].ds_addr); 1087ae813fd8SSepherosa Ziehau desc32->length = htole16(segs[i].ds_len - 1); 1088ae813fd8SSepherosa Ziehau desc32->flags = htole16(flags); 1089ae813fd8SSepherosa Ziehau } 1090ae813fd8SSepherosa Ziehau 1091ae813fd8SSepherosa Ziehau /* csum flags and vtag belong to the first fragment only */ 1092ae813fd8SSepherosa Ziehau flags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_CSUM); 1093ae813fd8SSepherosa Ziehau vtag = 0; 1094ae813fd8SSepherosa Ziehau 1095ae813fd8SSepherosa Ziehau ring->queued++; 1096ae813fd8SSepherosa Ziehau KKASSERT(ring->queued <= NFE_TX_RING_COUNT); 1097ae813fd8SSepherosa Ziehau } 1098ae813fd8SSepherosa Ziehau 1099ae813fd8SSepherosa Ziehau /* the whole mbuf chain has been DMA mapped, fix last descriptor */ 1100ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) { 1101ae813fd8SSepherosa Ziehau desc64->flags |= htole16(NFE_TX_LASTFRAG_V2); 1102ae813fd8SSepherosa Ziehau } else { 1103ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_JUMBO_SUP) 1104ae813fd8SSepherosa Ziehau flags = NFE_TX_LASTFRAG_V2; 1105ae813fd8SSepherosa Ziehau else 1106ae813fd8SSepherosa Ziehau flags = NFE_TX_LASTFRAG_V1; 1107ae813fd8SSepherosa Ziehau desc32->flags |= htole16(flags); 1108ae813fd8SSepherosa Ziehau } 1109ae813fd8SSepherosa Ziehau 1110ae813fd8SSepherosa Ziehau /* 1111ae813fd8SSepherosa Ziehau * Set NFE_TX_VALID backwards so the hardware doesn't see the 1112ae813fd8SSepherosa Ziehau * whole mess until the first descriptor in the map is flagged. 1113ae813fd8SSepherosa Ziehau */ 1114ae813fd8SSepherosa Ziehau for (i = ctx.nsegs - 1; i >= 0; --i) { 1115ae813fd8SSepherosa Ziehau j = (ring->cur + i) % NFE_TX_RING_COUNT; 1116ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) { 1117ae813fd8SSepherosa Ziehau desc64 = &ring->desc64[j]; 1118ae813fd8SSepherosa Ziehau desc64->flags |= htole16(NFE_TX_VALID); 1119ae813fd8SSepherosa Ziehau } else { 1120ae813fd8SSepherosa Ziehau desc32 = &ring->desc32[j]; 1121ae813fd8SSepherosa Ziehau desc32->flags |= htole16(NFE_TX_VALID); 1122ae813fd8SSepherosa Ziehau } 1123ae813fd8SSepherosa Ziehau } 1124ae813fd8SSepherosa Ziehau ring->cur = (ring->cur + ctx.nsegs) % NFE_TX_RING_COUNT; 1125ae813fd8SSepherosa Ziehau 1126ae813fd8SSepherosa Ziehau /* Exchange DMA map */ 1127ae813fd8SSepherosa Ziehau data_map->map = data->map; 1128ae813fd8SSepherosa Ziehau data->map = map; 1129ae813fd8SSepherosa Ziehau data->m = m0; 1130ae813fd8SSepherosa Ziehau 1131ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->data_tag, map, BUS_DMASYNC_PREWRITE); 1132ae813fd8SSepherosa Ziehau back: 1133ae813fd8SSepherosa Ziehau if (error) 1134ae813fd8SSepherosa Ziehau m_freem(m0); 1135ae813fd8SSepherosa Ziehau return error; 1136ae813fd8SSepherosa Ziehau } 1137ae813fd8SSepherosa Ziehau 1138ae813fd8SSepherosa Ziehau static void 1139ae813fd8SSepherosa Ziehau nfe_start(struct ifnet *ifp) 1140ae813fd8SSepherosa Ziehau { 1141ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 1142ae813fd8SSepherosa Ziehau struct nfe_tx_ring *ring = &sc->txq; 1143ae813fd8SSepherosa Ziehau int count = 0; 1144ae813fd8SSepherosa Ziehau struct mbuf *m0; 1145ae813fd8SSepherosa Ziehau 1146ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_OACTIVE) 1147ae813fd8SSepherosa Ziehau return; 1148ae813fd8SSepherosa Ziehau 1149ae813fd8SSepherosa Ziehau if (ifq_is_empty(&ifp->if_snd)) 1150ae813fd8SSepherosa Ziehau return; 1151ae813fd8SSepherosa Ziehau 1152ae813fd8SSepherosa Ziehau for (;;) { 1153ae813fd8SSepherosa Ziehau m0 = ifq_dequeue(&ifp->if_snd, NULL); 1154ae813fd8SSepherosa Ziehau if (m0 == NULL) 1155ae813fd8SSepherosa Ziehau break; 1156ae813fd8SSepherosa Ziehau 1157ae813fd8SSepherosa Ziehau BPF_MTAP(ifp, m0); 1158ae813fd8SSepherosa Ziehau 1159ae813fd8SSepherosa Ziehau if (nfe_encap(sc, ring, m0) != 0) { 1160ae813fd8SSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 1161ae813fd8SSepherosa Ziehau break; 1162ae813fd8SSepherosa Ziehau } 1163ae813fd8SSepherosa Ziehau ++count; 1164ae813fd8SSepherosa Ziehau 1165ae813fd8SSepherosa Ziehau /* 1166ae813fd8SSepherosa Ziehau * NOTE: 1167ae813fd8SSepherosa Ziehau * `m0' may be freed in nfe_encap(), so 1168ae813fd8SSepherosa Ziehau * it should not be touched any more. 1169ae813fd8SSepherosa Ziehau */ 1170ae813fd8SSepherosa Ziehau } 1171ae813fd8SSepherosa Ziehau if (count == 0) /* nothing sent */ 1172ae813fd8SSepherosa Ziehau return; 1173ae813fd8SSepherosa Ziehau 1174ae813fd8SSepherosa Ziehau /* Sync TX descriptor ring */ 1175ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 1176ae813fd8SSepherosa Ziehau 1177ae813fd8SSepherosa Ziehau /* Kick Tx */ 1178ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); 1179ae813fd8SSepherosa Ziehau 1180ae813fd8SSepherosa Ziehau /* 1181ae813fd8SSepherosa Ziehau * Set a timeout in case the chip goes out to lunch. 1182ae813fd8SSepherosa Ziehau */ 1183ae813fd8SSepherosa Ziehau ifp->if_timer = 5; 1184ae813fd8SSepherosa Ziehau } 1185ae813fd8SSepherosa Ziehau 1186ae813fd8SSepherosa Ziehau static void 1187ae813fd8SSepherosa Ziehau nfe_watchdog(struct ifnet *ifp) 1188ae813fd8SSepherosa Ziehau { 1189ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 1190ae813fd8SSepherosa Ziehau 1191ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 1192ae813fd8SSepherosa Ziehau if_printf(ifp, "watchdog timeout - lost interrupt recovered\n"); 1193ae813fd8SSepherosa Ziehau nfe_txeof(sc); 1194ae813fd8SSepherosa Ziehau return; 1195ae813fd8SSepherosa Ziehau } 1196ae813fd8SSepherosa Ziehau 1197ae813fd8SSepherosa Ziehau if_printf(ifp, "watchdog timeout\n"); 1198ae813fd8SSepherosa Ziehau 1199ae813fd8SSepherosa Ziehau nfe_init(ifp->if_softc); 1200ae813fd8SSepherosa Ziehau 1201ae813fd8SSepherosa Ziehau ifp->if_oerrors++; 1202ae813fd8SSepherosa Ziehau } 1203ae813fd8SSepherosa Ziehau 1204ae813fd8SSepherosa Ziehau static void 1205ae813fd8SSepherosa Ziehau nfe_init(void *xsc) 1206ae813fd8SSepherosa Ziehau { 1207ae813fd8SSepherosa Ziehau struct nfe_softc *sc = xsc; 1208ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1209ae813fd8SSepherosa Ziehau uint32_t tmp; 1210ae813fd8SSepherosa Ziehau int error; 1211ae813fd8SSepherosa Ziehau 1212ae813fd8SSepherosa Ziehau nfe_stop(sc); 1213ae813fd8SSepherosa Ziehau 1214a455c52eSSepherosa Ziehau /* 1215a455c52eSSepherosa Ziehau * NOTE: 1216a455c52eSSepherosa Ziehau * Switching between jumbo frames and normal frames should 1217a455c52eSSepherosa Ziehau * be done _after_ nfe_stop() but _before_ nfe_init_rx_ring(). 1218a455c52eSSepherosa Ziehau */ 1219a455c52eSSepherosa Ziehau if (ifp->if_mtu > ETHERMTU) { 1220a455c52eSSepherosa Ziehau sc->sc_flags |= NFE_USE_JUMBO; 1221a455c52eSSepherosa Ziehau sc->rxq.bufsz = NFE_JBYTES; 1222a455c52eSSepherosa Ziehau if (bootverbose) 1223a455c52eSSepherosa Ziehau if_printf(ifp, "use jumbo frames\n"); 1224a455c52eSSepherosa Ziehau } else { 1225a455c52eSSepherosa Ziehau sc->sc_flags &= ~NFE_USE_JUMBO; 1226a455c52eSSepherosa Ziehau sc->rxq.bufsz = MCLBYTES; 1227a455c52eSSepherosa Ziehau if (bootverbose) 1228a455c52eSSepherosa Ziehau if_printf(ifp, "use non-jumbo frames\n"); 1229a455c52eSSepherosa Ziehau } 1230a455c52eSSepherosa Ziehau 1231ae813fd8SSepherosa Ziehau error = nfe_init_tx_ring(sc, &sc->txq); 1232ae813fd8SSepherosa Ziehau if (error) { 1233ae813fd8SSepherosa Ziehau nfe_stop(sc); 1234ae813fd8SSepherosa Ziehau return; 1235ae813fd8SSepherosa Ziehau } 1236ae813fd8SSepherosa Ziehau 1237ae813fd8SSepherosa Ziehau error = nfe_init_rx_ring(sc, &sc->rxq); 1238ae813fd8SSepherosa Ziehau if (error) { 1239ae813fd8SSepherosa Ziehau nfe_stop(sc); 1240ae813fd8SSepherosa Ziehau return; 1241ae813fd8SSepherosa Ziehau } 1242ae813fd8SSepherosa Ziehau 1243ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_TX_UNK, 0); 1244ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_STATUS, 0); 1245ae813fd8SSepherosa Ziehau 1246ae813fd8SSepherosa Ziehau sc->rxtxctl = NFE_RXTX_BIT2; 1247ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) 1248ae813fd8SSepherosa Ziehau sc->rxtxctl |= NFE_RXTX_V3MAGIC; 1249ae813fd8SSepherosa Ziehau else if (sc->sc_flags & NFE_JUMBO_SUP) 1250ae813fd8SSepherosa Ziehau sc->rxtxctl |= NFE_RXTX_V2MAGIC; 125111db6c57SSepherosa Ziehau 1252bf2a5992SSepherosa Ziehau if (ifp->if_capenable & IFCAP_RXCSUM) 1253ae813fd8SSepherosa Ziehau sc->rxtxctl |= NFE_RXTX_RXCSUM; 1254ae813fd8SSepherosa Ziehau 1255ae813fd8SSepherosa Ziehau /* 1256ae813fd8SSepherosa Ziehau * Although the adapter is capable of stripping VLAN tags from received 1257ae813fd8SSepherosa Ziehau * frames (NFE_RXTX_VTAG_STRIP), we do not enable this functionality on 1258ae813fd8SSepherosa Ziehau * purpose. This will be done in software by our network stack. 1259ae813fd8SSepherosa Ziehau */ 1260ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_HW_VLAN) 1261ae813fd8SSepherosa Ziehau sc->rxtxctl |= NFE_RXTX_VTAG_INSERT; 1262ae813fd8SSepherosa Ziehau 1263ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | sc->rxtxctl); 1264ae813fd8SSepherosa Ziehau DELAY(10); 1265ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 1266ae813fd8SSepherosa Ziehau 1267ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_HW_VLAN) 1268ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_VTAG_CTL, NFE_VTAG_ENABLE); 1269ae813fd8SSepherosa Ziehau 1270ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R6, 0); 1271ae813fd8SSepherosa Ziehau 1272ae813fd8SSepherosa Ziehau /* set MAC address */ 1273ae813fd8SSepherosa Ziehau nfe_set_macaddr(sc, sc->arpcom.ac_enaddr); 1274ae813fd8SSepherosa Ziehau 1275ae813fd8SSepherosa Ziehau /* tell MAC where rings are in memory */ 1276ae813fd8SSepherosa Ziehau #ifdef __LP64__ 1277ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RX_RING_ADDR_HI, sc->rxq.physaddr >> 32); 1278ae813fd8SSepherosa Ziehau #endif 1279ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RX_RING_ADDR_LO, sc->rxq.physaddr & 0xffffffff); 1280ae813fd8SSepherosa Ziehau #ifdef __LP64__ 1281ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_TX_RING_ADDR_HI, sc->txq.physaddr >> 32); 1282ae813fd8SSepherosa Ziehau #endif 1283ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_TX_RING_ADDR_LO, sc->txq.physaddr & 0xffffffff); 1284ae813fd8SSepherosa Ziehau 1285ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RING_SIZE, 1286a455c52eSSepherosa Ziehau (nfe_rx_ring_count - 1) << 16 | 1287ae813fd8SSepherosa Ziehau (NFE_TX_RING_COUNT - 1)); 1288ae813fd8SSepherosa Ziehau 1289ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXBUFSZ, sc->rxq.bufsz); 1290ae813fd8SSepherosa Ziehau 1291ae813fd8SSepherosa Ziehau /* force MAC to wakeup */ 1292ae813fd8SSepherosa Ziehau tmp = NFE_READ(sc, NFE_PWR_STATE); 1293ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_WAKEUP); 1294ae813fd8SSepherosa Ziehau DELAY(10); 1295ae813fd8SSepherosa Ziehau tmp = NFE_READ(sc, NFE_PWR_STATE); 1296ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_VALID); 1297ae813fd8SSepherosa Ziehau 12986362c2faSMatthew Dillon /* 12996362c2faSMatthew Dillon * NFE_IMTIMER generates a periodic interrupt via NFE_IRQ_TIMER. 13006362c2faSMatthew Dillon * It is unclear how wide the timer is. Base programming does 13016362c2faSMatthew Dillon * not seem to effect NFE_IRQ_TX_DONE or NFE_IRQ_RX_DONE so 13026362c2faSMatthew Dillon * we don't get any interrupt moderation. TX moderation is 13036362c2faSMatthew Dillon * possible by using the timer interrupt instead of TX_DONE. 13046362c2faSMatthew Dillon * 13056362c2faSMatthew Dillon * It is unclear whether there are other bits that can be 13066362c2faSMatthew Dillon * set to make the NFE device actually do interrupt moderation 13076362c2faSMatthew Dillon * on the RX side. 13086362c2faSMatthew Dillon * 13096362c2faSMatthew Dillon * For now set a 128uS interval as a placemark, but don't use 13106362c2faSMatthew Dillon * the timer. 13116362c2faSMatthew Dillon */ 1312ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_IMTIMER, NFE_IM_DEFAULT); 1313ae813fd8SSepherosa Ziehau 1314ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R1, NFE_R1_MAGIC); 1315ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R2, NFE_R2_MAGIC); 1316ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R6, NFE_R6_MAGIC); 1317ae813fd8SSepherosa Ziehau 1318ae813fd8SSepherosa Ziehau /* update MAC knowledge of PHY; generates a NFE_IRQ_LINK interrupt */ 1319ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_STATUS, sc->mii_phyaddr << 24 | NFE_STATUS_MAGIC); 1320ae813fd8SSepherosa Ziehau 1321ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R4, NFE_R4_MAGIC); 1322ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_MAGIC); 1323ae813fd8SSepherosa Ziehau 1324ae813fd8SSepherosa Ziehau sc->rxtxctl &= ~NFE_RXTX_BIT2; 1325ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 1326ae813fd8SSepherosa Ziehau DELAY(10); 1327ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT1 | sc->rxtxctl); 1328ae813fd8SSepherosa Ziehau 1329ae813fd8SSepherosa Ziehau /* set Rx filter */ 1330ae813fd8SSepherosa Ziehau nfe_setmulti(sc); 1331ae813fd8SSepherosa Ziehau 1332ae813fd8SSepherosa Ziehau nfe_ifmedia_upd(ifp); 1333ae813fd8SSepherosa Ziehau 1334ae813fd8SSepherosa Ziehau /* enable Rx */ 1335ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RX_CTL, NFE_RX_START); 1336ae813fd8SSepherosa Ziehau 1337ae813fd8SSepherosa Ziehau /* enable Tx */ 1338ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_TX_CTL, NFE_TX_START); 1339ae813fd8SSepherosa Ziehau 1340ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 1341ae813fd8SSepherosa Ziehau 1342ae813fd8SSepherosa Ziehau #ifdef DEVICE_POLLING 1343ae813fd8SSepherosa Ziehau if ((ifp->if_flags & IFF_POLLING) == 0) 1344ae813fd8SSepherosa Ziehau #endif 1345ae813fd8SSepherosa Ziehau /* enable interrupts */ 1346ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); 1347ae813fd8SSepherosa Ziehau 1348ae813fd8SSepherosa Ziehau callout_reset(&sc->sc_tick_ch, hz, nfe_tick, sc); 1349ae813fd8SSepherosa Ziehau 1350ae813fd8SSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 1351ae813fd8SSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 1352751890abSMatthew Dillon 1353751890abSMatthew Dillon /* 1354751890abSMatthew Dillon * If we had stuff in the tx ring before its all cleaned out now 1355751890abSMatthew Dillon * so we are not going to get an interrupt, jump-start any pending 1356751890abSMatthew Dillon * output. 1357751890abSMatthew Dillon */ 1358751890abSMatthew Dillon ifp->if_start(ifp); 1359ae813fd8SSepherosa Ziehau } 1360ae813fd8SSepherosa Ziehau 1361ae813fd8SSepherosa Ziehau static void 1362ae813fd8SSepherosa Ziehau nfe_stop(struct nfe_softc *sc) 1363ae813fd8SSepherosa Ziehau { 1364ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1365ae813fd8SSepherosa Ziehau 1366ae813fd8SSepherosa Ziehau callout_stop(&sc->sc_tick_ch); 1367ae813fd8SSepherosa Ziehau 1368ae813fd8SSepherosa Ziehau ifp->if_timer = 0; 1369ae813fd8SSepherosa Ziehau ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1370ae813fd8SSepherosa Ziehau 1371d1daf8afSMatthew Dillon /* 1372d1daf8afSMatthew Dillon * Are NFE_TX_CTL and NFE_RX_CTL polled by the chip microcontroller 1373d1daf8afSMatthew Dillon * or do they directly reset/terminate the DMA hardware? Nobody 1374d1daf8afSMatthew Dillon * knows. 1375d1daf8afSMatthew Dillon * 1376d1daf8afSMatthew Dillon * Add two delays: 1377d1daf8afSMatthew Dillon * 1378d1daf8afSMatthew Dillon * (1) Delay before zeroing out NFE_TX_CTL. This seems to help a 1379d1daf8afSMatthew Dillon * watchdog timeout that occurs after a stop/init sequence. I am 1380d1daf8afSMatthew Dillon * theorizing that a TX KICK occuring just prior to a reinit (e.g. 1381d1daf8afSMatthew Dillon * due to dhclient) is queueing an interrupt to the microcontroller 1382d1daf8afSMatthew Dillon * which gets delayed until after we clear the control registers 1383d1daf8afSMatthew Dillon * down below, resulting in mass confusion. TX KICK is clearly 1384d1daf8afSMatthew Dillon * hardware aided whereas the other bits in the control register 1385d1daf8afSMatthew Dillon * are more likely to be polled by the microcontroller. 1386d1daf8afSMatthew Dillon * 1387d1daf8afSMatthew Dillon * (2) Delay after zeroing out TX and RX CTL registers, under the 1388d1daf8afSMatthew Dillon * assumption that primary DMA is initiated and terminated by 1389d1daf8afSMatthew Dillon * the microcontroller and not hardware (and anyway, one can hardly 1390d1daf8afSMatthew Dillon * expect the DMA engine to just instantly stop!). We don't want 1391d1daf8afSMatthew Dillon * to rip the rings out from under it before it has had a chance to 1392d1daf8afSMatthew Dillon * actually stop! 1393d1daf8afSMatthew Dillon */ 1394d1daf8afSMatthew Dillon DELAY(1000); 1395d1daf8afSMatthew Dillon 1396ae813fd8SSepherosa Ziehau /* Abort Tx */ 1397ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_TX_CTL, 0); 1398ae813fd8SSepherosa Ziehau 1399ae813fd8SSepherosa Ziehau /* Disable Rx */ 1400ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RX_CTL, 0); 1401ae813fd8SSepherosa Ziehau 1402ae813fd8SSepherosa Ziehau /* Disable interrupts */ 1403ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, 0); 1404ae813fd8SSepherosa Ziehau 1405d1daf8afSMatthew Dillon DELAY(1000); 1406d1daf8afSMatthew Dillon 1407ae813fd8SSepherosa Ziehau /* Reset Tx and Rx rings */ 1408ae813fd8SSepherosa Ziehau nfe_reset_tx_ring(sc, &sc->txq); 1409ae813fd8SSepherosa Ziehau nfe_reset_rx_ring(sc, &sc->rxq); 1410ae813fd8SSepherosa Ziehau } 1411ae813fd8SSepherosa Ziehau 1412ae813fd8SSepherosa Ziehau static int 1413ae813fd8SSepherosa Ziehau nfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1414ae813fd8SSepherosa Ziehau { 1415ae813fd8SSepherosa Ziehau int i, j, error, descsize; 1416ae813fd8SSepherosa Ziehau void **desc; 1417ae813fd8SSepherosa Ziehau 1418ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) { 1419ae813fd8SSepherosa Ziehau desc = (void **)&ring->desc64; 1420ae813fd8SSepherosa Ziehau descsize = sizeof(struct nfe_desc64); 1421ae813fd8SSepherosa Ziehau } else { 1422ae813fd8SSepherosa Ziehau desc = (void **)&ring->desc32; 1423ae813fd8SSepherosa Ziehau descsize = sizeof(struct nfe_desc32); 1424ae813fd8SSepherosa Ziehau } 1425ae813fd8SSepherosa Ziehau 1426a455c52eSSepherosa Ziehau ring->jbuf = kmalloc(sizeof(struct nfe_jbuf) * NFE_JPOOL_COUNT, 1427a455c52eSSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 1428a455c52eSSepherosa Ziehau ring->data = kmalloc(sizeof(struct nfe_rx_data) * nfe_rx_ring_count, 1429a455c52eSSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 1430a455c52eSSepherosa Ziehau 1431ae813fd8SSepherosa Ziehau ring->bufsz = MCLBYTES; 1432ae813fd8SSepherosa Ziehau ring->cur = ring->next = 0; 1433ae813fd8SSepherosa Ziehau 1434ae813fd8SSepherosa Ziehau error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 1435ae813fd8SSepherosa Ziehau BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 1436ae813fd8SSepherosa Ziehau NULL, NULL, 1437a455c52eSSepherosa Ziehau nfe_rx_ring_count * descsize, 1, 1438a455c52eSSepherosa Ziehau nfe_rx_ring_count * descsize, 1439ae813fd8SSepherosa Ziehau 0, &ring->tag); 1440ae813fd8SSepherosa Ziehau if (error) { 1441ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1442ae813fd8SSepherosa Ziehau "could not create desc RX DMA tag\n"); 1443ae813fd8SSepherosa Ziehau return error; 1444ae813fd8SSepherosa Ziehau } 1445ae813fd8SSepherosa Ziehau 1446ae813fd8SSepherosa Ziehau error = bus_dmamem_alloc(ring->tag, desc, BUS_DMA_WAITOK | BUS_DMA_ZERO, 1447ae813fd8SSepherosa Ziehau &ring->map); 1448ae813fd8SSepherosa Ziehau if (error) { 1449ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1450ae813fd8SSepherosa Ziehau "could not allocate RX desc DMA memory\n"); 1451ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->tag); 1452ae813fd8SSepherosa Ziehau ring->tag = NULL; 1453ae813fd8SSepherosa Ziehau return error; 1454ae813fd8SSepherosa Ziehau } 1455ae813fd8SSepherosa Ziehau 1456ae813fd8SSepherosa Ziehau error = bus_dmamap_load(ring->tag, ring->map, *desc, 1457a455c52eSSepherosa Ziehau nfe_rx_ring_count * descsize, 1458ae813fd8SSepherosa Ziehau nfe_ring_dma_addr, &ring->physaddr, 1459ae813fd8SSepherosa Ziehau BUS_DMA_WAITOK); 1460ae813fd8SSepherosa Ziehau if (error) { 1461ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1462ae813fd8SSepherosa Ziehau "could not load RX desc DMA map\n"); 1463ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->tag, *desc, ring->map); 1464ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->tag); 1465ae813fd8SSepherosa Ziehau ring->tag = NULL; 1466ae813fd8SSepherosa Ziehau return error; 1467ae813fd8SSepherosa Ziehau } 1468ae813fd8SSepherosa Ziehau 1469a455c52eSSepherosa Ziehau if (sc->sc_flags & NFE_JUMBO_SUP) { 1470ae813fd8SSepherosa Ziehau error = nfe_jpool_alloc(sc, ring); 1471ae813fd8SSepherosa Ziehau if (error) { 1472ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1473ae813fd8SSepherosa Ziehau "could not allocate jumbo frames\n"); 1474ae813fd8SSepherosa Ziehau return error; 1475ae813fd8SSepherosa Ziehau } 1476ae813fd8SSepherosa Ziehau } 1477ae813fd8SSepherosa Ziehau 1478ae813fd8SSepherosa Ziehau error = bus_dma_tag_create(NULL, 1, 0, 1479ae813fd8SSepherosa Ziehau BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 1480ae813fd8SSepherosa Ziehau NULL, NULL, 1481ae813fd8SSepherosa Ziehau MCLBYTES, 1, MCLBYTES, 1482ae813fd8SSepherosa Ziehau 0, &ring->data_tag); 1483ae813fd8SSepherosa Ziehau if (error) { 1484ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1485ae813fd8SSepherosa Ziehau "could not create RX mbuf DMA tag\n"); 1486ae813fd8SSepherosa Ziehau return error; 1487ae813fd8SSepherosa Ziehau } 1488ae813fd8SSepherosa Ziehau 1489ae813fd8SSepherosa Ziehau /* Create a spare RX mbuf DMA map */ 1490ae813fd8SSepherosa Ziehau error = bus_dmamap_create(ring->data_tag, 0, &ring->data_tmpmap); 1491ae813fd8SSepherosa Ziehau if (error) { 1492ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1493ae813fd8SSepherosa Ziehau "could not create spare RX mbuf DMA map\n"); 1494ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1495ae813fd8SSepherosa Ziehau ring->data_tag = NULL; 1496ae813fd8SSepherosa Ziehau return error; 1497ae813fd8SSepherosa Ziehau } 1498ae813fd8SSepherosa Ziehau 1499a455c52eSSepherosa Ziehau for (i = 0; i < nfe_rx_ring_count; i++) { 1500ae813fd8SSepherosa Ziehau error = bus_dmamap_create(ring->data_tag, 0, 1501ae813fd8SSepherosa Ziehau &ring->data[i].map); 1502ae813fd8SSepherosa Ziehau if (error) { 1503ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1504ae813fd8SSepherosa Ziehau "could not create %dth RX mbuf DMA mapn", i); 1505ae813fd8SSepherosa Ziehau goto fail; 1506ae813fd8SSepherosa Ziehau } 1507ae813fd8SSepherosa Ziehau } 1508ae813fd8SSepherosa Ziehau return 0; 1509ae813fd8SSepherosa Ziehau fail: 1510ae813fd8SSepherosa Ziehau for (j = 0; j < i; ++j) 1511ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, ring->data[i].map); 1512ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, ring->data_tmpmap); 1513ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1514ae813fd8SSepherosa Ziehau ring->data_tag = NULL; 1515ae813fd8SSepherosa Ziehau return error; 1516ae813fd8SSepherosa Ziehau } 1517ae813fd8SSepherosa Ziehau 1518ae813fd8SSepherosa Ziehau static void 1519ae813fd8SSepherosa Ziehau nfe_reset_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1520ae813fd8SSepherosa Ziehau { 1521ae813fd8SSepherosa Ziehau int i; 1522ae813fd8SSepherosa Ziehau 1523a455c52eSSepherosa Ziehau for (i = 0; i < nfe_rx_ring_count; i++) { 1524ae813fd8SSepherosa Ziehau struct nfe_rx_data *data = &ring->data[i]; 1525ae813fd8SSepherosa Ziehau 1526ae813fd8SSepherosa Ziehau if (data->m != NULL) { 1527a455c52eSSepherosa Ziehau if ((sc->sc_flags & NFE_USE_JUMBO) == 0) 1528ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 1529ae813fd8SSepherosa Ziehau m_freem(data->m); 1530ae813fd8SSepherosa Ziehau data->m = NULL; 1531ae813fd8SSepherosa Ziehau } 1532ae813fd8SSepherosa Ziehau } 1533ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 1534ae813fd8SSepherosa Ziehau 1535ae813fd8SSepherosa Ziehau ring->cur = ring->next = 0; 1536ae813fd8SSepherosa Ziehau } 1537ae813fd8SSepherosa Ziehau 1538ae813fd8SSepherosa Ziehau static int 1539ae813fd8SSepherosa Ziehau nfe_init_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1540ae813fd8SSepherosa Ziehau { 1541ae813fd8SSepherosa Ziehau int i; 1542ae813fd8SSepherosa Ziehau 1543a455c52eSSepherosa Ziehau for (i = 0; i < nfe_rx_ring_count; ++i) { 1544ae813fd8SSepherosa Ziehau int error; 1545ae813fd8SSepherosa Ziehau 1546ae813fd8SSepherosa Ziehau /* XXX should use a function pointer */ 1547ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_USE_JUMBO) 1548ae813fd8SSepherosa Ziehau error = nfe_newbuf_jumbo(sc, ring, i, 1); 1549ae813fd8SSepherosa Ziehau else 1550ae813fd8SSepherosa Ziehau error = nfe_newbuf_std(sc, ring, i, 1); 1551ae813fd8SSepherosa Ziehau if (error) { 1552ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1553ae813fd8SSepherosa Ziehau "could not allocate RX buffer\n"); 1554ae813fd8SSepherosa Ziehau return error; 1555ae813fd8SSepherosa Ziehau } 1556ae813fd8SSepherosa Ziehau 1557ae813fd8SSepherosa Ziehau nfe_set_ready_rxdesc(sc, ring, i); 1558ae813fd8SSepherosa Ziehau } 1559ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 1560ae813fd8SSepherosa Ziehau 1561ae813fd8SSepherosa Ziehau return 0; 1562ae813fd8SSepherosa Ziehau } 1563ae813fd8SSepherosa Ziehau 1564ae813fd8SSepherosa Ziehau static void 1565ae813fd8SSepherosa Ziehau nfe_free_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1566ae813fd8SSepherosa Ziehau { 1567ae813fd8SSepherosa Ziehau if (ring->data_tag != NULL) { 1568ae813fd8SSepherosa Ziehau struct nfe_rx_data *data; 1569ae813fd8SSepherosa Ziehau int i; 1570ae813fd8SSepherosa Ziehau 1571a455c52eSSepherosa Ziehau for (i = 0; i < nfe_rx_ring_count; i++) { 1572ae813fd8SSepherosa Ziehau data = &ring->data[i]; 1573ae813fd8SSepherosa Ziehau 1574ae813fd8SSepherosa Ziehau if (data->m != NULL) { 1575ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 1576ae813fd8SSepherosa Ziehau m_freem(data->m); 1577ae813fd8SSepherosa Ziehau } 1578ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, data->map); 1579ae813fd8SSepherosa Ziehau } 1580ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, ring->data_tmpmap); 1581ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1582ae813fd8SSepherosa Ziehau } 1583ae813fd8SSepherosa Ziehau 1584ae813fd8SSepherosa Ziehau nfe_jpool_free(sc, ring); 1585ae813fd8SSepherosa Ziehau 1586a455c52eSSepherosa Ziehau if (ring->jbuf != NULL) 1587a455c52eSSepherosa Ziehau kfree(ring->jbuf, M_DEVBUF); 1588a455c52eSSepherosa Ziehau if (ring->data != NULL) 1589a455c52eSSepherosa Ziehau kfree(ring->data, M_DEVBUF); 1590a455c52eSSepherosa Ziehau 1591ae813fd8SSepherosa Ziehau if (ring->tag != NULL) { 1592ae813fd8SSepherosa Ziehau void *desc; 1593ae813fd8SSepherosa Ziehau 1594ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) 1595ae813fd8SSepherosa Ziehau desc = ring->desc64; 1596ae813fd8SSepherosa Ziehau else 1597ae813fd8SSepherosa Ziehau desc = ring->desc32; 1598ae813fd8SSepherosa Ziehau 1599ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->tag, ring->map); 1600ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->tag, desc, ring->map); 1601ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->tag); 1602ae813fd8SSepherosa Ziehau } 1603ae813fd8SSepherosa Ziehau } 1604ae813fd8SSepherosa Ziehau 1605ae813fd8SSepherosa Ziehau static struct nfe_jbuf * 1606ae813fd8SSepherosa Ziehau nfe_jalloc(struct nfe_softc *sc) 1607ae813fd8SSepherosa Ziehau { 1608ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1609ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf; 1610ae813fd8SSepherosa Ziehau 1611ae813fd8SSepherosa Ziehau lwkt_serialize_enter(&sc->sc_jbuf_serializer); 1612ae813fd8SSepherosa Ziehau 1613ae813fd8SSepherosa Ziehau jbuf = SLIST_FIRST(&sc->rxq.jfreelist); 1614ae813fd8SSepherosa Ziehau if (jbuf != NULL) { 1615ae813fd8SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc->rxq.jfreelist, jnext); 1616ae813fd8SSepherosa Ziehau jbuf->inuse = 1; 1617ae813fd8SSepherosa Ziehau } else { 1618ae813fd8SSepherosa Ziehau if_printf(ifp, "no free jumbo buffer\n"); 1619ae813fd8SSepherosa Ziehau } 1620ae813fd8SSepherosa Ziehau 1621ae813fd8SSepherosa Ziehau lwkt_serialize_exit(&sc->sc_jbuf_serializer); 1622ae813fd8SSepherosa Ziehau 1623ae813fd8SSepherosa Ziehau return jbuf; 1624ae813fd8SSepherosa Ziehau } 1625ae813fd8SSepherosa Ziehau 1626ae813fd8SSepherosa Ziehau static void 1627ae813fd8SSepherosa Ziehau nfe_jfree(void *arg) 1628ae813fd8SSepherosa Ziehau { 1629ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf = arg; 1630ae813fd8SSepherosa Ziehau struct nfe_softc *sc = jbuf->sc; 1631ae813fd8SSepherosa Ziehau struct nfe_rx_ring *ring = jbuf->ring; 1632ae813fd8SSepherosa Ziehau 1633ae813fd8SSepherosa Ziehau if (&ring->jbuf[jbuf->slot] != jbuf) 1634ae813fd8SSepherosa Ziehau panic("%s: free wrong jumbo buffer\n", __func__); 1635ae813fd8SSepherosa Ziehau else if (jbuf->inuse == 0) 1636ae813fd8SSepherosa Ziehau panic("%s: jumbo buffer already freed\n", __func__); 1637ae813fd8SSepherosa Ziehau 1638ae813fd8SSepherosa Ziehau lwkt_serialize_enter(&sc->sc_jbuf_serializer); 1639ae813fd8SSepherosa Ziehau atomic_subtract_int(&jbuf->inuse, 1); 1640ae813fd8SSepherosa Ziehau if (jbuf->inuse == 0) 1641ae813fd8SSepherosa Ziehau SLIST_INSERT_HEAD(&ring->jfreelist, jbuf, jnext); 1642ae813fd8SSepherosa Ziehau lwkt_serialize_exit(&sc->sc_jbuf_serializer); 1643ae813fd8SSepherosa Ziehau } 1644ae813fd8SSepherosa Ziehau 1645ae813fd8SSepherosa Ziehau static void 1646ae813fd8SSepherosa Ziehau nfe_jref(void *arg) 1647ae813fd8SSepherosa Ziehau { 1648ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf = arg; 1649ae813fd8SSepherosa Ziehau struct nfe_rx_ring *ring = jbuf->ring; 1650ae813fd8SSepherosa Ziehau 1651ae813fd8SSepherosa Ziehau if (&ring->jbuf[jbuf->slot] != jbuf) 1652ae813fd8SSepherosa Ziehau panic("%s: ref wrong jumbo buffer\n", __func__); 1653ae813fd8SSepherosa Ziehau else if (jbuf->inuse == 0) 1654ae813fd8SSepherosa Ziehau panic("%s: jumbo buffer already freed\n", __func__); 1655ae813fd8SSepherosa Ziehau 165606406609SSepherosa Ziehau atomic_add_int(&jbuf->inuse, 1); 1657ae813fd8SSepherosa Ziehau } 1658ae813fd8SSepherosa Ziehau 1659ae813fd8SSepherosa Ziehau static int 1660ae813fd8SSepherosa Ziehau nfe_jpool_alloc(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1661ae813fd8SSepherosa Ziehau { 1662ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf; 1663ae813fd8SSepherosa Ziehau bus_addr_t physaddr; 1664ae813fd8SSepherosa Ziehau caddr_t buf; 1665ae813fd8SSepherosa Ziehau int i, error; 1666ae813fd8SSepherosa Ziehau 1667ae813fd8SSepherosa Ziehau /* 1668ae813fd8SSepherosa Ziehau * Allocate a big chunk of DMA'able memory. 1669ae813fd8SSepherosa Ziehau */ 1670ae813fd8SSepherosa Ziehau error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 1671ae813fd8SSepherosa Ziehau BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 1672ae813fd8SSepherosa Ziehau NULL, NULL, 1673ae813fd8SSepherosa Ziehau NFE_JPOOL_SIZE, 1, NFE_JPOOL_SIZE, 1674ae813fd8SSepherosa Ziehau 0, &ring->jtag); 1675ae813fd8SSepherosa Ziehau if (error) { 1676ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1677ae813fd8SSepherosa Ziehau "could not create jumbo DMA tag\n"); 1678ae813fd8SSepherosa Ziehau return error; 1679ae813fd8SSepherosa Ziehau } 1680ae813fd8SSepherosa Ziehau 1681ae813fd8SSepherosa Ziehau error = bus_dmamem_alloc(ring->jtag, (void **)&ring->jpool, 1682ae813fd8SSepherosa Ziehau BUS_DMA_WAITOK, &ring->jmap); 1683ae813fd8SSepherosa Ziehau if (error) { 1684ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1685ae813fd8SSepherosa Ziehau "could not allocate jumbo DMA memory\n"); 1686ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->jtag); 1687ae813fd8SSepherosa Ziehau ring->jtag = NULL; 1688ae813fd8SSepherosa Ziehau return error; 1689ae813fd8SSepherosa Ziehau } 1690ae813fd8SSepherosa Ziehau 1691ae813fd8SSepherosa Ziehau error = bus_dmamap_load(ring->jtag, ring->jmap, ring->jpool, 1692ae813fd8SSepherosa Ziehau NFE_JPOOL_SIZE, nfe_ring_dma_addr, &physaddr, 1693ae813fd8SSepherosa Ziehau BUS_DMA_WAITOK); 1694ae813fd8SSepherosa Ziehau if (error) { 1695ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1696ae813fd8SSepherosa Ziehau "could not load jumbo DMA map\n"); 1697ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->jtag, ring->jpool, ring->jmap); 1698ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->jtag); 1699ae813fd8SSepherosa Ziehau ring->jtag = NULL; 1700ae813fd8SSepherosa Ziehau return error; 1701ae813fd8SSepherosa Ziehau } 1702ae813fd8SSepherosa Ziehau 1703ae813fd8SSepherosa Ziehau /* ..and split it into 9KB chunks */ 1704ae813fd8SSepherosa Ziehau SLIST_INIT(&ring->jfreelist); 1705ae813fd8SSepherosa Ziehau 1706ae813fd8SSepherosa Ziehau buf = ring->jpool; 1707ae813fd8SSepherosa Ziehau for (i = 0; i < NFE_JPOOL_COUNT; i++) { 1708ae813fd8SSepherosa Ziehau jbuf = &ring->jbuf[i]; 1709ae813fd8SSepherosa Ziehau 1710ae813fd8SSepherosa Ziehau jbuf->sc = sc; 1711ae813fd8SSepherosa Ziehau jbuf->ring = ring; 1712ae813fd8SSepherosa Ziehau jbuf->inuse = 0; 1713ae813fd8SSepherosa Ziehau jbuf->slot = i; 1714ae813fd8SSepherosa Ziehau jbuf->buf = buf; 1715ae813fd8SSepherosa Ziehau jbuf->physaddr = physaddr; 1716ae813fd8SSepherosa Ziehau 1717ae813fd8SSepherosa Ziehau SLIST_INSERT_HEAD(&ring->jfreelist, jbuf, jnext); 1718ae813fd8SSepherosa Ziehau 1719ae813fd8SSepherosa Ziehau buf += NFE_JBYTES; 1720ae813fd8SSepherosa Ziehau physaddr += NFE_JBYTES; 1721ae813fd8SSepherosa Ziehau } 1722ae813fd8SSepherosa Ziehau 1723ae813fd8SSepherosa Ziehau return 0; 1724ae813fd8SSepherosa Ziehau } 1725ae813fd8SSepherosa Ziehau 1726ae813fd8SSepherosa Ziehau static void 1727ae813fd8SSepherosa Ziehau nfe_jpool_free(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1728ae813fd8SSepherosa Ziehau { 1729ae813fd8SSepherosa Ziehau if (ring->jtag != NULL) { 1730ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->jtag, ring->jmap); 1731ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->jtag, ring->jpool, ring->jmap); 1732ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->jtag); 1733ae813fd8SSepherosa Ziehau } 1734ae813fd8SSepherosa Ziehau } 1735ae813fd8SSepherosa Ziehau 1736ae813fd8SSepherosa Ziehau static int 1737ae813fd8SSepherosa Ziehau nfe_alloc_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1738ae813fd8SSepherosa Ziehau { 1739ae813fd8SSepherosa Ziehau int i, j, error, descsize; 1740ae813fd8SSepherosa Ziehau void **desc; 1741ae813fd8SSepherosa Ziehau 1742ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) { 1743ae813fd8SSepherosa Ziehau desc = (void **)&ring->desc64; 1744ae813fd8SSepherosa Ziehau descsize = sizeof(struct nfe_desc64); 1745ae813fd8SSepherosa Ziehau } else { 1746ae813fd8SSepherosa Ziehau desc = (void **)&ring->desc32; 1747ae813fd8SSepherosa Ziehau descsize = sizeof(struct nfe_desc32); 1748ae813fd8SSepherosa Ziehau } 1749ae813fd8SSepherosa Ziehau 1750ae813fd8SSepherosa Ziehau ring->queued = 0; 1751ae813fd8SSepherosa Ziehau ring->cur = ring->next = 0; 1752ae813fd8SSepherosa Ziehau 1753ae813fd8SSepherosa Ziehau error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 1754ae813fd8SSepherosa Ziehau BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 1755ae813fd8SSepherosa Ziehau NULL, NULL, 1756ae813fd8SSepherosa Ziehau NFE_TX_RING_COUNT * descsize, 1, 1757ae813fd8SSepherosa Ziehau NFE_TX_RING_COUNT * descsize, 1758ae813fd8SSepherosa Ziehau 0, &ring->tag); 1759ae813fd8SSepherosa Ziehau if (error) { 1760ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1761ae813fd8SSepherosa Ziehau "could not create TX desc DMA map\n"); 1762ae813fd8SSepherosa Ziehau return error; 1763ae813fd8SSepherosa Ziehau } 1764ae813fd8SSepherosa Ziehau 1765ae813fd8SSepherosa Ziehau error = bus_dmamem_alloc(ring->tag, desc, BUS_DMA_WAITOK | BUS_DMA_ZERO, 1766ae813fd8SSepherosa Ziehau &ring->map); 1767ae813fd8SSepherosa Ziehau if (error) { 1768ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1769ae813fd8SSepherosa Ziehau "could not allocate TX desc DMA memory\n"); 1770ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->tag); 1771ae813fd8SSepherosa Ziehau ring->tag = NULL; 1772ae813fd8SSepherosa Ziehau return error; 1773ae813fd8SSepherosa Ziehau } 1774ae813fd8SSepherosa Ziehau 1775ae813fd8SSepherosa Ziehau error = bus_dmamap_load(ring->tag, ring->map, *desc, 1776ae813fd8SSepherosa Ziehau NFE_TX_RING_COUNT * descsize, 1777ae813fd8SSepherosa Ziehau nfe_ring_dma_addr, &ring->physaddr, 1778ae813fd8SSepherosa Ziehau BUS_DMA_WAITOK); 1779ae813fd8SSepherosa Ziehau if (error) { 1780ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1781ae813fd8SSepherosa Ziehau "could not load TX desc DMA map\n"); 1782ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->tag, *desc, ring->map); 1783ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->tag); 1784ae813fd8SSepherosa Ziehau ring->tag = NULL; 1785ae813fd8SSepherosa Ziehau return error; 1786ae813fd8SSepherosa Ziehau } 1787ae813fd8SSepherosa Ziehau 1788ae813fd8SSepherosa Ziehau error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, 1789ae813fd8SSepherosa Ziehau BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 1790ae813fd8SSepherosa Ziehau NULL, NULL, 1791ae813fd8SSepherosa Ziehau NFE_JBYTES * NFE_MAX_SCATTER, 1792ae813fd8SSepherosa Ziehau NFE_MAX_SCATTER, NFE_JBYTES, 1793ae813fd8SSepherosa Ziehau 0, &ring->data_tag); 1794ae813fd8SSepherosa Ziehau if (error) { 1795ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1796ae813fd8SSepherosa Ziehau "could not create TX buf DMA tag\n"); 1797ae813fd8SSepherosa Ziehau return error; 1798ae813fd8SSepherosa Ziehau } 1799ae813fd8SSepherosa Ziehau 1800ae813fd8SSepherosa Ziehau for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1801ae813fd8SSepherosa Ziehau error = bus_dmamap_create(ring->data_tag, 0, 1802ae813fd8SSepherosa Ziehau &ring->data[i].map); 1803ae813fd8SSepherosa Ziehau if (error) { 1804ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1805ae813fd8SSepherosa Ziehau "could not create %dth TX buf DMA map\n", i); 1806ae813fd8SSepherosa Ziehau goto fail; 1807ae813fd8SSepherosa Ziehau } 1808ae813fd8SSepherosa Ziehau } 1809ae813fd8SSepherosa Ziehau 1810ae813fd8SSepherosa Ziehau return 0; 1811ae813fd8SSepherosa Ziehau fail: 1812ae813fd8SSepherosa Ziehau for (j = 0; j < i; ++j) 1813ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, ring->data[i].map); 1814ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1815ae813fd8SSepherosa Ziehau ring->data_tag = NULL; 1816ae813fd8SSepherosa Ziehau return error; 1817ae813fd8SSepherosa Ziehau } 1818ae813fd8SSepherosa Ziehau 1819ae813fd8SSepherosa Ziehau static void 1820ae813fd8SSepherosa Ziehau nfe_reset_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1821ae813fd8SSepherosa Ziehau { 1822ae813fd8SSepherosa Ziehau int i; 1823ae813fd8SSepherosa Ziehau 1824ae813fd8SSepherosa Ziehau for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1825ae813fd8SSepherosa Ziehau struct nfe_tx_data *data = &ring->data[i]; 1826ae813fd8SSepherosa Ziehau 1827ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) 1828ae813fd8SSepherosa Ziehau ring->desc64[i].flags = 0; 1829ae813fd8SSepherosa Ziehau else 1830ae813fd8SSepherosa Ziehau ring->desc32[i].flags = 0; 1831ae813fd8SSepherosa Ziehau 1832ae813fd8SSepherosa Ziehau if (data->m != NULL) { 1833ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->data_tag, data->map, 1834ae813fd8SSepherosa Ziehau BUS_DMASYNC_POSTWRITE); 1835ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 1836ae813fd8SSepherosa Ziehau m_freem(data->m); 1837ae813fd8SSepherosa Ziehau data->m = NULL; 1838ae813fd8SSepherosa Ziehau } 1839ae813fd8SSepherosa Ziehau } 1840ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 1841ae813fd8SSepherosa Ziehau 1842ae813fd8SSepherosa Ziehau ring->queued = 0; 1843ae813fd8SSepherosa Ziehau ring->cur = ring->next = 0; 1844ae813fd8SSepherosa Ziehau } 1845ae813fd8SSepherosa Ziehau 1846ae813fd8SSepherosa Ziehau static int 1847ae813fd8SSepherosa Ziehau nfe_init_tx_ring(struct nfe_softc *sc __unused, 1848ae813fd8SSepherosa Ziehau struct nfe_tx_ring *ring __unused) 1849ae813fd8SSepherosa Ziehau { 1850ae813fd8SSepherosa Ziehau return 0; 1851ae813fd8SSepherosa Ziehau } 1852ae813fd8SSepherosa Ziehau 1853ae813fd8SSepherosa Ziehau static void 1854ae813fd8SSepherosa Ziehau nfe_free_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1855ae813fd8SSepherosa Ziehau { 1856ae813fd8SSepherosa Ziehau if (ring->data_tag != NULL) { 1857ae813fd8SSepherosa Ziehau struct nfe_tx_data *data; 1858ae813fd8SSepherosa Ziehau int i; 1859ae813fd8SSepherosa Ziehau 1860ae813fd8SSepherosa Ziehau for (i = 0; i < NFE_TX_RING_COUNT; ++i) { 1861ae813fd8SSepherosa Ziehau data = &ring->data[i]; 1862ae813fd8SSepherosa Ziehau 1863ae813fd8SSepherosa Ziehau if (data->m != NULL) { 1864ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 1865ae813fd8SSepherosa Ziehau m_freem(data->m); 1866ae813fd8SSepherosa Ziehau } 1867ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, data->map); 1868ae813fd8SSepherosa Ziehau } 1869ae813fd8SSepherosa Ziehau 1870ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1871ae813fd8SSepherosa Ziehau } 1872ae813fd8SSepherosa Ziehau 1873ae813fd8SSepherosa Ziehau if (ring->tag != NULL) { 1874ae813fd8SSepherosa Ziehau void *desc; 1875ae813fd8SSepherosa Ziehau 1876ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) 1877ae813fd8SSepherosa Ziehau desc = ring->desc64; 1878ae813fd8SSepherosa Ziehau else 1879ae813fd8SSepherosa Ziehau desc = ring->desc32; 1880ae813fd8SSepherosa Ziehau 1881ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->tag, ring->map); 1882ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->tag, desc, ring->map); 1883ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->tag); 1884ae813fd8SSepherosa Ziehau } 1885ae813fd8SSepherosa Ziehau } 1886ae813fd8SSepherosa Ziehau 1887ae813fd8SSepherosa Ziehau static int 1888ae813fd8SSepherosa Ziehau nfe_ifmedia_upd(struct ifnet *ifp) 1889ae813fd8SSepherosa Ziehau { 1890ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 1891ae813fd8SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 1892ae813fd8SSepherosa Ziehau 1893ae813fd8SSepherosa Ziehau if (mii->mii_instance != 0) { 1894ae813fd8SSepherosa Ziehau struct mii_softc *miisc; 1895ae813fd8SSepherosa Ziehau 1896ae813fd8SSepherosa Ziehau LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1897ae813fd8SSepherosa Ziehau mii_phy_reset(miisc); 1898ae813fd8SSepherosa Ziehau } 1899ae813fd8SSepherosa Ziehau mii_mediachg(mii); 1900ae813fd8SSepherosa Ziehau 1901ae813fd8SSepherosa Ziehau return 0; 1902ae813fd8SSepherosa Ziehau } 1903ae813fd8SSepherosa Ziehau 1904ae813fd8SSepherosa Ziehau static void 1905ae813fd8SSepherosa Ziehau nfe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1906ae813fd8SSepherosa Ziehau { 1907ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 1908ae813fd8SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 1909ae813fd8SSepherosa Ziehau 1910ae813fd8SSepherosa Ziehau mii_pollstat(mii); 1911ae813fd8SSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 1912ae813fd8SSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 1913ae813fd8SSepherosa Ziehau } 1914ae813fd8SSepherosa Ziehau 1915ae813fd8SSepherosa Ziehau static void 1916ae813fd8SSepherosa Ziehau nfe_setmulti(struct nfe_softc *sc) 1917ae813fd8SSepherosa Ziehau { 1918ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1919ae813fd8SSepherosa Ziehau struct ifmultiaddr *ifma; 1920ae813fd8SSepherosa Ziehau uint8_t addr[ETHER_ADDR_LEN], mask[ETHER_ADDR_LEN]; 1921ae813fd8SSepherosa Ziehau uint32_t filter = NFE_RXFILTER_MAGIC; 1922ae813fd8SSepherosa Ziehau int i; 1923ae813fd8SSepherosa Ziehau 1924ae813fd8SSepherosa Ziehau if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) { 1925ae813fd8SSepherosa Ziehau bzero(addr, ETHER_ADDR_LEN); 1926ae813fd8SSepherosa Ziehau bzero(mask, ETHER_ADDR_LEN); 1927ae813fd8SSepherosa Ziehau goto done; 1928ae813fd8SSepherosa Ziehau } 1929ae813fd8SSepherosa Ziehau 1930ae813fd8SSepherosa Ziehau bcopy(etherbroadcastaddr, addr, ETHER_ADDR_LEN); 1931ae813fd8SSepherosa Ziehau bcopy(etherbroadcastaddr, mask, ETHER_ADDR_LEN); 1932ae813fd8SSepherosa Ziehau 1933ae813fd8SSepherosa Ziehau LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1934ae813fd8SSepherosa Ziehau caddr_t maddr; 1935ae813fd8SSepherosa Ziehau 1936ae813fd8SSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 1937ae813fd8SSepherosa Ziehau continue; 1938ae813fd8SSepherosa Ziehau 1939ae813fd8SSepherosa Ziehau maddr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); 1940ae813fd8SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN; i++) { 1941ae813fd8SSepherosa Ziehau addr[i] &= maddr[i]; 1942ae813fd8SSepherosa Ziehau mask[i] &= ~maddr[i]; 1943ae813fd8SSepherosa Ziehau } 1944ae813fd8SSepherosa Ziehau } 1945ae813fd8SSepherosa Ziehau 1946ae813fd8SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN; i++) 1947ae813fd8SSepherosa Ziehau mask[i] |= addr[i]; 1948ae813fd8SSepherosa Ziehau 1949ae813fd8SSepherosa Ziehau done: 1950ae813fd8SSepherosa Ziehau addr[0] |= 0x01; /* make sure multicast bit is set */ 1951ae813fd8SSepherosa Ziehau 1952ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MULTIADDR_HI, 1953ae813fd8SSepherosa Ziehau addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]); 1954ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MULTIADDR_LO, 1955ae813fd8SSepherosa Ziehau addr[5] << 8 | addr[4]); 1956ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MULTIMASK_HI, 1957ae813fd8SSepherosa Ziehau mask[3] << 24 | mask[2] << 16 | mask[1] << 8 | mask[0]); 1958ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MULTIMASK_LO, 1959ae813fd8SSepherosa Ziehau mask[5] << 8 | mask[4]); 1960ae813fd8SSepherosa Ziehau 1961ae813fd8SSepherosa Ziehau filter |= (ifp->if_flags & IFF_PROMISC) ? NFE_PROMISC : NFE_U2M; 1962ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXFILTER, filter); 1963ae813fd8SSepherosa Ziehau } 1964ae813fd8SSepherosa Ziehau 1965ae813fd8SSepherosa Ziehau static void 1966ae813fd8SSepherosa Ziehau nfe_get_macaddr(struct nfe_softc *sc, uint8_t *addr) 1967ae813fd8SSepherosa Ziehau { 1968ae813fd8SSepherosa Ziehau uint32_t tmp; 1969ae813fd8SSepherosa Ziehau 1970ae813fd8SSepherosa Ziehau tmp = NFE_READ(sc, NFE_MACADDR_LO); 1971ae813fd8SSepherosa Ziehau addr[0] = (tmp >> 8) & 0xff; 1972ae813fd8SSepherosa Ziehau addr[1] = (tmp & 0xff); 1973ae813fd8SSepherosa Ziehau 1974ae813fd8SSepherosa Ziehau tmp = NFE_READ(sc, NFE_MACADDR_HI); 1975ae813fd8SSepherosa Ziehau addr[2] = (tmp >> 24) & 0xff; 1976ae813fd8SSepherosa Ziehau addr[3] = (tmp >> 16) & 0xff; 1977ae813fd8SSepherosa Ziehau addr[4] = (tmp >> 8) & 0xff; 1978ae813fd8SSepherosa Ziehau addr[5] = (tmp & 0xff); 1979ae813fd8SSepherosa Ziehau } 1980ae813fd8SSepherosa Ziehau 1981ae813fd8SSepherosa Ziehau static void 1982ae813fd8SSepherosa Ziehau nfe_set_macaddr(struct nfe_softc *sc, const uint8_t *addr) 1983ae813fd8SSepherosa Ziehau { 1984ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MACADDR_LO, 1985ae813fd8SSepherosa Ziehau addr[5] << 8 | addr[4]); 1986ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MACADDR_HI, 1987ae813fd8SSepherosa Ziehau addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]); 1988ae813fd8SSepherosa Ziehau } 1989ae813fd8SSepherosa Ziehau 1990ae813fd8SSepherosa Ziehau static void 1991ae813fd8SSepherosa Ziehau nfe_tick(void *arg) 1992ae813fd8SSepherosa Ziehau { 1993ae813fd8SSepherosa Ziehau struct nfe_softc *sc = arg; 1994ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1995ae813fd8SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 1996ae813fd8SSepherosa Ziehau 1997ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 1998ae813fd8SSepherosa Ziehau 1999ae813fd8SSepherosa Ziehau mii_tick(mii); 2000ae813fd8SSepherosa Ziehau callout_reset(&sc->sc_tick_ch, hz, nfe_tick, sc); 2001ae813fd8SSepherosa Ziehau 2002ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 2003ae813fd8SSepherosa Ziehau } 2004ae813fd8SSepherosa Ziehau 2005ae813fd8SSepherosa Ziehau static void 2006ae813fd8SSepherosa Ziehau nfe_ring_dma_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) 2007ae813fd8SSepherosa Ziehau { 2008ae813fd8SSepherosa Ziehau if (error) 2009ae813fd8SSepherosa Ziehau return; 2010ae813fd8SSepherosa Ziehau 2011ae813fd8SSepherosa Ziehau KASSERT(nseg == 1, ("too many segments, should be 1\n")); 2012ae813fd8SSepherosa Ziehau 2013ae813fd8SSepherosa Ziehau *((uint32_t *)arg) = seg->ds_addr; 2014ae813fd8SSepherosa Ziehau } 2015ae813fd8SSepherosa Ziehau 2016ae813fd8SSepherosa Ziehau static void 2017ae813fd8SSepherosa Ziehau nfe_buf_dma_addr(void *arg, bus_dma_segment_t *segs, int nsegs, 2018ae813fd8SSepherosa Ziehau bus_size_t mapsz __unused, int error) 2019ae813fd8SSepherosa Ziehau { 2020ae813fd8SSepherosa Ziehau struct nfe_dma_ctx *ctx = arg; 2021ae813fd8SSepherosa Ziehau int i; 2022ae813fd8SSepherosa Ziehau 2023ae813fd8SSepherosa Ziehau if (error) 2024ae813fd8SSepherosa Ziehau return; 2025ae813fd8SSepherosa Ziehau 2026ae813fd8SSepherosa Ziehau KASSERT(nsegs <= ctx->nsegs, 2027ae813fd8SSepherosa Ziehau ("too many segments(%d), should be <= %d\n", 2028ae813fd8SSepherosa Ziehau nsegs, ctx->nsegs)); 2029ae813fd8SSepherosa Ziehau 2030ae813fd8SSepherosa Ziehau ctx->nsegs = nsegs; 2031ae813fd8SSepherosa Ziehau for (i = 0; i < nsegs; ++i) 2032ae813fd8SSepherosa Ziehau ctx->segs[i] = segs[i]; 2033ae813fd8SSepherosa Ziehau } 2034ae813fd8SSepherosa Ziehau 2035ae813fd8SSepherosa Ziehau static int 2036ae813fd8SSepherosa Ziehau nfe_newbuf_std(struct nfe_softc *sc, struct nfe_rx_ring *ring, int idx, 2037ae813fd8SSepherosa Ziehau int wait) 2038ae813fd8SSepherosa Ziehau { 2039ae813fd8SSepherosa Ziehau struct nfe_rx_data *data = &ring->data[idx]; 2040ae813fd8SSepherosa Ziehau struct nfe_dma_ctx ctx; 2041ae813fd8SSepherosa Ziehau bus_dma_segment_t seg; 2042ae813fd8SSepherosa Ziehau bus_dmamap_t map; 2043ae813fd8SSepherosa Ziehau struct mbuf *m; 2044ae813fd8SSepherosa Ziehau int error; 2045ae813fd8SSepherosa Ziehau 2046ae813fd8SSepherosa Ziehau m = m_getcl(wait ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR); 2047ae813fd8SSepherosa Ziehau if (m == NULL) 2048ae813fd8SSepherosa Ziehau return ENOBUFS; 2049ae813fd8SSepherosa Ziehau m->m_len = m->m_pkthdr.len = MCLBYTES; 2050ae813fd8SSepherosa Ziehau 2051ae813fd8SSepherosa Ziehau ctx.nsegs = 1; 2052ae813fd8SSepherosa Ziehau ctx.segs = &seg; 2053ae813fd8SSepherosa Ziehau error = bus_dmamap_load_mbuf(ring->data_tag, ring->data_tmpmap, 2054ae813fd8SSepherosa Ziehau m, nfe_buf_dma_addr, &ctx, 2055ae813fd8SSepherosa Ziehau wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); 2056ae813fd8SSepherosa Ziehau if (error) { 2057ae813fd8SSepherosa Ziehau m_freem(m); 2058ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "could map RX mbuf %d\n", error); 2059ae813fd8SSepherosa Ziehau return error; 2060ae813fd8SSepherosa Ziehau } 2061ae813fd8SSepherosa Ziehau 2062ae813fd8SSepherosa Ziehau /* Unload originally mapped mbuf */ 2063ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 2064ae813fd8SSepherosa Ziehau 2065ae813fd8SSepherosa Ziehau /* Swap this DMA map with tmp DMA map */ 2066ae813fd8SSepherosa Ziehau map = data->map; 2067ae813fd8SSepherosa Ziehau data->map = ring->data_tmpmap; 2068ae813fd8SSepherosa Ziehau ring->data_tmpmap = map; 2069ae813fd8SSepherosa Ziehau 2070ae813fd8SSepherosa Ziehau /* Caller is assumed to have collected the old mbuf */ 2071ae813fd8SSepherosa Ziehau data->m = m; 2072ae813fd8SSepherosa Ziehau 2073ae813fd8SSepherosa Ziehau nfe_set_paddr_rxdesc(sc, ring, idx, seg.ds_addr); 2074ae813fd8SSepherosa Ziehau 2075ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->data_tag, data->map, BUS_DMASYNC_PREREAD); 2076ae813fd8SSepherosa Ziehau return 0; 2077ae813fd8SSepherosa Ziehau } 2078ae813fd8SSepherosa Ziehau 2079ae813fd8SSepherosa Ziehau static int 2080ae813fd8SSepherosa Ziehau nfe_newbuf_jumbo(struct nfe_softc *sc, struct nfe_rx_ring *ring, int idx, 2081ae813fd8SSepherosa Ziehau int wait) 2082ae813fd8SSepherosa Ziehau { 2083ae813fd8SSepherosa Ziehau struct nfe_rx_data *data = &ring->data[idx]; 2084ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf; 2085ae813fd8SSepherosa Ziehau struct mbuf *m; 2086ae813fd8SSepherosa Ziehau 2087ae813fd8SSepherosa Ziehau MGETHDR(m, wait ? MB_WAIT : MB_DONTWAIT, MT_DATA); 2088ae813fd8SSepherosa Ziehau if (m == NULL) 2089ae813fd8SSepherosa Ziehau return ENOBUFS; 2090ae813fd8SSepherosa Ziehau 2091ae813fd8SSepherosa Ziehau jbuf = nfe_jalloc(sc); 2092ae813fd8SSepherosa Ziehau if (jbuf == NULL) { 2093ae813fd8SSepherosa Ziehau m_freem(m); 2094ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "jumbo allocation failed " 2095ae813fd8SSepherosa Ziehau "-- packet dropped!\n"); 2096ae813fd8SSepherosa Ziehau return ENOBUFS; 2097ae813fd8SSepherosa Ziehau } 2098ae813fd8SSepherosa Ziehau 2099ae813fd8SSepherosa Ziehau m->m_ext.ext_arg = jbuf; 2100ae813fd8SSepherosa Ziehau m->m_ext.ext_buf = jbuf->buf; 2101ae813fd8SSepherosa Ziehau m->m_ext.ext_free = nfe_jfree; 2102ae813fd8SSepherosa Ziehau m->m_ext.ext_ref = nfe_jref; 2103ae813fd8SSepherosa Ziehau m->m_ext.ext_size = NFE_JBYTES; 2104ae813fd8SSepherosa Ziehau 2105ae813fd8SSepherosa Ziehau m->m_data = m->m_ext.ext_buf; 2106ae813fd8SSepherosa Ziehau m->m_flags |= M_EXT; 2107ae813fd8SSepherosa Ziehau m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 2108ae813fd8SSepherosa Ziehau 2109ae813fd8SSepherosa Ziehau /* Caller is assumed to have collected the old mbuf */ 2110ae813fd8SSepherosa Ziehau data->m = m; 2111ae813fd8SSepherosa Ziehau 2112ae813fd8SSepherosa Ziehau nfe_set_paddr_rxdesc(sc, ring, idx, jbuf->physaddr); 2113ae813fd8SSepherosa Ziehau 2114ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->jtag, ring->jmap, BUS_DMASYNC_PREREAD); 2115ae813fd8SSepherosa Ziehau return 0; 2116ae813fd8SSepherosa Ziehau } 2117ae813fd8SSepherosa Ziehau 2118ae813fd8SSepherosa Ziehau static void 2119ae813fd8SSepherosa Ziehau nfe_set_paddr_rxdesc(struct nfe_softc *sc, struct nfe_rx_ring *ring, int idx, 2120ae813fd8SSepherosa Ziehau bus_addr_t physaddr) 2121ae813fd8SSepherosa Ziehau { 2122ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) { 2123ae813fd8SSepherosa Ziehau struct nfe_desc64 *desc64 = &ring->desc64[idx]; 2124ae813fd8SSepherosa Ziehau 2125ae813fd8SSepherosa Ziehau #if defined(__LP64__) 2126ae813fd8SSepherosa Ziehau desc64->physaddr[0] = htole32(physaddr >> 32); 2127ae813fd8SSepherosa Ziehau #endif 2128ae813fd8SSepherosa Ziehau desc64->physaddr[1] = htole32(physaddr & 0xffffffff); 2129ae813fd8SSepherosa Ziehau } else { 2130ae813fd8SSepherosa Ziehau struct nfe_desc32 *desc32 = &ring->desc32[idx]; 2131ae813fd8SSepherosa Ziehau 2132ae813fd8SSepherosa Ziehau desc32->physaddr = htole32(physaddr); 2133ae813fd8SSepherosa Ziehau } 2134ae813fd8SSepherosa Ziehau } 2135ae813fd8SSepherosa Ziehau 2136ae813fd8SSepherosa Ziehau static void 2137ae813fd8SSepherosa Ziehau nfe_set_ready_rxdesc(struct nfe_softc *sc, struct nfe_rx_ring *ring, int idx) 2138ae813fd8SSepherosa Ziehau { 2139ae813fd8SSepherosa Ziehau if (sc->sc_flags & NFE_40BIT_ADDR) { 2140ae813fd8SSepherosa Ziehau struct nfe_desc64 *desc64 = &ring->desc64[idx]; 2141ae813fd8SSepherosa Ziehau 2142ae813fd8SSepherosa Ziehau desc64->length = htole16(ring->bufsz); 2143ae813fd8SSepherosa Ziehau desc64->flags = htole16(NFE_RX_READY); 2144ae813fd8SSepherosa Ziehau } else { 2145ae813fd8SSepherosa Ziehau struct nfe_desc32 *desc32 = &ring->desc32[idx]; 2146ae813fd8SSepherosa Ziehau 2147ae813fd8SSepherosa Ziehau desc32->length = htole16(ring->bufsz); 2148ae813fd8SSepherosa Ziehau desc32->flags = htole16(NFE_RX_READY); 2149ae813fd8SSepherosa Ziehau } 2150ae813fd8SSepherosa Ziehau } 2151