1*19aa95e4SMarcin Wojtas /*- 2*19aa95e4SMarcin Wojtas * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*19aa95e4SMarcin Wojtas * 4*19aa95e4SMarcin Wojtas * Copyright (c) 2021 Alstom Group. 5*19aa95e4SMarcin Wojtas * Copyright (c) 2021 Semihalf. 6*19aa95e4SMarcin Wojtas * 7*19aa95e4SMarcin Wojtas * Redistribution and use in source and binary forms, with or without 8*19aa95e4SMarcin Wojtas * modification, are permitted provided that the following conditions 9*19aa95e4SMarcin Wojtas * are met: 10*19aa95e4SMarcin Wojtas * 1. Redistributions of source code must retain the above copyright 11*19aa95e4SMarcin Wojtas * notice, this list of conditions and the following disclaimer. 12*19aa95e4SMarcin Wojtas * 2. Redistributions in binary form must reproduce the above copyright 13*19aa95e4SMarcin Wojtas * notice, this list of conditions and the following disclaimer in the 14*19aa95e4SMarcin Wojtas * documentation and/or other materials provided with the distribution. 15*19aa95e4SMarcin Wojtas * 16*19aa95e4SMarcin Wojtas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17*19aa95e4SMarcin Wojtas * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18*19aa95e4SMarcin Wojtas * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19*19aa95e4SMarcin Wojtas * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20*19aa95e4SMarcin Wojtas * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21*19aa95e4SMarcin Wojtas * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22*19aa95e4SMarcin Wojtas * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23*19aa95e4SMarcin Wojtas * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24*19aa95e4SMarcin Wojtas * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25*19aa95e4SMarcin Wojtas * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*19aa95e4SMarcin Wojtas */ 27*19aa95e4SMarcin Wojtas 28*19aa95e4SMarcin Wojtas #include <sys/cdefs.h> 29*19aa95e4SMarcin Wojtas __FBSDID("$FreeBSD$"); 30*19aa95e4SMarcin Wojtas 31*19aa95e4SMarcin Wojtas #include <sys/param.h> 32*19aa95e4SMarcin Wojtas #include <sys/bus.h> 33*19aa95e4SMarcin Wojtas #include <sys/endian.h> 34*19aa95e4SMarcin Wojtas #include <sys/kernel.h> 35*19aa95e4SMarcin Wojtas #include <sys/module.h> 36*19aa95e4SMarcin Wojtas #include <sys/rman.h> 37*19aa95e4SMarcin Wojtas #include <sys/socket.h> 38*19aa95e4SMarcin Wojtas #include <sys/sockio.h> 39*19aa95e4SMarcin Wojtas 40*19aa95e4SMarcin Wojtas #include <machine/bus.h> 41*19aa95e4SMarcin Wojtas #include <machine/resource.h> 42*19aa95e4SMarcin Wojtas 43*19aa95e4SMarcin Wojtas #include <net/ethernet.h> 44*19aa95e4SMarcin Wojtas #include <net/if.h> 45*19aa95e4SMarcin Wojtas #include <net/if_dl.h> 46*19aa95e4SMarcin Wojtas #include <net/if_var.h> 47*19aa95e4SMarcin Wojtas #include <net/if_types.h> 48*19aa95e4SMarcin Wojtas #include <net/if_media.h> 49*19aa95e4SMarcin Wojtas #include <net/iflib.h> 50*19aa95e4SMarcin Wojtas 51*19aa95e4SMarcin Wojtas #include <dev/enetc/enetc_hw.h> 52*19aa95e4SMarcin Wojtas #include <dev/enetc/enetc.h> 53*19aa95e4SMarcin Wojtas #include <dev/enetc/enetc_mdio.h> 54*19aa95e4SMarcin Wojtas #include <dev/mii/mii.h> 55*19aa95e4SMarcin Wojtas #include <dev/mii/miivar.h> 56*19aa95e4SMarcin Wojtas #include <dev/pci/pcireg.h> 57*19aa95e4SMarcin Wojtas #include <dev/pci/pcivar.h> 58*19aa95e4SMarcin Wojtas 59*19aa95e4SMarcin Wojtas #include <dev/ofw/ofw_bus.h> 60*19aa95e4SMarcin Wojtas #include <dev/ofw/ofw_bus_subr.h> 61*19aa95e4SMarcin Wojtas 62*19aa95e4SMarcin Wojtas #include "ifdi_if.h" 63*19aa95e4SMarcin Wojtas #include "miibus_if.h" 64*19aa95e4SMarcin Wojtas 65*19aa95e4SMarcin Wojtas static device_register_t enetc_register; 66*19aa95e4SMarcin Wojtas 67*19aa95e4SMarcin Wojtas static ifdi_attach_pre_t enetc_attach_pre; 68*19aa95e4SMarcin Wojtas static ifdi_attach_post_t enetc_attach_post; 69*19aa95e4SMarcin Wojtas static ifdi_detach_t enetc_detach; 70*19aa95e4SMarcin Wojtas 71*19aa95e4SMarcin Wojtas static ifdi_tx_queues_alloc_t enetc_tx_queues_alloc; 72*19aa95e4SMarcin Wojtas static ifdi_rx_queues_alloc_t enetc_rx_queues_alloc; 73*19aa95e4SMarcin Wojtas static ifdi_queues_free_t enetc_queues_free; 74*19aa95e4SMarcin Wojtas 75*19aa95e4SMarcin Wojtas static ifdi_init_t enetc_init; 76*19aa95e4SMarcin Wojtas static ifdi_stop_t enetc_stop; 77*19aa95e4SMarcin Wojtas 78*19aa95e4SMarcin Wojtas static ifdi_msix_intr_assign_t enetc_msix_intr_assign; 79*19aa95e4SMarcin Wojtas static ifdi_tx_queue_intr_enable_t enetc_tx_queue_intr_enable; 80*19aa95e4SMarcin Wojtas static ifdi_rx_queue_intr_enable_t enetc_rx_queue_intr_enable; 81*19aa95e4SMarcin Wojtas static ifdi_intr_enable_t enetc_intr_enable; 82*19aa95e4SMarcin Wojtas static ifdi_intr_disable_t enetc_intr_disable; 83*19aa95e4SMarcin Wojtas 84*19aa95e4SMarcin Wojtas static int enetc_isc_txd_encap(void*, if_pkt_info_t); 85*19aa95e4SMarcin Wojtas static void enetc_isc_txd_flush(void*, uint16_t, qidx_t); 86*19aa95e4SMarcin Wojtas static int enetc_isc_txd_credits_update(void*, uint16_t, bool); 87*19aa95e4SMarcin Wojtas static int enetc_isc_rxd_available(void*, uint16_t, qidx_t, qidx_t); 88*19aa95e4SMarcin Wojtas static int enetc_isc_rxd_pkt_get(void*, if_rxd_info_t); 89*19aa95e4SMarcin Wojtas static void enetc_isc_rxd_refill(void*, if_rxd_update_t); 90*19aa95e4SMarcin Wojtas static void enetc_isc_rxd_flush(void*, uint16_t, uint8_t, qidx_t); 91*19aa95e4SMarcin Wojtas 92*19aa95e4SMarcin Wojtas static void enetc_vlan_register(if_ctx_t, uint16_t); 93*19aa95e4SMarcin Wojtas static void enetc_vlan_unregister(if_ctx_t, uint16_t); 94*19aa95e4SMarcin Wojtas 95*19aa95e4SMarcin Wojtas static uint64_t enetc_get_counter(if_ctx_t, ift_counter); 96*19aa95e4SMarcin Wojtas static int enetc_promisc_set(if_ctx_t, int); 97*19aa95e4SMarcin Wojtas static int enetc_mtu_set(if_ctx_t, uint32_t); 98*19aa95e4SMarcin Wojtas static void enetc_setup_multicast(if_ctx_t); 99*19aa95e4SMarcin Wojtas static void enetc_timer(if_ctx_t, uint16_t); 100*19aa95e4SMarcin Wojtas static void enetc_update_admin_status(if_ctx_t); 101*19aa95e4SMarcin Wojtas 102*19aa95e4SMarcin Wojtas static miibus_readreg_t enetc_miibus_readreg; 103*19aa95e4SMarcin Wojtas static miibus_writereg_t enetc_miibus_writereg; 104*19aa95e4SMarcin Wojtas static miibus_linkchg_t enetc_miibus_linkchg; 105*19aa95e4SMarcin Wojtas static miibus_statchg_t enetc_miibus_statchg; 106*19aa95e4SMarcin Wojtas 107*19aa95e4SMarcin Wojtas static int enetc_media_change(if_t); 108*19aa95e4SMarcin Wojtas static void enetc_media_status(if_t, struct ifmediareq*); 109*19aa95e4SMarcin Wojtas 110*19aa95e4SMarcin Wojtas static int enetc_fixed_media_change(if_t); 111*19aa95e4SMarcin Wojtas static void enetc_fixed_media_status(if_t, struct ifmediareq*); 112*19aa95e4SMarcin Wojtas 113*19aa95e4SMarcin Wojtas static void enetc_max_nqueues(struct enetc_softc*, int*, int*); 114*19aa95e4SMarcin Wojtas static int enetc_setup_phy(struct enetc_softc*); 115*19aa95e4SMarcin Wojtas 116*19aa95e4SMarcin Wojtas static void enetc_get_hwaddr(struct enetc_softc*); 117*19aa95e4SMarcin Wojtas static void enetc_set_hwaddr(struct enetc_softc*); 118*19aa95e4SMarcin Wojtas static int enetc_setup_rss(struct enetc_softc*); 119*19aa95e4SMarcin Wojtas 120*19aa95e4SMarcin Wojtas static void enetc_init_hw(struct enetc_softc*); 121*19aa95e4SMarcin Wojtas static void enetc_init_ctrl(struct enetc_softc*); 122*19aa95e4SMarcin Wojtas static void enetc_init_tx(struct enetc_softc*); 123*19aa95e4SMarcin Wojtas static void enetc_init_rx(struct enetc_softc*); 124*19aa95e4SMarcin Wojtas 125*19aa95e4SMarcin Wojtas static int enetc_ctrl_send(struct enetc_softc*, 126*19aa95e4SMarcin Wojtas uint16_t, uint16_t, iflib_dma_info_t); 127*19aa95e4SMarcin Wojtas 128*19aa95e4SMarcin Wojtas static const char enetc_driver_version[] = "1.0.0"; 129*19aa95e4SMarcin Wojtas 130*19aa95e4SMarcin Wojtas static pci_vendor_info_t enetc_vendor_info_array[] = { 131*19aa95e4SMarcin Wojtas PVID(PCI_VENDOR_FREESCALE, ENETC_DEV_ID_PF, 132*19aa95e4SMarcin Wojtas "Freescale ENETC PCIe Gigabit Ethernet Controller"), 133*19aa95e4SMarcin Wojtas PVID_END 134*19aa95e4SMarcin Wojtas }; 135*19aa95e4SMarcin Wojtas 136*19aa95e4SMarcin Wojtas #define ENETC_IFCAPS (IFCAP_VLAN_MTU | IFCAP_RXCSUM | IFCAP_JUMBO_MTU | \ 137*19aa95e4SMarcin Wojtas IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWFILTER) 138*19aa95e4SMarcin Wojtas 139*19aa95e4SMarcin Wojtas static device_method_t enetc_methods[] = { 140*19aa95e4SMarcin Wojtas DEVMETHOD(device_register, enetc_register), 141*19aa95e4SMarcin Wojtas DEVMETHOD(device_probe, iflib_device_probe), 142*19aa95e4SMarcin Wojtas DEVMETHOD(device_attach, iflib_device_attach), 143*19aa95e4SMarcin Wojtas DEVMETHOD(device_detach, iflib_device_detach), 144*19aa95e4SMarcin Wojtas DEVMETHOD(device_shutdown, iflib_device_shutdown), 145*19aa95e4SMarcin Wojtas DEVMETHOD(device_suspend, iflib_device_suspend), 146*19aa95e4SMarcin Wojtas DEVMETHOD(device_resume, iflib_device_resume), 147*19aa95e4SMarcin Wojtas 148*19aa95e4SMarcin Wojtas DEVMETHOD(miibus_readreg, enetc_miibus_readreg), 149*19aa95e4SMarcin Wojtas DEVMETHOD(miibus_writereg, enetc_miibus_writereg), 150*19aa95e4SMarcin Wojtas DEVMETHOD(miibus_linkchg, enetc_miibus_linkchg), 151*19aa95e4SMarcin Wojtas DEVMETHOD(miibus_statchg, enetc_miibus_statchg), 152*19aa95e4SMarcin Wojtas 153*19aa95e4SMarcin Wojtas DEVMETHOD_END 154*19aa95e4SMarcin Wojtas }; 155*19aa95e4SMarcin Wojtas 156*19aa95e4SMarcin Wojtas static driver_t enetc_driver = { 157*19aa95e4SMarcin Wojtas "enetc", enetc_methods, sizeof(struct enetc_softc) 158*19aa95e4SMarcin Wojtas }; 159*19aa95e4SMarcin Wojtas 160*19aa95e4SMarcin Wojtas static devclass_t enetc_devclass; 161*19aa95e4SMarcin Wojtas DRIVER_MODULE(enetc, pci, enetc_driver, enetc_devclass, NULL, NULL); 162*19aa95e4SMarcin Wojtas DRIVER_MODULE(miibus, enetc, miibus_driver, miibus_devclass, NULL, NULL); 163*19aa95e4SMarcin Wojtas MODULE_VERSION(enetc, 1); 164*19aa95e4SMarcin Wojtas 165*19aa95e4SMarcin Wojtas IFLIB_PNP_INFO(pci, enetc, enetc_vendor_info_array); 166*19aa95e4SMarcin Wojtas 167*19aa95e4SMarcin Wojtas MODULE_DEPEND(enetc, ether, 1, 1, 1); 168*19aa95e4SMarcin Wojtas MODULE_DEPEND(enetc, iflib, 1, 1, 1); 169*19aa95e4SMarcin Wojtas MODULE_DEPEND(enetc, miibus, 1, 1, 1); 170*19aa95e4SMarcin Wojtas 171*19aa95e4SMarcin Wojtas static device_method_t enetc_iflib_methods[] = { 172*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_attach_pre, enetc_attach_pre), 173*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_attach_post, enetc_attach_post), 174*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_detach, enetc_detach), 175*19aa95e4SMarcin Wojtas 176*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_init, enetc_init), 177*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_stop, enetc_stop), 178*19aa95e4SMarcin Wojtas 179*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_tx_queues_alloc, enetc_tx_queues_alloc), 180*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_rx_queues_alloc, enetc_rx_queues_alloc), 181*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_queues_free, enetc_queues_free), 182*19aa95e4SMarcin Wojtas 183*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_msix_intr_assign, enetc_msix_intr_assign), 184*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_tx_queue_intr_enable, enetc_tx_queue_intr_enable), 185*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_rx_queue_intr_enable, enetc_rx_queue_intr_enable), 186*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_intr_enable, enetc_intr_enable), 187*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_intr_disable, enetc_intr_disable), 188*19aa95e4SMarcin Wojtas 189*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_vlan_register, enetc_vlan_register), 190*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_vlan_unregister, enetc_vlan_unregister), 191*19aa95e4SMarcin Wojtas 192*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_get_counter, enetc_get_counter), 193*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_mtu_set, enetc_mtu_set), 194*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_multi_set, enetc_setup_multicast), 195*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_promisc_set, enetc_promisc_set), 196*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_timer, enetc_timer), 197*19aa95e4SMarcin Wojtas DEVMETHOD(ifdi_update_admin_status, enetc_update_admin_status), 198*19aa95e4SMarcin Wojtas 199*19aa95e4SMarcin Wojtas DEVMETHOD_END 200*19aa95e4SMarcin Wojtas }; 201*19aa95e4SMarcin Wojtas 202*19aa95e4SMarcin Wojtas static driver_t enetc_iflib_driver = { 203*19aa95e4SMarcin Wojtas "enetc", enetc_iflib_methods, sizeof(struct enetc_softc) 204*19aa95e4SMarcin Wojtas }; 205*19aa95e4SMarcin Wojtas 206*19aa95e4SMarcin Wojtas static struct if_txrx enetc_txrx = { 207*19aa95e4SMarcin Wojtas .ift_txd_encap = enetc_isc_txd_encap, 208*19aa95e4SMarcin Wojtas .ift_txd_flush = enetc_isc_txd_flush, 209*19aa95e4SMarcin Wojtas .ift_txd_credits_update = enetc_isc_txd_credits_update, 210*19aa95e4SMarcin Wojtas .ift_rxd_available = enetc_isc_rxd_available, 211*19aa95e4SMarcin Wojtas .ift_rxd_pkt_get = enetc_isc_rxd_pkt_get, 212*19aa95e4SMarcin Wojtas .ift_rxd_refill = enetc_isc_rxd_refill, 213*19aa95e4SMarcin Wojtas .ift_rxd_flush = enetc_isc_rxd_flush 214*19aa95e4SMarcin Wojtas }; 215*19aa95e4SMarcin Wojtas 216*19aa95e4SMarcin Wojtas static struct if_shared_ctx enetc_sctx_init = { 217*19aa95e4SMarcin Wojtas .isc_magic = IFLIB_MAGIC, 218*19aa95e4SMarcin Wojtas 219*19aa95e4SMarcin Wojtas .isc_q_align = ENETC_RING_ALIGN, 220*19aa95e4SMarcin Wojtas 221*19aa95e4SMarcin Wojtas .isc_tx_maxsize = ENETC_MAX_FRAME_LEN, 222*19aa95e4SMarcin Wojtas .isc_tx_maxsegsize = PAGE_SIZE, 223*19aa95e4SMarcin Wojtas 224*19aa95e4SMarcin Wojtas .isc_rx_maxsize = ENETC_MAX_FRAME_LEN, 225*19aa95e4SMarcin Wojtas .isc_rx_maxsegsize = ENETC_MAX_FRAME_LEN, 226*19aa95e4SMarcin Wojtas .isc_rx_nsegments = ENETC_MAX_SCATTER, 227*19aa95e4SMarcin Wojtas 228*19aa95e4SMarcin Wojtas .isc_admin_intrcnt = 0, 229*19aa95e4SMarcin Wojtas 230*19aa95e4SMarcin Wojtas .isc_nfl = 1, 231*19aa95e4SMarcin Wojtas .isc_nrxqs = 1, 232*19aa95e4SMarcin Wojtas .isc_ntxqs = 1, 233*19aa95e4SMarcin Wojtas 234*19aa95e4SMarcin Wojtas .isc_vendor_info = enetc_vendor_info_array, 235*19aa95e4SMarcin Wojtas .isc_driver_version = enetc_driver_version, 236*19aa95e4SMarcin Wojtas .isc_driver = &enetc_iflib_driver, 237*19aa95e4SMarcin Wojtas 238*19aa95e4SMarcin Wojtas .isc_flags = IFLIB_DRIVER_MEDIA | IFLIB_PRESERVE_TX_INDICES, 239*19aa95e4SMarcin Wojtas .isc_ntxd_min = {ENETC_MIN_DESC}, 240*19aa95e4SMarcin Wojtas .isc_ntxd_max = {ENETC_MAX_DESC}, 241*19aa95e4SMarcin Wojtas .isc_ntxd_default = {ENETC_DEFAULT_DESC}, 242*19aa95e4SMarcin Wojtas .isc_nrxd_min = {ENETC_MIN_DESC}, 243*19aa95e4SMarcin Wojtas .isc_nrxd_max = {ENETC_MAX_DESC}, 244*19aa95e4SMarcin Wojtas .isc_nrxd_default = {ENETC_DEFAULT_DESC} 245*19aa95e4SMarcin Wojtas }; 246*19aa95e4SMarcin Wojtas 247*19aa95e4SMarcin Wojtas static void* 248*19aa95e4SMarcin Wojtas enetc_register(device_t dev) 249*19aa95e4SMarcin Wojtas { 250*19aa95e4SMarcin Wojtas 251*19aa95e4SMarcin Wojtas if (!ofw_bus_status_okay(dev)) 252*19aa95e4SMarcin Wojtas return (NULL); 253*19aa95e4SMarcin Wojtas 254*19aa95e4SMarcin Wojtas return (&enetc_sctx_init); 255*19aa95e4SMarcin Wojtas } 256*19aa95e4SMarcin Wojtas 257*19aa95e4SMarcin Wojtas static void 258*19aa95e4SMarcin Wojtas enetc_max_nqueues(struct enetc_softc *sc, int *max_tx_nqueues, 259*19aa95e4SMarcin Wojtas int *max_rx_nqueues) 260*19aa95e4SMarcin Wojtas { 261*19aa95e4SMarcin Wojtas uint32_t val; 262*19aa95e4SMarcin Wojtas 263*19aa95e4SMarcin Wojtas val = ENETC_PORT_RD4(sc, ENETC_PCAPR0); 264*19aa95e4SMarcin Wojtas *max_tx_nqueues = MIN(ENETC_PCAPR0_TXBDR(val), ENETC_MAX_QUEUES); 265*19aa95e4SMarcin Wojtas *max_rx_nqueues = MIN(ENETC_PCAPR0_RXBDR(val), ENETC_MAX_QUEUES); 266*19aa95e4SMarcin Wojtas } 267*19aa95e4SMarcin Wojtas 268*19aa95e4SMarcin Wojtas static int 269*19aa95e4SMarcin Wojtas enetc_setup_fixed(struct enetc_softc *sc, phandle_t node) 270*19aa95e4SMarcin Wojtas { 271*19aa95e4SMarcin Wojtas ssize_t size; 272*19aa95e4SMarcin Wojtas int speed; 273*19aa95e4SMarcin Wojtas 274*19aa95e4SMarcin Wojtas size = OF_getencprop(node, "speed", &speed, sizeof(speed)); 275*19aa95e4SMarcin Wojtas if (size <= 0) { 276*19aa95e4SMarcin Wojtas device_printf(sc->dev, 277*19aa95e4SMarcin Wojtas "Device has fixed-link node without link speed specified\n"); 278*19aa95e4SMarcin Wojtas return (ENXIO); 279*19aa95e4SMarcin Wojtas } 280*19aa95e4SMarcin Wojtas switch (speed) { 281*19aa95e4SMarcin Wojtas case 10: 282*19aa95e4SMarcin Wojtas speed = IFM_10_T; 283*19aa95e4SMarcin Wojtas break; 284*19aa95e4SMarcin Wojtas case 100: 285*19aa95e4SMarcin Wojtas speed = IFM_100_TX; 286*19aa95e4SMarcin Wojtas break; 287*19aa95e4SMarcin Wojtas case 1000: 288*19aa95e4SMarcin Wojtas speed = IFM_1000_T; 289*19aa95e4SMarcin Wojtas break; 290*19aa95e4SMarcin Wojtas default: 291*19aa95e4SMarcin Wojtas device_printf(sc->dev, "Unsupported link speed value of %d\n", 292*19aa95e4SMarcin Wojtas speed); 293*19aa95e4SMarcin Wojtas return (ENXIO); 294*19aa95e4SMarcin Wojtas } 295*19aa95e4SMarcin Wojtas speed |= IFM_ETHER; 296*19aa95e4SMarcin Wojtas 297*19aa95e4SMarcin Wojtas if (OF_hasprop(node, "full-duplex")) 298*19aa95e4SMarcin Wojtas speed |= IFM_FDX; 299*19aa95e4SMarcin Wojtas else 300*19aa95e4SMarcin Wojtas speed |= IFM_HDX; 301*19aa95e4SMarcin Wojtas 302*19aa95e4SMarcin Wojtas sc->fixed_link = true; 303*19aa95e4SMarcin Wojtas 304*19aa95e4SMarcin Wojtas ifmedia_init(&sc->fixed_ifmedia, 0, enetc_fixed_media_change, 305*19aa95e4SMarcin Wojtas enetc_fixed_media_status); 306*19aa95e4SMarcin Wojtas ifmedia_add(&sc->fixed_ifmedia, speed, 0, NULL); 307*19aa95e4SMarcin Wojtas ifmedia_set(&sc->fixed_ifmedia, speed); 308*19aa95e4SMarcin Wojtas sc->shared->isc_media = &sc->fixed_ifmedia; 309*19aa95e4SMarcin Wojtas 310*19aa95e4SMarcin Wojtas return (0); 311*19aa95e4SMarcin Wojtas } 312*19aa95e4SMarcin Wojtas 313*19aa95e4SMarcin Wojtas static int 314*19aa95e4SMarcin Wojtas enetc_setup_phy(struct enetc_softc *sc) 315*19aa95e4SMarcin Wojtas { 316*19aa95e4SMarcin Wojtas phandle_t node, fixed_link, phy_handle; 317*19aa95e4SMarcin Wojtas struct mii_data *miid; 318*19aa95e4SMarcin Wojtas int phy_addr, error; 319*19aa95e4SMarcin Wojtas ssize_t size; 320*19aa95e4SMarcin Wojtas 321*19aa95e4SMarcin Wojtas node = ofw_bus_get_node(sc->dev); 322*19aa95e4SMarcin Wojtas fixed_link = ofw_bus_find_child(node, "fixed-link"); 323*19aa95e4SMarcin Wojtas if (fixed_link != 0) 324*19aa95e4SMarcin Wojtas return (enetc_setup_fixed(sc, fixed_link)); 325*19aa95e4SMarcin Wojtas 326*19aa95e4SMarcin Wojtas size = OF_getencprop(node, "phy-handle", &phy_handle, sizeof(phy_handle)); 327*19aa95e4SMarcin Wojtas if (size <= 0) { 328*19aa95e4SMarcin Wojtas device_printf(sc->dev, 329*19aa95e4SMarcin Wojtas "Failed to acquire PHY handle from FDT.\n"); 330*19aa95e4SMarcin Wojtas return (ENXIO); 331*19aa95e4SMarcin Wojtas } 332*19aa95e4SMarcin Wojtas phy_handle = OF_node_from_xref(phy_handle); 333*19aa95e4SMarcin Wojtas size = OF_getencprop(phy_handle, "reg", &phy_addr, sizeof(phy_addr)); 334*19aa95e4SMarcin Wojtas if (size <= 0) { 335*19aa95e4SMarcin Wojtas device_printf(sc->dev, "Failed to obtain PHY address\n"); 336*19aa95e4SMarcin Wojtas return (ENXIO); 337*19aa95e4SMarcin Wojtas } 338*19aa95e4SMarcin Wojtas error = mii_attach(sc->dev, &sc->miibus, iflib_get_ifp(sc->ctx), 339*19aa95e4SMarcin Wojtas enetc_media_change, enetc_media_status, 340*19aa95e4SMarcin Wojtas BMSR_DEFCAPMASK, phy_addr, MII_OFFSET_ANY, MIIF_DOPAUSE); 341*19aa95e4SMarcin Wojtas if (error != 0) { 342*19aa95e4SMarcin Wojtas device_printf(sc->dev, "mii_attach failed\n"); 343*19aa95e4SMarcin Wojtas return (error); 344*19aa95e4SMarcin Wojtas } 345*19aa95e4SMarcin Wojtas miid = device_get_softc(sc->miibus); 346*19aa95e4SMarcin Wojtas sc->shared->isc_media = &miid->mii_media; 347*19aa95e4SMarcin Wojtas 348*19aa95e4SMarcin Wojtas return (0); 349*19aa95e4SMarcin Wojtas } 350*19aa95e4SMarcin Wojtas 351*19aa95e4SMarcin Wojtas static int 352*19aa95e4SMarcin Wojtas enetc_attach_pre(if_ctx_t ctx) 353*19aa95e4SMarcin Wojtas { 354*19aa95e4SMarcin Wojtas struct ifnet *ifp; 355*19aa95e4SMarcin Wojtas if_softc_ctx_t scctx; 356*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 357*19aa95e4SMarcin Wojtas int error, rid; 358*19aa95e4SMarcin Wojtas 359*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 360*19aa95e4SMarcin Wojtas scctx = iflib_get_softc_ctx(ctx); 361*19aa95e4SMarcin Wojtas sc->ctx = ctx; 362*19aa95e4SMarcin Wojtas sc->dev = iflib_get_dev(ctx); 363*19aa95e4SMarcin Wojtas sc->shared = scctx; 364*19aa95e4SMarcin Wojtas ifp = iflib_get_ifp(ctx); 365*19aa95e4SMarcin Wojtas 366*19aa95e4SMarcin Wojtas rid = PCIR_BAR(ENETC_BAR_REGS); 367*19aa95e4SMarcin Wojtas sc->regs = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 368*19aa95e4SMarcin Wojtas if (sc->regs == NULL) { 369*19aa95e4SMarcin Wojtas device_printf(sc->dev, 370*19aa95e4SMarcin Wojtas "Failed to allocate BAR %d\n", ENETC_BAR_REGS); 371*19aa95e4SMarcin Wojtas return (ENXIO); 372*19aa95e4SMarcin Wojtas } 373*19aa95e4SMarcin Wojtas 374*19aa95e4SMarcin Wojtas error = iflib_dma_alloc_align(ctx, 375*19aa95e4SMarcin Wojtas ENETC_MIN_DESC * sizeof(struct enetc_cbd), 376*19aa95e4SMarcin Wojtas ENETC_RING_ALIGN, 377*19aa95e4SMarcin Wojtas &sc->ctrl_queue.dma, 378*19aa95e4SMarcin Wojtas 0); 379*19aa95e4SMarcin Wojtas if (error != 0) { 380*19aa95e4SMarcin Wojtas device_printf(sc->dev, "Failed to allocate control ring\n"); 381*19aa95e4SMarcin Wojtas goto fail; 382*19aa95e4SMarcin Wojtas } 383*19aa95e4SMarcin Wojtas sc->ctrl_queue.ring = (struct enetc_cbd*)sc->ctrl_queue.dma.idi_vaddr; 384*19aa95e4SMarcin Wojtas 385*19aa95e4SMarcin Wojtas scctx->isc_txrx = &enetc_txrx; 386*19aa95e4SMarcin Wojtas scctx->isc_tx_nsegments = ENETC_MAX_SCATTER; 387*19aa95e4SMarcin Wojtas enetc_max_nqueues(sc, &scctx->isc_nrxqsets_max, &scctx->isc_ntxqsets_max); 388*19aa95e4SMarcin Wojtas 389*19aa95e4SMarcin Wojtas if (scctx->isc_ntxd[0] % ENETC_DESC_ALIGN != 0) { 390*19aa95e4SMarcin Wojtas device_printf(sc->dev, 391*19aa95e4SMarcin Wojtas "The number of TX descriptors has to be a multiple of %d\n", 392*19aa95e4SMarcin Wojtas ENETC_DESC_ALIGN); 393*19aa95e4SMarcin Wojtas error = EINVAL; 394*19aa95e4SMarcin Wojtas goto fail; 395*19aa95e4SMarcin Wojtas } 396*19aa95e4SMarcin Wojtas if (scctx->isc_nrxd[0] % ENETC_DESC_ALIGN != 0) { 397*19aa95e4SMarcin Wojtas device_printf(sc->dev, 398*19aa95e4SMarcin Wojtas "The number of RX descriptors has to be a multiple of %d\n", 399*19aa95e4SMarcin Wojtas ENETC_DESC_ALIGN); 400*19aa95e4SMarcin Wojtas error = EINVAL; 401*19aa95e4SMarcin Wojtas goto fail; 402*19aa95e4SMarcin Wojtas } 403*19aa95e4SMarcin Wojtas scctx->isc_txqsizes[0] = scctx->isc_ntxd[0] * sizeof(union enetc_tx_bd); 404*19aa95e4SMarcin Wojtas scctx->isc_rxqsizes[0] = scctx->isc_nrxd[0] * sizeof(union enetc_rx_bd); 405*19aa95e4SMarcin Wojtas scctx->isc_txd_size[0] = sizeof(union enetc_tx_bd); 406*19aa95e4SMarcin Wojtas scctx->isc_rxd_size[0] = sizeof(union enetc_rx_bd); 407*19aa95e4SMarcin Wojtas scctx->isc_tx_csum_flags = 0; 408*19aa95e4SMarcin Wojtas scctx->isc_capabilities = scctx->isc_capenable = ENETC_IFCAPS; 409*19aa95e4SMarcin Wojtas 410*19aa95e4SMarcin Wojtas error = enetc_mtu_set(ctx, ETHERMTU); 411*19aa95e4SMarcin Wojtas if (error != 0) 412*19aa95e4SMarcin Wojtas goto fail; 413*19aa95e4SMarcin Wojtas 414*19aa95e4SMarcin Wojtas scctx->isc_msix_bar = pci_msix_table_bar(sc->dev); 415*19aa95e4SMarcin Wojtas 416*19aa95e4SMarcin Wojtas error = enetc_setup_phy(sc); 417*19aa95e4SMarcin Wojtas if (error != 0) 418*19aa95e4SMarcin Wojtas goto fail; 419*19aa95e4SMarcin Wojtas 420*19aa95e4SMarcin Wojtas enetc_get_hwaddr(sc); 421*19aa95e4SMarcin Wojtas 422*19aa95e4SMarcin Wojtas return (0); 423*19aa95e4SMarcin Wojtas fail: 424*19aa95e4SMarcin Wojtas enetc_detach(ctx); 425*19aa95e4SMarcin Wojtas return (error); 426*19aa95e4SMarcin Wojtas } 427*19aa95e4SMarcin Wojtas 428*19aa95e4SMarcin Wojtas static int 429*19aa95e4SMarcin Wojtas enetc_attach_post(if_ctx_t ctx) 430*19aa95e4SMarcin Wojtas { 431*19aa95e4SMarcin Wojtas 432*19aa95e4SMarcin Wojtas enetc_init_hw(iflib_get_softc(ctx)); 433*19aa95e4SMarcin Wojtas return (0); 434*19aa95e4SMarcin Wojtas } 435*19aa95e4SMarcin Wojtas 436*19aa95e4SMarcin Wojtas static int 437*19aa95e4SMarcin Wojtas enetc_detach(if_ctx_t ctx) 438*19aa95e4SMarcin Wojtas { 439*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 440*19aa95e4SMarcin Wojtas int error = 0, i; 441*19aa95e4SMarcin Wojtas 442*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 443*19aa95e4SMarcin Wojtas 444*19aa95e4SMarcin Wojtas for (i = 0; i < sc->rx_num_queues; i++) 445*19aa95e4SMarcin Wojtas iflib_irq_free(ctx, &sc->rx_queues[i].irq); 446*19aa95e4SMarcin Wojtas 447*19aa95e4SMarcin Wojtas if (sc->miibus != NULL) 448*19aa95e4SMarcin Wojtas device_delete_child(sc->dev, sc->miibus); 449*19aa95e4SMarcin Wojtas 450*19aa95e4SMarcin Wojtas if (sc->regs != NULL) 451*19aa95e4SMarcin Wojtas error = bus_release_resource(sc->dev, SYS_RES_MEMORY, 452*19aa95e4SMarcin Wojtas rman_get_rid(sc->regs), sc->regs); 453*19aa95e4SMarcin Wojtas 454*19aa95e4SMarcin Wojtas if (sc->ctrl_queue.dma.idi_size != 0) 455*19aa95e4SMarcin Wojtas iflib_dma_free(&sc->ctrl_queue.dma); 456*19aa95e4SMarcin Wojtas 457*19aa95e4SMarcin Wojtas return (error); 458*19aa95e4SMarcin Wojtas } 459*19aa95e4SMarcin Wojtas 460*19aa95e4SMarcin Wojtas static int 461*19aa95e4SMarcin Wojtas enetc_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, 462*19aa95e4SMarcin Wojtas int ntxqs, int ntxqsets) 463*19aa95e4SMarcin Wojtas { 464*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 465*19aa95e4SMarcin Wojtas struct enetc_tx_queue *queue; 466*19aa95e4SMarcin Wojtas int i; 467*19aa95e4SMarcin Wojtas 468*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 469*19aa95e4SMarcin Wojtas 470*19aa95e4SMarcin Wojtas MPASS(ntxqs == 1); 471*19aa95e4SMarcin Wojtas 472*19aa95e4SMarcin Wojtas sc->tx_queues = mallocarray(sc->tx_num_queues, 473*19aa95e4SMarcin Wojtas sizeof(struct enetc_tx_queue), M_DEVBUF, M_NOWAIT | M_ZERO); 474*19aa95e4SMarcin Wojtas if (sc->tx_queues == NULL) { 475*19aa95e4SMarcin Wojtas device_printf(sc->dev, 476*19aa95e4SMarcin Wojtas "Failed to allocate memory for TX queues.\n"); 477*19aa95e4SMarcin Wojtas return (ENOMEM); 478*19aa95e4SMarcin Wojtas } 479*19aa95e4SMarcin Wojtas 480*19aa95e4SMarcin Wojtas for (i = 0; i < sc->tx_num_queues; i++) { 481*19aa95e4SMarcin Wojtas queue = &sc->tx_queues[i]; 482*19aa95e4SMarcin Wojtas queue->sc = sc; 483*19aa95e4SMarcin Wojtas queue->ring = (union enetc_tx_bd*)(vaddrs[i]); 484*19aa95e4SMarcin Wojtas queue->ring_paddr = paddrs[i]; 485*19aa95e4SMarcin Wojtas queue->next_to_clean = 0; 486*19aa95e4SMarcin Wojtas queue->ring_full = false; 487*19aa95e4SMarcin Wojtas } 488*19aa95e4SMarcin Wojtas 489*19aa95e4SMarcin Wojtas return (0); 490*19aa95e4SMarcin Wojtas } 491*19aa95e4SMarcin Wojtas 492*19aa95e4SMarcin Wojtas static int 493*19aa95e4SMarcin Wojtas enetc_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, 494*19aa95e4SMarcin Wojtas int nrxqs, int nrxqsets) 495*19aa95e4SMarcin Wojtas { 496*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 497*19aa95e4SMarcin Wojtas struct enetc_rx_queue *queue; 498*19aa95e4SMarcin Wojtas int i; 499*19aa95e4SMarcin Wojtas 500*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 501*19aa95e4SMarcin Wojtas MPASS(nrxqs == 1); 502*19aa95e4SMarcin Wojtas 503*19aa95e4SMarcin Wojtas sc->rx_queues = mallocarray(sc->rx_num_queues, 504*19aa95e4SMarcin Wojtas sizeof(struct enetc_rx_queue), M_DEVBUF, M_NOWAIT | M_ZERO); 505*19aa95e4SMarcin Wojtas if (sc->rx_queues == NULL) { 506*19aa95e4SMarcin Wojtas device_printf(sc->dev, 507*19aa95e4SMarcin Wojtas "Failed to allocate memory for RX queues.\n"); 508*19aa95e4SMarcin Wojtas return (ENOMEM); 509*19aa95e4SMarcin Wojtas } 510*19aa95e4SMarcin Wojtas 511*19aa95e4SMarcin Wojtas for (i = 0; i < sc->rx_num_queues; i++) { 512*19aa95e4SMarcin Wojtas queue = &sc->rx_queues[i]; 513*19aa95e4SMarcin Wojtas queue->sc = sc; 514*19aa95e4SMarcin Wojtas queue->qid = i; 515*19aa95e4SMarcin Wojtas queue->ring = (union enetc_rx_bd*)(vaddrs[i]); 516*19aa95e4SMarcin Wojtas queue->ring_paddr = paddrs[i]; 517*19aa95e4SMarcin Wojtas } 518*19aa95e4SMarcin Wojtas 519*19aa95e4SMarcin Wojtas return (0); 520*19aa95e4SMarcin Wojtas } 521*19aa95e4SMarcin Wojtas 522*19aa95e4SMarcin Wojtas static void 523*19aa95e4SMarcin Wojtas enetc_queues_free(if_ctx_t ctx) 524*19aa95e4SMarcin Wojtas { 525*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 526*19aa95e4SMarcin Wojtas 527*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 528*19aa95e4SMarcin Wojtas 529*19aa95e4SMarcin Wojtas if (sc->tx_queues != NULL) { 530*19aa95e4SMarcin Wojtas free(sc->tx_queues, M_DEVBUF); 531*19aa95e4SMarcin Wojtas sc->tx_queues = NULL; 532*19aa95e4SMarcin Wojtas } 533*19aa95e4SMarcin Wojtas if (sc->rx_queues != NULL) { 534*19aa95e4SMarcin Wojtas free(sc->rx_queues, M_DEVBUF); 535*19aa95e4SMarcin Wojtas sc->rx_queues = NULL; 536*19aa95e4SMarcin Wojtas } 537*19aa95e4SMarcin Wojtas } 538*19aa95e4SMarcin Wojtas 539*19aa95e4SMarcin Wojtas static void 540*19aa95e4SMarcin Wojtas enetc_get_hwaddr(struct enetc_softc *sc) 541*19aa95e4SMarcin Wojtas { 542*19aa95e4SMarcin Wojtas struct ether_addr hwaddr; 543*19aa95e4SMarcin Wojtas uint16_t high; 544*19aa95e4SMarcin Wojtas uint32_t low; 545*19aa95e4SMarcin Wojtas 546*19aa95e4SMarcin Wojtas low = ENETC_PORT_RD4(sc, ENETC_PSIPMAR0(0)); 547*19aa95e4SMarcin Wojtas high = ENETC_PORT_RD2(sc, ENETC_PSIPMAR1(0)); 548*19aa95e4SMarcin Wojtas 549*19aa95e4SMarcin Wojtas memcpy(&hwaddr.octet[0], &low, 4); 550*19aa95e4SMarcin Wojtas memcpy(&hwaddr.octet[4], &high, 2); 551*19aa95e4SMarcin Wojtas 552*19aa95e4SMarcin Wojtas if (ETHER_IS_BROADCAST(hwaddr.octet) || 553*19aa95e4SMarcin Wojtas ETHER_IS_MULTICAST(hwaddr.octet) || 554*19aa95e4SMarcin Wojtas ETHER_IS_ZERO(hwaddr.octet)) { 555*19aa95e4SMarcin Wojtas ether_gen_addr(iflib_get_ifp(sc->ctx), &hwaddr); 556*19aa95e4SMarcin Wojtas device_printf(sc->dev, 557*19aa95e4SMarcin Wojtas "Failed to obtain MAC address, using a random one\n"); 558*19aa95e4SMarcin Wojtas memcpy(&low, &hwaddr.octet[0], 4); 559*19aa95e4SMarcin Wojtas memcpy(&high, &hwaddr.octet[4], 2); 560*19aa95e4SMarcin Wojtas } 561*19aa95e4SMarcin Wojtas 562*19aa95e4SMarcin Wojtas iflib_set_mac(sc->ctx, hwaddr.octet); 563*19aa95e4SMarcin Wojtas } 564*19aa95e4SMarcin Wojtas 565*19aa95e4SMarcin Wojtas static void 566*19aa95e4SMarcin Wojtas enetc_set_hwaddr(struct enetc_softc *sc) 567*19aa95e4SMarcin Wojtas { 568*19aa95e4SMarcin Wojtas struct ifnet *ifp; 569*19aa95e4SMarcin Wojtas uint16_t high; 570*19aa95e4SMarcin Wojtas uint32_t low; 571*19aa95e4SMarcin Wojtas uint8_t *hwaddr; 572*19aa95e4SMarcin Wojtas 573*19aa95e4SMarcin Wojtas ifp = iflib_get_ifp(sc->ctx); 574*19aa95e4SMarcin Wojtas hwaddr = (uint8_t*)if_getlladdr(ifp); 575*19aa95e4SMarcin Wojtas low = *((uint32_t*)hwaddr); 576*19aa95e4SMarcin Wojtas high = *((uint16_t*)(hwaddr+4)); 577*19aa95e4SMarcin Wojtas 578*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIPMAR0(0), low); 579*19aa95e4SMarcin Wojtas ENETC_PORT_WR2(sc, ENETC_PSIPMAR1(0), high); 580*19aa95e4SMarcin Wojtas } 581*19aa95e4SMarcin Wojtas 582*19aa95e4SMarcin Wojtas static int 583*19aa95e4SMarcin Wojtas enetc_setup_rss(struct enetc_softc *sc) 584*19aa95e4SMarcin Wojtas { 585*19aa95e4SMarcin Wojtas struct iflib_dma_info dma; 586*19aa95e4SMarcin Wojtas int error, i, buckets_num = 0; 587*19aa95e4SMarcin Wojtas uint8_t *rss_table; 588*19aa95e4SMarcin Wojtas uint32_t reg; 589*19aa95e4SMarcin Wojtas 590*19aa95e4SMarcin Wojtas reg = ENETC_RD4(sc, ENETC_SIPCAPR0); 591*19aa95e4SMarcin Wojtas if (reg & ENETC_SIPCAPR0_RSS) { 592*19aa95e4SMarcin Wojtas reg = ENETC_RD4(sc, ENETC_SIRSSCAPR); 593*19aa95e4SMarcin Wojtas buckets_num = ENETC_SIRSSCAPR_GET_NUM_RSS(reg); 594*19aa95e4SMarcin Wojtas } 595*19aa95e4SMarcin Wojtas if (buckets_num == 0) 596*19aa95e4SMarcin Wojtas return (ENOTSUP); 597*19aa95e4SMarcin Wojtas 598*19aa95e4SMarcin Wojtas for (i = 0; i < ENETC_RSSHASH_KEY_SIZE / sizeof(uint32_t); i++) { 599*19aa95e4SMarcin Wojtas arc4rand((uint8_t *)®, sizeof(reg), 0); 600*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PRSSK(i), reg); 601*19aa95e4SMarcin Wojtas } 602*19aa95e4SMarcin Wojtas 603*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SIRBGCR, sc->rx_num_queues); 604*19aa95e4SMarcin Wojtas 605*19aa95e4SMarcin Wojtas error = iflib_dma_alloc_align(sc->ctx, 606*19aa95e4SMarcin Wojtas buckets_num * sizeof(*rss_table), 607*19aa95e4SMarcin Wojtas ENETC_RING_ALIGN, 608*19aa95e4SMarcin Wojtas &dma, 609*19aa95e4SMarcin Wojtas 0); 610*19aa95e4SMarcin Wojtas if (error != 0) { 611*19aa95e4SMarcin Wojtas device_printf(sc->dev, "Failed to allocate DMA buffer for RSS\n"); 612*19aa95e4SMarcin Wojtas return (error); 613*19aa95e4SMarcin Wojtas } 614*19aa95e4SMarcin Wojtas rss_table = (uint8_t *)dma.idi_vaddr; 615*19aa95e4SMarcin Wojtas 616*19aa95e4SMarcin Wojtas for (i = 0; i < buckets_num; i++) 617*19aa95e4SMarcin Wojtas rss_table[i] = i % sc->rx_num_queues; 618*19aa95e4SMarcin Wojtas 619*19aa95e4SMarcin Wojtas error = enetc_ctrl_send(sc, (BDCR_CMD_RSS << 8) | BDCR_CMD_RSS_WRITE, 620*19aa95e4SMarcin Wojtas buckets_num * sizeof(*rss_table), &dma); 621*19aa95e4SMarcin Wojtas if (error != 0) 622*19aa95e4SMarcin Wojtas device_printf(sc->dev, "Failed to setup RSS table\n"); 623*19aa95e4SMarcin Wojtas 624*19aa95e4SMarcin Wojtas iflib_dma_free(&dma); 625*19aa95e4SMarcin Wojtas 626*19aa95e4SMarcin Wojtas return (error); 627*19aa95e4SMarcin Wojtas } 628*19aa95e4SMarcin Wojtas 629*19aa95e4SMarcin Wojtas static int 630*19aa95e4SMarcin Wojtas enetc_ctrl_send(struct enetc_softc *sc, uint16_t cmd, uint16_t size, 631*19aa95e4SMarcin Wojtas iflib_dma_info_t dma) 632*19aa95e4SMarcin Wojtas { 633*19aa95e4SMarcin Wojtas struct enetc_ctrl_queue *queue; 634*19aa95e4SMarcin Wojtas struct enetc_cbd *desc; 635*19aa95e4SMarcin Wojtas int timeout = 1000; 636*19aa95e4SMarcin Wojtas 637*19aa95e4SMarcin Wojtas queue = &sc->ctrl_queue; 638*19aa95e4SMarcin Wojtas desc = &queue->ring[queue->pidx]; 639*19aa95e4SMarcin Wojtas 640*19aa95e4SMarcin Wojtas if (++queue->pidx == ENETC_MIN_DESC) 641*19aa95e4SMarcin Wojtas queue->pidx = 0; 642*19aa95e4SMarcin Wojtas 643*19aa95e4SMarcin Wojtas desc->addr[0] = (uint32_t)dma->idi_paddr; 644*19aa95e4SMarcin Wojtas desc->addr[1] = (uint32_t)(dma->idi_paddr >> 32); 645*19aa95e4SMarcin Wojtas desc->index = 0; 646*19aa95e4SMarcin Wojtas desc->length = (uint16_t)size; 647*19aa95e4SMarcin Wojtas desc->cmd = (uint8_t)cmd; 648*19aa95e4SMarcin Wojtas desc->cls = (uint8_t)(cmd >> 8); 649*19aa95e4SMarcin Wojtas desc->status_flags = 0; 650*19aa95e4SMarcin Wojtas 651*19aa95e4SMarcin Wojtas /* Sync command packet, */ 652*19aa95e4SMarcin Wojtas bus_dmamap_sync(dma->idi_tag, dma->idi_map, BUS_DMASYNC_PREWRITE); 653*19aa95e4SMarcin Wojtas /* and the control ring. */ 654*19aa95e4SMarcin Wojtas bus_dmamap_sync(queue->dma.idi_tag, queue->dma.idi_map, BUS_DMASYNC_PREWRITE); 655*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICBDRPIR, queue->pidx); 656*19aa95e4SMarcin Wojtas 657*19aa95e4SMarcin Wojtas while (--timeout != 0) { 658*19aa95e4SMarcin Wojtas DELAY(20); 659*19aa95e4SMarcin Wojtas if (ENETC_RD4(sc, ENETC_SICBDRCIR) == queue->pidx) 660*19aa95e4SMarcin Wojtas break; 661*19aa95e4SMarcin Wojtas } 662*19aa95e4SMarcin Wojtas 663*19aa95e4SMarcin Wojtas if (timeout == 0) 664*19aa95e4SMarcin Wojtas return (ETIMEDOUT); 665*19aa95e4SMarcin Wojtas 666*19aa95e4SMarcin Wojtas bus_dmamap_sync(dma->idi_tag, dma->idi_map, BUS_DMASYNC_POSTREAD); 667*19aa95e4SMarcin Wojtas return (0); 668*19aa95e4SMarcin Wojtas } 669*19aa95e4SMarcin Wojtas 670*19aa95e4SMarcin Wojtas static void 671*19aa95e4SMarcin Wojtas enetc_init_hw(struct enetc_softc *sc) 672*19aa95e4SMarcin Wojtas { 673*19aa95e4SMarcin Wojtas uint32_t val; 674*19aa95e4SMarcin Wojtas int error; 675*19aa95e4SMarcin Wojtas 676*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PM0_CMD_CFG, 677*19aa95e4SMarcin Wojtas ENETC_PM0_CMD_TXP | ENETC_PM0_PROMISC | 678*19aa95e4SMarcin Wojtas ENETC_PM0_TX_EN | ENETC_PM0_RX_EN); 679*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PM0_RX_FIFO, ENETC_PM0_RX_FIFO_VAL); 680*19aa95e4SMarcin Wojtas val = ENETC_PSICFGR0_SET_TXBDR(sc->tx_num_queues); 681*19aa95e4SMarcin Wojtas val |= ENETC_PSICFGR0_SET_RXBDR(sc->rx_num_queues); 682*19aa95e4SMarcin Wojtas val |= ENETC_PSICFGR0_SIVC(ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S); 683*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSICFGR0(0), val); 684*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIPVMR, ENETC_PSIPVMR_SET_VUTA(1)); 685*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PVCLCTR, ENETC_VLAN_TYPE_C | ENETC_VLAN_TYPE_S); 686*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIVLANFMR, ENETC_PSIVLANFMR_VS); 687*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PAR_PORT_CFG, ENETC_PAR_PORT_L4CD); 688*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PMR, ENETC_PMR_SI0EN | ENETC_PMR_PSPEED_1000M); 689*19aa95e4SMarcin Wojtas 690*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICAR0, 691*19aa95e4SMarcin Wojtas ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT); 692*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICAR1, ENETC_SICAR_MSI); 693*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICAR2, 694*19aa95e4SMarcin Wojtas ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT); 695*19aa95e4SMarcin Wojtas 696*19aa95e4SMarcin Wojtas enetc_init_ctrl(sc); 697*19aa95e4SMarcin Wojtas error = enetc_setup_rss(sc); 698*19aa95e4SMarcin Wojtas if (error != 0) 699*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SIMR, ENETC_SIMR_EN); 700*19aa95e4SMarcin Wojtas else 701*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SIMR, ENETC_SIMR_EN | ENETC_SIMR_RSSE); 702*19aa95e4SMarcin Wojtas 703*19aa95e4SMarcin Wojtas } 704*19aa95e4SMarcin Wojtas 705*19aa95e4SMarcin Wojtas static void 706*19aa95e4SMarcin Wojtas enetc_init_ctrl(struct enetc_softc *sc) 707*19aa95e4SMarcin Wojtas { 708*19aa95e4SMarcin Wojtas struct enetc_ctrl_queue *queue = &sc->ctrl_queue; 709*19aa95e4SMarcin Wojtas 710*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICBDRBAR0, 711*19aa95e4SMarcin Wojtas (uint32_t)queue->dma.idi_paddr); 712*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICBDRBAR1, 713*19aa95e4SMarcin Wojtas (uint32_t)(queue->dma.idi_paddr >> 32)); 714*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICBDRLENR, 715*19aa95e4SMarcin Wojtas queue->dma.idi_size / sizeof(struct enetc_cbd)); 716*19aa95e4SMarcin Wojtas 717*19aa95e4SMarcin Wojtas queue->pidx = 0; 718*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICBDRPIR, queue->pidx); 719*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICBDRCIR, queue->pidx); 720*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SICBDRMR, ENETC_SICBDRMR_EN); 721*19aa95e4SMarcin Wojtas } 722*19aa95e4SMarcin Wojtas 723*19aa95e4SMarcin Wojtas static void 724*19aa95e4SMarcin Wojtas enetc_init_tx(struct enetc_softc *sc) 725*19aa95e4SMarcin Wojtas { 726*19aa95e4SMarcin Wojtas struct enetc_tx_queue *queue; 727*19aa95e4SMarcin Wojtas int i; 728*19aa95e4SMarcin Wojtas 729*19aa95e4SMarcin Wojtas for (i = 0; i < sc->tx_num_queues; i++) { 730*19aa95e4SMarcin Wojtas queue = &sc->tx_queues[i]; 731*19aa95e4SMarcin Wojtas 732*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBBAR0, 733*19aa95e4SMarcin Wojtas (uint32_t)queue->ring_paddr); 734*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBBAR1, 735*19aa95e4SMarcin Wojtas (uint32_t)(queue->ring_paddr >> 32)); 736*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBLENR, sc->tx_queue_size); 737*19aa95e4SMarcin Wojtas 738*19aa95e4SMarcin Wojtas /* 739*19aa95e4SMarcin Wojtas * Even though it is undoccumented resetting the TX ring 740*19aa95e4SMarcin Wojtas * indices results in TX hang. 741*19aa95e4SMarcin Wojtas * Do the same as Linux and simply keep those unchanged 742*19aa95e4SMarcin Wojtas * for the drivers lifetime. 743*19aa95e4SMarcin Wojtas */ 744*19aa95e4SMarcin Wojtas #if 0 745*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBPIR, 0); 746*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBCIR, 0); 747*19aa95e4SMarcin Wojtas #endif 748*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBMR, ENETC_TBMR_EN); 749*19aa95e4SMarcin Wojtas } 750*19aa95e4SMarcin Wojtas 751*19aa95e4SMarcin Wojtas } 752*19aa95e4SMarcin Wojtas 753*19aa95e4SMarcin Wojtas static void 754*19aa95e4SMarcin Wojtas enetc_init_rx(struct enetc_softc *sc) 755*19aa95e4SMarcin Wojtas { 756*19aa95e4SMarcin Wojtas struct enetc_rx_queue *queue; 757*19aa95e4SMarcin Wojtas uint32_t rx_buf_size; 758*19aa95e4SMarcin Wojtas int i; 759*19aa95e4SMarcin Wojtas 760*19aa95e4SMarcin Wojtas rx_buf_size = iflib_get_rx_mbuf_sz(sc->ctx); 761*19aa95e4SMarcin Wojtas 762*19aa95e4SMarcin Wojtas for (i = 0; i < sc->rx_num_queues; i++) { 763*19aa95e4SMarcin Wojtas queue = &sc->rx_queues[i]; 764*19aa95e4SMarcin Wojtas 765*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBBAR0, 766*19aa95e4SMarcin Wojtas (uint32_t)queue->ring_paddr); 767*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBBAR1, 768*19aa95e4SMarcin Wojtas (uint32_t)(queue->ring_paddr >> 32)); 769*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBLENR, sc->rx_queue_size); 770*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBBSR, rx_buf_size); 771*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBPIR, 0); 772*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBCIR, 0); 773*19aa95e4SMarcin Wojtas queue->enabled = false; 774*19aa95e4SMarcin Wojtas } 775*19aa95e4SMarcin Wojtas } 776*19aa95e4SMarcin Wojtas 777*19aa95e4SMarcin Wojtas static u_int 778*19aa95e4SMarcin Wojtas enetc_hash_mac(void *arg, struct sockaddr_dl *sdl, u_int cnt) 779*19aa95e4SMarcin Wojtas { 780*19aa95e4SMarcin Wojtas uint64_t *bitmap = arg; 781*19aa95e4SMarcin Wojtas uint64_t address = 0; 782*19aa95e4SMarcin Wojtas uint8_t hash = 0; 783*19aa95e4SMarcin Wojtas bool bit; 784*19aa95e4SMarcin Wojtas int i, j; 785*19aa95e4SMarcin Wojtas 786*19aa95e4SMarcin Wojtas bcopy(LLADDR(sdl), &address, ETHER_ADDR_LEN); 787*19aa95e4SMarcin Wojtas 788*19aa95e4SMarcin Wojtas /* 789*19aa95e4SMarcin Wojtas * The six bit hash is calculated by xoring every 790*19aa95e4SMarcin Wojtas * 6th bit of the address. 791*19aa95e4SMarcin Wojtas * It is then used as an index in a bitmap that is 792*19aa95e4SMarcin Wojtas * written to the device. 793*19aa95e4SMarcin Wojtas */ 794*19aa95e4SMarcin Wojtas for (i = 0; i < 6; i++) { 795*19aa95e4SMarcin Wojtas bit = 0; 796*19aa95e4SMarcin Wojtas for (j = 0; j < 8; j++) 797*19aa95e4SMarcin Wojtas bit ^= address & BIT(i + j*6); 798*19aa95e4SMarcin Wojtas 799*19aa95e4SMarcin Wojtas hash |= bit << i; 800*19aa95e4SMarcin Wojtas } 801*19aa95e4SMarcin Wojtas 802*19aa95e4SMarcin Wojtas *bitmap |= (1 << hash); 803*19aa95e4SMarcin Wojtas return (1); 804*19aa95e4SMarcin Wojtas } 805*19aa95e4SMarcin Wojtas 806*19aa95e4SMarcin Wojtas static void 807*19aa95e4SMarcin Wojtas enetc_setup_multicast(if_ctx_t ctx) 808*19aa95e4SMarcin Wojtas { 809*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 810*19aa95e4SMarcin Wojtas struct ifnet *ifp; 811*19aa95e4SMarcin Wojtas uint64_t bitmap = 0; 812*19aa95e4SMarcin Wojtas uint8_t revid; 813*19aa95e4SMarcin Wojtas 814*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 815*19aa95e4SMarcin Wojtas ifp = iflib_get_ifp(ctx); 816*19aa95e4SMarcin Wojtas revid = pci_get_revid(sc->dev); 817*19aa95e4SMarcin Wojtas 818*19aa95e4SMarcin Wojtas if_foreach_llmaddr(ifp, enetc_hash_mac, &bitmap); 819*19aa95e4SMarcin Wojtas 820*19aa95e4SMarcin Wojtas /* 821*19aa95e4SMarcin Wojtas * In revid 1 of this chip the positions multicast and unicast 822*19aa95e4SMarcin Wojtas * hash filter registers are flipped. 823*19aa95e4SMarcin Wojtas */ 824*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIMMHFR0(0, revid == 1), bitmap & UINT32_MAX); 825*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIMMHFR1(0), bitmap >> 32); 826*19aa95e4SMarcin Wojtas 827*19aa95e4SMarcin Wojtas } 828*19aa95e4SMarcin Wojtas 829*19aa95e4SMarcin Wojtas static uint8_t 830*19aa95e4SMarcin Wojtas enetc_hash_vid(uint16_t vid) 831*19aa95e4SMarcin Wojtas { 832*19aa95e4SMarcin Wojtas uint8_t hash = 0; 833*19aa95e4SMarcin Wojtas bool bit; 834*19aa95e4SMarcin Wojtas int i; 835*19aa95e4SMarcin Wojtas 836*19aa95e4SMarcin Wojtas for (i = 0;i < 6;i++) { 837*19aa95e4SMarcin Wojtas bit = vid & BIT(i); 838*19aa95e4SMarcin Wojtas bit ^= vid & BIT(i + 6); 839*19aa95e4SMarcin Wojtas hash |= bit << i; 840*19aa95e4SMarcin Wojtas } 841*19aa95e4SMarcin Wojtas 842*19aa95e4SMarcin Wojtas return (hash); 843*19aa95e4SMarcin Wojtas } 844*19aa95e4SMarcin Wojtas 845*19aa95e4SMarcin Wojtas static void 846*19aa95e4SMarcin Wojtas enetc_vlan_register(if_ctx_t ctx, uint16_t vid) 847*19aa95e4SMarcin Wojtas { 848*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 849*19aa95e4SMarcin Wojtas uint8_t hash; 850*19aa95e4SMarcin Wojtas uint64_t bitmap; 851*19aa95e4SMarcin Wojtas 852*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 853*19aa95e4SMarcin Wojtas hash = enetc_hash_vid(vid); 854*19aa95e4SMarcin Wojtas 855*19aa95e4SMarcin Wojtas /* Check if hash is alredy present in the bitmap. */ 856*19aa95e4SMarcin Wojtas if (++sc->vlan_bitmap[hash] != 1) 857*19aa95e4SMarcin Wojtas return; 858*19aa95e4SMarcin Wojtas 859*19aa95e4SMarcin Wojtas bitmap = ENETC_PORT_RD4(sc, ENETC_PSIVHFR0(0)); 860*19aa95e4SMarcin Wojtas bitmap |= (uint64_t)ENETC_PORT_RD4(sc, ENETC_PSIVHFR1(0)) << 32; 861*19aa95e4SMarcin Wojtas bitmap |= BIT(hash); 862*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIVHFR0(0), bitmap & UINT32_MAX); 863*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIVHFR1(0), bitmap >> 32); 864*19aa95e4SMarcin Wojtas } 865*19aa95e4SMarcin Wojtas 866*19aa95e4SMarcin Wojtas static void 867*19aa95e4SMarcin Wojtas enetc_vlan_unregister(if_ctx_t ctx, uint16_t vid) 868*19aa95e4SMarcin Wojtas { 869*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 870*19aa95e4SMarcin Wojtas uint8_t hash; 871*19aa95e4SMarcin Wojtas uint64_t bitmap; 872*19aa95e4SMarcin Wojtas 873*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 874*19aa95e4SMarcin Wojtas hash = enetc_hash_vid(vid); 875*19aa95e4SMarcin Wojtas 876*19aa95e4SMarcin Wojtas MPASS(sc->vlan_bitmap[hash] > 0); 877*19aa95e4SMarcin Wojtas if (--sc->vlan_bitmap[hash] != 0) 878*19aa95e4SMarcin Wojtas return; 879*19aa95e4SMarcin Wojtas 880*19aa95e4SMarcin Wojtas bitmap = ENETC_PORT_RD4(sc, ENETC_PSIVHFR0(0)); 881*19aa95e4SMarcin Wojtas bitmap |= (uint64_t)ENETC_PORT_RD4(sc, ENETC_PSIVHFR1(0)) << 32; 882*19aa95e4SMarcin Wojtas bitmap &= ~BIT(hash); 883*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIVHFR0(0), bitmap & UINT32_MAX); 884*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIVHFR1(0), bitmap >> 32); 885*19aa95e4SMarcin Wojtas } 886*19aa95e4SMarcin Wojtas 887*19aa95e4SMarcin Wojtas static void 888*19aa95e4SMarcin Wojtas enetc_init(if_ctx_t ctx) 889*19aa95e4SMarcin Wojtas { 890*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 891*19aa95e4SMarcin Wojtas struct mii_data *miid; 892*19aa95e4SMarcin Wojtas struct ifnet *ifp; 893*19aa95e4SMarcin Wojtas uint16_t max_frame_length; 894*19aa95e4SMarcin Wojtas int baudrate; 895*19aa95e4SMarcin Wojtas 896*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 897*19aa95e4SMarcin Wojtas ifp = iflib_get_ifp(ctx); 898*19aa95e4SMarcin Wojtas 899*19aa95e4SMarcin Wojtas max_frame_length = sc->shared->isc_max_frame_size; 900*19aa95e4SMarcin Wojtas MPASS(max_frame_length < ENETC_MAX_FRAME_LEN); 901*19aa95e4SMarcin Wojtas 902*19aa95e4SMarcin Wojtas /* Set max RX and TX frame lengths. */ 903*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PM0_MAXFRM, max_frame_length); 904*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PTCMSDUR(0), max_frame_length); 905*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PTXMBAR, 2 * max_frame_length); 906*19aa95e4SMarcin Wojtas 907*19aa95e4SMarcin Wojtas /* Set "VLAN promiscious" mode if filtering is disabled. */ 908*19aa95e4SMarcin Wojtas if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER) == 0) 909*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIPVMR, 910*19aa95e4SMarcin Wojtas ENETC_PSIPVMR_SET_VUTA(1) | ENETC_PSIPVMR_SET_VP(1)); 911*19aa95e4SMarcin Wojtas else 912*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIPVMR, 913*19aa95e4SMarcin Wojtas ENETC_PSIPVMR_SET_VUTA(1)); 914*19aa95e4SMarcin Wojtas 915*19aa95e4SMarcin Wojtas sc->rbmr = ENETC_RBMR_EN | ENETC_RBMR_AL; 916*19aa95e4SMarcin Wojtas 917*19aa95e4SMarcin Wojtas if (if_getcapenable(ifp) & IFCAP_VLAN_HWTAGGING) 918*19aa95e4SMarcin Wojtas sc->rbmr |= ENETC_RBMR_VTE; 919*19aa95e4SMarcin Wojtas 920*19aa95e4SMarcin Wojtas /* Write MAC address to hardware. */ 921*19aa95e4SMarcin Wojtas enetc_set_hwaddr(sc); 922*19aa95e4SMarcin Wojtas 923*19aa95e4SMarcin Wojtas enetc_init_tx(sc); 924*19aa95e4SMarcin Wojtas enetc_init_rx(sc); 925*19aa95e4SMarcin Wojtas 926*19aa95e4SMarcin Wojtas if (sc->fixed_link) { 927*19aa95e4SMarcin Wojtas baudrate = ifmedia_baudrate(sc->fixed_ifmedia.ifm_cur->ifm_media); 928*19aa95e4SMarcin Wojtas iflib_link_state_change(sc->ctx, LINK_STATE_UP, baudrate); 929*19aa95e4SMarcin Wojtas } else { 930*19aa95e4SMarcin Wojtas /* 931*19aa95e4SMarcin Wojtas * Can't return an error from this function, there is not much 932*19aa95e4SMarcin Wojtas * we can do if this fails. 933*19aa95e4SMarcin Wojtas */ 934*19aa95e4SMarcin Wojtas miid = device_get_softc(sc->miibus); 935*19aa95e4SMarcin Wojtas (void)mii_mediachg(miid); 936*19aa95e4SMarcin Wojtas } 937*19aa95e4SMarcin Wojtas 938*19aa95e4SMarcin Wojtas enetc_promisc_set(ctx, if_getflags(ifp)); 939*19aa95e4SMarcin Wojtas } 940*19aa95e4SMarcin Wojtas 941*19aa95e4SMarcin Wojtas static void 942*19aa95e4SMarcin Wojtas enetc_stop(if_ctx_t ctx) 943*19aa95e4SMarcin Wojtas { 944*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 945*19aa95e4SMarcin Wojtas int i; 946*19aa95e4SMarcin Wojtas 947*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 948*19aa95e4SMarcin Wojtas 949*19aa95e4SMarcin Wojtas for (i = 0; i < sc->tx_num_queues; i++) 950*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBMR, 0); 951*19aa95e4SMarcin Wojtas 952*19aa95e4SMarcin Wojtas for (i = 0; i < sc->rx_num_queues; i++) 953*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBMR, 0); 954*19aa95e4SMarcin Wojtas } 955*19aa95e4SMarcin Wojtas 956*19aa95e4SMarcin Wojtas static int 957*19aa95e4SMarcin Wojtas enetc_msix_intr_assign(if_ctx_t ctx, int msix) 958*19aa95e4SMarcin Wojtas { 959*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 960*19aa95e4SMarcin Wojtas struct enetc_rx_queue *rx_queue; 961*19aa95e4SMarcin Wojtas struct enetc_tx_queue *tx_queue; 962*19aa95e4SMarcin Wojtas int vector = 0, i, error; 963*19aa95e4SMarcin Wojtas char irq_name[16]; 964*19aa95e4SMarcin Wojtas 965*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 966*19aa95e4SMarcin Wojtas 967*19aa95e4SMarcin Wojtas MPASS(sc->rx_num_queues + 1 <= ENETC_MSIX_COUNT); 968*19aa95e4SMarcin Wojtas MPASS(sc->rx_num_queues == sc->tx_num_queues); 969*19aa95e4SMarcin Wojtas 970*19aa95e4SMarcin Wojtas for (i = 0; i < sc->rx_num_queues; i++, vector++) { 971*19aa95e4SMarcin Wojtas rx_queue = &sc->rx_queues[i]; 972*19aa95e4SMarcin Wojtas snprintf(irq_name, sizeof(irq_name), "rxtxq%d", i); 973*19aa95e4SMarcin Wojtas error = iflib_irq_alloc_generic(ctx, 974*19aa95e4SMarcin Wojtas &rx_queue->irq, vector + 1, IFLIB_INTR_RXTX, 975*19aa95e4SMarcin Wojtas NULL, rx_queue, i, irq_name); 976*19aa95e4SMarcin Wojtas if (error != 0) 977*19aa95e4SMarcin Wojtas goto fail; 978*19aa95e4SMarcin Wojtas 979*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SIMSIRRV(i), vector); 980*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBICR1, ENETC_RX_INTR_TIME_THR); 981*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBICR0, 982*19aa95e4SMarcin Wojtas ENETC_RBICR0_ICEN | ENETC_RBICR0_SET_ICPT(ENETC_RX_INTR_PKT_THR)); 983*19aa95e4SMarcin Wojtas } 984*19aa95e4SMarcin Wojtas vector = 0; 985*19aa95e4SMarcin Wojtas for (i = 0;i < sc->tx_num_queues; i++, vector++) { 986*19aa95e4SMarcin Wojtas tx_queue = &sc->tx_queues[i]; 987*19aa95e4SMarcin Wojtas snprintf(irq_name, sizeof(irq_name), "txq%d", i); 988*19aa95e4SMarcin Wojtas iflib_softirq_alloc_generic(ctx, &tx_queue->irq, 989*19aa95e4SMarcin Wojtas IFLIB_INTR_TX, tx_queue, i, irq_name); 990*19aa95e4SMarcin Wojtas 991*19aa95e4SMarcin Wojtas ENETC_WR4(sc, ENETC_SIMSITRV(i), vector); 992*19aa95e4SMarcin Wojtas } 993*19aa95e4SMarcin Wojtas 994*19aa95e4SMarcin Wojtas return (0); 995*19aa95e4SMarcin Wojtas fail: 996*19aa95e4SMarcin Wojtas for (i = 0; i < sc->rx_num_queues; i++) { 997*19aa95e4SMarcin Wojtas rx_queue = &sc->rx_queues[i]; 998*19aa95e4SMarcin Wojtas iflib_irq_free(ctx, &rx_queue->irq); 999*19aa95e4SMarcin Wojtas } 1000*19aa95e4SMarcin Wojtas return (error); 1001*19aa95e4SMarcin Wojtas } 1002*19aa95e4SMarcin Wojtas 1003*19aa95e4SMarcin Wojtas static int 1004*19aa95e4SMarcin Wojtas enetc_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) 1005*19aa95e4SMarcin Wojtas { 1006*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1007*19aa95e4SMarcin Wojtas 1008*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 1009*19aa95e4SMarcin Wojtas ENETC_TXQ_RD4(sc, qid, ENETC_TBIDR); 1010*19aa95e4SMarcin Wojtas return (0); 1011*19aa95e4SMarcin Wojtas } 1012*19aa95e4SMarcin Wojtas 1013*19aa95e4SMarcin Wojtas static int 1014*19aa95e4SMarcin Wojtas enetc_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) 1015*19aa95e4SMarcin Wojtas { 1016*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1017*19aa95e4SMarcin Wojtas 1018*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 1019*19aa95e4SMarcin Wojtas ENETC_RXQ_RD4(sc, qid, ENETC_RBIDR); 1020*19aa95e4SMarcin Wojtas return (0); 1021*19aa95e4SMarcin Wojtas } 1022*19aa95e4SMarcin Wojtas static void 1023*19aa95e4SMarcin Wojtas enetc_intr_enable(if_ctx_t ctx) 1024*19aa95e4SMarcin Wojtas { 1025*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1026*19aa95e4SMarcin Wojtas int i; 1027*19aa95e4SMarcin Wojtas 1028*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 1029*19aa95e4SMarcin Wojtas 1030*19aa95e4SMarcin Wojtas for (i = 0; i < sc->rx_num_queues; i++) 1031*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBIER, ENETC_RBIER_RXTIE); 1032*19aa95e4SMarcin Wojtas 1033*19aa95e4SMarcin Wojtas for (i = 0; i < sc->tx_num_queues; i++) 1034*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBIER, ENETC_TBIER_TXF); 1035*19aa95e4SMarcin Wojtas } 1036*19aa95e4SMarcin Wojtas 1037*19aa95e4SMarcin Wojtas static void 1038*19aa95e4SMarcin Wojtas enetc_intr_disable(if_ctx_t ctx) 1039*19aa95e4SMarcin Wojtas { 1040*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1041*19aa95e4SMarcin Wojtas int i; 1042*19aa95e4SMarcin Wojtas 1043*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 1044*19aa95e4SMarcin Wojtas 1045*19aa95e4SMarcin Wojtas for (i = 0; i < sc->rx_num_queues; i++) 1046*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, i, ENETC_RBIER, 0); 1047*19aa95e4SMarcin Wojtas 1048*19aa95e4SMarcin Wojtas for (i = 0; i < sc->tx_num_queues; i++) 1049*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, i, ENETC_TBIER, 0); 1050*19aa95e4SMarcin Wojtas } 1051*19aa95e4SMarcin Wojtas 1052*19aa95e4SMarcin Wojtas static int 1053*19aa95e4SMarcin Wojtas enetc_isc_txd_encap(void *data, if_pkt_info_t ipi) 1054*19aa95e4SMarcin Wojtas { 1055*19aa95e4SMarcin Wojtas struct enetc_softc *sc = data; 1056*19aa95e4SMarcin Wojtas struct enetc_tx_queue *queue; 1057*19aa95e4SMarcin Wojtas union enetc_tx_bd *desc; 1058*19aa95e4SMarcin Wojtas bus_dma_segment_t *segs; 1059*19aa95e4SMarcin Wojtas qidx_t pidx, queue_len; 1060*19aa95e4SMarcin Wojtas qidx_t i = 0; 1061*19aa95e4SMarcin Wojtas 1062*19aa95e4SMarcin Wojtas queue = &sc->tx_queues[ipi->ipi_qsidx]; 1063*19aa95e4SMarcin Wojtas segs = ipi->ipi_segs; 1064*19aa95e4SMarcin Wojtas pidx = ipi->ipi_pidx; 1065*19aa95e4SMarcin Wojtas queue_len = sc->tx_queue_size; 1066*19aa95e4SMarcin Wojtas 1067*19aa95e4SMarcin Wojtas /* 1068*19aa95e4SMarcin Wojtas * First descriptor is special. We use it to set frame 1069*19aa95e4SMarcin Wojtas * related information and offloads, e.g. VLAN tag. 1070*19aa95e4SMarcin Wojtas */ 1071*19aa95e4SMarcin Wojtas desc = &queue->ring[pidx]; 1072*19aa95e4SMarcin Wojtas bzero(desc, sizeof(*desc)); 1073*19aa95e4SMarcin Wojtas desc->frm_len = ipi->ipi_len; 1074*19aa95e4SMarcin Wojtas desc->addr = segs[i].ds_addr; 1075*19aa95e4SMarcin Wojtas desc->buf_len = segs[i].ds_len; 1076*19aa95e4SMarcin Wojtas if (ipi->ipi_flags & IPI_TX_INTR) 1077*19aa95e4SMarcin Wojtas desc->flags = ENETC_TXBD_FLAGS_FI; 1078*19aa95e4SMarcin Wojtas 1079*19aa95e4SMarcin Wojtas i++; 1080*19aa95e4SMarcin Wojtas if (++pidx == queue_len) 1081*19aa95e4SMarcin Wojtas pidx = 0; 1082*19aa95e4SMarcin Wojtas 1083*19aa95e4SMarcin Wojtas if (ipi->ipi_mflags & M_VLANTAG) { 1084*19aa95e4SMarcin Wojtas /* VLAN tag is inserted in a separate descriptor. */ 1085*19aa95e4SMarcin Wojtas desc->flags |= ENETC_TXBD_FLAGS_EX; 1086*19aa95e4SMarcin Wojtas desc = &queue->ring[pidx]; 1087*19aa95e4SMarcin Wojtas bzero(desc, sizeof(*desc)); 1088*19aa95e4SMarcin Wojtas desc->ext.vid = ipi->ipi_vtag; 1089*19aa95e4SMarcin Wojtas desc->ext.e_flags = ENETC_TXBD_E_FLAGS_VLAN_INS; 1090*19aa95e4SMarcin Wojtas if (++pidx == queue_len) 1091*19aa95e4SMarcin Wojtas pidx = 0; 1092*19aa95e4SMarcin Wojtas } 1093*19aa95e4SMarcin Wojtas 1094*19aa95e4SMarcin Wojtas /* Now add remaining descriptors. */ 1095*19aa95e4SMarcin Wojtas for (;i < ipi->ipi_nsegs; i++) { 1096*19aa95e4SMarcin Wojtas desc = &queue->ring[pidx]; 1097*19aa95e4SMarcin Wojtas bzero(desc, sizeof(*desc)); 1098*19aa95e4SMarcin Wojtas desc->addr = segs[i].ds_addr; 1099*19aa95e4SMarcin Wojtas desc->buf_len = segs[i].ds_len; 1100*19aa95e4SMarcin Wojtas 1101*19aa95e4SMarcin Wojtas if (++pidx == queue_len) 1102*19aa95e4SMarcin Wojtas pidx = 0; 1103*19aa95e4SMarcin Wojtas } 1104*19aa95e4SMarcin Wojtas 1105*19aa95e4SMarcin Wojtas desc->flags |= ENETC_TXBD_FLAGS_F; 1106*19aa95e4SMarcin Wojtas ipi->ipi_new_pidx = pidx; 1107*19aa95e4SMarcin Wojtas if (pidx == queue->next_to_clean) 1108*19aa95e4SMarcin Wojtas queue->ring_full = true; 1109*19aa95e4SMarcin Wojtas 1110*19aa95e4SMarcin Wojtas return (0); 1111*19aa95e4SMarcin Wojtas } 1112*19aa95e4SMarcin Wojtas 1113*19aa95e4SMarcin Wojtas static void 1114*19aa95e4SMarcin Wojtas enetc_isc_txd_flush(void *data, uint16_t qid, qidx_t pidx) 1115*19aa95e4SMarcin Wojtas { 1116*19aa95e4SMarcin Wojtas struct enetc_softc *sc = data; 1117*19aa95e4SMarcin Wojtas 1118*19aa95e4SMarcin Wojtas ENETC_TXQ_WR4(sc, qid, ENETC_TBPIR, pidx); 1119*19aa95e4SMarcin Wojtas } 1120*19aa95e4SMarcin Wojtas 1121*19aa95e4SMarcin Wojtas static int 1122*19aa95e4SMarcin Wojtas enetc_isc_txd_credits_update(void *data, uint16_t qid, bool clear) 1123*19aa95e4SMarcin Wojtas { 1124*19aa95e4SMarcin Wojtas struct enetc_softc *sc = data; 1125*19aa95e4SMarcin Wojtas struct enetc_tx_queue *queue; 1126*19aa95e4SMarcin Wojtas qidx_t next_to_clean, next_to_process; 1127*19aa95e4SMarcin Wojtas int clean_count; 1128*19aa95e4SMarcin Wojtas 1129*19aa95e4SMarcin Wojtas queue = &sc->tx_queues[qid]; 1130*19aa95e4SMarcin Wojtas next_to_process = 1131*19aa95e4SMarcin Wojtas ENETC_TXQ_RD4(sc, qid, ENETC_TBCIR) & ENETC_TBCIR_IDX_MASK; 1132*19aa95e4SMarcin Wojtas next_to_clean = queue->next_to_clean; 1133*19aa95e4SMarcin Wojtas 1134*19aa95e4SMarcin Wojtas if (next_to_clean == next_to_process && !queue->ring_full) 1135*19aa95e4SMarcin Wojtas return (0); 1136*19aa95e4SMarcin Wojtas 1137*19aa95e4SMarcin Wojtas if (!clear) 1138*19aa95e4SMarcin Wojtas return (1); 1139*19aa95e4SMarcin Wojtas 1140*19aa95e4SMarcin Wojtas clean_count = next_to_process - next_to_clean; 1141*19aa95e4SMarcin Wojtas if (clean_count <= 0) 1142*19aa95e4SMarcin Wojtas clean_count += sc->tx_queue_size; 1143*19aa95e4SMarcin Wojtas 1144*19aa95e4SMarcin Wojtas queue->next_to_clean = next_to_process; 1145*19aa95e4SMarcin Wojtas queue->ring_full = false; 1146*19aa95e4SMarcin Wojtas 1147*19aa95e4SMarcin Wojtas return (clean_count); 1148*19aa95e4SMarcin Wojtas } 1149*19aa95e4SMarcin Wojtas 1150*19aa95e4SMarcin Wojtas static int 1151*19aa95e4SMarcin Wojtas enetc_isc_rxd_available(void *data, uint16_t qid, qidx_t pidx, qidx_t budget) 1152*19aa95e4SMarcin Wojtas { 1153*19aa95e4SMarcin Wojtas struct enetc_softc *sc = data; 1154*19aa95e4SMarcin Wojtas struct enetc_rx_queue *queue; 1155*19aa95e4SMarcin Wojtas qidx_t hw_pidx, queue_len; 1156*19aa95e4SMarcin Wojtas union enetc_rx_bd *desc; 1157*19aa95e4SMarcin Wojtas int count = 0; 1158*19aa95e4SMarcin Wojtas 1159*19aa95e4SMarcin Wojtas queue = &sc->rx_queues[qid]; 1160*19aa95e4SMarcin Wojtas desc = &queue->ring[pidx]; 1161*19aa95e4SMarcin Wojtas queue_len = sc->rx_queue_size; 1162*19aa95e4SMarcin Wojtas 1163*19aa95e4SMarcin Wojtas if (desc->r.lstatus == 0) 1164*19aa95e4SMarcin Wojtas return (0); 1165*19aa95e4SMarcin Wojtas 1166*19aa95e4SMarcin Wojtas if (budget == 1) 1167*19aa95e4SMarcin Wojtas return (1); 1168*19aa95e4SMarcin Wojtas 1169*19aa95e4SMarcin Wojtas hw_pidx = ENETC_RXQ_RD4(sc, qid, ENETC_RBPIR); 1170*19aa95e4SMarcin Wojtas while (pidx != hw_pidx && count < budget) { 1171*19aa95e4SMarcin Wojtas desc = &queue->ring[pidx]; 1172*19aa95e4SMarcin Wojtas if (desc->r.lstatus & ENETC_RXBD_LSTATUS_F) 1173*19aa95e4SMarcin Wojtas count++; 1174*19aa95e4SMarcin Wojtas 1175*19aa95e4SMarcin Wojtas if (++pidx == queue_len) 1176*19aa95e4SMarcin Wojtas pidx = 0; 1177*19aa95e4SMarcin Wojtas } 1178*19aa95e4SMarcin Wojtas 1179*19aa95e4SMarcin Wojtas return (count); 1180*19aa95e4SMarcin Wojtas } 1181*19aa95e4SMarcin Wojtas 1182*19aa95e4SMarcin Wojtas static int 1183*19aa95e4SMarcin Wojtas enetc_isc_rxd_pkt_get(void *data, if_rxd_info_t ri) 1184*19aa95e4SMarcin Wojtas { 1185*19aa95e4SMarcin Wojtas struct enetc_softc *sc = data; 1186*19aa95e4SMarcin Wojtas struct enetc_rx_queue *queue; 1187*19aa95e4SMarcin Wojtas union enetc_rx_bd *desc; 1188*19aa95e4SMarcin Wojtas uint16_t buf_len, pkt_size = 0; 1189*19aa95e4SMarcin Wojtas qidx_t cidx, queue_len; 1190*19aa95e4SMarcin Wojtas uint32_t status; 1191*19aa95e4SMarcin Wojtas int i; 1192*19aa95e4SMarcin Wojtas 1193*19aa95e4SMarcin Wojtas cidx = ri->iri_cidx; 1194*19aa95e4SMarcin Wojtas queue = &sc->rx_queues[ri->iri_qsidx]; 1195*19aa95e4SMarcin Wojtas desc = &queue->ring[cidx]; 1196*19aa95e4SMarcin Wojtas status = desc->r.lstatus; 1197*19aa95e4SMarcin Wojtas queue_len = sc->rx_queue_size; 1198*19aa95e4SMarcin Wojtas 1199*19aa95e4SMarcin Wojtas /* 1200*19aa95e4SMarcin Wojtas * Ready bit will be set only when all descriptors 1201*19aa95e4SMarcin Wojtas * in the chain have been processed. 1202*19aa95e4SMarcin Wojtas */ 1203*19aa95e4SMarcin Wojtas if ((status & ENETC_RXBD_LSTATUS_R) == 0) 1204*19aa95e4SMarcin Wojtas return (EAGAIN); 1205*19aa95e4SMarcin Wojtas 1206*19aa95e4SMarcin Wojtas /* Pass RSS hash. */ 1207*19aa95e4SMarcin Wojtas if (status & ENETC_RXBD_FLAG_RSSV) { 1208*19aa95e4SMarcin Wojtas ri->iri_flowid = desc->r.rss_hash; 1209*19aa95e4SMarcin Wojtas ri->iri_rsstype = M_HASHTYPE_OPAQUE_HASH; 1210*19aa95e4SMarcin Wojtas } 1211*19aa95e4SMarcin Wojtas 1212*19aa95e4SMarcin Wojtas /* Pass IP checksum status. */ 1213*19aa95e4SMarcin Wojtas ri->iri_csum_flags = CSUM_IP_CHECKED; 1214*19aa95e4SMarcin Wojtas if ((desc->r.parse_summary & ENETC_RXBD_PARSER_ERROR) == 0) 1215*19aa95e4SMarcin Wojtas ri->iri_csum_flags |= CSUM_IP_VALID; 1216*19aa95e4SMarcin Wojtas 1217*19aa95e4SMarcin Wojtas /* Pass extracted VLAN tag. */ 1218*19aa95e4SMarcin Wojtas if (status & ENETC_RXBD_FLAG_VLAN) { 1219*19aa95e4SMarcin Wojtas ri->iri_vtag = desc->r.vlan_opt; 1220*19aa95e4SMarcin Wojtas ri->iri_flags = M_VLANTAG; 1221*19aa95e4SMarcin Wojtas } 1222*19aa95e4SMarcin Wojtas 1223*19aa95e4SMarcin Wojtas for (i = 0; i < ENETC_MAX_SCATTER; i++) { 1224*19aa95e4SMarcin Wojtas buf_len = desc->r.buf_len; 1225*19aa95e4SMarcin Wojtas ri->iri_frags[i].irf_idx = cidx; 1226*19aa95e4SMarcin Wojtas ri->iri_frags[i].irf_len = buf_len; 1227*19aa95e4SMarcin Wojtas pkt_size += buf_len; 1228*19aa95e4SMarcin Wojtas if (desc->r.lstatus & ENETC_RXBD_LSTATUS_F) 1229*19aa95e4SMarcin Wojtas break; 1230*19aa95e4SMarcin Wojtas 1231*19aa95e4SMarcin Wojtas if (++cidx == queue_len) 1232*19aa95e4SMarcin Wojtas cidx = 0; 1233*19aa95e4SMarcin Wojtas 1234*19aa95e4SMarcin Wojtas desc = &queue->ring[cidx]; 1235*19aa95e4SMarcin Wojtas } 1236*19aa95e4SMarcin Wojtas ri->iri_nfrags = i + 1; 1237*19aa95e4SMarcin Wojtas ri->iri_len = pkt_size + ENETC_RX_IP_ALIGN; 1238*19aa95e4SMarcin Wojtas ri->iri_pad = ENETC_RX_IP_ALIGN; 1239*19aa95e4SMarcin Wojtas 1240*19aa95e4SMarcin Wojtas MPASS(desc->r.lstatus & ENETC_RXBD_LSTATUS_F); 1241*19aa95e4SMarcin Wojtas if (status & ENETC_RXBD_LSTATUS(ENETC_RXBD_ERR_MASK)) 1242*19aa95e4SMarcin Wojtas return (EBADMSG); 1243*19aa95e4SMarcin Wojtas 1244*19aa95e4SMarcin Wojtas return (0); 1245*19aa95e4SMarcin Wojtas } 1246*19aa95e4SMarcin Wojtas 1247*19aa95e4SMarcin Wojtas static void 1248*19aa95e4SMarcin Wojtas enetc_isc_rxd_refill(void *data, if_rxd_update_t iru) 1249*19aa95e4SMarcin Wojtas { 1250*19aa95e4SMarcin Wojtas struct enetc_softc *sc = data; 1251*19aa95e4SMarcin Wojtas struct enetc_rx_queue *queue; 1252*19aa95e4SMarcin Wojtas union enetc_rx_bd *desc; 1253*19aa95e4SMarcin Wojtas qidx_t pidx, queue_len; 1254*19aa95e4SMarcin Wojtas uint64_t *paddrs; 1255*19aa95e4SMarcin Wojtas int i, count; 1256*19aa95e4SMarcin Wojtas 1257*19aa95e4SMarcin Wojtas queue = &sc->rx_queues[iru->iru_qsidx]; 1258*19aa95e4SMarcin Wojtas paddrs = iru->iru_paddrs; 1259*19aa95e4SMarcin Wojtas pidx = iru->iru_pidx; 1260*19aa95e4SMarcin Wojtas count = iru->iru_count; 1261*19aa95e4SMarcin Wojtas queue_len = sc->rx_queue_size; 1262*19aa95e4SMarcin Wojtas 1263*19aa95e4SMarcin Wojtas for (i = 0; i < count; i++) { 1264*19aa95e4SMarcin Wojtas desc = &queue->ring[pidx]; 1265*19aa95e4SMarcin Wojtas bzero(desc, sizeof(*desc)); 1266*19aa95e4SMarcin Wojtas 1267*19aa95e4SMarcin Wojtas desc->w.addr = paddrs[i]; 1268*19aa95e4SMarcin Wojtas if (++pidx == queue_len) 1269*19aa95e4SMarcin Wojtas pidx = 0; 1270*19aa95e4SMarcin Wojtas } 1271*19aa95e4SMarcin Wojtas /* 1272*19aa95e4SMarcin Wojtas * After enabling the queue NIC will prefetch the first 1273*19aa95e4SMarcin Wojtas * 8 descriptors. It probably assumes that the RX is fully 1274*19aa95e4SMarcin Wojtas * refilled when cidx == pidx. 1275*19aa95e4SMarcin Wojtas * Enable it only if we have enough decriptors ready on the ring. 1276*19aa95e4SMarcin Wojtas */ 1277*19aa95e4SMarcin Wojtas if (!queue->enabled && pidx >= 8) { 1278*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, iru->iru_qsidx, ENETC_RBMR, sc->rbmr); 1279*19aa95e4SMarcin Wojtas queue->enabled = true; 1280*19aa95e4SMarcin Wojtas } 1281*19aa95e4SMarcin Wojtas } 1282*19aa95e4SMarcin Wojtas 1283*19aa95e4SMarcin Wojtas static void 1284*19aa95e4SMarcin Wojtas enetc_isc_rxd_flush(void *data, uint16_t qid, uint8_t flid, qidx_t pidx) 1285*19aa95e4SMarcin Wojtas { 1286*19aa95e4SMarcin Wojtas struct enetc_softc *sc = data; 1287*19aa95e4SMarcin Wojtas 1288*19aa95e4SMarcin Wojtas ENETC_RXQ_WR4(sc, qid, ENETC_RBCIR, pidx); 1289*19aa95e4SMarcin Wojtas } 1290*19aa95e4SMarcin Wojtas 1291*19aa95e4SMarcin Wojtas static uint64_t 1292*19aa95e4SMarcin Wojtas enetc_get_counter(if_ctx_t ctx, ift_counter cnt) 1293*19aa95e4SMarcin Wojtas { 1294*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1295*19aa95e4SMarcin Wojtas struct ifnet *ifp; 1296*19aa95e4SMarcin Wojtas 1297*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 1298*19aa95e4SMarcin Wojtas ifp = iflib_get_ifp(ctx); 1299*19aa95e4SMarcin Wojtas 1300*19aa95e4SMarcin Wojtas switch (cnt) { 1301*19aa95e4SMarcin Wojtas case IFCOUNTER_IERRORS: 1302*19aa95e4SMarcin Wojtas return (ENETC_PORT_RD8(sc, ENETC_PM0_RERR)); 1303*19aa95e4SMarcin Wojtas case IFCOUNTER_OERRORS: 1304*19aa95e4SMarcin Wojtas return (ENETC_PORT_RD8(sc, ENETC_PM0_TERR)); 1305*19aa95e4SMarcin Wojtas default: 1306*19aa95e4SMarcin Wojtas return (if_get_counter_default(ifp, cnt)); 1307*19aa95e4SMarcin Wojtas } 1308*19aa95e4SMarcin Wojtas } 1309*19aa95e4SMarcin Wojtas 1310*19aa95e4SMarcin Wojtas static int 1311*19aa95e4SMarcin Wojtas enetc_mtu_set(if_ctx_t ctx, uint32_t mtu) 1312*19aa95e4SMarcin Wojtas { 1313*19aa95e4SMarcin Wojtas struct enetc_softc *sc = iflib_get_softc(ctx); 1314*19aa95e4SMarcin Wojtas uint32_t max_frame_size; 1315*19aa95e4SMarcin Wojtas 1316*19aa95e4SMarcin Wojtas max_frame_size = mtu + 1317*19aa95e4SMarcin Wojtas ETHER_HDR_LEN + 1318*19aa95e4SMarcin Wojtas ETHER_CRC_LEN + 1319*19aa95e4SMarcin Wojtas sizeof(struct ether_vlan_header); 1320*19aa95e4SMarcin Wojtas 1321*19aa95e4SMarcin Wojtas if (max_frame_size > ENETC_MAX_FRAME_LEN) 1322*19aa95e4SMarcin Wojtas return (EINVAL); 1323*19aa95e4SMarcin Wojtas 1324*19aa95e4SMarcin Wojtas sc->shared->isc_max_frame_size = max_frame_size; 1325*19aa95e4SMarcin Wojtas 1326*19aa95e4SMarcin Wojtas return (0); 1327*19aa95e4SMarcin Wojtas } 1328*19aa95e4SMarcin Wojtas 1329*19aa95e4SMarcin Wojtas static int 1330*19aa95e4SMarcin Wojtas enetc_promisc_set(if_ctx_t ctx, int flags) 1331*19aa95e4SMarcin Wojtas { 1332*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1333*19aa95e4SMarcin Wojtas uint32_t reg = 0; 1334*19aa95e4SMarcin Wojtas 1335*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 1336*19aa95e4SMarcin Wojtas 1337*19aa95e4SMarcin Wojtas if (flags & IFF_PROMISC) 1338*19aa95e4SMarcin Wojtas reg = ENETC_PSIPMR_SET_UP(0) | ENETC_PSIPMR_SET_MP(0); 1339*19aa95e4SMarcin Wojtas else if (flags & IFF_ALLMULTI) 1340*19aa95e4SMarcin Wojtas reg = ENETC_PSIPMR_SET_MP(0); 1341*19aa95e4SMarcin Wojtas 1342*19aa95e4SMarcin Wojtas ENETC_PORT_WR4(sc, ENETC_PSIPMR, reg); 1343*19aa95e4SMarcin Wojtas 1344*19aa95e4SMarcin Wojtas return (0); 1345*19aa95e4SMarcin Wojtas } 1346*19aa95e4SMarcin Wojtas 1347*19aa95e4SMarcin Wojtas static void 1348*19aa95e4SMarcin Wojtas enetc_timer(if_ctx_t ctx, uint16_t qid) 1349*19aa95e4SMarcin Wojtas { 1350*19aa95e4SMarcin Wojtas /* 1351*19aa95e4SMarcin Wojtas * Poll PHY status. Do this only for qid 0 to save 1352*19aa95e4SMarcin Wojtas * some cycles. 1353*19aa95e4SMarcin Wojtas */ 1354*19aa95e4SMarcin Wojtas if (qid == 0) 1355*19aa95e4SMarcin Wojtas iflib_admin_intr_deferred(ctx); 1356*19aa95e4SMarcin Wojtas } 1357*19aa95e4SMarcin Wojtas 1358*19aa95e4SMarcin Wojtas static void 1359*19aa95e4SMarcin Wojtas enetc_update_admin_status(if_ctx_t ctx) 1360*19aa95e4SMarcin Wojtas { 1361*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1362*19aa95e4SMarcin Wojtas struct mii_data *miid; 1363*19aa95e4SMarcin Wojtas 1364*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ctx); 1365*19aa95e4SMarcin Wojtas 1366*19aa95e4SMarcin Wojtas if (!sc->fixed_link) { 1367*19aa95e4SMarcin Wojtas miid = device_get_softc(sc->miibus); 1368*19aa95e4SMarcin Wojtas mii_tick(miid); 1369*19aa95e4SMarcin Wojtas } 1370*19aa95e4SMarcin Wojtas } 1371*19aa95e4SMarcin Wojtas 1372*19aa95e4SMarcin Wojtas static int 1373*19aa95e4SMarcin Wojtas enetc_miibus_readreg(device_t dev, int phy, int reg) 1374*19aa95e4SMarcin Wojtas { 1375*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1376*19aa95e4SMarcin Wojtas 1377*19aa95e4SMarcin Wojtas sc = iflib_get_softc(device_get_softc(dev)); 1378*19aa95e4SMarcin Wojtas return (enetc_mdio_read(sc->regs, ENETC_PORT_BASE + ENETC_EMDIO_BASE, 1379*19aa95e4SMarcin Wojtas phy, reg)); 1380*19aa95e4SMarcin Wojtas } 1381*19aa95e4SMarcin Wojtas 1382*19aa95e4SMarcin Wojtas static int 1383*19aa95e4SMarcin Wojtas enetc_miibus_writereg(device_t dev, int phy, int reg, int data) 1384*19aa95e4SMarcin Wojtas { 1385*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1386*19aa95e4SMarcin Wojtas 1387*19aa95e4SMarcin Wojtas sc = iflib_get_softc(device_get_softc(dev)); 1388*19aa95e4SMarcin Wojtas return (enetc_mdio_write(sc->regs, ENETC_PORT_BASE + ENETC_EMDIO_BASE, 1389*19aa95e4SMarcin Wojtas phy, reg, data)); 1390*19aa95e4SMarcin Wojtas } 1391*19aa95e4SMarcin Wojtas 1392*19aa95e4SMarcin Wojtas static void 1393*19aa95e4SMarcin Wojtas enetc_miibus_linkchg(device_t dev) 1394*19aa95e4SMarcin Wojtas { 1395*19aa95e4SMarcin Wojtas 1396*19aa95e4SMarcin Wojtas enetc_miibus_statchg(dev); 1397*19aa95e4SMarcin Wojtas } 1398*19aa95e4SMarcin Wojtas 1399*19aa95e4SMarcin Wojtas static void 1400*19aa95e4SMarcin Wojtas enetc_miibus_statchg(device_t dev) 1401*19aa95e4SMarcin Wojtas { 1402*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1403*19aa95e4SMarcin Wojtas struct mii_data *miid; 1404*19aa95e4SMarcin Wojtas int link_state, baudrate; 1405*19aa95e4SMarcin Wojtas 1406*19aa95e4SMarcin Wojtas sc = iflib_get_softc(device_get_softc(dev)); 1407*19aa95e4SMarcin Wojtas miid = device_get_softc(sc->miibus); 1408*19aa95e4SMarcin Wojtas 1409*19aa95e4SMarcin Wojtas baudrate = ifmedia_baudrate(miid->mii_media_active); 1410*19aa95e4SMarcin Wojtas if (miid->mii_media_status & IFM_AVALID) { 1411*19aa95e4SMarcin Wojtas if (miid->mii_media_status & IFM_ACTIVE) 1412*19aa95e4SMarcin Wojtas link_state = LINK_STATE_UP; 1413*19aa95e4SMarcin Wojtas else 1414*19aa95e4SMarcin Wojtas link_state = LINK_STATE_DOWN; 1415*19aa95e4SMarcin Wojtas } else { 1416*19aa95e4SMarcin Wojtas link_state = LINK_STATE_UNKNOWN; 1417*19aa95e4SMarcin Wojtas } 1418*19aa95e4SMarcin Wojtas 1419*19aa95e4SMarcin Wojtas iflib_link_state_change(sc->ctx, link_state, baudrate); 1420*19aa95e4SMarcin Wojtas 1421*19aa95e4SMarcin Wojtas } 1422*19aa95e4SMarcin Wojtas 1423*19aa95e4SMarcin Wojtas static int 1424*19aa95e4SMarcin Wojtas enetc_media_change(if_t ifp) 1425*19aa95e4SMarcin Wojtas { 1426*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1427*19aa95e4SMarcin Wojtas struct mii_data *miid; 1428*19aa95e4SMarcin Wojtas 1429*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ifp->if_softc); 1430*19aa95e4SMarcin Wojtas miid = device_get_softc(sc->miibus); 1431*19aa95e4SMarcin Wojtas 1432*19aa95e4SMarcin Wojtas mii_mediachg(miid); 1433*19aa95e4SMarcin Wojtas return (0); 1434*19aa95e4SMarcin Wojtas } 1435*19aa95e4SMarcin Wojtas 1436*19aa95e4SMarcin Wojtas static void 1437*19aa95e4SMarcin Wojtas enetc_media_status(if_t ifp, struct ifmediareq* ifmr) 1438*19aa95e4SMarcin Wojtas { 1439*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1440*19aa95e4SMarcin Wojtas struct mii_data *miid; 1441*19aa95e4SMarcin Wojtas 1442*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ifp->if_softc); 1443*19aa95e4SMarcin Wojtas miid = device_get_softc(sc->miibus); 1444*19aa95e4SMarcin Wojtas 1445*19aa95e4SMarcin Wojtas mii_pollstat(miid); 1446*19aa95e4SMarcin Wojtas 1447*19aa95e4SMarcin Wojtas ifmr->ifm_active = miid->mii_media_active; 1448*19aa95e4SMarcin Wojtas ifmr->ifm_status = miid->mii_media_status; 1449*19aa95e4SMarcin Wojtas } 1450*19aa95e4SMarcin Wojtas 1451*19aa95e4SMarcin Wojtas static int 1452*19aa95e4SMarcin Wojtas enetc_fixed_media_change(if_t ifp) 1453*19aa95e4SMarcin Wojtas { 1454*19aa95e4SMarcin Wojtas 1455*19aa95e4SMarcin Wojtas if_printf(ifp, "Can't change media in fixed-link mode.\n"); 1456*19aa95e4SMarcin Wojtas return (0); 1457*19aa95e4SMarcin Wojtas } 1458*19aa95e4SMarcin Wojtas static void 1459*19aa95e4SMarcin Wojtas enetc_fixed_media_status(if_t ifp, struct ifmediareq* ifmr) 1460*19aa95e4SMarcin Wojtas { 1461*19aa95e4SMarcin Wojtas struct enetc_softc *sc; 1462*19aa95e4SMarcin Wojtas 1463*19aa95e4SMarcin Wojtas sc = iflib_get_softc(ifp->if_softc); 1464*19aa95e4SMarcin Wojtas 1465*19aa95e4SMarcin Wojtas ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; 1466*19aa95e4SMarcin Wojtas ifmr->ifm_active = sc->fixed_ifmedia.ifm_cur->ifm_media; 1467*19aa95e4SMarcin Wojtas return; 1468*19aa95e4SMarcin Wojtas } 1469