1*493d26c5SEd Maste /* 2*493d26c5SEd Maste * aQuantia Corporation Network Driver 3*493d26c5SEd Maste * Copyright (C) 2019 aQuantia Corporation. All rights reserved 4*493d26c5SEd Maste * 5*493d26c5SEd Maste * Redistribution and use in source and binary forms, with or without 6*493d26c5SEd Maste * modification, are permitted provided that the following conditions 7*493d26c5SEd Maste * are met: 8*493d26c5SEd Maste * 9*493d26c5SEd Maste * (1) Redistributions of source code must retain the above 10*493d26c5SEd Maste * copyright notice, this list of conditions and the following 11*493d26c5SEd Maste * disclaimer. 12*493d26c5SEd Maste * 13*493d26c5SEd Maste * (2) Redistributions in binary form must reproduce the above 14*493d26c5SEd Maste * copyright notice, this list of conditions and the following 15*493d26c5SEd Maste * disclaimer in the documentation and/or other materials provided 16*493d26c5SEd Maste * with the distribution. 17*493d26c5SEd Maste * 18*493d26c5SEd Maste * (3)The name of the author may not be used to endorse or promote 19*493d26c5SEd Maste * products derived from this software without specific prior 20*493d26c5SEd Maste * written permission. 21*493d26c5SEd Maste * 22*493d26c5SEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 23*493d26c5SEd Maste * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24*493d26c5SEd Maste * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*493d26c5SEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 26*493d26c5SEd Maste * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*493d26c5SEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 28*493d26c5SEd Maste * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29*493d26c5SEd Maste * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30*493d26c5SEd Maste * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31*493d26c5SEd Maste * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32*493d26c5SEd Maste * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33*493d26c5SEd Maste */ 34*493d26c5SEd Maste 35*493d26c5SEd Maste 36*493d26c5SEd Maste #include <sys/cdefs.h> 37*493d26c5SEd Maste __FBSDID("$FreeBSD$"); 38*493d26c5SEd Maste 39*493d26c5SEd Maste #include <sys/param.h> 40*493d26c5SEd Maste #include <sys/malloc.h> 41*493d26c5SEd Maste #include <sys/socket.h> 42*493d26c5SEd Maste #include <sys/kernel.h> 43*493d26c5SEd Maste #include <sys/bus.h> 44*493d26c5SEd Maste #include <sys/module.h> 45*493d26c5SEd Maste #include <sys/rman.h> 46*493d26c5SEd Maste #include <sys/endian.h> 47*493d26c5SEd Maste #include <sys/sockio.h> 48*493d26c5SEd Maste #include <sys/priv.h> 49*493d26c5SEd Maste #include <sys/sysctl.h> 50*493d26c5SEd Maste #include <sys/sbuf.h> 51*493d26c5SEd Maste #include <sys/bitstring.h> 52*493d26c5SEd Maste 53*493d26c5SEd Maste #include <machine/bus.h> 54*493d26c5SEd Maste #include <machine/resource.h> 55*493d26c5SEd Maste 56*493d26c5SEd Maste #include <dev/pci/pcireg.h> 57*493d26c5SEd Maste #include <dev/pci/pcivar.h> 58*493d26c5SEd Maste 59*493d26c5SEd Maste #include <net/if.h> 60*493d26c5SEd Maste #include <net/if_media.h> 61*493d26c5SEd Maste #include <net/if_var.h> 62*493d26c5SEd Maste #include <net/if_dl.h> 63*493d26c5SEd Maste #include <net/ethernet.h> 64*493d26c5SEd Maste #include <net/iflib.h> 65*493d26c5SEd Maste #include <net/rss_config.h> 66*493d26c5SEd Maste 67*493d26c5SEd Maste #include "opt_inet.h" 68*493d26c5SEd Maste #include "opt_inet6.h" 69*493d26c5SEd Maste #include "opt_rss.h" 70*493d26c5SEd Maste 71*493d26c5SEd Maste #include "ifdi_if.h" 72*493d26c5SEd Maste 73*493d26c5SEd Maste #include "aq_device.h" 74*493d26c5SEd Maste #include "aq_fw.h" 75*493d26c5SEd Maste #include "aq_hw.h" 76*493d26c5SEd Maste #include "aq_hw_llh.h" 77*493d26c5SEd Maste #include "aq_ring.h" 78*493d26c5SEd Maste #include "aq_dbg.h" 79*493d26c5SEd Maste 80*493d26c5SEd Maste 81*493d26c5SEd Maste #define AQ_XXX_UNIMPLEMENTED_FUNCTION do { \ 82*493d26c5SEd Maste printf("atlantic: unimplemented function: %s@%s:%d\n", __func__, \ 83*493d26c5SEd Maste __FILE__, __LINE__); \ 84*493d26c5SEd Maste } while (0) 85*493d26c5SEd Maste 86*493d26c5SEd Maste MALLOC_DEFINE(M_AQ, "aq", "Aquantia"); 87*493d26c5SEd Maste 88*493d26c5SEd Maste char aq_driver_version[] = AQ_VER; 89*493d26c5SEd Maste 90*493d26c5SEd Maste #define AQUANTIA_VENDOR_ID 0x1D6A 91*493d26c5SEd Maste 92*493d26c5SEd Maste #define AQ_DEVICE_ID_0001 0x0001 93*493d26c5SEd Maste #define AQ_DEVICE_ID_D100 0xD100 94*493d26c5SEd Maste #define AQ_DEVICE_ID_D107 0xD107 95*493d26c5SEd Maste #define AQ_DEVICE_ID_D108 0xD108 96*493d26c5SEd Maste #define AQ_DEVICE_ID_D109 0xD109 97*493d26c5SEd Maste 98*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC100 0x00B1 99*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC107 0x07B1 100*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC108 0x08B1 101*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC109 0x09B1 102*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC111 0x11B1 103*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC112 0x12B1 104*493d26c5SEd Maste 105*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC100S 0x80B1 106*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC107S 0x87B1 107*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC108S 0x88B1 108*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC109S 0x89B1 109*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC111S 0x91B1 110*493d26c5SEd Maste #define AQ_DEVICE_ID_AQC112S 0x92B1 111*493d26c5SEd Maste 112*493d26c5SEd Maste static pci_vendor_info_t aq_vendor_info_array[] = { 113*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_0001, "Aquantia AQtion 10Gbit Network Adapter"), 114*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_D107, "Aquantia AQtion 10Gbit Network Adapter"), 115*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_D108, "Aquantia AQtion 5Gbit Network Adapter"), 116*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_D109, "Aquantia AQtion 2.5Gbit Network Adapter"), 117*493d26c5SEd Maste 118*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC107, "Aquantia AQtion 10Gbit Network Adapter"), 119*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC108, "Aquantia AQtion 5Gbit Network Adapter"), 120*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC109, "Aquantia AQtion 2.5Gbit Network Adapter"), 121*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC100, "Aquantia AQtion 10Gbit Network Adapter"), 122*493d26c5SEd Maste 123*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC107S, "Aquantia AQtion 10Gbit Network Adapter"), 124*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC108S, "Aquantia AQtion 5Gbit Network Adapter"), 125*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC109S, "Aquantia AQtion 2.5Gbit Network Adapter"), 126*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC100S, "Aquantia AQtion 10Gbit Network Adapter"), 127*493d26c5SEd Maste 128*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC111, "Aquantia AQtion 5Gbit Network Adapter"), 129*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC112, "Aquantia AQtion 2.5Gbit Network Adapter"), 130*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC111S, "Aquantia AQtion 5Gbit Network Adapter"), 131*493d26c5SEd Maste PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC112S, "Aquantia AQtion 2.5Gbit Network Adapter"), 132*493d26c5SEd Maste 133*493d26c5SEd Maste PVID_END 134*493d26c5SEd Maste }; 135*493d26c5SEd Maste 136*493d26c5SEd Maste 137*493d26c5SEd Maste /* Device setup, teardown, etc */ 138*493d26c5SEd Maste static void *aq_register(device_t dev); 139*493d26c5SEd Maste static int aq_if_attach_pre(if_ctx_t ctx); 140*493d26c5SEd Maste static int aq_if_attach_post(if_ctx_t ctx); 141*493d26c5SEd Maste static int aq_if_detach(if_ctx_t ctx); 142*493d26c5SEd Maste static int aq_if_shutdown(if_ctx_t ctx); 143*493d26c5SEd Maste static int aq_if_suspend(if_ctx_t ctx); 144*493d26c5SEd Maste static int aq_if_resume(if_ctx_t ctx); 145*493d26c5SEd Maste 146*493d26c5SEd Maste /* Soft queue setup and teardown */ 147*493d26c5SEd Maste static int aq_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 148*493d26c5SEd Maste uint64_t *paddrs, int ntxqs, int ntxqsets); 149*493d26c5SEd Maste static int aq_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 150*493d26c5SEd Maste uint64_t *paddrs, int nrxqs, int nrxqsets); 151*493d26c5SEd Maste static void aq_if_queues_free(if_ctx_t ctx); 152*493d26c5SEd Maste 153*493d26c5SEd Maste /* Device configuration */ 154*493d26c5SEd Maste static void aq_if_init(if_ctx_t ctx); 155*493d26c5SEd Maste static void aq_if_stop(if_ctx_t ctx); 156*493d26c5SEd Maste static void aq_if_multi_set(if_ctx_t ctx); 157*493d26c5SEd Maste static int aq_if_mtu_set(if_ctx_t ctx, uint32_t mtu); 158*493d26c5SEd Maste static void aq_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr); 159*493d26c5SEd Maste static int aq_if_media_change(if_ctx_t ctx); 160*493d26c5SEd Maste static int aq_if_promisc_set(if_ctx_t ctx, int flags); 161*493d26c5SEd Maste static uint64_t aq_if_get_counter(if_ctx_t ctx, ift_counter cnt); 162*493d26c5SEd Maste static void aq_if_timer(if_ctx_t ctx, uint16_t qid); 163*493d26c5SEd Maste static int aq_if_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); 164*493d26c5SEd Maste static int aq_hw_capabilities(struct aq_dev *softc); 165*493d26c5SEd Maste static void aq_add_stats_sysctls(struct aq_dev *softc); 166*493d26c5SEd Maste 167*493d26c5SEd Maste /* Interrupt enable / disable */ 168*493d26c5SEd Maste static void aq_if_enable_intr(if_ctx_t ctx); 169*493d26c5SEd Maste static void aq_if_disable_intr(if_ctx_t ctx); 170*493d26c5SEd Maste static int aq_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid); 171*493d26c5SEd Maste static int aq_if_msix_intr_assign(if_ctx_t ctx, int msix); 172*493d26c5SEd Maste 173*493d26c5SEd Maste /* VLAN support */ 174*493d26c5SEd Maste static bool aq_is_vlan_promisc_required(struct aq_dev *softc); 175*493d26c5SEd Maste static void aq_update_vlan_filters(struct aq_dev *softc); 176*493d26c5SEd Maste static void aq_if_vlan_register(if_ctx_t ctx, uint16_t vtag); 177*493d26c5SEd Maste static void aq_if_vlan_unregister(if_ctx_t ctx, uint16_t vtag); 178*493d26c5SEd Maste 179*493d26c5SEd Maste /* Informational/diagnostic */ 180*493d26c5SEd Maste static void aq_if_debug(if_ctx_t ctx); 181*493d26c5SEd Maste static void aq_if_led_func(if_ctx_t ctx, int onoff); 182*493d26c5SEd Maste 183*493d26c5SEd Maste static device_method_t aq_methods[] = { 184*493d26c5SEd Maste DEVMETHOD(device_register, aq_register), 185*493d26c5SEd Maste DEVMETHOD(device_probe, iflib_device_probe), 186*493d26c5SEd Maste DEVMETHOD(device_attach, iflib_device_attach), 187*493d26c5SEd Maste DEVMETHOD(device_detach, iflib_device_detach), 188*493d26c5SEd Maste DEVMETHOD(device_shutdown, iflib_device_shutdown), 189*493d26c5SEd Maste DEVMETHOD(device_suspend, iflib_device_suspend), 190*493d26c5SEd Maste DEVMETHOD(device_resume, iflib_device_resume), 191*493d26c5SEd Maste 192*493d26c5SEd Maste DEVMETHOD_END 193*493d26c5SEd Maste }; 194*493d26c5SEd Maste 195*493d26c5SEd Maste static driver_t aq_driver = { 196*493d26c5SEd Maste "aq", aq_methods, sizeof(struct aq_dev), 197*493d26c5SEd Maste }; 198*493d26c5SEd Maste 199*493d26c5SEd Maste static devclass_t aq_devclass; 200*493d26c5SEd Maste DRIVER_MODULE(atlantic, pci, aq_driver, aq_devclass, 0, 0); 201*493d26c5SEd Maste 202*493d26c5SEd Maste MODULE_DEPEND(atlantic, pci, 1, 1, 1); 203*493d26c5SEd Maste MODULE_DEPEND(atlantic, ether, 1, 1, 1); 204*493d26c5SEd Maste MODULE_DEPEND(atlantic, iflib, 1, 1, 1); 205*493d26c5SEd Maste 206*493d26c5SEd Maste IFLIB_PNP_INFO(pci, atlantic, aq_vendor_info_array); 207*493d26c5SEd Maste 208*493d26c5SEd Maste static device_method_t aq_if_methods[] = { 209*493d26c5SEd Maste /* Device setup, teardown, etc */ 210*493d26c5SEd Maste DEVMETHOD(ifdi_attach_pre, aq_if_attach_pre), 211*493d26c5SEd Maste DEVMETHOD(ifdi_attach_post, aq_if_attach_post), 212*493d26c5SEd Maste DEVMETHOD(ifdi_detach, aq_if_detach), 213*493d26c5SEd Maste 214*493d26c5SEd Maste DEVMETHOD(ifdi_shutdown, aq_if_shutdown), 215*493d26c5SEd Maste DEVMETHOD(ifdi_suspend, aq_if_suspend), 216*493d26c5SEd Maste DEVMETHOD(ifdi_resume, aq_if_resume), 217*493d26c5SEd Maste 218*493d26c5SEd Maste /* Soft queue setup and teardown */ 219*493d26c5SEd Maste DEVMETHOD(ifdi_tx_queues_alloc, aq_if_tx_queues_alloc), 220*493d26c5SEd Maste DEVMETHOD(ifdi_rx_queues_alloc, aq_if_rx_queues_alloc), 221*493d26c5SEd Maste DEVMETHOD(ifdi_queues_free, aq_if_queues_free), 222*493d26c5SEd Maste 223*493d26c5SEd Maste /* Device configuration */ 224*493d26c5SEd Maste DEVMETHOD(ifdi_init, aq_if_init), 225*493d26c5SEd Maste DEVMETHOD(ifdi_stop, aq_if_stop), 226*493d26c5SEd Maste DEVMETHOD(ifdi_multi_set, aq_if_multi_set), 227*493d26c5SEd Maste DEVMETHOD(ifdi_mtu_set, aq_if_mtu_set), 228*493d26c5SEd Maste DEVMETHOD(ifdi_media_status, aq_if_media_status), 229*493d26c5SEd Maste DEVMETHOD(ifdi_media_change, aq_if_media_change), 230*493d26c5SEd Maste DEVMETHOD(ifdi_promisc_set, aq_if_promisc_set), 231*493d26c5SEd Maste DEVMETHOD(ifdi_get_counter, aq_if_get_counter), 232*493d26c5SEd Maste DEVMETHOD(ifdi_update_admin_status, aq_if_update_admin_status), 233*493d26c5SEd Maste DEVMETHOD(ifdi_timer, aq_if_timer), 234*493d26c5SEd Maste // DEVMETHOD(ifdi_priv_ioctl, aq_if_priv_ioctl), 235*493d26c5SEd Maste 236*493d26c5SEd Maste /* Interrupt enable / disable */ 237*493d26c5SEd Maste DEVMETHOD(ifdi_intr_enable, aq_if_enable_intr), 238*493d26c5SEd Maste DEVMETHOD(ifdi_intr_disable, aq_if_disable_intr), 239*493d26c5SEd Maste DEVMETHOD(ifdi_rx_queue_intr_enable, aq_if_rx_queue_intr_enable), 240*493d26c5SEd Maste DEVMETHOD(ifdi_tx_queue_intr_enable, aq_if_rx_queue_intr_enable), 241*493d26c5SEd Maste DEVMETHOD(ifdi_msix_intr_assign, aq_if_msix_intr_assign), 242*493d26c5SEd Maste 243*493d26c5SEd Maste /* VLAN support */ 244*493d26c5SEd Maste DEVMETHOD(ifdi_vlan_register, aq_if_vlan_register), 245*493d26c5SEd Maste DEVMETHOD(ifdi_vlan_unregister, aq_if_vlan_unregister), 246*493d26c5SEd Maste 247*493d26c5SEd Maste /* Informational/diagnostic */ 248*493d26c5SEd Maste DEVMETHOD(ifdi_led_func, aq_if_led_func), 249*493d26c5SEd Maste // DEVMETHOD(ifdi_debug, aq_if_debug), 250*493d26c5SEd Maste 251*493d26c5SEd Maste DEVMETHOD_END 252*493d26c5SEd Maste }; 253*493d26c5SEd Maste 254*493d26c5SEd Maste static driver_t aq_if_driver = { 255*493d26c5SEd Maste "aq_if", aq_if_methods, sizeof(struct aq_dev) 256*493d26c5SEd Maste }; 257*493d26c5SEd Maste 258*493d26c5SEd Maste static struct if_shared_ctx aq_sctx_init = { 259*493d26c5SEd Maste .isc_magic = IFLIB_MAGIC, 260*493d26c5SEd Maste .isc_q_align = PAGE_SIZE, 261*493d26c5SEd Maste .isc_tx_maxsize = HW_ATL_B0_TSO_SIZE, 262*493d26c5SEd Maste .isc_tx_maxsegsize = HW_ATL_B0_MTU_JUMBO, 263*493d26c5SEd Maste #if __FreeBSD__ >= 12 264*493d26c5SEd Maste .isc_tso_maxsize = HW_ATL_B0_TSO_SIZE, 265*493d26c5SEd Maste .isc_tso_maxsegsize = HW_ATL_B0_MTU_JUMBO, 266*493d26c5SEd Maste #endif 267*493d26c5SEd Maste .isc_rx_maxsize = HW_ATL_B0_MTU_JUMBO, 268*493d26c5SEd Maste .isc_rx_nsegments = 16, 269*493d26c5SEd Maste .isc_rx_maxsegsize = PAGE_SIZE, 270*493d26c5SEd Maste .isc_nfl = 1, 271*493d26c5SEd Maste .isc_nrxqs = 1, 272*493d26c5SEd Maste .isc_ntxqs = 1, 273*493d26c5SEd Maste .isc_admin_intrcnt = 1, 274*493d26c5SEd Maste .isc_vendor_info = aq_vendor_info_array, 275*493d26c5SEd Maste .isc_driver_version = aq_driver_version, 276*493d26c5SEd Maste .isc_driver = &aq_if_driver, 277*493d26c5SEd Maste .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | 278*493d26c5SEd Maste IFLIB_NEED_ZERO_CSUM, 279*493d26c5SEd Maste 280*493d26c5SEd Maste .isc_nrxd_min = {HW_ATL_B0_MIN_RXD}, 281*493d26c5SEd Maste .isc_ntxd_min = {HW_ATL_B0_MIN_TXD}, 282*493d26c5SEd Maste .isc_nrxd_max = {HW_ATL_B0_MAX_RXD}, 283*493d26c5SEd Maste .isc_ntxd_max = {HW_ATL_B0_MAX_TXD}, 284*493d26c5SEd Maste .isc_nrxd_default = {PAGE_SIZE / sizeof(aq_txc_desc_t) * 4}, 285*493d26c5SEd Maste .isc_ntxd_default = {PAGE_SIZE / sizeof(aq_txc_desc_t) * 4}, 286*493d26c5SEd Maste }; 287*493d26c5SEd Maste 288*493d26c5SEd Maste /* 289*493d26c5SEd Maste * TUNEABLE PARAMETERS: 290*493d26c5SEd Maste */ 291*493d26c5SEd Maste 292*493d26c5SEd Maste static SYSCTL_NODE(_hw, OID_AUTO, aq, CTLFLAG_RD, 0, "Atlantic driver parameters"); 293*493d26c5SEd Maste /* UDP Receive-Side Scaling */ 294*493d26c5SEd Maste static int aq_enable_rss_udp = 1; 295*493d26c5SEd Maste SYSCTL_INT(_hw_aq, OID_AUTO, enable_rss_udp, CTLFLAG_RDTUN, &aq_enable_rss_udp, 0, 296*493d26c5SEd Maste "Enable Receive-Side Scaling (RSS) for UDP"); 297*493d26c5SEd Maste 298*493d26c5SEd Maste 299*493d26c5SEd Maste /* 300*493d26c5SEd Maste * Device Methods 301*493d26c5SEd Maste */ 302*493d26c5SEd Maste static void *aq_register(device_t dev) 303*493d26c5SEd Maste { 304*493d26c5SEd Maste return (&aq_sctx_init); 305*493d26c5SEd Maste } 306*493d26c5SEd Maste 307*493d26c5SEd Maste static int aq_if_attach_pre(if_ctx_t ctx) 308*493d26c5SEd Maste { 309*493d26c5SEd Maste struct aq_dev *softc; 310*493d26c5SEd Maste struct aq_hw *hw; 311*493d26c5SEd Maste if_softc_ctx_t scctx; 312*493d26c5SEd Maste int rc; 313*493d26c5SEd Maste 314*493d26c5SEd Maste AQ_DBG_ENTER(); 315*493d26c5SEd Maste softc = iflib_get_softc(ctx); 316*493d26c5SEd Maste rc = 0; 317*493d26c5SEd Maste 318*493d26c5SEd Maste softc->ctx = ctx; 319*493d26c5SEd Maste softc->dev = iflib_get_dev(ctx); 320*493d26c5SEd Maste softc->media = iflib_get_media(ctx); 321*493d26c5SEd Maste softc->scctx = iflib_get_softc_ctx(ctx); 322*493d26c5SEd Maste softc->sctx = iflib_get_sctx(ctx); 323*493d26c5SEd Maste scctx = softc->scctx; 324*493d26c5SEd Maste 325*493d26c5SEd Maste softc->mmio_rid = PCIR_BAR(0); 326*493d26c5SEd Maste softc->mmio_res = bus_alloc_resource_any(softc->dev, SYS_RES_MEMORY, 327*493d26c5SEd Maste &softc->mmio_rid, RF_ACTIVE|RF_SHAREABLE); 328*493d26c5SEd Maste if (softc->mmio_res == NULL) { 329*493d26c5SEd Maste device_printf(softc->dev, 330*493d26c5SEd Maste "failed to allocate MMIO resources\n"); 331*493d26c5SEd Maste rc = ENXIO; 332*493d26c5SEd Maste goto fail; 333*493d26c5SEd Maste } 334*493d26c5SEd Maste 335*493d26c5SEd Maste softc->mmio_tag = rman_get_bustag(softc->mmio_res); 336*493d26c5SEd Maste softc->mmio_handle = rman_get_bushandle(softc->mmio_res); 337*493d26c5SEd Maste softc->mmio_size = rman_get_size(softc->mmio_res); 338*493d26c5SEd Maste softc->hw.hw_addr = (u8*) softc->mmio_handle; 339*493d26c5SEd Maste hw = &softc->hw; 340*493d26c5SEd Maste hw->link_rate = aq_fw_speed_auto; 341*493d26c5SEd Maste hw->itr = -1; 342*493d26c5SEd Maste hw->fc.fc_rx = 1; 343*493d26c5SEd Maste hw->fc.fc_tx = 1; 344*493d26c5SEd Maste softc->linkup = 0U; 345*493d26c5SEd Maste 346*493d26c5SEd Maste /* Look up ops and caps. */ 347*493d26c5SEd Maste rc = aq_hw_mpi_create(hw); 348*493d26c5SEd Maste if (rc < 0) { 349*493d26c5SEd Maste AQ_DBG_ERROR(" %s: aq_hw_mpi_create fail err=%d", __func__, rc); 350*493d26c5SEd Maste goto fail; 351*493d26c5SEd Maste } 352*493d26c5SEd Maste 353*493d26c5SEd Maste if (hw->fast_start_enabled) { 354*493d26c5SEd Maste if (hw->fw_ops && hw->fw_ops->reset) 355*493d26c5SEd Maste hw->fw_ops->reset(hw); 356*493d26c5SEd Maste } else 357*493d26c5SEd Maste aq_hw_reset(&softc->hw); 358*493d26c5SEd Maste aq_hw_capabilities(softc); 359*493d26c5SEd Maste 360*493d26c5SEd Maste if (aq_hw_get_mac_permanent(hw, hw->mac_addr) < 0) { 361*493d26c5SEd Maste AQ_DBG_ERROR("Unable to get mac addr from hw"); 362*493d26c5SEd Maste goto fail; 363*493d26c5SEd Maste }; 364*493d26c5SEd Maste 365*493d26c5SEd Maste softc->admin_ticks = 0; 366*493d26c5SEd Maste 367*493d26c5SEd Maste iflib_set_mac(ctx, hw->mac_addr); 368*493d26c5SEd Maste #if __FreeBSD__ < 13 369*493d26c5SEd Maste /* since FreeBSD13 deadlock due to calling iflib_led_func() under CTX_LOCK() */ 370*493d26c5SEd Maste iflib_led_create(ctx); 371*493d26c5SEd Maste #endif 372*493d26c5SEd Maste scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO; 373*493d26c5SEd Maste #if __FreeBSD__ >= 12 374*493d26c5SEd Maste scctx->isc_capabilities = IFCAP_RXCSUM | IFCAP_TXCSUM | IFCAP_HWCSUM | IFCAP_TSO | 375*493d26c5SEd Maste IFCAP_JUMBO_MTU | IFCAP_VLAN_HWFILTER | 376*493d26c5SEd Maste IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | 377*493d26c5SEd Maste IFCAP_VLAN_HWCSUM; 378*493d26c5SEd Maste scctx->isc_capenable = scctx->isc_capabilities; 379*493d26c5SEd Maste #else 380*493d26c5SEd Maste if_t ifp; 381*493d26c5SEd Maste ifp = iflib_get_ifp(ctx); 382*493d26c5SEd Maste ifp->if_capenable = IFCAP_RXCSUM | IFCAP_TXCSUM | IFCAP_HWCSUM | IFCAP_TSO | 383*493d26c5SEd Maste IFCAP_JUMBO_MTU | IFCAP_VLAN_HWFILTER | 384*493d26c5SEd Maste IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | 385*493d26c5SEd Maste IFCAP_VLAN_HWCSUM; 386*493d26c5SEd Maste #endif 387*493d26c5SEd Maste scctx->isc_tx_nsegments = 31, 388*493d26c5SEd Maste scctx->isc_tx_tso_segments_max = 31; 389*493d26c5SEd Maste scctx->isc_tx_tso_size_max = HW_ATL_B0_TSO_SIZE - sizeof(struct ether_vlan_header); 390*493d26c5SEd Maste scctx->isc_tx_tso_segsize_max = HW_ATL_B0_MTU_JUMBO; 391*493d26c5SEd Maste scctx->isc_min_frame_size = 52; 392*493d26c5SEd Maste scctx->isc_txrx = &aq_txrx; 393*493d26c5SEd Maste 394*493d26c5SEd Maste scctx->isc_txqsizes[0] = sizeof(aq_tx_desc_t) * scctx->isc_ntxd[0]; 395*493d26c5SEd Maste scctx->isc_rxqsizes[0] = sizeof(aq_rx_desc_t) * scctx->isc_nrxd[0]; 396*493d26c5SEd Maste 397*493d26c5SEd Maste scctx->isc_ntxqsets_max = HW_ATL_B0_RINGS_MAX; 398*493d26c5SEd Maste scctx->isc_nrxqsets_max = HW_ATL_B0_RINGS_MAX; 399*493d26c5SEd Maste 400*493d26c5SEd Maste /* iflib will map and release this bar */ 401*493d26c5SEd Maste scctx->isc_msix_bar = pci_msix_table_bar(softc->dev); 402*493d26c5SEd Maste 403*493d26c5SEd Maste softc->vlan_tags = bit_alloc(4096, M_AQ, M_NOWAIT); 404*493d26c5SEd Maste 405*493d26c5SEd Maste AQ_DBG_EXIT(rc); 406*493d26c5SEd Maste return (rc); 407*493d26c5SEd Maste 408*493d26c5SEd Maste fail: 409*493d26c5SEd Maste if (softc->mmio_res != NULL) 410*493d26c5SEd Maste bus_release_resource(softc->dev, SYS_RES_MEMORY, 411*493d26c5SEd Maste softc->mmio_rid, softc->mmio_res); 412*493d26c5SEd Maste 413*493d26c5SEd Maste AQ_DBG_EXIT(rc); 414*493d26c5SEd Maste return (ENXIO); 415*493d26c5SEd Maste } 416*493d26c5SEd Maste 417*493d26c5SEd Maste 418*493d26c5SEd Maste static int aq_if_attach_post(if_ctx_t ctx) 419*493d26c5SEd Maste { 420*493d26c5SEd Maste struct aq_dev *softc; 421*493d26c5SEd Maste int rc; 422*493d26c5SEd Maste 423*493d26c5SEd Maste AQ_DBG_ENTER(); 424*493d26c5SEd Maste 425*493d26c5SEd Maste softc = iflib_get_softc(ctx); 426*493d26c5SEd Maste rc = 0; 427*493d26c5SEd Maste 428*493d26c5SEd Maste aq_update_hw_stats(softc); 429*493d26c5SEd Maste 430*493d26c5SEd Maste aq_initmedia(softc); 431*493d26c5SEd Maste 432*493d26c5SEd Maste 433*493d26c5SEd Maste switch (softc->scctx->isc_intr) { 434*493d26c5SEd Maste case IFLIB_INTR_LEGACY: 435*493d26c5SEd Maste rc = EOPNOTSUPP; 436*493d26c5SEd Maste goto exit; 437*493d26c5SEd Maste goto exit; 438*493d26c5SEd Maste break; 439*493d26c5SEd Maste case IFLIB_INTR_MSI: 440*493d26c5SEd Maste break; 441*493d26c5SEd Maste case IFLIB_INTR_MSIX: 442*493d26c5SEd Maste break; 443*493d26c5SEd Maste default: 444*493d26c5SEd Maste device_printf(softc->dev, "unknown interrupt mode\n"); 445*493d26c5SEd Maste rc = EOPNOTSUPP; 446*493d26c5SEd Maste goto exit; 447*493d26c5SEd Maste } 448*493d26c5SEd Maste 449*493d26c5SEd Maste aq_add_stats_sysctls(softc); 450*493d26c5SEd Maste /* RSS */ 451*493d26c5SEd Maste arc4rand(softc->rss_key, HW_ATL_RSS_HASHKEY_SIZE, 0); 452*493d26c5SEd Maste for (int i = ARRAY_SIZE(softc->rss_table); i--;){ 453*493d26c5SEd Maste softc->rss_table[i] = i & (softc->rx_rings_count - 1); 454*493d26c5SEd Maste } 455*493d26c5SEd Maste exit: 456*493d26c5SEd Maste AQ_DBG_EXIT(rc); 457*493d26c5SEd Maste return (rc); 458*493d26c5SEd Maste } 459*493d26c5SEd Maste 460*493d26c5SEd Maste 461*493d26c5SEd Maste static int aq_if_detach(if_ctx_t ctx) 462*493d26c5SEd Maste { 463*493d26c5SEd Maste struct aq_dev *softc; 464*493d26c5SEd Maste int i; 465*493d26c5SEd Maste 466*493d26c5SEd Maste AQ_DBG_ENTER(); 467*493d26c5SEd Maste softc = iflib_get_softc(ctx); 468*493d26c5SEd Maste 469*493d26c5SEd Maste aq_hw_deinit(&softc->hw); 470*493d26c5SEd Maste 471*493d26c5SEd Maste for (i = 0; i < softc->scctx->isc_nrxqsets; i++) 472*493d26c5SEd Maste iflib_irq_free(ctx, &softc->rx_rings[i]->irq); 473*493d26c5SEd Maste iflib_irq_free(ctx, &softc->irq); 474*493d26c5SEd Maste 475*493d26c5SEd Maste 476*493d26c5SEd Maste if (softc->mmio_res != NULL) 477*493d26c5SEd Maste bus_release_resource(softc->dev, SYS_RES_MEMORY, 478*493d26c5SEd Maste softc->mmio_rid, softc->mmio_res); 479*493d26c5SEd Maste 480*493d26c5SEd Maste free(softc->vlan_tags, M_AQ); 481*493d26c5SEd Maste 482*493d26c5SEd Maste AQ_DBG_EXIT(0); 483*493d26c5SEd Maste return (0); 484*493d26c5SEd Maste } 485*493d26c5SEd Maste 486*493d26c5SEd Maste static int aq_if_shutdown(if_ctx_t ctx) 487*493d26c5SEd Maste { 488*493d26c5SEd Maste 489*493d26c5SEd Maste AQ_DBG_ENTER(); 490*493d26c5SEd Maste 491*493d26c5SEd Maste AQ_XXX_UNIMPLEMENTED_FUNCTION; 492*493d26c5SEd Maste 493*493d26c5SEd Maste AQ_DBG_EXIT(0); 494*493d26c5SEd Maste return (0); 495*493d26c5SEd Maste } 496*493d26c5SEd Maste 497*493d26c5SEd Maste static int aq_if_suspend(if_ctx_t ctx) 498*493d26c5SEd Maste { 499*493d26c5SEd Maste AQ_DBG_ENTER(); 500*493d26c5SEd Maste 501*493d26c5SEd Maste AQ_XXX_UNIMPLEMENTED_FUNCTION; 502*493d26c5SEd Maste 503*493d26c5SEd Maste AQ_DBG_EXIT(0); 504*493d26c5SEd Maste return (0); 505*493d26c5SEd Maste } 506*493d26c5SEd Maste 507*493d26c5SEd Maste static int aq_if_resume(if_ctx_t ctx) 508*493d26c5SEd Maste { 509*493d26c5SEd Maste AQ_DBG_ENTER(); 510*493d26c5SEd Maste 511*493d26c5SEd Maste AQ_XXX_UNIMPLEMENTED_FUNCTION; 512*493d26c5SEd Maste 513*493d26c5SEd Maste AQ_DBG_EXIT(0); 514*493d26c5SEd Maste return (0); 515*493d26c5SEd Maste } 516*493d26c5SEd Maste 517*493d26c5SEd Maste /* Soft queue setup and teardown */ 518*493d26c5SEd Maste static int aq_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 519*493d26c5SEd Maste uint64_t *paddrs, int ntxqs, int ntxqsets) 520*493d26c5SEd Maste { 521*493d26c5SEd Maste struct aq_dev *softc; 522*493d26c5SEd Maste struct aq_ring *ring; 523*493d26c5SEd Maste int rc = 0, i; 524*493d26c5SEd Maste 525*493d26c5SEd Maste AQ_DBG_ENTERA("ntxqs=%d, ntxqsets=%d", ntxqs, ntxqsets); 526*493d26c5SEd Maste softc = iflib_get_softc(ctx); 527*493d26c5SEd Maste AQ_DBG_PRINT("tx descriptors number %d", softc->scctx->isc_ntxd[0]); 528*493d26c5SEd Maste 529*493d26c5SEd Maste for (i = 0; i < ntxqsets; i++) { 530*493d26c5SEd Maste ring = softc->tx_rings[i] = malloc(sizeof(struct aq_ring), 531*493d26c5SEd Maste M_AQ, M_NOWAIT | M_ZERO); 532*493d26c5SEd Maste if (!ring){ 533*493d26c5SEd Maste rc = ENOMEM; 534*493d26c5SEd Maste device_printf(softc->dev, "atlantic: tx_ring malloc fail\n"); 535*493d26c5SEd Maste goto fail; 536*493d26c5SEd Maste } 537*493d26c5SEd Maste ring->tx_descs = (aq_tx_desc_t*)vaddrs[i]; 538*493d26c5SEd Maste ring->tx_size = softc->scctx->isc_ntxd[0]; 539*493d26c5SEd Maste ring->tx_descs_phys = paddrs[i]; 540*493d26c5SEd Maste ring->tx_head = ring->tx_tail = 0; 541*493d26c5SEd Maste ring->index = i; 542*493d26c5SEd Maste ring->dev = softc; 543*493d26c5SEd Maste 544*493d26c5SEd Maste softc->tx_rings_count++; 545*493d26c5SEd Maste } 546*493d26c5SEd Maste 547*493d26c5SEd Maste AQ_DBG_EXIT(rc); 548*493d26c5SEd Maste return (rc); 549*493d26c5SEd Maste 550*493d26c5SEd Maste fail: 551*493d26c5SEd Maste aq_if_queues_free(ctx); 552*493d26c5SEd Maste AQ_DBG_EXIT(rc); 553*493d26c5SEd Maste return (rc); 554*493d26c5SEd Maste } 555*493d26c5SEd Maste 556*493d26c5SEd Maste static int aq_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 557*493d26c5SEd Maste uint64_t *paddrs, int nrxqs, int nrxqsets) 558*493d26c5SEd Maste { 559*493d26c5SEd Maste struct aq_dev *softc; 560*493d26c5SEd Maste struct aq_ring *ring; 561*493d26c5SEd Maste int rc = 0, i; 562*493d26c5SEd Maste 563*493d26c5SEd Maste AQ_DBG_ENTERA("nrxqs=%d, nrxqsets=%d", nrxqs, nrxqsets); 564*493d26c5SEd Maste softc = iflib_get_softc(ctx); 565*493d26c5SEd Maste 566*493d26c5SEd Maste for (i = 0; i < nrxqsets; i++) { 567*493d26c5SEd Maste ring = softc->rx_rings[i] = malloc(sizeof(struct aq_ring), 568*493d26c5SEd Maste M_AQ, M_NOWAIT | M_ZERO); 569*493d26c5SEd Maste if (!ring){ 570*493d26c5SEd Maste rc = ENOMEM; 571*493d26c5SEd Maste device_printf(softc->dev, "atlantic: rx_ring malloc fail\n"); 572*493d26c5SEd Maste goto fail; 573*493d26c5SEd Maste } 574*493d26c5SEd Maste 575*493d26c5SEd Maste ring->rx_descs = (aq_rx_desc_t*)vaddrs[i]; 576*493d26c5SEd Maste ring->rx_descs_phys = paddrs[i]; 577*493d26c5SEd Maste ring->rx_size = softc->scctx->isc_nrxd[0]; 578*493d26c5SEd Maste ring->index = i; 579*493d26c5SEd Maste ring->dev = softc; 580*493d26c5SEd Maste 581*493d26c5SEd Maste switch (MCLBYTES) { 582*493d26c5SEd Maste case (4 * 1024): 583*493d26c5SEd Maste case (8 * 1024): 584*493d26c5SEd Maste case (16 * 1024): 585*493d26c5SEd Maste ring->rx_max_frame_size = MCLBYTES; 586*493d26c5SEd Maste break; 587*493d26c5SEd Maste default: 588*493d26c5SEd Maste ring->rx_max_frame_size = 2048; 589*493d26c5SEd Maste break; 590*493d26c5SEd Maste } 591*493d26c5SEd Maste 592*493d26c5SEd Maste softc->rx_rings_count++; 593*493d26c5SEd Maste } 594*493d26c5SEd Maste 595*493d26c5SEd Maste AQ_DBG_EXIT(rc); 596*493d26c5SEd Maste return (rc); 597*493d26c5SEd Maste 598*493d26c5SEd Maste fail: 599*493d26c5SEd Maste aq_if_queues_free(ctx); 600*493d26c5SEd Maste AQ_DBG_EXIT(rc); 601*493d26c5SEd Maste return (rc); 602*493d26c5SEd Maste } 603*493d26c5SEd Maste 604*493d26c5SEd Maste static void aq_if_queues_free(if_ctx_t ctx) 605*493d26c5SEd Maste { 606*493d26c5SEd Maste struct aq_dev *softc; 607*493d26c5SEd Maste int i; 608*493d26c5SEd Maste 609*493d26c5SEd Maste AQ_DBG_ENTER(); 610*493d26c5SEd Maste softc = iflib_get_softc(ctx); 611*493d26c5SEd Maste 612*493d26c5SEd Maste for (i = 0; i < softc->tx_rings_count; i++) { 613*493d26c5SEd Maste if (softc->tx_rings[i]) { 614*493d26c5SEd Maste free(softc->tx_rings[i], M_AQ); 615*493d26c5SEd Maste softc->tx_rings[i] = NULL; 616*493d26c5SEd Maste } 617*493d26c5SEd Maste } 618*493d26c5SEd Maste softc->tx_rings_count = 0; 619*493d26c5SEd Maste for (i = 0; i < softc->rx_rings_count; i++) { 620*493d26c5SEd Maste if (softc->rx_rings[i]){ 621*493d26c5SEd Maste free(softc->rx_rings[i], M_AQ); 622*493d26c5SEd Maste softc->rx_rings[i] = NULL; 623*493d26c5SEd Maste } 624*493d26c5SEd Maste } 625*493d26c5SEd Maste softc->rx_rings_count = 0; 626*493d26c5SEd Maste 627*493d26c5SEd Maste AQ_DBG_EXIT(0); 628*493d26c5SEd Maste return; 629*493d26c5SEd Maste } 630*493d26c5SEd Maste 631*493d26c5SEd Maste /* Device configuration */ 632*493d26c5SEd Maste static void aq_if_init(if_ctx_t ctx) 633*493d26c5SEd Maste { 634*493d26c5SEd Maste struct aq_dev *softc; 635*493d26c5SEd Maste struct aq_hw *hw; 636*493d26c5SEd Maste struct ifmediareq ifmr; 637*493d26c5SEd Maste int i, err; 638*493d26c5SEd Maste 639*493d26c5SEd Maste AQ_DBG_ENTER(); 640*493d26c5SEd Maste softc = iflib_get_softc(ctx); 641*493d26c5SEd Maste hw = &softc->hw; 642*493d26c5SEd Maste 643*493d26c5SEd Maste err = aq_hw_init(&softc->hw, softc->hw.mac_addr, softc->msix, 644*493d26c5SEd Maste softc->scctx->isc_intr == IFLIB_INTR_MSIX); 645*493d26c5SEd Maste if (err != EOK) { 646*493d26c5SEd Maste device_printf(softc->dev, "atlantic: aq_hw_init: %d", err); 647*493d26c5SEd Maste } 648*493d26c5SEd Maste 649*493d26c5SEd Maste aq_if_media_status(ctx, &ifmr); 650*493d26c5SEd Maste 651*493d26c5SEd Maste aq_update_vlan_filters(softc); 652*493d26c5SEd Maste 653*493d26c5SEd Maste for (i = 0; i < softc->tx_rings_count; i++) { 654*493d26c5SEd Maste struct aq_ring *ring = softc->tx_rings[i]; 655*493d26c5SEd Maste err = aq_ring_tx_init(&softc->hw, ring); 656*493d26c5SEd Maste if (err) { 657*493d26c5SEd Maste device_printf(softc->dev, "atlantic: aq_ring_tx_init: %d", err); 658*493d26c5SEd Maste } 659*493d26c5SEd Maste err = aq_ring_tx_start(hw, ring); 660*493d26c5SEd Maste if (err != EOK) { 661*493d26c5SEd Maste device_printf(softc->dev, "atlantic: aq_ring_tx_start: %d", err); 662*493d26c5SEd Maste } 663*493d26c5SEd Maste } 664*493d26c5SEd Maste for (i = 0; i < softc->rx_rings_count; i++) { 665*493d26c5SEd Maste struct aq_ring *ring = softc->rx_rings[i]; 666*493d26c5SEd Maste err = aq_ring_rx_init(&softc->hw, ring); 667*493d26c5SEd Maste if (err) { 668*493d26c5SEd Maste device_printf(softc->dev, "atlantic: aq_ring_rx_init: %d", err); 669*493d26c5SEd Maste } 670*493d26c5SEd Maste err = aq_ring_rx_start(hw, ring); 671*493d26c5SEd Maste if (err != EOK) { 672*493d26c5SEd Maste device_printf(softc->dev, "atlantic: aq_ring_rx_start: %d", err); 673*493d26c5SEd Maste } 674*493d26c5SEd Maste aq_if_rx_queue_intr_enable(ctx, i); 675*493d26c5SEd Maste } 676*493d26c5SEd Maste 677*493d26c5SEd Maste aq_hw_start(hw); 678*493d26c5SEd Maste aq_if_enable_intr(ctx); 679*493d26c5SEd Maste aq_hw_rss_hash_set(&softc->hw, softc->rss_key); 680*493d26c5SEd Maste aq_hw_rss_set(&softc->hw, softc->rss_table); 681*493d26c5SEd Maste aq_hw_udp_rss_enable(hw, aq_enable_rss_udp); 682*493d26c5SEd Maste aq_hw_set_link_speed(hw, hw->link_rate); 683*493d26c5SEd Maste 684*493d26c5SEd Maste AQ_DBG_EXIT(0); 685*493d26c5SEd Maste } 686*493d26c5SEd Maste 687*493d26c5SEd Maste 688*493d26c5SEd Maste static void aq_if_stop(if_ctx_t ctx) 689*493d26c5SEd Maste { 690*493d26c5SEd Maste struct aq_dev *softc; 691*493d26c5SEd Maste struct aq_hw *hw; 692*493d26c5SEd Maste int i; 693*493d26c5SEd Maste 694*493d26c5SEd Maste AQ_DBG_ENTER(); 695*493d26c5SEd Maste 696*493d26c5SEd Maste softc = iflib_get_softc(ctx); 697*493d26c5SEd Maste hw = &softc->hw; 698*493d26c5SEd Maste 699*493d26c5SEd Maste /* disable interrupt */ 700*493d26c5SEd Maste aq_if_disable_intr(ctx); 701*493d26c5SEd Maste 702*493d26c5SEd Maste for (i = 0; i < softc->tx_rings_count; i++) { 703*493d26c5SEd Maste aq_ring_tx_stop(hw, softc->tx_rings[i]); 704*493d26c5SEd Maste softc->tx_rings[i]->tx_head = 0; 705*493d26c5SEd Maste softc->tx_rings[i]->tx_tail = 0; 706*493d26c5SEd Maste } 707*493d26c5SEd Maste for (i = 0; i < softc->rx_rings_count; i++) { 708*493d26c5SEd Maste aq_ring_rx_stop(hw, softc->rx_rings[i]); 709*493d26c5SEd Maste } 710*493d26c5SEd Maste 711*493d26c5SEd Maste aq_hw_reset(&softc->hw); 712*493d26c5SEd Maste memset(&softc->last_stats, 0, sizeof(softc->last_stats)); 713*493d26c5SEd Maste softc->linkup = false; 714*493d26c5SEd Maste aq_if_update_admin_status(ctx); 715*493d26c5SEd Maste AQ_DBG_EXIT(0); 716*493d26c5SEd Maste } 717*493d26c5SEd Maste 718*493d26c5SEd Maste static uint64_t aq_if_get_counter(if_ctx_t ctx, ift_counter cnt) 719*493d26c5SEd Maste { 720*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 721*493d26c5SEd Maste struct ifnet *ifp = iflib_get_ifp(ctx); 722*493d26c5SEd Maste 723*493d26c5SEd Maste switch (cnt) { 724*493d26c5SEd Maste case IFCOUNTER_IERRORS: 725*493d26c5SEd Maste return (softc->curr_stats.erpr); 726*493d26c5SEd Maste case IFCOUNTER_IQDROPS: 727*493d26c5SEd Maste return (softc->curr_stats.dpc); 728*493d26c5SEd Maste case IFCOUNTER_OERRORS: 729*493d26c5SEd Maste return (softc->curr_stats.erpt); 730*493d26c5SEd Maste default: 731*493d26c5SEd Maste return (if_get_counter_default(ifp, cnt)); 732*493d26c5SEd Maste } 733*493d26c5SEd Maste } 734*493d26c5SEd Maste 735*493d26c5SEd Maste #if __FreeBSD_version >= 1300054 736*493d26c5SEd Maste static u_int aq_mc_filter_apply(void *arg, struct sockaddr_dl *dl, u_int count) 737*493d26c5SEd Maste { 738*493d26c5SEd Maste struct aq_dev *softc = arg; 739*493d26c5SEd Maste struct aq_hw *hw = &softc->hw; 740*493d26c5SEd Maste u8 *mac_addr = NULL; 741*493d26c5SEd Maste 742*493d26c5SEd Maste if (count == AQ_HW_MAC_MAX) 743*493d26c5SEd Maste return (0); 744*493d26c5SEd Maste 745*493d26c5SEd Maste mac_addr = LLADDR(dl); 746*493d26c5SEd Maste aq_hw_mac_addr_set(hw, mac_addr, count + 1); 747*493d26c5SEd Maste 748*493d26c5SEd Maste aq_log_detail("set %d mc address %6D", count + 1, mac_addr, ":"); 749*493d26c5SEd Maste return (1); 750*493d26c5SEd Maste } 751*493d26c5SEd Maste #else 752*493d26c5SEd Maste static int aq_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count) 753*493d26c5SEd Maste { 754*493d26c5SEd Maste struct aq_dev *softc = arg; 755*493d26c5SEd Maste struct aq_hw *hw = &softc->hw; 756*493d26c5SEd Maste u8 *mac_addr = NULL; 757*493d26c5SEd Maste 758*493d26c5SEd Maste if (ifma->ifma_addr->sa_family != AF_LINK) 759*493d26c5SEd Maste return (0); 760*493d26c5SEd Maste if (count == AQ_HW_MAC_MAX) 761*493d26c5SEd Maste return (0); 762*493d26c5SEd Maste 763*493d26c5SEd Maste mac_addr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); 764*493d26c5SEd Maste aq_hw_mac_addr_set(hw, mac_addr, count + 1); 765*493d26c5SEd Maste 766*493d26c5SEd Maste aq_log_detail("set %d mc address %6D", count + 1, mac_addr, ":"); 767*493d26c5SEd Maste return (1); 768*493d26c5SEd Maste } 769*493d26c5SEd Maste #endif 770*493d26c5SEd Maste 771*493d26c5SEd Maste static bool aq_is_mc_promisc_required(struct aq_dev *softc) 772*493d26c5SEd Maste { 773*493d26c5SEd Maste return (softc->mcnt >= AQ_HW_MAC_MAX); 774*493d26c5SEd Maste } 775*493d26c5SEd Maste 776*493d26c5SEd Maste static void aq_if_multi_set(if_ctx_t ctx) 777*493d26c5SEd Maste { 778*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 779*493d26c5SEd Maste struct ifnet *ifp = iflib_get_ifp(ctx); 780*493d26c5SEd Maste struct aq_hw *hw = &softc->hw; 781*493d26c5SEd Maste AQ_DBG_ENTER(); 782*493d26c5SEd Maste #if __FreeBSD_version >= 1300054 783*493d26c5SEd Maste softc->mcnt = if_llmaddr_count(iflib_get_ifp(ctx)); 784*493d26c5SEd Maste #else 785*493d26c5SEd Maste softc->mcnt = if_multiaddr_count(iflib_get_ifp(ctx), AQ_HW_MAC_MAX); 786*493d26c5SEd Maste #endif 787*493d26c5SEd Maste if (softc->mcnt >= AQ_HW_MAC_MAX) 788*493d26c5SEd Maste { 789*493d26c5SEd Maste aq_hw_set_promisc(hw, !!(ifp->if_flags & IFF_PROMISC), 790*493d26c5SEd Maste aq_is_vlan_promisc_required(softc), 791*493d26c5SEd Maste !!(ifp->if_flags & IFF_ALLMULTI) || aq_is_mc_promisc_required(softc)); 792*493d26c5SEd Maste }else{ 793*493d26c5SEd Maste #if __FreeBSD_version >= 1300054 794*493d26c5SEd Maste if_foreach_llmaddr(iflib_get_ifp(ctx), &aq_mc_filter_apply, softc); 795*493d26c5SEd Maste #else 796*493d26c5SEd Maste if_multi_apply(iflib_get_ifp(ctx), aq_mc_filter_apply, softc); 797*493d26c5SEd Maste #endif 798*493d26c5SEd Maste } 799*493d26c5SEd Maste AQ_DBG_EXIT(0); 800*493d26c5SEd Maste } 801*493d26c5SEd Maste 802*493d26c5SEd Maste static int aq_if_mtu_set(if_ctx_t ctx, uint32_t mtu) 803*493d26c5SEd Maste { 804*493d26c5SEd Maste int err = 0; 805*493d26c5SEd Maste AQ_DBG_ENTER(); 806*493d26c5SEd Maste 807*493d26c5SEd Maste AQ_DBG_EXIT(err); 808*493d26c5SEd Maste return (err); 809*493d26c5SEd Maste } 810*493d26c5SEd Maste 811*493d26c5SEd Maste static void aq_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) 812*493d26c5SEd Maste { 813*493d26c5SEd Maste struct ifnet *ifp; 814*493d26c5SEd Maste 815*493d26c5SEd Maste AQ_DBG_ENTER(); 816*493d26c5SEd Maste 817*493d26c5SEd Maste ifp = iflib_get_ifp(ctx); 818*493d26c5SEd Maste 819*493d26c5SEd Maste aq_mediastatus(ifp, ifmr); 820*493d26c5SEd Maste 821*493d26c5SEd Maste AQ_DBG_EXIT(0); 822*493d26c5SEd Maste } 823*493d26c5SEd Maste 824*493d26c5SEd Maste static int aq_if_media_change(if_ctx_t ctx) 825*493d26c5SEd Maste { 826*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 827*493d26c5SEd Maste struct ifnet *ifp = iflib_get_ifp(ctx); 828*493d26c5SEd Maste int rc = 0; 829*493d26c5SEd Maste 830*493d26c5SEd Maste AQ_DBG_ENTER(); 831*493d26c5SEd Maste 832*493d26c5SEd Maste /* Not allowd in UP state, since causes unsync of rings */ 833*493d26c5SEd Maste if ((ifp->if_flags & IFF_UP)){ 834*493d26c5SEd Maste rc = EPERM; 835*493d26c5SEd Maste goto exit; 836*493d26c5SEd Maste } 837*493d26c5SEd Maste 838*493d26c5SEd Maste ifp = iflib_get_ifp(softc->ctx); 839*493d26c5SEd Maste 840*493d26c5SEd Maste rc = aq_mediachange(ifp); 841*493d26c5SEd Maste 842*493d26c5SEd Maste exit: 843*493d26c5SEd Maste AQ_DBG_EXIT(rc); 844*493d26c5SEd Maste return (rc); 845*493d26c5SEd Maste } 846*493d26c5SEd Maste 847*493d26c5SEd Maste static int aq_if_promisc_set(if_ctx_t ctx, int flags) 848*493d26c5SEd Maste { 849*493d26c5SEd Maste struct aq_dev *softc; 850*493d26c5SEd Maste 851*493d26c5SEd Maste AQ_DBG_ENTER(); 852*493d26c5SEd Maste 853*493d26c5SEd Maste softc = iflib_get_softc(ctx); 854*493d26c5SEd Maste 855*493d26c5SEd Maste aq_hw_set_promisc(&softc->hw, !!(flags & IFF_PROMISC), 856*493d26c5SEd Maste aq_is_vlan_promisc_required(softc), 857*493d26c5SEd Maste !!(flags & IFF_ALLMULTI) || aq_is_mc_promisc_required(softc)); 858*493d26c5SEd Maste 859*493d26c5SEd Maste AQ_DBG_EXIT(0); 860*493d26c5SEd Maste return (0); 861*493d26c5SEd Maste } 862*493d26c5SEd Maste 863*493d26c5SEd Maste static void aq_if_timer(if_ctx_t ctx, uint16_t qid) 864*493d26c5SEd Maste { 865*493d26c5SEd Maste struct aq_dev *softc; 866*493d26c5SEd Maste uint64_t ticks_now; 867*493d26c5SEd Maste 868*493d26c5SEd Maste // AQ_DBG_ENTER(); 869*493d26c5SEd Maste 870*493d26c5SEd Maste softc = iflib_get_softc(ctx); 871*493d26c5SEd Maste ticks_now = ticks; 872*493d26c5SEd Maste 873*493d26c5SEd Maste /* Schedule aqc_if_update_admin_status() once per sec */ 874*493d26c5SEd Maste if (ticks_now - softc->admin_ticks >= hz) { 875*493d26c5SEd Maste softc->admin_ticks = ticks_now; 876*493d26c5SEd Maste iflib_admin_intr_deferred(ctx); 877*493d26c5SEd Maste } 878*493d26c5SEd Maste 879*493d26c5SEd Maste // AQ_DBG_EXIT(0); 880*493d26c5SEd Maste return; 881*493d26c5SEd Maste 882*493d26c5SEd Maste } 883*493d26c5SEd Maste 884*493d26c5SEd Maste /* Interrupt enable / disable */ 885*493d26c5SEd Maste static void aq_if_enable_intr(if_ctx_t ctx) 886*493d26c5SEd Maste { 887*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 888*493d26c5SEd Maste struct aq_hw *hw = &softc->hw; 889*493d26c5SEd Maste 890*493d26c5SEd Maste AQ_DBG_ENTER(); 891*493d26c5SEd Maste 892*493d26c5SEd Maste /* Enable interrupts */ 893*493d26c5SEd Maste itr_irq_msk_setlsw_set(hw, BIT(softc->msix + 1) - 1); 894*493d26c5SEd Maste 895*493d26c5SEd Maste AQ_DBG_EXIT(0); 896*493d26c5SEd Maste } 897*493d26c5SEd Maste 898*493d26c5SEd Maste static void aq_if_disable_intr(if_ctx_t ctx) 899*493d26c5SEd Maste { 900*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 901*493d26c5SEd Maste struct aq_hw *hw = &softc->hw; 902*493d26c5SEd Maste 903*493d26c5SEd Maste AQ_DBG_ENTER(); 904*493d26c5SEd Maste 905*493d26c5SEd Maste /* Disable interrupts */ 906*493d26c5SEd Maste itr_irq_msk_clearlsw_set(hw, BIT(softc->msix + 1) - 1); 907*493d26c5SEd Maste 908*493d26c5SEd Maste AQ_DBG_EXIT(0); 909*493d26c5SEd Maste } 910*493d26c5SEd Maste 911*493d26c5SEd Maste static int aq_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid) 912*493d26c5SEd Maste { 913*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 914*493d26c5SEd Maste struct aq_hw *hw = &softc->hw; 915*493d26c5SEd Maste 916*493d26c5SEd Maste AQ_DBG_ENTER(); 917*493d26c5SEd Maste 918*493d26c5SEd Maste itr_irq_msk_setlsw_set(hw, BIT(softc->rx_rings[rxqid]->msix)); 919*493d26c5SEd Maste 920*493d26c5SEd Maste AQ_DBG_EXIT(0); 921*493d26c5SEd Maste return (0); 922*493d26c5SEd Maste } 923*493d26c5SEd Maste 924*493d26c5SEd Maste static int aq_if_msix_intr_assign(if_ctx_t ctx, int msix) 925*493d26c5SEd Maste { 926*493d26c5SEd Maste struct aq_dev *softc; 927*493d26c5SEd Maste int i, vector = 0, rc; 928*493d26c5SEd Maste char irq_name[16]; 929*493d26c5SEd Maste int rx_vectors; 930*493d26c5SEd Maste 931*493d26c5SEd Maste AQ_DBG_ENTER(); 932*493d26c5SEd Maste softc = iflib_get_softc(ctx); 933*493d26c5SEd Maste 934*493d26c5SEd Maste for (i = 0; i < softc->rx_rings_count; i++, vector++) { 935*493d26c5SEd Maste snprintf(irq_name, sizeof(irq_name), "rxq%d", i); 936*493d26c5SEd Maste rc = iflib_irq_alloc_generic(ctx, &softc->rx_rings[i]->irq, 937*493d26c5SEd Maste vector + 1, IFLIB_INTR_RX, aq_isr_rx, softc->rx_rings[i], 938*493d26c5SEd Maste softc->rx_rings[i]->index, irq_name); 939*493d26c5SEd Maste device_printf(softc->dev, "Assign IRQ %u to rx ring %u\n", 940*493d26c5SEd Maste vector, softc->rx_rings[i]->index); 941*493d26c5SEd Maste 942*493d26c5SEd Maste if (rc) { 943*493d26c5SEd Maste device_printf(softc->dev, "failed to set up RX handler\n"); 944*493d26c5SEd Maste i--; 945*493d26c5SEd Maste goto fail; 946*493d26c5SEd Maste } 947*493d26c5SEd Maste 948*493d26c5SEd Maste softc->rx_rings[i]->msix = vector; 949*493d26c5SEd Maste } 950*493d26c5SEd Maste 951*493d26c5SEd Maste rx_vectors = vector; 952*493d26c5SEd Maste 953*493d26c5SEd Maste for (i = 0; i < softc->tx_rings_count; i++, vector++) { 954*493d26c5SEd Maste snprintf(irq_name, sizeof(irq_name), "txq%d", i); 955*493d26c5SEd Maste iflib_softirq_alloc_generic(ctx, &softc->rx_rings[i]->irq, IFLIB_INTR_TX, 956*493d26c5SEd Maste softc->tx_rings[i], i, irq_name); 957*493d26c5SEd Maste 958*493d26c5SEd Maste softc->tx_rings[i]->msix = (vector % softc->rx_rings_count); 959*493d26c5SEd Maste device_printf(softc->dev, "Assign IRQ %u to tx ring %u\n", 960*493d26c5SEd Maste softc->tx_rings[i]->msix, softc->tx_rings[i]->index); 961*493d26c5SEd Maste } 962*493d26c5SEd Maste 963*493d26c5SEd Maste rc = iflib_irq_alloc_generic(ctx, &softc->irq, rx_vectors + 1, 964*493d26c5SEd Maste IFLIB_INTR_ADMIN, aq_linkstat_isr, 965*493d26c5SEd Maste softc, 0, "aq"); 966*493d26c5SEd Maste softc->msix = rx_vectors; 967*493d26c5SEd Maste device_printf(softc->dev, "Assign IRQ %u to admin proc \n", 968*493d26c5SEd Maste rx_vectors); 969*493d26c5SEd Maste if (rc) { 970*493d26c5SEd Maste device_printf(iflib_get_dev(ctx), "Failed to register admin handler"); 971*493d26c5SEd Maste i = softc->rx_rings_count; 972*493d26c5SEd Maste goto fail; 973*493d26c5SEd Maste } 974*493d26c5SEd Maste AQ_DBG_EXIT(0); 975*493d26c5SEd Maste return (0); 976*493d26c5SEd Maste 977*493d26c5SEd Maste fail: 978*493d26c5SEd Maste for (; i >= 0; i--) 979*493d26c5SEd Maste iflib_irq_free(ctx, &softc->rx_rings[i]->irq); 980*493d26c5SEd Maste AQ_DBG_EXIT(rc); 981*493d26c5SEd Maste return (rc); 982*493d26c5SEd Maste } 983*493d26c5SEd Maste 984*493d26c5SEd Maste static bool aq_is_vlan_promisc_required(struct aq_dev *softc) 985*493d26c5SEd Maste { 986*493d26c5SEd Maste int vlan_tag_count; 987*493d26c5SEd Maste 988*493d26c5SEd Maste bit_count(softc->vlan_tags, 0, 4096, &vlan_tag_count); 989*493d26c5SEd Maste 990*493d26c5SEd Maste if (vlan_tag_count <= AQ_HW_VLAN_MAX_FILTERS) 991*493d26c5SEd Maste return (false); 992*493d26c5SEd Maste else 993*493d26c5SEd Maste return (true); 994*493d26c5SEd Maste 995*493d26c5SEd Maste } 996*493d26c5SEd Maste 997*493d26c5SEd Maste static void aq_update_vlan_filters(struct aq_dev *softc) 998*493d26c5SEd Maste { 999*493d26c5SEd Maste struct aq_rx_filter_vlan aq_vlans[AQ_HW_VLAN_MAX_FILTERS]; 1000*493d26c5SEd Maste struct aq_hw *hw = &softc->hw; 1001*493d26c5SEd Maste int bit_pos = 0; 1002*493d26c5SEd Maste int vlan_tag = -1; 1003*493d26c5SEd Maste int i; 1004*493d26c5SEd Maste 1005*493d26c5SEd Maste hw_atl_b0_hw_vlan_promisc_set(hw, true); 1006*493d26c5SEd Maste for (i = 0; i < AQ_HW_VLAN_MAX_FILTERS; i++) { 1007*493d26c5SEd Maste bit_ffs_at(softc->vlan_tags, bit_pos, 4096, &vlan_tag); 1008*493d26c5SEd Maste if (vlan_tag != -1) { 1009*493d26c5SEd Maste aq_vlans[i].enable = true; 1010*493d26c5SEd Maste aq_vlans[i].location = i; 1011*493d26c5SEd Maste aq_vlans[i].queue = 0xFF; 1012*493d26c5SEd Maste aq_vlans[i].vlan_id = vlan_tag; 1013*493d26c5SEd Maste bit_pos = vlan_tag; 1014*493d26c5SEd Maste } else { 1015*493d26c5SEd Maste aq_vlans[i].enable = false; 1016*493d26c5SEd Maste } 1017*493d26c5SEd Maste } 1018*493d26c5SEd Maste 1019*493d26c5SEd Maste hw_atl_b0_hw_vlan_set(hw, aq_vlans); 1020*493d26c5SEd Maste hw_atl_b0_hw_vlan_promisc_set(hw, aq_is_vlan_promisc_required(softc)); 1021*493d26c5SEd Maste } 1022*493d26c5SEd Maste 1023*493d26c5SEd Maste /* VLAN support */ 1024*493d26c5SEd Maste static void aq_if_vlan_register(if_ctx_t ctx, uint16_t vtag) 1025*493d26c5SEd Maste { 1026*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 1027*493d26c5SEd Maste 1028*493d26c5SEd Maste AQ_DBG_ENTERA("%d", vtag); 1029*493d26c5SEd Maste 1030*493d26c5SEd Maste bit_set(softc->vlan_tags, vtag); 1031*493d26c5SEd Maste 1032*493d26c5SEd Maste aq_update_vlan_filters(softc); 1033*493d26c5SEd Maste 1034*493d26c5SEd Maste AQ_DBG_EXIT(0); 1035*493d26c5SEd Maste } 1036*493d26c5SEd Maste 1037*493d26c5SEd Maste static void aq_if_vlan_unregister(if_ctx_t ctx, uint16_t vtag) 1038*493d26c5SEd Maste { 1039*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 1040*493d26c5SEd Maste 1041*493d26c5SEd Maste AQ_DBG_ENTERA("%d", vtag); 1042*493d26c5SEd Maste 1043*493d26c5SEd Maste bit_clear(softc->vlan_tags, vtag); 1044*493d26c5SEd Maste 1045*493d26c5SEd Maste aq_update_vlan_filters(softc); 1046*493d26c5SEd Maste 1047*493d26c5SEd Maste AQ_DBG_EXIT(0); 1048*493d26c5SEd Maste } 1049*493d26c5SEd Maste 1050*493d26c5SEd Maste static void aq_if_led_func(if_ctx_t ctx, int onoff) 1051*493d26c5SEd Maste { 1052*493d26c5SEd Maste struct aq_dev *softc = iflib_get_softc(ctx); 1053*493d26c5SEd Maste struct aq_hw *hw = &softc->hw; 1054*493d26c5SEd Maste 1055*493d26c5SEd Maste AQ_DBG_ENTERA("%d", onoff); 1056*493d26c5SEd Maste if (hw->fw_ops && hw->fw_ops->led_control) 1057*493d26c5SEd Maste hw->fw_ops->led_control(hw, onoff); 1058*493d26c5SEd Maste 1059*493d26c5SEd Maste AQ_DBG_EXIT(0); 1060*493d26c5SEd Maste } 1061*493d26c5SEd Maste 1062*493d26c5SEd Maste static int aq_hw_capabilities(struct aq_dev *softc) 1063*493d26c5SEd Maste { 1064*493d26c5SEd Maste 1065*493d26c5SEd Maste if (pci_get_vendor(softc->dev) != AQUANTIA_VENDOR_ID) 1066*493d26c5SEd Maste return (ENXIO); 1067*493d26c5SEd Maste 1068*493d26c5SEd Maste switch (pci_get_device(softc->dev)) { 1069*493d26c5SEd Maste case AQ_DEVICE_ID_D100: 1070*493d26c5SEd Maste case AQ_DEVICE_ID_AQC100: 1071*493d26c5SEd Maste case AQ_DEVICE_ID_AQC100S: 1072*493d26c5SEd Maste softc->media_type = AQ_MEDIA_TYPE_FIBRE; 1073*493d26c5SEd Maste softc->link_speeds = AQ_LINK_ALL & ~AQ_LINK_10G; 1074*493d26c5SEd Maste break; 1075*493d26c5SEd Maste 1076*493d26c5SEd Maste case AQ_DEVICE_ID_0001: 1077*493d26c5SEd Maste case AQ_DEVICE_ID_D107: 1078*493d26c5SEd Maste case AQ_DEVICE_ID_AQC107: 1079*493d26c5SEd Maste case AQ_DEVICE_ID_AQC107S: 1080*493d26c5SEd Maste softc->media_type = AQ_MEDIA_TYPE_TP; 1081*493d26c5SEd Maste softc->link_speeds = AQ_LINK_ALL; 1082*493d26c5SEd Maste break; 1083*493d26c5SEd Maste 1084*493d26c5SEd Maste case AQ_DEVICE_ID_D108: 1085*493d26c5SEd Maste case AQ_DEVICE_ID_AQC108: 1086*493d26c5SEd Maste case AQ_DEVICE_ID_AQC108S: 1087*493d26c5SEd Maste case AQ_DEVICE_ID_AQC111: 1088*493d26c5SEd Maste case AQ_DEVICE_ID_AQC111S: 1089*493d26c5SEd Maste softc->media_type = AQ_MEDIA_TYPE_TP; 1090*493d26c5SEd Maste softc->link_speeds = AQ_LINK_ALL & ~AQ_LINK_10G; 1091*493d26c5SEd Maste break; 1092*493d26c5SEd Maste 1093*493d26c5SEd Maste case AQ_DEVICE_ID_D109: 1094*493d26c5SEd Maste case AQ_DEVICE_ID_AQC109: 1095*493d26c5SEd Maste case AQ_DEVICE_ID_AQC109S: 1096*493d26c5SEd Maste case AQ_DEVICE_ID_AQC112: 1097*493d26c5SEd Maste case AQ_DEVICE_ID_AQC112S: 1098*493d26c5SEd Maste softc->media_type = AQ_MEDIA_TYPE_TP; 1099*493d26c5SEd Maste softc->link_speeds = AQ_LINK_ALL & ~(AQ_LINK_10G | AQ_LINK_5G); 1100*493d26c5SEd Maste break; 1101*493d26c5SEd Maste 1102*493d26c5SEd Maste default: 1103*493d26c5SEd Maste return (ENXIO); 1104*493d26c5SEd Maste } 1105*493d26c5SEd Maste 1106*493d26c5SEd Maste return (0); 1107*493d26c5SEd Maste } 1108*493d26c5SEd Maste 1109*493d26c5SEd Maste static int aq_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS) 1110*493d26c5SEd Maste { 1111*493d26c5SEd Maste struct aq_dev *softc = (struct aq_dev *)arg1; 1112*493d26c5SEd Maste device_t dev = softc->dev; 1113*493d26c5SEd Maste struct sbuf *buf; 1114*493d26c5SEd Maste int error = 0; 1115*493d26c5SEd Maste 1116*493d26c5SEd Maste buf = sbuf_new_for_sysctl(NULL, NULL, 256, req); 1117*493d26c5SEd Maste if (!buf) { 1118*493d26c5SEd Maste device_printf(dev, "Could not allocate sbuf for output.\n"); 1119*493d26c5SEd Maste return (ENOMEM); 1120*493d26c5SEd Maste } 1121*493d26c5SEd Maste 1122*493d26c5SEd Maste /* Print out the redirection table */ 1123*493d26c5SEd Maste sbuf_cat(buf, "\nRSS Indirection table:\n"); 1124*493d26c5SEd Maste for (int i = 0; i < HW_ATL_RSS_INDIRECTION_TABLE_MAX; i++) { 1125*493d26c5SEd Maste sbuf_printf(buf, "%d ", softc->rss_table[i]); 1126*493d26c5SEd Maste if ((i+1) % 10 == 0) 1127*493d26c5SEd Maste sbuf_printf(buf, "\n"); 1128*493d26c5SEd Maste } 1129*493d26c5SEd Maste 1130*493d26c5SEd Maste sbuf_cat(buf, "\nRSS Key:\n"); 1131*493d26c5SEd Maste for (int i = 0; i < HW_ATL_RSS_HASHKEY_SIZE; i++) { 1132*493d26c5SEd Maste sbuf_printf(buf, "0x%02x ", softc->rss_key[i]); 1133*493d26c5SEd Maste } 1134*493d26c5SEd Maste sbuf_printf(buf, "\n"); 1135*493d26c5SEd Maste 1136*493d26c5SEd Maste error = sbuf_finish(buf); 1137*493d26c5SEd Maste if (error) 1138*493d26c5SEd Maste device_printf(dev, "Error finishing sbuf: %d\n", error); 1139*493d26c5SEd Maste 1140*493d26c5SEd Maste sbuf_delete(buf); 1141*493d26c5SEd Maste 1142*493d26c5SEd Maste return (0); 1143*493d26c5SEd Maste } 1144*493d26c5SEd Maste 1145*493d26c5SEd Maste static int aq_sysctl_print_tx_head(SYSCTL_HANDLER_ARGS) 1146*493d26c5SEd Maste { 1147*493d26c5SEd Maste struct aq_ring *ring = arg1; 1148*493d26c5SEd Maste int error = 0; 1149*493d26c5SEd Maste unsigned int val; 1150*493d26c5SEd Maste 1151*493d26c5SEd Maste if (!ring) 1152*493d26c5SEd Maste return (0); 1153*493d26c5SEd Maste 1154*493d26c5SEd Maste val = tdm_tx_desc_head_ptr_get(&ring->dev->hw, ring->index); 1155*493d26c5SEd Maste 1156*493d26c5SEd Maste error = sysctl_handle_int(oidp, &val, 0, req); 1157*493d26c5SEd Maste if (error || !req->newptr) 1158*493d26c5SEd Maste return (error); 1159*493d26c5SEd Maste 1160*493d26c5SEd Maste return (0); 1161*493d26c5SEd Maste } 1162*493d26c5SEd Maste 1163*493d26c5SEd Maste static int aq_sysctl_print_tx_tail(SYSCTL_HANDLER_ARGS) 1164*493d26c5SEd Maste { 1165*493d26c5SEd Maste struct aq_ring *ring = arg1; 1166*493d26c5SEd Maste int error = 0; 1167*493d26c5SEd Maste unsigned int val; 1168*493d26c5SEd Maste 1169*493d26c5SEd Maste if (!ring) 1170*493d26c5SEd Maste return (0); 1171*493d26c5SEd Maste 1172*493d26c5SEd Maste val = reg_tx_dma_desc_tail_ptr_get(&ring->dev->hw, ring->index); 1173*493d26c5SEd Maste 1174*493d26c5SEd Maste error = sysctl_handle_int(oidp, &val, 0, req); 1175*493d26c5SEd Maste if (error || !req->newptr) 1176*493d26c5SEd Maste return (error); 1177*493d26c5SEd Maste 1178*493d26c5SEd Maste return (0); 1179*493d26c5SEd Maste } 1180*493d26c5SEd Maste 1181*493d26c5SEd Maste static int aq_sysctl_print_rx_head(SYSCTL_HANDLER_ARGS) 1182*493d26c5SEd Maste { 1183*493d26c5SEd Maste struct aq_ring *ring = arg1; 1184*493d26c5SEd Maste int error = 0; 1185*493d26c5SEd Maste unsigned int val; 1186*493d26c5SEd Maste 1187*493d26c5SEd Maste if (!ring) 1188*493d26c5SEd Maste return (0); 1189*493d26c5SEd Maste 1190*493d26c5SEd Maste val = rdm_rx_desc_head_ptr_get(&ring->dev->hw, ring->index); 1191*493d26c5SEd Maste 1192*493d26c5SEd Maste error = sysctl_handle_int(oidp, &val, 0, req); 1193*493d26c5SEd Maste if (error || !req->newptr) 1194*493d26c5SEd Maste return (error); 1195*493d26c5SEd Maste 1196*493d26c5SEd Maste return (0); 1197*493d26c5SEd Maste } 1198*493d26c5SEd Maste 1199*493d26c5SEd Maste static int aq_sysctl_print_rx_tail(SYSCTL_HANDLER_ARGS) 1200*493d26c5SEd Maste { 1201*493d26c5SEd Maste struct aq_ring *ring = arg1; 1202*493d26c5SEd Maste int error = 0; 1203*493d26c5SEd Maste unsigned int val; 1204*493d26c5SEd Maste 1205*493d26c5SEd Maste if (!ring) 1206*493d26c5SEd Maste return (0); 1207*493d26c5SEd Maste 1208*493d26c5SEd Maste val = reg_rx_dma_desc_tail_ptr_get(&ring->dev->hw, ring->index); 1209*493d26c5SEd Maste 1210*493d26c5SEd Maste error = sysctl_handle_int(oidp, &val, 0, req); 1211*493d26c5SEd Maste if (error || !req->newptr) 1212*493d26c5SEd Maste return (error); 1213*493d26c5SEd Maste 1214*493d26c5SEd Maste return (0); 1215*493d26c5SEd Maste } 1216*493d26c5SEd Maste 1217*493d26c5SEd Maste static void aq_add_stats_sysctls(struct aq_dev *softc) 1218*493d26c5SEd Maste { 1219*493d26c5SEd Maste device_t dev = softc->dev; 1220*493d26c5SEd Maste struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev); 1221*493d26c5SEd Maste struct sysctl_oid *tree = device_get_sysctl_tree(dev); 1222*493d26c5SEd Maste struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); 1223*493d26c5SEd Maste struct aq_stats_s *stats = &softc->curr_stats; 1224*493d26c5SEd Maste struct sysctl_oid *stat_node, *queue_node; 1225*493d26c5SEd Maste struct sysctl_oid_list *stat_list, *queue_list; 1226*493d26c5SEd Maste 1227*493d26c5SEd Maste #define QUEUE_NAME_LEN 32 1228*493d26c5SEd Maste char namebuf[QUEUE_NAME_LEN]; 1229*493d26c5SEd Maste /* RSS configuration */ 1230*493d26c5SEd Maste SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config", 1231*493d26c5SEd Maste CTLTYPE_STRING | CTLFLAG_RD, softc, 0, 1232*493d26c5SEd Maste aq_sysctl_print_rss_config, "A", "Prints RSS Configuration"); 1233*493d26c5SEd Maste 1234*493d26c5SEd Maste /* Driver Statistics */ 1235*493d26c5SEd Maste for (int i = 0; i < softc->tx_rings_count; i++) { 1236*493d26c5SEd Maste struct aq_ring *ring = softc->tx_rings[i]; 1237*493d26c5SEd Maste snprintf(namebuf, QUEUE_NAME_LEN, "tx_queue%d", i); 1238*493d26c5SEd Maste queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 1239*493d26c5SEd Maste CTLFLAG_RD, NULL, "Queue Name"); 1240*493d26c5SEd Maste queue_list = SYSCTL_CHILDREN(queue_node); 1241*493d26c5SEd Maste 1242*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_pkts", 1243*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.tx_pkts), "TX Packets"); 1244*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_bytes", 1245*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.tx_bytes), "TX Octets"); 1246*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_drops", 1247*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.tx_drops), "TX Drops"); 1248*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_queue_full", 1249*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.tx_queue_full), "TX Queue Full"); 1250*493d26c5SEd Maste SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "tx_head", 1251*493d26c5SEd Maste CTLTYPE_UINT | CTLFLAG_RD, ring, 0, 1252*493d26c5SEd Maste aq_sysctl_print_tx_head, "IU", "ring head pointer"); 1253*493d26c5SEd Maste SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "tx_tail", 1254*493d26c5SEd Maste CTLTYPE_UINT | CTLFLAG_RD, ring, 0, 1255*493d26c5SEd Maste aq_sysctl_print_tx_tail, "IU", "ring tail pointer"); 1256*493d26c5SEd Maste } 1257*493d26c5SEd Maste 1258*493d26c5SEd Maste for (int i = 0; i < softc->rx_rings_count; i++) { 1259*493d26c5SEd Maste struct aq_ring *ring = softc->rx_rings[i]; 1260*493d26c5SEd Maste snprintf(namebuf, QUEUE_NAME_LEN, "rx_queue%d", i); 1261*493d26c5SEd Maste queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf, 1262*493d26c5SEd Maste CTLFLAG_RD, NULL, "Queue Name"); 1263*493d26c5SEd Maste queue_list = SYSCTL_CHILDREN(queue_node); 1264*493d26c5SEd Maste 1265*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_pkts", 1266*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.rx_pkts), "RX Packets"); 1267*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes", 1268*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.rx_bytes), "TX Octets"); 1269*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "jumbo_pkts", 1270*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.jumbo_pkts), "Jumbo Packets"); 1271*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_err", 1272*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.rx_err), "RX Errors"); 1273*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irq", 1274*493d26c5SEd Maste CTLFLAG_RD, &(ring->stats.irq), "RX interrupts"); 1275*493d26c5SEd Maste SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rx_head", 1276*493d26c5SEd Maste CTLTYPE_UINT | CTLFLAG_RD, ring, 0, 1277*493d26c5SEd Maste aq_sysctl_print_rx_head, "IU", "ring head pointer"); 1278*493d26c5SEd Maste SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rx_tail", 1279*493d26c5SEd Maste CTLTYPE_UINT | CTLFLAG_RD, ring, 0, 1280*493d26c5SEd Maste aq_sysctl_print_rx_tail, "IU", " ring tail pointer"); 1281*493d26c5SEd Maste } 1282*493d26c5SEd Maste 1283*493d26c5SEd Maste stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac", 1284*493d26c5SEd Maste CTLFLAG_RD, NULL, "Statistics (read from HW registers)"); 1285*493d26c5SEd Maste stat_list = SYSCTL_CHILDREN(stat_node); 1286*493d26c5SEd Maste 1287*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd", 1288*493d26c5SEd Maste CTLFLAG_RD, &stats->prc, "Good Packets Received"); 1289*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ucast_pkts_rcvd", 1290*493d26c5SEd Maste CTLFLAG_RD, &stats->uprc, "Unicast Packets Received"); 1291*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd", 1292*493d26c5SEd Maste CTLFLAG_RD, &stats->mprc, "Multicast Packets Received"); 1293*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd", 1294*493d26c5SEd Maste CTLFLAG_RD, &stats->bprc, "Broadcast Packets Received"); 1295*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rsc_pkts_rcvd", 1296*493d26c5SEd Maste CTLFLAG_RD, &stats->cprc, "Coalesced Packets Received"); 1297*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "err_pkts_rcvd", 1298*493d26c5SEd Maste CTLFLAG_RD, &stats->erpr, "Errors of Packet Receive"); 1299*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "drop_pkts_dma", 1300*493d26c5SEd Maste CTLFLAG_RD, &stats->dpc, "Dropped Packets in DMA"); 1301*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd", 1302*493d26c5SEd Maste CTLFLAG_RD, &stats->brc, "Good Octets Received"); 1303*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ucast_octets_rcvd", 1304*493d26c5SEd Maste CTLFLAG_RD, &stats->ubrc, "Unicast Octets Received"); 1305*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_octets_rcvd", 1306*493d26c5SEd Maste CTLFLAG_RD, &stats->mbrc, "Multicast Octets Received"); 1307*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_octets_rcvd", 1308*493d26c5SEd Maste CTLFLAG_RD, &stats->bbrc, "Broadcast Octets Received"); 1309*493d26c5SEd Maste 1310*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd", 1311*493d26c5SEd Maste CTLFLAG_RD, &stats->ptc, "Good Packets Transmitted"); 1312*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ucast_pkts_txd", 1313*493d26c5SEd Maste CTLFLAG_RD, &stats->uptc, "Unicast Packets Transmitted"); 1314*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd", 1315*493d26c5SEd Maste CTLFLAG_RD, &stats->mptc, "Multicast Packets Transmitted"); 1316*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd", 1317*493d26c5SEd Maste CTLFLAG_RD, &stats->bptc, "Broadcast Packets Transmitted"); 1318*493d26c5SEd Maste 1319*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "err_pkts_txd", 1320*493d26c5SEd Maste CTLFLAG_RD, &stats->erpt, "Errors of Packet Transmit"); 1321*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd", 1322*493d26c5SEd Maste CTLFLAG_RD, &stats->btc, "Good Octets Transmitted"); 1323*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ucast_octets_txd", 1324*493d26c5SEd Maste CTLFLAG_RD, &stats->ubtc, "Unicast Octets Transmitted"); 1325*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_octets_txd", 1326*493d26c5SEd Maste CTLFLAG_RD, &stats->mbtc, "Multicast Octets Transmitted"); 1327*493d26c5SEd Maste SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_octets_txd", 1328*493d26c5SEd Maste CTLFLAG_RD, &stats->bbtc, "Broadcast Octets Transmitted"); 1329*493d26c5SEd Maste } 1330