if_bnxt.c revision 331161
1308696Sshurd/*- 2308696Sshurd * Broadcom NetXtreme-C/E network driver. 3308696Sshurd * 4308696Sshurd * Copyright (c) 2016 Broadcom, All Rights Reserved. 5308696Sshurd * The term Broadcom refers to Broadcom Limited and/or its subsidiaries 6308696Sshurd * 7308696Sshurd * Redistribution and use in source and binary forms, with or without 8308696Sshurd * modification, are permitted provided that the following conditions 9308696Sshurd * are met: 10308696Sshurd * 1. Redistributions of source code must retain the above copyright 11308696Sshurd * notice, this list of conditions and the following disclaimer. 12308696Sshurd * 2. Redistributions in binary form must reproduce the above copyright 13308696Sshurd * notice, this list of conditions and the following disclaimer in the 14308696Sshurd * documentation and/or other materials provided with the distribution. 15308696Sshurd * 16308696Sshurd * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS' 17308696Sshurd * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18308696Sshurd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19308696Sshurd * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20308696Sshurd * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21308696Sshurd * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22308696Sshurd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23308696Sshurd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24308696Sshurd * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25308696Sshurd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26308696Sshurd * THE POSSIBILITY OF SUCH DAMAGE. 27308696Sshurd */ 28308696Sshurd 29308696Sshurd#include <sys/cdefs.h> 30308696Sshurd__FBSDID("$FreeBSD: stable/11/sys/dev/bnxt/if_bnxt.c 331161 2018-03-19 03:15:33Z eadler $"); 31308696Sshurd 32308696Sshurd#include <sys/param.h> 33308696Sshurd#include <sys/socket.h> 34308696Sshurd#include <sys/kernel.h> 35308696Sshurd#include <sys/bus.h> 36308696Sshurd#include <sys/module.h> 37308696Sshurd#include <sys/rman.h> 38308696Sshurd#include <sys/endian.h> 39308696Sshurd#include <sys/sockio.h> 40308696Sshurd#include <sys/priv.h> 41308696Sshurd 42308696Sshurd#include <machine/bus.h> 43308696Sshurd#include <machine/resource.h> 44308696Sshurd 45308696Sshurd#include <dev/pci/pcireg.h> 46308696Sshurd#include <dev/pci/pcivar.h> 47308696Sshurd 48308696Sshurd#include <net/if.h> 49308696Sshurd#include <net/if_media.h> 50308696Sshurd#include <net/if_var.h> 51308696Sshurd#include <net/ethernet.h> 52308696Sshurd#include <net/iflib.h> 53308696Sshurd 54308696Sshurd#include "opt_inet.h" 55308696Sshurd#include "opt_inet6.h" 56308696Sshurd#include "opt_rss.h" 57308696Sshurd 58308696Sshurd#include "ifdi_if.h" 59308696Sshurd 60308696Sshurd#include "bnxt.h" 61308696Sshurd#include "bnxt_hwrm.h" 62308696Sshurd#include "bnxt_ioctl.h" 63308696Sshurd#include "bnxt_sysctl.h" 64308696Sshurd#include "hsi_struct_def.h" 65308696Sshurd 66308696Sshurd/* 67308696Sshurd * PCI Device ID Table 68308696Sshurd */ 69308696Sshurd 70308696Sshurdstatic pci_vendor_info_t bnxt_vendor_info_array[] = 71308696Sshurd{ 72308696Sshurd PVID(BROADCOM_VENDOR_ID, BCM57301, 73308696Sshurd "Broadcom BCM57301 NetXtreme-C 10Gb Ethernet Controller"), 74308696Sshurd PVID(BROADCOM_VENDOR_ID, BCM57302, 75308696Sshurd "Broadcom BCM57302 NetXtreme-C 10Gb/25Gb Ethernet Controller"), 76308696Sshurd PVID(BROADCOM_VENDOR_ID, BCM57304, 77308696Sshurd "Broadcom BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller"), 78309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57311, 79309377Sshurd "Broadcom BCM57311 NetXtreme-C 10Gb Ethernet"), 80309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57312, 81309377Sshurd "Broadcom BCM57312 NetXtreme-C 10Gb/25Gb Ethernet"), 82309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57314, 83309377Sshurd "Broadcom BCM57314 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet"), 84308696Sshurd PVID(BROADCOM_VENDOR_ID, BCM57402, 85308696Sshurd "Broadcom BCM57402 NetXtreme-E 10Gb Ethernet Controller"), 86309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57402_NPAR, 87309377Sshurd "Broadcom BCM57402 NetXtreme-E Partition"), 88308696Sshurd PVID(BROADCOM_VENDOR_ID, BCM57404, 89308696Sshurd "Broadcom BCM57404 NetXtreme-E 10Gb/25Gb Ethernet Controller"), 90309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57404_NPAR, 91309377Sshurd "Broadcom BCM57404 NetXtreme-E Partition"), 92308696Sshurd PVID(BROADCOM_VENDOR_ID, BCM57406, 93308696Sshurd "Broadcom BCM57406 NetXtreme-E 10GBase-T Ethernet Controller"), 94309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57406_NPAR, 95309377Sshurd "Broadcom BCM57406 NetXtreme-E Partition"), 96308696Sshurd PVID(BROADCOM_VENDOR_ID, BCM57407, 97308696Sshurd "Broadcom BCM57407 NetXtreme-E 10GBase-T Ethernet Controller"), 98309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57407_NPAR, 99309377Sshurd "Broadcom BCM57407 NetXtreme-E Ethernet Partition"), 100308696Sshurd PVID(BROADCOM_VENDOR_ID, BCM57407_SFP, 101308696Sshurd "Broadcom BCM57407 NetXtreme-E 25Gb Ethernet Controller"), 102309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57412, 103309377Sshurd "Broadcom BCM57412 NetXtreme-E 10Gb Ethernet"), 104309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57412_NPAR1, 105309377Sshurd "Broadcom BCM57412 NetXtreme-E Ethernet Partition"), 106309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57412_NPAR2, 107309377Sshurd "Broadcom BCM57412 NetXtreme-E Ethernet Partition"), 108309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57414, 109309377Sshurd "Broadcom BCM57414 NetXtreme-E 10Gb/25Gb Ethernet"), 110309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57414_NPAR1, 111309377Sshurd "Broadcom BCM57414 NetXtreme-E Ethernet Partition"), 112309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57414_NPAR2, 113309377Sshurd "Broadcom BCM57414 NetXtreme-E Ethernet Partition"), 114309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57416, 115309377Sshurd "Broadcom BCM57416 NetXtreme-E 10GBase-T Ethernet"), 116309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57416_NPAR1, 117309377Sshurd "Broadcom BCM57416 NetXtreme-E Ethernet Partition"), 118309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57416_NPAR2, 119309377Sshurd "Broadcom BCM57416 NetXtreme-E Ethernet Partition"), 120309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57416_SFP, 121309377Sshurd "Broadcom BCM57416 NetXtreme-E 10Gb Ethernet"), 122309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57417, 123309377Sshurd "Broadcom BCM57417 NetXtreme-E 10GBase-T Ethernet"), 124309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57417_NPAR1, 125309377Sshurd "Broadcom BCM57417 NetXtreme-E Ethernet Partition"), 126309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57417_NPAR2, 127309377Sshurd "Broadcom BCM57417 NetXtreme-E Ethernet Partition"), 128309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM57417_SFP, 129309377Sshurd "Broadcom BCM57417 NetXtreme-E 10Gb/25Gb Ethernet"), 130331161Seadler PVID(BROADCOM_VENDOR_ID, BCM57454, 131331161Seadler "Broadcom BCM57454 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet"), 132309377Sshurd PVID(BROADCOM_VENDOR_ID, BCM58700, 133309377Sshurd "Broadcom BCM58700 Nitro 1Gb/2.5Gb/10Gb Ethernet"), 134309377Sshurd PVID(BROADCOM_VENDOR_ID, NETXTREME_C_VF1, 135309377Sshurd "Broadcom NetXtreme-C Ethernet Virtual Function"), 136309377Sshurd PVID(BROADCOM_VENDOR_ID, NETXTREME_C_VF2, 137309377Sshurd "Broadcom NetXtreme-C Ethernet Virtual Function"), 138309377Sshurd PVID(BROADCOM_VENDOR_ID, NETXTREME_C_VF3, 139309377Sshurd "Broadcom NetXtreme-C Ethernet Virtual Function"), 140309377Sshurd PVID(BROADCOM_VENDOR_ID, NETXTREME_E_VF1, 141309377Sshurd "Broadcom NetXtreme-E Ethernet Virtual Function"), 142309377Sshurd PVID(BROADCOM_VENDOR_ID, NETXTREME_E_VF2, 143309377Sshurd "Broadcom NetXtreme-E Ethernet Virtual Function"), 144309377Sshurd PVID(BROADCOM_VENDOR_ID, NETXTREME_E_VF3, 145309377Sshurd "Broadcom NetXtreme-E Ethernet Virtual Function"), 146308696Sshurd /* required last entry */ 147308696Sshurd 148308696Sshurd PVID_END 149308696Sshurd}; 150308696Sshurd 151308696Sshurd/* 152308696Sshurd * Function prototypes 153308696Sshurd */ 154308696Sshurd 155308696Sshurdstatic void *bnxt_register(device_t dev); 156308696Sshurd 157308696Sshurd/* Soft queue setup and teardown */ 158308696Sshurdstatic int bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 159308696Sshurd uint64_t *paddrs, int ntxqs, int ntxqsets); 160308696Sshurdstatic int bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 161308696Sshurd uint64_t *paddrs, int nrxqs, int nrxqsets); 162308696Sshurdstatic void bnxt_queues_free(if_ctx_t ctx); 163308696Sshurd 164308696Sshurd/* Device setup and teardown */ 165308696Sshurdstatic int bnxt_attach_pre(if_ctx_t ctx); 166308696Sshurdstatic int bnxt_attach_post(if_ctx_t ctx); 167308696Sshurdstatic int bnxt_detach(if_ctx_t ctx); 168308696Sshurd 169308696Sshurd/* Device configuration */ 170308696Sshurdstatic void bnxt_init(if_ctx_t ctx); 171308696Sshurdstatic void bnxt_stop(if_ctx_t ctx); 172308696Sshurdstatic void bnxt_multi_set(if_ctx_t ctx); 173308696Sshurdstatic int bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu); 174308696Sshurdstatic void bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr); 175308696Sshurdstatic int bnxt_media_change(if_ctx_t ctx); 176308696Sshurdstatic int bnxt_promisc_set(if_ctx_t ctx, int flags); 177308696Sshurdstatic uint64_t bnxt_get_counter(if_ctx_t, ift_counter); 178308696Sshurdstatic void bnxt_update_admin_status(if_ctx_t ctx); 179308696Sshurd 180308696Sshurd/* Interrupt enable / disable */ 181308696Sshurdstatic void bnxt_intr_enable(if_ctx_t ctx); 182308696Sshurdstatic int bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid); 183308696Sshurdstatic void bnxt_disable_intr(if_ctx_t ctx); 184308696Sshurdstatic int bnxt_msix_intr_assign(if_ctx_t ctx, int msix); 185308696Sshurd 186308696Sshurd/* vlan support */ 187308696Sshurdstatic void bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag); 188308696Sshurdstatic void bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag); 189308696Sshurd 190308696Sshurd/* ioctl */ 191308696Sshurdstatic int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); 192308696Sshurd 193308696Sshurd/* Internal support functions */ 194308696Sshurdstatic int bnxt_probe_phy(struct bnxt_softc *softc); 195308696Sshurdstatic void bnxt_add_media_types(struct bnxt_softc *softc); 196308696Sshurdstatic int bnxt_pci_mapping(struct bnxt_softc *softc); 197308696Sshurdstatic void bnxt_pci_mapping_free(struct bnxt_softc *softc); 198308696Sshurdstatic int bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state); 199308696Sshurdstatic int bnxt_handle_def_cp(void *arg); 200308696Sshurdstatic int bnxt_handle_rx_cp(void *arg); 201308696Sshurdstatic void bnxt_clear_ids(struct bnxt_softc *softc); 202308696Sshurdstatic void inline bnxt_do_enable_intr(struct bnxt_cp_ring *cpr); 203308696Sshurdstatic void inline bnxt_do_disable_intr(struct bnxt_cp_ring *cpr); 204308696Sshurdstatic void bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr); 205308696Sshurdstatic void bnxt_def_cp_task(void *context); 206308696Sshurdstatic void bnxt_handle_async_event(struct bnxt_softc *softc, 207308696Sshurd struct cmpl_base *cmpl); 208308696Sshurdstatic uint8_t get_phy_type(struct bnxt_softc *softc); 209308696Sshurdstatic uint64_t bnxt_get_baudrate(struct bnxt_link_info *link); 210308696Sshurd 211308696Sshurd/* 212308696Sshurd * Device Interface Declaration 213308696Sshurd */ 214308696Sshurd 215308696Sshurdstatic device_method_t bnxt_methods[] = { 216308696Sshurd /* Device interface */ 217308696Sshurd DEVMETHOD(device_register, bnxt_register), 218308696Sshurd DEVMETHOD(device_probe, iflib_device_probe), 219308696Sshurd DEVMETHOD(device_attach, iflib_device_attach), 220308696Sshurd DEVMETHOD(device_detach, iflib_device_detach), 221308696Sshurd DEVMETHOD(device_shutdown, iflib_device_shutdown), 222308696Sshurd DEVMETHOD(device_suspend, iflib_device_suspend), 223308696Sshurd DEVMETHOD(device_resume, iflib_device_resume), 224308696Sshurd DEVMETHOD_END 225308696Sshurd}; 226308696Sshurd 227308696Sshurdstatic driver_t bnxt_driver = { 228308696Sshurd "bnxt", bnxt_methods, sizeof(struct bnxt_softc), 229308696Sshurd}; 230308696Sshurd 231308696Sshurddevclass_t bnxt_devclass; 232308696SshurdDRIVER_MODULE(bnxt, pci, bnxt_driver, bnxt_devclass, 0, 0); 233308696Sshurd 234308696SshurdMODULE_DEPEND(bnxt, pci, 1, 1, 1); 235308696SshurdMODULE_DEPEND(bnxt, ether, 1, 1, 1); 236308696SshurdMODULE_DEPEND(bnxt, iflib, 1, 1, 1); 237308696Sshurd 238308696Sshurdstatic device_method_t bnxt_iflib_methods[] = { 239308696Sshurd DEVMETHOD(ifdi_tx_queues_alloc, bnxt_tx_queues_alloc), 240308696Sshurd DEVMETHOD(ifdi_rx_queues_alloc, bnxt_rx_queues_alloc), 241308696Sshurd DEVMETHOD(ifdi_queues_free, bnxt_queues_free), 242308696Sshurd 243308696Sshurd DEVMETHOD(ifdi_attach_pre, bnxt_attach_pre), 244308696Sshurd DEVMETHOD(ifdi_attach_post, bnxt_attach_post), 245308696Sshurd DEVMETHOD(ifdi_detach, bnxt_detach), 246308696Sshurd 247308696Sshurd DEVMETHOD(ifdi_init, bnxt_init), 248308696Sshurd DEVMETHOD(ifdi_stop, bnxt_stop), 249308696Sshurd DEVMETHOD(ifdi_multi_set, bnxt_multi_set), 250308696Sshurd DEVMETHOD(ifdi_mtu_set, bnxt_mtu_set), 251308696Sshurd DEVMETHOD(ifdi_media_status, bnxt_media_status), 252308696Sshurd DEVMETHOD(ifdi_media_change, bnxt_media_change), 253308696Sshurd DEVMETHOD(ifdi_promisc_set, bnxt_promisc_set), 254308696Sshurd DEVMETHOD(ifdi_get_counter, bnxt_get_counter), 255308696Sshurd DEVMETHOD(ifdi_update_admin_status, bnxt_update_admin_status), 256308696Sshurd 257308696Sshurd DEVMETHOD(ifdi_intr_enable, bnxt_intr_enable), 258308696Sshurd DEVMETHOD(ifdi_queue_intr_enable, bnxt_queue_intr_enable), 259308696Sshurd DEVMETHOD(ifdi_intr_disable, bnxt_disable_intr), 260308696Sshurd DEVMETHOD(ifdi_msix_intr_assign, bnxt_msix_intr_assign), 261308696Sshurd 262308696Sshurd DEVMETHOD(ifdi_vlan_register, bnxt_vlan_register), 263308696Sshurd DEVMETHOD(ifdi_vlan_unregister, bnxt_vlan_unregister), 264308696Sshurd 265308696Sshurd DEVMETHOD(ifdi_priv_ioctl, bnxt_priv_ioctl), 266308696Sshurd 267308696Sshurd DEVMETHOD_END 268308696Sshurd}; 269308696Sshurd 270308696Sshurdstatic driver_t bnxt_iflib_driver = { 271308696Sshurd "bnxt", bnxt_iflib_methods, sizeof(struct bnxt_softc) 272308696Sshurd}; 273308696Sshurd 274308696Sshurd/* 275308696Sshurd * iflib shared context 276308696Sshurd */ 277308696Sshurd 278309377Sshurdchar bnxt_driver_version[] = "FreeBSD base"; 279308696Sshurdextern struct if_txrx bnxt_txrx; 280308696Sshurdstatic struct if_shared_ctx bnxt_sctx_init = { 281308696Sshurd .isc_magic = IFLIB_MAGIC, 282308696Sshurd .isc_txrx = &bnxt_txrx, 283308696Sshurd .isc_driver = &bnxt_iflib_driver, 284308696Sshurd .isc_nfl = 2, // Number of Free Lists 285308696Sshurd .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ, 286308696Sshurd .isc_q_align = PAGE_SIZE, 287308696Sshurd .isc_tx_maxsize = BNXT_TSO_SIZE, 288308696Sshurd .isc_tx_maxsegsize = BNXT_TSO_SIZE, 289308696Sshurd .isc_rx_maxsize = BNXT_TSO_SIZE, 290308696Sshurd .isc_rx_maxsegsize = BNXT_TSO_SIZE, 291308696Sshurd 292308696Sshurd // Only use a single segment to avoid page size constraints 293308696Sshurd .isc_rx_nsegments = 1, 294308696Sshurd .isc_ntxqs = 2, 295308696Sshurd .isc_nrxqs = 3, 296308696Sshurd .isc_nrxd_min = {16, 16, 16}, 297308696Sshurd .isc_nrxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 8, 298308696Sshurd PAGE_SIZE / sizeof(struct rx_prod_pkt_bd), 299308696Sshurd PAGE_SIZE / sizeof(struct rx_prod_pkt_bd)}, 300308696Sshurd .isc_nrxd_max = {INT32_MAX, INT32_MAX, INT32_MAX}, 301308696Sshurd .isc_ntxd_min = {16, 16, 16}, 302308696Sshurd .isc_ntxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 2, 303308696Sshurd PAGE_SIZE / sizeof(struct tx_bd_short)}, 304308696Sshurd .isc_ntxd_max = {INT32_MAX, INT32_MAX, INT32_MAX}, 305308696Sshurd 306308696Sshurd .isc_admin_intrcnt = 1, 307308696Sshurd .isc_vendor_info = bnxt_vendor_info_array, 308308696Sshurd .isc_driver_version = bnxt_driver_version, 309308696Sshurd}; 310308696Sshurd 311308696Sshurdif_shared_ctx_t bnxt_sctx = &bnxt_sctx_init; 312308696Sshurd 313308696Sshurd/* 314308696Sshurd * Device Methods 315308696Sshurd */ 316308696Sshurd 317308696Sshurdstatic void * 318308696Sshurdbnxt_register(device_t dev) 319308696Sshurd{ 320308696Sshurd return bnxt_sctx; 321308696Sshurd} 322308696Sshurd 323308696Sshurd/* 324308696Sshurd * Device Dependent Configuration Functions 325308696Sshurd*/ 326308696Sshurd 327308696Sshurd/* Soft queue setup and teardown */ 328308696Sshurdstatic int 329308696Sshurdbnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 330308696Sshurd uint64_t *paddrs, int ntxqs, int ntxqsets) 331308696Sshurd{ 332308696Sshurd struct bnxt_softc *softc; 333308696Sshurd int i; 334308696Sshurd int rc; 335308696Sshurd 336308696Sshurd softc = iflib_get_softc(ctx); 337308696Sshurd 338308696Sshurd softc->tx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * ntxqsets, 339308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 340308696Sshurd if (!softc->tx_cp_rings) { 341308696Sshurd device_printf(iflib_get_dev(ctx), 342308696Sshurd "unable to allocate TX completion rings\n"); 343308696Sshurd rc = ENOMEM; 344308696Sshurd goto cp_alloc_fail; 345308696Sshurd } 346308696Sshurd softc->tx_rings = malloc(sizeof(struct bnxt_ring) * ntxqsets, 347308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 348308696Sshurd if (!softc->tx_rings) { 349308696Sshurd device_printf(iflib_get_dev(ctx), 350308696Sshurd "unable to allocate TX rings\n"); 351308696Sshurd rc = ENOMEM; 352308696Sshurd goto ring_alloc_fail; 353308696Sshurd } 354308696Sshurd rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * ntxqsets, 355308696Sshurd &softc->tx_stats, 0); 356308696Sshurd if (rc) 357308696Sshurd goto dma_alloc_fail; 358308696Sshurd bus_dmamap_sync(softc->tx_stats.idi_tag, softc->tx_stats.idi_map, 359308696Sshurd BUS_DMASYNC_PREREAD); 360308696Sshurd 361308696Sshurd for (i = 0; i < ntxqsets; i++) { 362308696Sshurd /* Set up the completion ring */ 363308696Sshurd softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; 364308696Sshurd softc->tx_cp_rings[i].ring.phys_id = 365308696Sshurd (uint16_t)HWRM_NA_SIGNATURE; 366308696Sshurd softc->tx_cp_rings[i].ring.softc = softc; 367308696Sshurd softc->tx_cp_rings[i].ring.id = 368308696Sshurd (softc->scctx->isc_nrxqsets * 2) + 1 + i; 369308696Sshurd softc->tx_cp_rings[i].ring.doorbell = 370308696Sshurd softc->tx_cp_rings[i].ring.id * 0x80; 371308696Sshurd softc->tx_cp_rings[i].ring.ring_size = 372308696Sshurd softc->scctx->isc_ntxd[0]; 373308696Sshurd softc->tx_cp_rings[i].ring.vaddr = vaddrs[i * ntxqs]; 374308696Sshurd softc->tx_cp_rings[i].ring.paddr = paddrs[i * ntxqs]; 375308696Sshurd 376308696Sshurd /* Set up the TX ring */ 377308696Sshurd softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 378308696Sshurd softc->tx_rings[i].softc = softc; 379308696Sshurd softc->tx_rings[i].id = 380308696Sshurd (softc->scctx->isc_nrxqsets * 2) + 1 + i; 381308696Sshurd softc->tx_rings[i].doorbell = softc->tx_rings[i].id * 0x80; 382308696Sshurd softc->tx_rings[i].ring_size = softc->scctx->isc_ntxd[1]; 383308696Sshurd softc->tx_rings[i].vaddr = vaddrs[i * ntxqs + 1]; 384308696Sshurd softc->tx_rings[i].paddr = paddrs[i * ntxqs + 1]; 385308696Sshurd 386308696Sshurd bnxt_create_tx_sysctls(softc, i); 387308696Sshurd } 388308696Sshurd 389308696Sshurd softc->ntxqsets = ntxqsets; 390308696Sshurd return rc; 391308696Sshurd 392308696Sshurddma_alloc_fail: 393308696Sshurd free(softc->tx_rings, M_DEVBUF); 394308696Sshurdring_alloc_fail: 395308696Sshurd free(softc->tx_cp_rings, M_DEVBUF); 396308696Sshurdcp_alloc_fail: 397308696Sshurd return rc; 398308696Sshurd} 399308696Sshurd 400308696Sshurdstatic void 401308696Sshurdbnxt_queues_free(if_ctx_t ctx) 402308696Sshurd{ 403308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 404308696Sshurd 405308696Sshurd // Free TX queues 406308696Sshurd iflib_dma_free(&softc->tx_stats); 407308696Sshurd free(softc->tx_rings, M_DEVBUF); 408308696Sshurd softc->tx_rings = NULL; 409308696Sshurd free(softc->tx_cp_rings, M_DEVBUF); 410308696Sshurd softc->tx_cp_rings = NULL; 411308696Sshurd softc->ntxqsets = 0; 412308696Sshurd 413308696Sshurd // Free RX queues 414308696Sshurd iflib_dma_free(&softc->rx_stats); 415308696Sshurd free(softc->grp_info, M_DEVBUF); 416308696Sshurd free(softc->ag_rings, M_DEVBUF); 417308696Sshurd free(softc->rx_rings, M_DEVBUF); 418308696Sshurd free(softc->rx_cp_rings, M_DEVBUF); 419308696Sshurd} 420308696Sshurd 421308696Sshurdstatic int 422308696Sshurdbnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 423308696Sshurd uint64_t *paddrs, int nrxqs, int nrxqsets) 424308696Sshurd{ 425308696Sshurd struct bnxt_softc *softc; 426308696Sshurd int i; 427308696Sshurd int rc; 428308696Sshurd 429308696Sshurd softc = iflib_get_softc(ctx); 430308696Sshurd 431308696Sshurd softc->rx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * nrxqsets, 432308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 433308696Sshurd if (!softc->rx_cp_rings) { 434308696Sshurd device_printf(iflib_get_dev(ctx), 435308696Sshurd "unable to allocate RX completion rings\n"); 436308696Sshurd rc = ENOMEM; 437308696Sshurd goto cp_alloc_fail; 438308696Sshurd } 439308696Sshurd softc->rx_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets, 440308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 441308696Sshurd if (!softc->rx_rings) { 442308696Sshurd device_printf(iflib_get_dev(ctx), 443308696Sshurd "unable to allocate RX rings\n"); 444308696Sshurd rc = ENOMEM; 445308696Sshurd goto ring_alloc_fail; 446308696Sshurd } 447308696Sshurd softc->ag_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets, 448308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 449308696Sshurd if (!softc->ag_rings) { 450308696Sshurd device_printf(iflib_get_dev(ctx), 451308696Sshurd "unable to allocate aggregation rings\n"); 452308696Sshurd rc = ENOMEM; 453308696Sshurd goto ag_alloc_fail; 454308696Sshurd } 455308696Sshurd softc->grp_info = malloc(sizeof(struct bnxt_grp_info) * nrxqsets, 456308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 457308696Sshurd if (!softc->grp_info) { 458308696Sshurd device_printf(iflib_get_dev(ctx), 459308696Sshurd "unable to allocate ring groups\n"); 460308696Sshurd rc = ENOMEM; 461308696Sshurd goto grp_alloc_fail; 462308696Sshurd } 463308696Sshurd 464308696Sshurd rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * nrxqsets, 465308696Sshurd &softc->rx_stats, 0); 466308696Sshurd if (rc) 467308696Sshurd goto hw_stats_alloc_fail; 468308696Sshurd bus_dmamap_sync(softc->rx_stats.idi_tag, softc->rx_stats.idi_map, 469308696Sshurd BUS_DMASYNC_PREREAD); 470308696Sshurd 471308696Sshurd for (i = 0; i < nrxqsets; i++) { 472308696Sshurd /* Allocation the completion ring */ 473308696Sshurd softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; 474308696Sshurd softc->rx_cp_rings[i].ring.phys_id = 475308696Sshurd (uint16_t)HWRM_NA_SIGNATURE; 476308696Sshurd softc->rx_cp_rings[i].ring.softc = softc; 477308696Sshurd softc->rx_cp_rings[i].ring.id = i + 1; 478308696Sshurd softc->rx_cp_rings[i].ring.doorbell = 479308696Sshurd softc->rx_cp_rings[i].ring.id * 0x80; 480308696Sshurd /* 481308696Sshurd * If this ring overflows, RX stops working. 482308696Sshurd */ 483308696Sshurd softc->rx_cp_rings[i].ring.ring_size = 484308696Sshurd softc->scctx->isc_nrxd[0]; 485308696Sshurd softc->rx_cp_rings[i].ring.vaddr = vaddrs[i * nrxqs]; 486308696Sshurd softc->rx_cp_rings[i].ring.paddr = paddrs[i * nrxqs]; 487308696Sshurd 488308696Sshurd /* Allocate the RX ring */ 489308696Sshurd softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 490308696Sshurd softc->rx_rings[i].softc = softc; 491308696Sshurd softc->rx_rings[i].id = i + 1; 492308696Sshurd softc->rx_rings[i].doorbell = softc->rx_rings[i].id * 0x80; 493308696Sshurd softc->rx_rings[i].ring_size = softc->scctx->isc_nrxd[1]; 494308696Sshurd softc->rx_rings[i].vaddr = vaddrs[i * nrxqs + 1]; 495308696Sshurd softc->rx_rings[i].paddr = paddrs[i * nrxqs + 1]; 496308696Sshurd 497308696Sshurd /* Allocate the AG ring */ 498308696Sshurd softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 499308696Sshurd softc->ag_rings[i].softc = softc; 500308696Sshurd softc->ag_rings[i].id = nrxqsets + i + 1; 501308696Sshurd softc->ag_rings[i].doorbell = softc->ag_rings[i].id * 0x80; 502308696Sshurd softc->ag_rings[i].ring_size = softc->scctx->isc_nrxd[2]; 503308696Sshurd softc->ag_rings[i].vaddr = vaddrs[i * nrxqs + 2]; 504308696Sshurd softc->ag_rings[i].paddr = paddrs[i * nrxqs + 2]; 505308696Sshurd 506308696Sshurd /* Allocate the ring group */ 507308696Sshurd softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE; 508308696Sshurd softc->grp_info[i].stats_ctx = 509308696Sshurd softc->rx_cp_rings[i].stats_ctx_id; 510308696Sshurd softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id; 511308696Sshurd softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id; 512308696Sshurd softc->grp_info[i].cp_ring_id = 513308696Sshurd softc->rx_cp_rings[i].ring.phys_id; 514308696Sshurd 515308696Sshurd bnxt_create_rx_sysctls(softc, i); 516308696Sshurd } 517308696Sshurd 518308696Sshurd /* And finally, the VNIC */ 519308696Sshurd softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE; 520308696Sshurd softc->vnic_info.flow_id = (uint16_t)HWRM_NA_SIGNATURE; 521308696Sshurd softc->vnic_info.filter_id = -1; 522308696Sshurd softc->vnic_info.def_ring_grp = (uint16_t)HWRM_NA_SIGNATURE; 523308696Sshurd softc->vnic_info.cos_rule = (uint16_t)HWRM_NA_SIGNATURE; 524308696Sshurd softc->vnic_info.lb_rule = (uint16_t)HWRM_NA_SIGNATURE; 525308696Sshurd softc->vnic_info.rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST; 526308696Sshurd softc->vnic_info.mc_list_count = 0; 527308696Sshurd softc->vnic_info.flags = BNXT_VNIC_FLAG_DEFAULT; 528308696Sshurd rc = iflib_dma_alloc(ctx, BNXT_MAX_MC_ADDRS * ETHER_ADDR_LEN, 529308696Sshurd &softc->vnic_info.mc_list, 0); 530308696Sshurd if (rc) 531308696Sshurd goto mc_list_alloc_fail; 532308696Sshurd 533308696Sshurd /* The VNIC RSS Hash Key */ 534308696Sshurd rc = iflib_dma_alloc(ctx, HW_HASH_KEY_SIZE, 535308696Sshurd &softc->vnic_info.rss_hash_key_tbl, 0); 536308696Sshurd if (rc) 537308696Sshurd goto rss_hash_alloc_fail; 538308696Sshurd bus_dmamap_sync(softc->vnic_info.rss_hash_key_tbl.idi_tag, 539308696Sshurd softc->vnic_info.rss_hash_key_tbl.idi_map, 540308696Sshurd BUS_DMASYNC_PREWRITE); 541308696Sshurd memcpy(softc->vnic_info.rss_hash_key_tbl.idi_vaddr, 542308696Sshurd softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE); 543308696Sshurd 544308696Sshurd /* Allocate the RSS tables */ 545308696Sshurd rc = iflib_dma_alloc(ctx, HW_HASH_INDEX_SIZE * sizeof(uint16_t), 546308696Sshurd &softc->vnic_info.rss_grp_tbl, 0); 547308696Sshurd if (rc) 548308696Sshurd goto rss_grp_alloc_fail; 549308696Sshurd bus_dmamap_sync(softc->vnic_info.rss_grp_tbl.idi_tag, 550308696Sshurd softc->vnic_info.rss_grp_tbl.idi_map, 551308696Sshurd BUS_DMASYNC_PREWRITE); 552308696Sshurd memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff, 553308696Sshurd softc->vnic_info.rss_grp_tbl.idi_size); 554308696Sshurd 555308696Sshurd softc->nrxqsets = nrxqsets; 556308696Sshurd return rc; 557308696Sshurd 558308696Sshurdrss_grp_alloc_fail: 559308696Sshurd iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); 560308696Sshurdrss_hash_alloc_fail: 561308696Sshurd iflib_dma_free(&softc->vnic_info.mc_list); 562308696Sshurdmc_list_alloc_fail: 563308696Sshurd iflib_dma_free(&softc->rx_stats); 564308696Sshurdhw_stats_alloc_fail: 565308696Sshurd free(softc->grp_info, M_DEVBUF); 566308696Sshurdgrp_alloc_fail: 567308696Sshurd free(softc->ag_rings, M_DEVBUF); 568308696Sshurdag_alloc_fail: 569308696Sshurd free(softc->rx_rings, M_DEVBUF); 570308696Sshurdring_alloc_fail: 571308696Sshurd free(softc->rx_cp_rings, M_DEVBUF); 572308696Sshurdcp_alloc_fail: 573308696Sshurd return rc; 574308696Sshurd} 575308696Sshurd 576308696Sshurd/* Device setup and teardown */ 577308696Sshurdstatic int 578308696Sshurdbnxt_attach_pre(if_ctx_t ctx) 579308696Sshurd{ 580308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 581308696Sshurd if_softc_ctx_t scctx; 582308696Sshurd int rc = 0; 583308696Sshurd 584308696Sshurd softc->ctx = ctx; 585308696Sshurd softc->dev = iflib_get_dev(ctx); 586308696Sshurd softc->media = iflib_get_media(ctx); 587308696Sshurd softc->scctx = iflib_get_softc_ctx(ctx); 588308696Sshurd softc->sctx = iflib_get_sctx(ctx); 589308696Sshurd scctx = softc->scctx; 590308696Sshurd 591309377Sshurd /* TODO: Better way of detecting NPAR/VF is needed */ 592308696Sshurd switch (softc->sctx->isc_vendor_info->pvi_device_id) { 593308696Sshurd case BCM57402_NPAR: 594308696Sshurd case BCM57404_NPAR: 595308696Sshurd case BCM57406_NPAR: 596309377Sshurd case BCM57407_NPAR: 597309377Sshurd case BCM57412_NPAR1: 598309377Sshurd case BCM57412_NPAR2: 599309377Sshurd case BCM57414_NPAR1: 600309377Sshurd case BCM57414_NPAR2: 601309377Sshurd case BCM57416_NPAR1: 602309377Sshurd case BCM57416_NPAR2: 603308696Sshurd softc->flags |= BNXT_FLAG_NPAR; 604308696Sshurd break; 605309377Sshurd case NETXTREME_C_VF1: 606309377Sshurd case NETXTREME_C_VF2: 607309377Sshurd case NETXTREME_C_VF3: 608309377Sshurd case NETXTREME_E_VF1: 609309377Sshurd case NETXTREME_E_VF2: 610309377Sshurd case NETXTREME_E_VF3: 611308696Sshurd softc->flags |= BNXT_FLAG_VF; 612308696Sshurd break; 613308696Sshurd } 614308696Sshurd 615308696Sshurd pci_enable_busmaster(softc->dev); 616308696Sshurd 617308696Sshurd if (bnxt_pci_mapping(softc)) 618308696Sshurd return (ENXIO); 619308696Sshurd 620308696Sshurd /* HWRM setup/init */ 621308696Sshurd BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev)); 622308696Sshurd rc = bnxt_alloc_hwrm_dma_mem(softc); 623308696Sshurd if (rc) 624308696Sshurd goto dma_fail; 625308696Sshurd 626308696Sshurd /* Allocate the TPA start buffer */ 627308696Sshurd softc->tpa_start = malloc(sizeof(struct bnxt_full_tpa_start) * 628308696Sshurd (RX_TPA_START_CMPL_AGG_ID_MASK >> RX_TPA_START_CMPL_AGG_ID_SFT), 629308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 630308696Sshurd if (softc->tpa_start == NULL) { 631308696Sshurd rc = ENOMEM; 632308696Sshurd device_printf(softc->dev, 633308696Sshurd "Unable to allocate space for TPA\n"); 634308696Sshurd goto tpa_failed; 635308696Sshurd } 636308696Sshurd 637308696Sshurd /* Get firmware version and compare with driver */ 638308696Sshurd softc->ver_info = malloc(sizeof(struct bnxt_ver_info), 639308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 640308696Sshurd if (softc->ver_info == NULL) { 641308696Sshurd rc = ENOMEM; 642308696Sshurd device_printf(softc->dev, 643308696Sshurd "Unable to allocate space for version info\n"); 644308696Sshurd goto ver_alloc_fail; 645308696Sshurd } 646308696Sshurd /* Default minimum required HWRM version */ 647308696Sshurd softc->ver_info->hwrm_min_major = 1; 648308696Sshurd softc->ver_info->hwrm_min_minor = 2; 649308696Sshurd softc->ver_info->hwrm_min_update = 2; 650308696Sshurd 651308696Sshurd rc = bnxt_hwrm_ver_get(softc); 652308696Sshurd if (rc) { 653308696Sshurd device_printf(softc->dev, "attach: hwrm ver get failed\n"); 654308696Sshurd goto ver_fail; 655308696Sshurd } 656308696Sshurd 657308696Sshurd /* Get NVRAM info */ 658308696Sshurd softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info), 659308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 660308696Sshurd if (softc->nvm_info == NULL) { 661308696Sshurd rc = ENOMEM; 662308696Sshurd device_printf(softc->dev, 663308696Sshurd "Unable to allocate space for NVRAM info\n"); 664308696Sshurd goto nvm_alloc_fail; 665308696Sshurd } 666308696Sshurd rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id, 667308696Sshurd &softc->nvm_info->device_id, &softc->nvm_info->sector_size, 668308696Sshurd &softc->nvm_info->size, &softc->nvm_info->reserved_size, 669308696Sshurd &softc->nvm_info->available_size); 670308696Sshurd 671308696Sshurd /* Register the driver with the FW */ 672308696Sshurd rc = bnxt_hwrm_func_drv_rgtr(softc); 673308696Sshurd if (rc) { 674308696Sshurd device_printf(softc->dev, "attach: hwrm drv rgtr failed\n"); 675308696Sshurd goto drv_rgtr_fail; 676308696Sshurd } 677308696Sshurd 678308696Sshurd /* Get the HW capabilities */ 679308696Sshurd rc = bnxt_hwrm_func_qcaps(softc); 680308696Sshurd if (rc) 681308696Sshurd goto failed; 682308696Sshurd iflib_set_mac(ctx, softc->func.mac_addr); 683308696Sshurd 684308696Sshurd /* Get the queue config */ 685308696Sshurd rc = bnxt_hwrm_queue_qportcfg(softc); 686308696Sshurd if (rc) { 687308696Sshurd device_printf(softc->dev, "attach: hwrm qportcfg failed\n"); 688308696Sshurd goto failed; 689308696Sshurd } 690308696Sshurd 691308696Sshurd /* Now perform a function reset */ 692308696Sshurd rc = bnxt_hwrm_func_reset(softc); 693308696Sshurd bnxt_clear_ids(softc); 694308696Sshurd if (rc) 695308696Sshurd goto failed; 696308696Sshurd 697308696Sshurd /* Now set up iflib sc */ 698308696Sshurd scctx->isc_tx_nsegments = 31, 699308696Sshurd scctx->isc_tx_tso_segments_max = 31; 700308696Sshurd scctx->isc_tx_tso_size_max = BNXT_TSO_SIZE; 701308696Sshurd scctx->isc_tx_tso_segsize_max = BNXT_TSO_SIZE; 702308696Sshurd scctx->isc_vectors = softc->func.max_cp_rings; 703308696Sshurd if (scctx->isc_nrxd[0] < 704308696Sshurd ((scctx->isc_nrxd[1] * 4) + scctx->isc_nrxd[2])) 705308696Sshurd device_printf(softc->dev, 706308696Sshurd "WARNING: nrxd0 (%d) should be at least 4 * nrxd1 (%d) + nrxd2 (%d). Driver may be unstable\n", 707308696Sshurd scctx->isc_nrxd[0], scctx->isc_nrxd[1], scctx->isc_nrxd[2]); 708308696Sshurd if (scctx->isc_ntxd[0] < scctx->isc_ntxd[1] * 2) 709308696Sshurd device_printf(softc->dev, 710308696Sshurd "WARNING: ntxd0 (%d) should be at least 2 * ntxd1 (%d). Driver may be unstable\n", 711308696Sshurd scctx->isc_ntxd[0], scctx->isc_ntxd[1]); 712308696Sshurd scctx->isc_txqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_ntxd[0]; 713308696Sshurd scctx->isc_txqsizes[1] = sizeof(struct tx_bd_short) * 714308696Sshurd scctx->isc_ntxd[1]; 715308696Sshurd scctx->isc_rxqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_nrxd[0]; 716308696Sshurd scctx->isc_rxqsizes[1] = sizeof(struct rx_prod_pkt_bd) * 717308696Sshurd scctx->isc_nrxd[1]; 718308696Sshurd scctx->isc_rxqsizes[2] = sizeof(struct rx_prod_pkt_bd) * 719308696Sshurd scctx->isc_nrxd[2]; 720308696Sshurd scctx->isc_max_rxqsets = min(pci_msix_count(softc->dev)-1, 721308696Sshurd softc->func.max_cp_rings - 1); 722308696Sshurd scctx->isc_max_rxqsets = min(scctx->isc_max_rxqsets, 723308696Sshurd softc->func.max_rx_rings); 724308696Sshurd scctx->isc_max_txqsets = min(softc->func.max_rx_rings, 725308696Sshurd softc->func.max_cp_rings - scctx->isc_max_rxqsets - 1); 726308696Sshurd scctx->isc_rss_table_size = HW_HASH_INDEX_SIZE; 727308696Sshurd scctx->isc_rss_table_mask = scctx->isc_rss_table_size - 1; 728308696Sshurd 729308696Sshurd /* iflib will map and release this bar */ 730308696Sshurd scctx->isc_msix_bar = pci_msix_table_bar(softc->dev); 731308696Sshurd 732308696Sshurd /* Allocate the default completion ring */ 733308696Sshurd softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE; 734308696Sshurd softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; 735308696Sshurd softc->def_cp_ring.ring.softc = softc; 736308696Sshurd softc->def_cp_ring.ring.id = 0; 737308696Sshurd softc->def_cp_ring.ring.doorbell = softc->def_cp_ring.ring.id * 0x80; 738308696Sshurd softc->def_cp_ring.ring.ring_size = PAGE_SIZE / 739308696Sshurd sizeof(struct cmpl_base); 740308696Sshurd rc = iflib_dma_alloc(ctx, 741308696Sshurd sizeof(struct cmpl_base) * softc->def_cp_ring.ring.ring_size, 742308696Sshurd &softc->def_cp_ring_mem, 0); 743308696Sshurd softc->def_cp_ring.ring.vaddr = softc->def_cp_ring_mem.idi_vaddr; 744308696Sshurd softc->def_cp_ring.ring.paddr = softc->def_cp_ring_mem.idi_paddr; 745308696Sshurd iflib_config_gtask_init(ctx, &softc->def_cp_task, bnxt_def_cp_task, 746308696Sshurd "dflt_cp"); 747308696Sshurd 748308696Sshurd rc = bnxt_init_sysctl_ctx(softc); 749308696Sshurd if (rc) 750308696Sshurd goto init_sysctl_failed; 751308696Sshurd rc = bnxt_create_nvram_sysctls(softc->nvm_info); 752308696Sshurd if (rc) 753308696Sshurd goto failed; 754308696Sshurd 755308696Sshurd arc4rand(softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE, 0); 756308696Sshurd softc->vnic_info.rss_hash_type = 757308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 | 758308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 | 759308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 | 760308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 | 761308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 | 762308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6; 763308696Sshurd rc = bnxt_create_config_sysctls_pre(softc); 764308696Sshurd if (rc) 765308696Sshurd goto failed; 766308696Sshurd 767308696Sshurd /* Initialize the vlan list */ 768308696Sshurd SLIST_INIT(&softc->vnic_info.vlan_tags); 769308696Sshurd softc->vnic_info.vlan_tag_list.idi_vaddr = NULL; 770308696Sshurd 771308696Sshurd return (rc); 772308696Sshurd 773308696Sshurdfailed: 774308696Sshurd bnxt_free_sysctl_ctx(softc); 775308696Sshurdinit_sysctl_failed: 776308696Sshurd bnxt_hwrm_func_drv_unrgtr(softc, false); 777308696Sshurddrv_rgtr_fail: 778308696Sshurd free(softc->nvm_info, M_DEVBUF); 779308696Sshurdnvm_alloc_fail: 780308696Sshurdver_fail: 781308696Sshurd free(softc->ver_info, M_DEVBUF); 782308696Sshurdver_alloc_fail: 783308696Sshurd free(softc->tpa_start, M_DEVBUF); 784308696Sshurdtpa_failed: 785308696Sshurd bnxt_free_hwrm_dma_mem(softc); 786308696Sshurddma_fail: 787308696Sshurd BNXT_HWRM_LOCK_DESTROY(softc); 788308696Sshurd bnxt_pci_mapping_free(softc); 789308696Sshurd pci_disable_busmaster(softc->dev); 790308696Sshurd return (rc); 791308696Sshurd} 792308696Sshurd 793308696Sshurdstatic int 794308696Sshurdbnxt_attach_post(if_ctx_t ctx) 795308696Sshurd{ 796308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 797308696Sshurd if_t ifp = iflib_get_ifp(ctx); 798308696Sshurd int capabilities, enabling; 799308696Sshurd int rc; 800308696Sshurd 801308696Sshurd bnxt_create_config_sysctls_post(softc); 802308696Sshurd 803308696Sshurd /* Update link state etc... */ 804308696Sshurd rc = bnxt_probe_phy(softc); 805308696Sshurd if (rc) 806308696Sshurd goto failed; 807308696Sshurd 808308696Sshurd /* Needs to be done after probing the phy */ 809308696Sshurd bnxt_create_ver_sysctls(softc); 810308696Sshurd bnxt_add_media_types(softc); 811308696Sshurd ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); 812308696Sshurd 813308696Sshurd if_sethwassist(ifp, (CSUM_TCP | CSUM_UDP | CSUM_TCP_IPV6 | 814308696Sshurd CSUM_UDP_IPV6 | CSUM_TSO)); 815308696Sshurd 816308696Sshurd capabilities = 817308696Sshurd /* These are translated to hwassit bits */ 818308696Sshurd IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_TSO4 | IFCAP_TSO6 | 819308696Sshurd /* These are checked by iflib */ 820308696Sshurd IFCAP_LRO | IFCAP_VLAN_HWFILTER | 821308696Sshurd /* These are part of the iflib mask */ 822308696Sshurd IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_VLAN_MTU | 823308696Sshurd IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | 824308696Sshurd /* These likely get lost... */ 825308696Sshurd IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU; 826308696Sshurd 827308696Sshurd if_setcapabilities(ifp, capabilities); 828308696Sshurd 829308696Sshurd enabling = capabilities; 830308696Sshurd 831308696Sshurd if_setcapenable(ifp, enabling); 832308696Sshurd 833308696Sshurd softc->scctx->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + 834308696Sshurd ETHER_CRC_LEN; 835308696Sshurd 836308696Sshurdfailed: 837308696Sshurd return rc; 838308696Sshurd} 839308696Sshurd 840308696Sshurdstatic int 841308696Sshurdbnxt_detach(if_ctx_t ctx) 842308696Sshurd{ 843308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 844308696Sshurd struct bnxt_vlan_tag *tag; 845308696Sshurd struct bnxt_vlan_tag *tmp; 846308696Sshurd int i; 847308696Sshurd 848308696Sshurd bnxt_do_disable_intr(&softc->def_cp_ring); 849308696Sshurd bnxt_free_sysctl_ctx(softc); 850308696Sshurd bnxt_hwrm_func_reset(softc); 851308696Sshurd bnxt_clear_ids(softc); 852308696Sshurd iflib_irq_free(ctx, &softc->def_cp_ring.irq); 853308696Sshurd iflib_config_gtask_deinit(&softc->def_cp_task); 854308696Sshurd /* We need to free() these here... */ 855308696Sshurd for (i = softc->nrxqsets-1; i>=0; i--) { 856308696Sshurd iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); 857308696Sshurd } 858308696Sshurd iflib_dma_free(&softc->vnic_info.mc_list); 859308696Sshurd iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); 860308696Sshurd iflib_dma_free(&softc->vnic_info.rss_grp_tbl); 861308696Sshurd if (softc->vnic_info.vlan_tag_list.idi_vaddr) 862308696Sshurd iflib_dma_free(&softc->vnic_info.vlan_tag_list); 863308696Sshurd SLIST_FOREACH_SAFE(tag, &softc->vnic_info.vlan_tags, next, tmp) 864308696Sshurd free(tag, M_DEVBUF); 865308696Sshurd iflib_dma_free(&softc->def_cp_ring_mem); 866308696Sshurd free(softc->tpa_start, M_DEVBUF); 867308696Sshurd free(softc->ver_info, M_DEVBUF); 868308696Sshurd free(softc->nvm_info, M_DEVBUF); 869308696Sshurd 870308696Sshurd bnxt_hwrm_func_drv_unrgtr(softc, false); 871308696Sshurd bnxt_free_hwrm_dma_mem(softc); 872308696Sshurd BNXT_HWRM_LOCK_DESTROY(softc); 873308696Sshurd 874308696Sshurd pci_disable_busmaster(softc->dev); 875308696Sshurd bnxt_pci_mapping_free(softc); 876308696Sshurd 877308696Sshurd return 0; 878308696Sshurd} 879308696Sshurd 880308696Sshurd/* Device configuration */ 881308696Sshurdstatic void 882308696Sshurdbnxt_init(if_ctx_t ctx) 883308696Sshurd{ 884308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 885309377Sshurd struct ifmediareq ifmr; 886308696Sshurd int i, j; 887308696Sshurd int rc; 888308696Sshurd 889308696Sshurd rc = bnxt_hwrm_func_reset(softc); 890308696Sshurd if (rc) 891308696Sshurd return; 892308696Sshurd bnxt_clear_ids(softc); 893308696Sshurd 894308696Sshurd /* Allocate the default completion ring */ 895308696Sshurd softc->def_cp_ring.cons = UINT32_MAX; 896308696Sshurd softc->def_cp_ring.v_bit = 1; 897308696Sshurd bnxt_mark_cpr_invalid(&softc->def_cp_ring); 898308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 899308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, 900308696Sshurd &softc->def_cp_ring.ring, 901308696Sshurd (uint16_t)HWRM_NA_SIGNATURE, 902308696Sshurd HWRM_NA_SIGNATURE, true); 903308696Sshurd if (rc) 904308696Sshurd goto fail; 905308696Sshurd 906308696Sshurd /* And now set the default CP ring as the async CP ring */ 907308696Sshurd rc = bnxt_hwrm_func_cfg(softc); 908308696Sshurd if (rc) 909308696Sshurd goto fail; 910308696Sshurd 911308696Sshurd for (i = 0; i < softc->nrxqsets; i++) { 912308696Sshurd /* Allocate the statistics context */ 913308696Sshurd rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i], 914308696Sshurd softc->rx_stats.idi_paddr + 915308696Sshurd (sizeof(struct ctx_hw_stats) * i)); 916308696Sshurd if (rc) 917308696Sshurd goto fail; 918308696Sshurd 919308696Sshurd /* Allocate the completion ring */ 920308696Sshurd softc->rx_cp_rings[i].cons = UINT32_MAX; 921308696Sshurd softc->rx_cp_rings[i].v_bit = 1; 922308696Sshurd softc->rx_cp_rings[i].last_idx = UINT32_MAX; 923308696Sshurd bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]); 924308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 925308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, 926308696Sshurd &softc->rx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, 927308696Sshurd HWRM_NA_SIGNATURE, true); 928308696Sshurd if (rc) 929308696Sshurd goto fail; 930308696Sshurd 931308696Sshurd /* Allocate the RX ring */ 932308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 933308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, 934308696Sshurd &softc->rx_rings[i], (uint16_t)HWRM_NA_SIGNATURE, 935308696Sshurd HWRM_NA_SIGNATURE, false); 936308696Sshurd if (rc) 937308696Sshurd goto fail; 938308696Sshurd BNXT_RX_DB(&softc->rx_rings[i], 0); 939308696Sshurd /* TODO: Cumulus+ doesn't need the double doorbell */ 940308696Sshurd BNXT_RX_DB(&softc->rx_rings[i], 0); 941308696Sshurd 942308696Sshurd /* Allocate the AG ring */ 943308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 944308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, 945308696Sshurd &softc->ag_rings[i], (uint16_t)HWRM_NA_SIGNATURE, 946308696Sshurd HWRM_NA_SIGNATURE, false); 947308696Sshurd if (rc) 948308696Sshurd goto fail; 949308696Sshurd BNXT_RX_DB(&softc->rx_rings[i], 0); 950308696Sshurd /* TODO: Cumulus+ doesn't need the double doorbell */ 951308696Sshurd BNXT_RX_DB(&softc->ag_rings[i], 0); 952308696Sshurd 953308696Sshurd /* Allocate the ring group */ 954308696Sshurd softc->grp_info[i].stats_ctx = 955308696Sshurd softc->rx_cp_rings[i].stats_ctx_id; 956308696Sshurd softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id; 957308696Sshurd softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id; 958308696Sshurd softc->grp_info[i].cp_ring_id = 959308696Sshurd softc->rx_cp_rings[i].ring.phys_id; 960308696Sshurd rc = bnxt_hwrm_ring_grp_alloc(softc, &softc->grp_info[i]); 961308696Sshurd if (rc) 962308696Sshurd goto fail; 963308696Sshurd 964308696Sshurd } 965308696Sshurd 966308696Sshurd /* Allocate the VNIC RSS context */ 967308696Sshurd rc = bnxt_hwrm_vnic_ctx_alloc(softc, &softc->vnic_info.rss_id); 968308696Sshurd if (rc) 969308696Sshurd goto fail; 970308696Sshurd 971308696Sshurd /* Allocate the vnic */ 972308696Sshurd softc->vnic_info.def_ring_grp = softc->grp_info[0].grp_id; 973308696Sshurd softc->vnic_info.mru = softc->scctx->isc_max_frame_size; 974308696Sshurd rc = bnxt_hwrm_vnic_alloc(softc, &softc->vnic_info); 975308696Sshurd if (rc) 976308696Sshurd goto fail; 977308696Sshurd rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info); 978308696Sshurd if (rc) 979308696Sshurd goto fail; 980308696Sshurd rc = bnxt_hwrm_set_filter(softc, &softc->vnic_info); 981308696Sshurd if (rc) 982308696Sshurd goto fail; 983308696Sshurd 984308696Sshurd /* Enable RSS on the VNICs */ 985308696Sshurd for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) { 986308696Sshurd ((uint16_t *) 987308696Sshurd softc->vnic_info.rss_grp_tbl.idi_vaddr)[i] = 988308696Sshurd htole16(softc->grp_info[j].grp_id); 989308696Sshurd if (++j == softc->nrxqsets) 990308696Sshurd j = 0; 991308696Sshurd } 992308696Sshurd 993308696Sshurd rc = bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, 994308696Sshurd softc->vnic_info.rss_hash_type); 995308696Sshurd if (rc) 996308696Sshurd goto fail; 997308696Sshurd 998308696Sshurd#ifdef notyet 999308696Sshurd /* Enable LRO/TPA/GRO */ 1000308696Sshurd rc = bnxt_hwrm_vnic_tpa_cfg(softc, &softc->vnic_info, 1001308696Sshurd (if_getcapenable(iflib_get_ifp(ctx)) & IFCAP_LRO) ? 1002308696Sshurd HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA : 0); 1003308696Sshurd if (rc) 1004308696Sshurd goto fail; 1005308696Sshurd#endif 1006308696Sshurd 1007308696Sshurd for (i = 0; i < softc->ntxqsets; i++) { 1008308696Sshurd /* Allocate the statistics context */ 1009308696Sshurd rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->tx_cp_rings[i], 1010308696Sshurd softc->tx_stats.idi_paddr + 1011308696Sshurd (sizeof(struct ctx_hw_stats) * i)); 1012308696Sshurd if (rc) 1013308696Sshurd goto fail; 1014308696Sshurd 1015308696Sshurd /* Allocate the completion ring */ 1016308696Sshurd softc->tx_cp_rings[i].cons = UINT32_MAX; 1017308696Sshurd softc->tx_cp_rings[i].v_bit = 1; 1018308696Sshurd bnxt_mark_cpr_invalid(&softc->tx_cp_rings[i]); 1019308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 1020308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL, 1021308696Sshurd &softc->tx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, 1022308696Sshurd HWRM_NA_SIGNATURE, false); 1023308696Sshurd if (rc) 1024308696Sshurd goto fail; 1025308696Sshurd 1026308696Sshurd /* Allocate the TX ring */ 1027308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 1028308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_TX, 1029308696Sshurd &softc->tx_rings[i], softc->tx_cp_rings[i].ring.phys_id, 1030308696Sshurd softc->tx_cp_rings[i].stats_ctx_id, false); 1031308696Sshurd if (rc) 1032308696Sshurd goto fail; 1033308696Sshurd BNXT_TX_DB(&softc->tx_rings[i], 0); 1034308696Sshurd /* TODO: Cumulus+ doesn't need the double doorbell */ 1035308696Sshurd BNXT_TX_DB(&softc->tx_rings[i], 0); 1036308696Sshurd } 1037308696Sshurd 1038308696Sshurd bnxt_do_enable_intr(&softc->def_cp_ring); 1039309377Sshurd bnxt_media_status(softc->ctx, &ifmr); 1040308696Sshurd return; 1041308696Sshurd 1042308696Sshurdfail: 1043308696Sshurd bnxt_hwrm_func_reset(softc); 1044308696Sshurd bnxt_clear_ids(softc); 1045308696Sshurd return; 1046308696Sshurd} 1047308696Sshurd 1048308696Sshurdstatic void 1049308696Sshurdbnxt_stop(if_ctx_t ctx) 1050308696Sshurd{ 1051308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1052308696Sshurd 1053308696Sshurd bnxt_do_disable_intr(&softc->def_cp_ring); 1054308696Sshurd bnxt_hwrm_func_reset(softc); 1055308696Sshurd bnxt_clear_ids(softc); 1056308696Sshurd return; 1057308696Sshurd} 1058308696Sshurd 1059308696Sshurdstatic void 1060308696Sshurdbnxt_multi_set(if_ctx_t ctx) 1061308696Sshurd{ 1062308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1063308696Sshurd if_t ifp = iflib_get_ifp(ctx); 1064308696Sshurd uint8_t *mta; 1065308696Sshurd int cnt, mcnt; 1066308696Sshurd 1067308696Sshurd mcnt = if_multiaddr_count(ifp, -1); 1068308696Sshurd 1069308696Sshurd if (mcnt > BNXT_MAX_MC_ADDRS) { 1070308696Sshurd softc->vnic_info.rx_mask |= 1071308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; 1072308696Sshurd bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); 1073308696Sshurd } 1074308696Sshurd else { 1075308696Sshurd softc->vnic_info.rx_mask &= 1076308696Sshurd ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; 1077308696Sshurd mta = softc->vnic_info.mc_list.idi_vaddr; 1078308696Sshurd bzero(mta, softc->vnic_info.mc_list.idi_size); 1079308696Sshurd if_multiaddr_array(ifp, mta, &cnt, mcnt); 1080308696Sshurd bus_dmamap_sync(softc->vnic_info.mc_list.idi_tag, 1081308696Sshurd softc->vnic_info.mc_list.idi_map, BUS_DMASYNC_PREWRITE); 1082308696Sshurd softc->vnic_info.mc_list_count = cnt; 1083308696Sshurd softc->vnic_info.rx_mask |= 1084308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST; 1085308696Sshurd if (bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info)) 1086308696Sshurd device_printf(softc->dev, 1087308696Sshurd "set_multi: rx_mask set failed\n"); 1088308696Sshurd } 1089308696Sshurd} 1090308696Sshurd 1091308696Sshurdstatic int 1092308696Sshurdbnxt_mtu_set(if_ctx_t ctx, uint32_t mtu) 1093308696Sshurd{ 1094308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1095308696Sshurd 1096308696Sshurd if (mtu > BNXT_MAX_MTU) 1097308696Sshurd return EINVAL; 1098308696Sshurd 1099308696Sshurd softc->scctx->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 1100308696Sshurd return 0; 1101308696Sshurd} 1102308696Sshurd 1103308696Sshurdstatic void 1104308696Sshurdbnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) 1105308696Sshurd{ 1106308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1107308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 1108308696Sshurd uint8_t phy_type = get_phy_type(softc); 1109308696Sshurd 1110308696Sshurd bnxt_update_link(softc, true); 1111308696Sshurd 1112308696Sshurd ifmr->ifm_status = IFM_AVALID; 1113308696Sshurd ifmr->ifm_active = IFM_ETHER; 1114308696Sshurd 1115308696Sshurd if (link_info->link_up) 1116308696Sshurd ifmr->ifm_status |= IFM_ACTIVE; 1117308696Sshurd else 1118308696Sshurd ifmr->ifm_status &= ~IFM_ACTIVE; 1119308696Sshurd 1120308696Sshurd if (link_info->duplex == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL) 1121308696Sshurd ifmr->ifm_active |= IFM_FDX; 1122308696Sshurd else 1123308696Sshurd ifmr->ifm_active |= IFM_HDX; 1124308696Sshurd 1125308696Sshurd switch (link_info->link_speed) { 1126308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB: 1127308696Sshurd ifmr->ifm_active |= IFM_100_T; 1128308696Sshurd break; 1129308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB: 1130308696Sshurd switch (phy_type) { 1131308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: 1132308696Sshurd ifmr->ifm_active |= IFM_1000_KX; 1133308696Sshurd break; 1134308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: 1135308696Sshurd ifmr->ifm_active |= IFM_1000_T; 1136308696Sshurd break; 1137308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: 1138308696Sshurd ifmr->ifm_active |= IFM_1000_SGMII; 1139308696Sshurd break; 1140308696Sshurd default: 1141308696Sshurd ifmr->ifm_active |= IFM_UNKNOWN; 1142308696Sshurd break; 1143308696Sshurd } 1144308696Sshurd break; 1145308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB: 1146308696Sshurd switch (phy_type) { 1147308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: 1148308696Sshurd ifmr->ifm_active |= IFM_2500_KX; 1149308696Sshurd break; 1150308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: 1151308696Sshurd ifmr->ifm_active |= IFM_2500_T; 1152308696Sshurd break; 1153308696Sshurd default: 1154308696Sshurd ifmr->ifm_active |= IFM_UNKNOWN; 1155308696Sshurd break; 1156308696Sshurd } 1157308696Sshurd break; 1158308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB: 1159308696Sshurd switch (phy_type) { 1160308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: 1161308696Sshurd ifmr->ifm_active |= IFM_10G_CR1; 1162308696Sshurd break; 1163308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: 1164308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: 1165308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: 1166308696Sshurd ifmr->ifm_active |= IFM_10G_KR; 1167308696Sshurd break; 1168308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: 1169308696Sshurd ifmr->ifm_active |= IFM_10G_LR; 1170308696Sshurd break; 1171308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: 1172308696Sshurd ifmr->ifm_active |= IFM_10G_SR; 1173308696Sshurd break; 1174308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: 1175308696Sshurd ifmr->ifm_active |= IFM_10G_KX4; 1176308696Sshurd break; 1177308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: 1178308696Sshurd ifmr->ifm_active |= IFM_10G_T; 1179308696Sshurd break; 1180308696Sshurd default: 1181308696Sshurd ifmr->ifm_active |= IFM_UNKNOWN; 1182308696Sshurd break; 1183308696Sshurd } 1184308696Sshurd break; 1185308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB: 1186308696Sshurd ifmr->ifm_active |= IFM_20G_KR2; 1187308696Sshurd break; 1188308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB: 1189308696Sshurd switch (phy_type) { 1190308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: 1191308696Sshurd ifmr->ifm_active |= IFM_25G_CR; 1192308696Sshurd break; 1193308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: 1194308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: 1195308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: 1196308696Sshurd ifmr->ifm_active |= IFM_25G_KR; 1197308696Sshurd break; 1198308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: 1199308696Sshurd ifmr->ifm_active |= IFM_25G_SR; 1200308696Sshurd break; 1201308696Sshurd default: 1202308696Sshurd ifmr->ifm_active |= IFM_UNKNOWN; 1203308696Sshurd break; 1204308696Sshurd } 1205308696Sshurd break; 1206308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB: 1207308696Sshurd switch (phy_type) { 1208308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: 1209308696Sshurd ifmr->ifm_active |= IFM_40G_CR4; 1210308696Sshurd break; 1211308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: 1212308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: 1213308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: 1214308696Sshurd ifmr->ifm_active |= IFM_40G_KR4; 1215308696Sshurd break; 1216308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: 1217308696Sshurd ifmr->ifm_active |= IFM_40G_LR4; 1218308696Sshurd break; 1219308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: 1220308696Sshurd ifmr->ifm_active |= IFM_40G_SR4; 1221308696Sshurd break; 1222308696Sshurd default: 1223308696Sshurd ifmr->ifm_active |= IFM_UNKNOWN; 1224308696Sshurd break; 1225308696Sshurd } 1226308696Sshurd break; 1227308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: 1228308696Sshurd switch (phy_type) { 1229308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: 1230308696Sshurd ifmr->ifm_active |= IFM_50G_CR2; 1231308696Sshurd break; 1232308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: 1233308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: 1234308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: 1235308696Sshurd ifmr->ifm_active |= IFM_50G_KR2; 1236308696Sshurd break; 1237308696Sshurd default: 1238308696Sshurd ifmr->ifm_active |= IFM_UNKNOWN; 1239308696Sshurd break; 1240308696Sshurd } 1241308696Sshurd break; 1242308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: 1243308696Sshurd switch (phy_type) { 1244308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: 1245308696Sshurd ifmr->ifm_active |= IFM_100G_CR4; 1246308696Sshurd break; 1247308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: 1248308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: 1249308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: 1250308696Sshurd ifmr->ifm_active |= IFM_100G_KR4; 1251308696Sshurd break; 1252308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: 1253308696Sshurd ifmr->ifm_active |= IFM_100G_LR4; 1254308696Sshurd break; 1255308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: 1256308696Sshurd ifmr->ifm_active |= IFM_100G_SR4; 1257308696Sshurd break; 1258308696Sshurd default: 1259308696Sshurd ifmr->ifm_active |= IFM_UNKNOWN; 1260308696Sshurd break; 1261308696Sshurd } 1262308696Sshurd default: 1263308696Sshurd return; 1264308696Sshurd } 1265308696Sshurd 1266308696Sshurd if (link_info->pause == (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | 1267308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) 1268308696Sshurd ifmr->ifm_active |= (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE); 1269308696Sshurd else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) 1270308696Sshurd ifmr->ifm_active |= IFM_ETH_TXPAUSE; 1271308696Sshurd else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) 1272308696Sshurd ifmr->ifm_active |= IFM_ETH_RXPAUSE; 1273308696Sshurd 1274308696Sshurd bnxt_report_link(softc); 1275308696Sshurd return; 1276308696Sshurd} 1277308696Sshurd 1278308696Sshurdstatic int 1279308696Sshurdbnxt_media_change(if_ctx_t ctx) 1280308696Sshurd{ 1281308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1282308696Sshurd struct ifmedia *ifm = iflib_get_media(ctx); 1283308696Sshurd struct ifmediareq ifmr; 1284308696Sshurd int rc; 1285308696Sshurd 1286308696Sshurd if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1287308696Sshurd return EINVAL; 1288308696Sshurd 1289308696Sshurd switch (IFM_SUBTYPE(ifm->ifm_media)) { 1290308696Sshurd case IFM_100_T: 1291308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1292308696Sshurd softc->link_info.req_link_speed = 1293308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100MB; 1294308696Sshurd break; 1295308696Sshurd case IFM_1000_KX: 1296308696Sshurd case IFM_1000_T: 1297308696Sshurd case IFM_1000_SGMII: 1298308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1299308696Sshurd softc->link_info.req_link_speed = 1300308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB; 1301308696Sshurd break; 1302308696Sshurd case IFM_2500_KX: 1303308696Sshurd case IFM_2500_T: 1304308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1305308696Sshurd softc->link_info.req_link_speed = 1306308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2_5GB; 1307308696Sshurd break; 1308308696Sshurd case IFM_10G_CR1: 1309308696Sshurd case IFM_10G_KR: 1310308696Sshurd case IFM_10G_LR: 1311308696Sshurd case IFM_10G_SR: 1312308696Sshurd case IFM_10G_T: 1313308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1314308696Sshurd softc->link_info.req_link_speed = 1315308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB; 1316308696Sshurd break; 1317308696Sshurd case IFM_20G_KR2: 1318308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1319308696Sshurd softc->link_info.req_link_speed = 1320308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_20GB; 1321308696Sshurd break; 1322308696Sshurd case IFM_25G_CR: 1323308696Sshurd case IFM_25G_KR: 1324308696Sshurd case IFM_25G_SR: 1325308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1326308696Sshurd softc->link_info.req_link_speed = 1327308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB; 1328308696Sshurd break; 1329308696Sshurd case IFM_40G_CR4: 1330308696Sshurd case IFM_40G_KR4: 1331308696Sshurd case IFM_40G_LR4: 1332308696Sshurd case IFM_40G_SR4: 1333308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1334308696Sshurd softc->link_info.req_link_speed = 1335308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB; 1336308696Sshurd break; 1337308696Sshurd case IFM_50G_CR2: 1338308696Sshurd case IFM_50G_KR2: 1339308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1340308696Sshurd softc->link_info.req_link_speed = 1341308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB; 1342308696Sshurd break; 1343308696Sshurd case IFM_100G_CR4: 1344308696Sshurd case IFM_100G_KR4: 1345308696Sshurd case IFM_100G_LR4: 1346308696Sshurd case IFM_100G_SR4: 1347308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1348308696Sshurd softc->link_info.req_link_speed = 1349308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB; 1350308696Sshurd break; 1351308696Sshurd default: 1352308696Sshurd device_printf(softc->dev, 1353308696Sshurd "Unsupported media type! Using auto\n"); 1354308696Sshurd /* Fall-through */ 1355308696Sshurd case IFM_AUTO: 1356308696Sshurd // Auto 1357308696Sshurd softc->link_info.autoneg |= BNXT_AUTONEG_SPEED; 1358308696Sshurd break; 1359308696Sshurd } 1360308696Sshurd rc = bnxt_hwrm_set_link_setting(softc, true, true); 1361308696Sshurd bnxt_media_status(softc->ctx, &ifmr); 1362308696Sshurd return rc; 1363308696Sshurd} 1364308696Sshurd 1365308696Sshurdstatic int 1366308696Sshurdbnxt_promisc_set(if_ctx_t ctx, int flags) 1367308696Sshurd{ 1368308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1369308696Sshurd if_t ifp = iflib_get_ifp(ctx); 1370308696Sshurd int rc; 1371308696Sshurd 1372308696Sshurd if (ifp->if_flags & IFF_ALLMULTI || 1373308696Sshurd if_multiaddr_count(ifp, -1) > BNXT_MAX_MC_ADDRS) 1374308696Sshurd softc->vnic_info.rx_mask |= 1375308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; 1376308696Sshurd else 1377308696Sshurd softc->vnic_info.rx_mask &= 1378308696Sshurd ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; 1379308696Sshurd 1380308696Sshurd if (ifp->if_flags & IFF_PROMISC) 1381308696Sshurd softc->vnic_info.rx_mask |= 1382308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS | 1383308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN; 1384308696Sshurd else 1385308696Sshurd softc->vnic_info.rx_mask &= 1386308696Sshurd ~(HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS | 1387308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN); 1388308696Sshurd 1389308696Sshurd rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); 1390308696Sshurd 1391308696Sshurd return rc; 1392308696Sshurd} 1393308696Sshurd 1394308696Sshurdstatic uint64_t 1395308696Sshurdbnxt_get_counter(if_ctx_t ctx, ift_counter cnt) 1396308696Sshurd{ 1397308696Sshurd if_t ifp = iflib_get_ifp(ctx); 1398308696Sshurd 1399308696Sshurd if (cnt < IFCOUNTERS) 1400308696Sshurd return if_get_counter_default(ifp, cnt); 1401308696Sshurd 1402308696Sshurd return 0; 1403308696Sshurd} 1404308696Sshurd 1405308696Sshurdstatic void 1406308696Sshurdbnxt_update_admin_status(if_ctx_t ctx) 1407308696Sshurd{ 1408308696Sshurd /* TODO: do we need to do anything here? */ 1409308696Sshurd return; 1410308696Sshurd} 1411308696Sshurd 1412308696Sshurdstatic void inline 1413308696Sshurdbnxt_do_enable_intr(struct bnxt_cp_ring *cpr) 1414308696Sshurd{ 1415308696Sshurd if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) { 1416308696Sshurd /* First time enabling, do not set index */ 1417308696Sshurd if (cpr->cons == UINT32_MAX) 1418308696Sshurd BNXT_CP_ENABLE_DB(&cpr->ring); 1419308696Sshurd else 1420308696Sshurd BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons); 1421308696Sshurd } 1422308696Sshurd} 1423308696Sshurd 1424308696Sshurdstatic void inline 1425308696Sshurdbnxt_do_disable_intr(struct bnxt_cp_ring *cpr) 1426308696Sshurd{ 1427308696Sshurd if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) 1428308696Sshurd BNXT_CP_DISABLE_DB(&cpr->ring); 1429308696Sshurd} 1430308696Sshurd 1431308696Sshurd/* Enable all interrupts */ 1432308696Sshurdstatic void 1433308696Sshurdbnxt_intr_enable(if_ctx_t ctx) 1434308696Sshurd{ 1435308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1436308696Sshurd int i; 1437308696Sshurd 1438308696Sshurd bnxt_do_enable_intr(&softc->def_cp_ring); 1439308696Sshurd for (i = 0; i < softc->nrxqsets; i++) 1440308696Sshurd bnxt_do_enable_intr(&softc->rx_cp_rings[i]); 1441308696Sshurd 1442308696Sshurd return; 1443308696Sshurd} 1444308696Sshurd 1445308696Sshurd/* Enable interrupt for a single queue */ 1446308696Sshurdstatic int 1447308696Sshurdbnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid) 1448308696Sshurd{ 1449308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1450308696Sshurd 1451308696Sshurd bnxt_do_enable_intr(&softc->rx_cp_rings[qid]); 1452308696Sshurd return 0; 1453308696Sshurd} 1454308696Sshurd 1455308696Sshurd/* Disable all interrupts */ 1456308696Sshurdstatic void 1457308696Sshurdbnxt_disable_intr(if_ctx_t ctx) 1458308696Sshurd{ 1459308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1460308696Sshurd int i; 1461308696Sshurd 1462308696Sshurd /* 1463308696Sshurd * NOTE: These TX interrupts should never get enabled, so don't 1464308696Sshurd * update the index 1465308696Sshurd */ 1466308696Sshurd for (i = 0; i < softc->ntxqsets; i++) 1467308696Sshurd bnxt_do_disable_intr(&softc->tx_cp_rings[i]); 1468308696Sshurd for (i = 0; i < softc->nrxqsets; i++) 1469308696Sshurd bnxt_do_disable_intr(&softc->rx_cp_rings[i]); 1470308696Sshurd 1471308696Sshurd return; 1472308696Sshurd} 1473308696Sshurd 1474308696Sshurdstatic int 1475308696Sshurdbnxt_msix_intr_assign(if_ctx_t ctx, int msix) 1476308696Sshurd{ 1477308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1478308696Sshurd int rc; 1479308696Sshurd int i; 1480308696Sshurd 1481308696Sshurd rc = iflib_irq_alloc_generic(ctx, &softc->def_cp_ring.irq, 1482308696Sshurd softc->def_cp_ring.ring.id + 1, IFLIB_INTR_ADMIN, 1483308696Sshurd bnxt_handle_def_cp, softc, 0, "def_cp"); 1484308696Sshurd if (rc) { 1485308696Sshurd device_printf(iflib_get_dev(ctx), 1486308696Sshurd "Failed to register default completion ring handler\n"); 1487308696Sshurd return rc; 1488308696Sshurd } 1489308696Sshurd 1490308696Sshurd for (i=0; i<softc->scctx->isc_nrxqsets; i++) { 1491308696Sshurd rc = iflib_irq_alloc_generic(ctx, &softc->rx_cp_rings[i].irq, 1492308696Sshurd softc->rx_cp_rings[i].ring.id + 1, IFLIB_INTR_RX, 1493308696Sshurd bnxt_handle_rx_cp, &softc->rx_cp_rings[i], i, "rx_cp"); 1494308696Sshurd if (rc) { 1495308696Sshurd device_printf(iflib_get_dev(ctx), 1496308696Sshurd "Failed to register RX completion ring handler\n"); 1497308696Sshurd i--; 1498308696Sshurd goto fail; 1499308696Sshurd } 1500308696Sshurd } 1501308696Sshurd 1502308696Sshurd for (i=0; i<softc->scctx->isc_ntxqsets; i++) 1503308696Sshurd iflib_softirq_alloc_generic(ctx, i + 1, IFLIB_INTR_TX, NULL, i, 1504308696Sshurd "tx_cp"); 1505308696Sshurd 1506308696Sshurd return rc; 1507308696Sshurd 1508308696Sshurdfail: 1509308696Sshurd for (; i>=0; i--) 1510308696Sshurd iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); 1511308696Sshurd iflib_irq_free(ctx, &softc->def_cp_ring.irq); 1512308696Sshurd return rc; 1513308696Sshurd} 1514308696Sshurd 1515308696Sshurd/* 1516308696Sshurd * We're explicitly allowing duplicates here. They will need to be 1517308696Sshurd * removed as many times as they are added. 1518308696Sshurd */ 1519308696Sshurdstatic void 1520308696Sshurdbnxt_vlan_register(if_ctx_t ctx, uint16_t vtag) 1521308696Sshurd{ 1522308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1523308696Sshurd struct bnxt_vlan_tag *new_tag; 1524308696Sshurd 1525308696Sshurd new_tag = malloc(sizeof(struct bnxt_vlan_tag), M_DEVBUF, M_NOWAIT); 1526308696Sshurd if (new_tag == NULL) 1527308696Sshurd return; 1528308696Sshurd new_tag->tag = vtag; 1529308696Sshurd new_tag->tpid = 8100; 1530308696Sshurd SLIST_INSERT_HEAD(&softc->vnic_info.vlan_tags, new_tag, next); 1531308696Sshurd}; 1532308696Sshurd 1533308696Sshurdstatic void 1534308696Sshurdbnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag) 1535308696Sshurd{ 1536308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1537308696Sshurd struct bnxt_vlan_tag *vlan_tag; 1538308696Sshurd 1539308696Sshurd SLIST_FOREACH(vlan_tag, &softc->vnic_info.vlan_tags, next) { 1540308696Sshurd if (vlan_tag->tag == vtag) { 1541308696Sshurd SLIST_REMOVE(&softc->vnic_info.vlan_tags, vlan_tag, 1542308696Sshurd bnxt_vlan_tag, next); 1543308696Sshurd free(vlan_tag, M_DEVBUF); 1544308696Sshurd break; 1545308696Sshurd } 1546308696Sshurd } 1547308696Sshurd} 1548308696Sshurd 1549308696Sshurdstatic int 1550308696Sshurdbnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data) 1551308696Sshurd{ 1552308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1553308696Sshurd struct ifreq *ifr = (struct ifreq *)data; 1554308696Sshurd struct ifreq_buffer *ifbuf = &ifr->ifr_ifru.ifru_buffer; 1555308696Sshurd struct bnxt_ioctl_header *ioh = 1556308696Sshurd (struct bnxt_ioctl_header *)(ifbuf->buffer); 1557308696Sshurd int rc = ENOTSUP; 1558308696Sshurd struct bnxt_ioctl_data *iod = NULL; 1559308696Sshurd 1560308696Sshurd switch (command) { 1561308696Sshurd case SIOCGPRIVATE_0: 1562308696Sshurd if ((rc = priv_check(curthread, PRIV_DRIVER)) != 0) 1563308696Sshurd goto exit; 1564308696Sshurd 1565308696Sshurd iod = malloc(ifbuf->length, M_DEVBUF, M_NOWAIT | M_ZERO); 1566308696Sshurd if (!iod) { 1567308696Sshurd rc = ENOMEM; 1568308696Sshurd goto exit; 1569308696Sshurd } 1570308696Sshurd copyin(ioh, iod, ifbuf->length); 1571308696Sshurd 1572308696Sshurd switch (ioh->type) { 1573308696Sshurd case BNXT_HWRM_NVM_FIND_DIR_ENTRY: 1574308696Sshurd { 1575308696Sshurd struct bnxt_ioctl_hwrm_nvm_find_dir_entry *find = 1576308696Sshurd &iod->find; 1577308696Sshurd 1578308696Sshurd rc = bnxt_hwrm_nvm_find_dir_entry(softc, find->type, 1579308696Sshurd &find->ordinal, find->ext, &find->index, 1580308696Sshurd find->use_index, find->search_opt, 1581308696Sshurd &find->data_length, &find->item_length, 1582308696Sshurd &find->fw_ver); 1583308696Sshurd if (rc) { 1584308696Sshurd iod->hdr.rc = rc; 1585308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1586308696Sshurd sizeof(ioh->rc)); 1587308696Sshurd } 1588308696Sshurd else { 1589308696Sshurd iod->hdr.rc = 0; 1590308696Sshurd copyout(iod, ioh, ifbuf->length); 1591308696Sshurd } 1592308696Sshurd 1593308696Sshurd rc = 0; 1594308696Sshurd goto exit; 1595308696Sshurd } 1596308696Sshurd case BNXT_HWRM_NVM_READ: 1597308696Sshurd { 1598308696Sshurd struct bnxt_ioctl_hwrm_nvm_read *rd = &iod->read; 1599308696Sshurd struct iflib_dma_info dma_data; 1600308696Sshurd size_t offset; 1601308696Sshurd size_t remain; 1602308696Sshurd size_t csize; 1603308696Sshurd 1604308696Sshurd /* 1605308696Sshurd * Some HWRM versions can't read more than 0x8000 bytes 1606308696Sshurd */ 1607308696Sshurd rc = iflib_dma_alloc(softc->ctx, 1608308696Sshurd min(rd->length, 0x8000), &dma_data, BUS_DMA_NOWAIT); 1609308696Sshurd if (rc) 1610308696Sshurd break; 1611308696Sshurd for (remain = rd->length, offset = 0; 1612308696Sshurd remain && offset < rd->length; offset += 0x8000) { 1613308696Sshurd csize = min(remain, 0x8000); 1614308696Sshurd rc = bnxt_hwrm_nvm_read(softc, rd->index, 1615308696Sshurd rd->offset + offset, csize, &dma_data); 1616308696Sshurd if (rc) { 1617308696Sshurd iod->hdr.rc = rc; 1618308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1619308696Sshurd sizeof(ioh->rc)); 1620308696Sshurd break; 1621308696Sshurd } 1622308696Sshurd else { 1623308696Sshurd copyout(dma_data.idi_vaddr, 1624308696Sshurd rd->data + offset, csize); 1625308696Sshurd iod->hdr.rc = 0; 1626308696Sshurd } 1627308696Sshurd remain -= csize; 1628308696Sshurd } 1629308696Sshurd if (iod->hdr.rc == 0) 1630308696Sshurd copyout(iod, ioh, ifbuf->length); 1631308696Sshurd 1632308696Sshurd iflib_dma_free(&dma_data); 1633308696Sshurd rc = 0; 1634308696Sshurd goto exit; 1635308696Sshurd } 1636308696Sshurd case BNXT_HWRM_FW_RESET: 1637308696Sshurd { 1638308696Sshurd struct bnxt_ioctl_hwrm_fw_reset *rst = 1639308696Sshurd &iod->reset; 1640308696Sshurd 1641308696Sshurd rc = bnxt_hwrm_fw_reset(softc, rst->processor, 1642308696Sshurd &rst->selfreset); 1643308696Sshurd if (rc) { 1644308696Sshurd iod->hdr.rc = rc; 1645308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1646308696Sshurd sizeof(ioh->rc)); 1647308696Sshurd } 1648308696Sshurd else { 1649308696Sshurd iod->hdr.rc = 0; 1650308696Sshurd copyout(iod, ioh, ifbuf->length); 1651308696Sshurd } 1652308696Sshurd 1653308696Sshurd rc = 0; 1654308696Sshurd goto exit; 1655308696Sshurd } 1656308696Sshurd case BNXT_HWRM_FW_QSTATUS: 1657308696Sshurd { 1658308696Sshurd struct bnxt_ioctl_hwrm_fw_qstatus *qstat = 1659308696Sshurd &iod->status; 1660308696Sshurd 1661308696Sshurd rc = bnxt_hwrm_fw_qstatus(softc, qstat->processor, 1662308696Sshurd &qstat->selfreset); 1663308696Sshurd if (rc) { 1664308696Sshurd iod->hdr.rc = rc; 1665308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1666308696Sshurd sizeof(ioh->rc)); 1667308696Sshurd } 1668308696Sshurd else { 1669308696Sshurd iod->hdr.rc = 0; 1670308696Sshurd copyout(iod, ioh, ifbuf->length); 1671308696Sshurd } 1672308696Sshurd 1673308696Sshurd rc = 0; 1674308696Sshurd goto exit; 1675308696Sshurd } 1676308696Sshurd case BNXT_HWRM_NVM_WRITE: 1677308696Sshurd { 1678308696Sshurd struct bnxt_ioctl_hwrm_nvm_write *wr = 1679308696Sshurd &iod->write; 1680308696Sshurd 1681308696Sshurd rc = bnxt_hwrm_nvm_write(softc, wr->data, true, 1682308696Sshurd wr->type, wr->ordinal, wr->ext, wr->attr, 1683308696Sshurd wr->option, wr->data_length, wr->keep, 1684308696Sshurd &wr->item_length, &wr->index); 1685308696Sshurd if (rc) { 1686308696Sshurd iod->hdr.rc = rc; 1687308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1688308696Sshurd sizeof(ioh->rc)); 1689308696Sshurd } 1690308696Sshurd else { 1691308696Sshurd iod->hdr.rc = 0; 1692308696Sshurd copyout(iod, ioh, ifbuf->length); 1693308696Sshurd } 1694308696Sshurd 1695308696Sshurd rc = 0; 1696308696Sshurd goto exit; 1697308696Sshurd } 1698308696Sshurd case BNXT_HWRM_NVM_ERASE_DIR_ENTRY: 1699308696Sshurd { 1700308696Sshurd struct bnxt_ioctl_hwrm_nvm_erase_dir_entry *erase = 1701308696Sshurd &iod->erase; 1702308696Sshurd 1703308696Sshurd rc = bnxt_hwrm_nvm_erase_dir_entry(softc, erase->index); 1704308696Sshurd if (rc) { 1705308696Sshurd iod->hdr.rc = rc; 1706308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1707308696Sshurd sizeof(ioh->rc)); 1708308696Sshurd } 1709308696Sshurd else { 1710308696Sshurd iod->hdr.rc = 0; 1711308696Sshurd copyout(iod, ioh, ifbuf->length); 1712308696Sshurd } 1713308696Sshurd 1714308696Sshurd rc = 0; 1715308696Sshurd goto exit; 1716308696Sshurd } 1717308696Sshurd case BNXT_HWRM_NVM_GET_DIR_INFO: 1718308696Sshurd { 1719308696Sshurd struct bnxt_ioctl_hwrm_nvm_get_dir_info *info = 1720308696Sshurd &iod->dir_info; 1721308696Sshurd 1722308696Sshurd rc = bnxt_hwrm_nvm_get_dir_info(softc, &info->entries, 1723308696Sshurd &info->entry_length); 1724308696Sshurd if (rc) { 1725308696Sshurd iod->hdr.rc = rc; 1726308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1727308696Sshurd sizeof(ioh->rc)); 1728308696Sshurd } 1729308696Sshurd else { 1730308696Sshurd iod->hdr.rc = 0; 1731308696Sshurd copyout(iod, ioh, ifbuf->length); 1732308696Sshurd } 1733308696Sshurd 1734308696Sshurd rc = 0; 1735308696Sshurd goto exit; 1736308696Sshurd } 1737308696Sshurd case BNXT_HWRM_NVM_GET_DIR_ENTRIES: 1738308696Sshurd { 1739308696Sshurd struct bnxt_ioctl_hwrm_nvm_get_dir_entries *get = 1740308696Sshurd &iod->dir_entries; 1741308696Sshurd struct iflib_dma_info dma_data; 1742308696Sshurd 1743308696Sshurd rc = iflib_dma_alloc(softc->ctx, get->max_size, 1744308696Sshurd &dma_data, BUS_DMA_NOWAIT); 1745308696Sshurd if (rc) 1746308696Sshurd break; 1747308696Sshurd rc = bnxt_hwrm_nvm_get_dir_entries(softc, &get->entries, 1748308696Sshurd &get->entry_length, &dma_data); 1749308696Sshurd if (rc) { 1750308696Sshurd iod->hdr.rc = rc; 1751308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1752308696Sshurd sizeof(ioh->rc)); 1753308696Sshurd } 1754308696Sshurd else { 1755308696Sshurd copyout(dma_data.idi_vaddr, get->data, 1756308696Sshurd get->entry_length * get->entries); 1757308696Sshurd iod->hdr.rc = 0; 1758308696Sshurd copyout(iod, ioh, ifbuf->length); 1759308696Sshurd } 1760308696Sshurd iflib_dma_free(&dma_data); 1761308696Sshurd 1762308696Sshurd rc = 0; 1763308696Sshurd goto exit; 1764308696Sshurd } 1765308696Sshurd case BNXT_HWRM_NVM_VERIFY_UPDATE: 1766308696Sshurd { 1767308696Sshurd struct bnxt_ioctl_hwrm_nvm_verify_update *vrfy = 1768308696Sshurd &iod->verify; 1769308696Sshurd 1770308696Sshurd rc = bnxt_hwrm_nvm_verify_update(softc, vrfy->type, 1771308696Sshurd vrfy->ordinal, vrfy->ext); 1772308696Sshurd if (rc) { 1773308696Sshurd iod->hdr.rc = rc; 1774308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1775308696Sshurd sizeof(ioh->rc)); 1776308696Sshurd } 1777308696Sshurd else { 1778308696Sshurd iod->hdr.rc = 0; 1779308696Sshurd copyout(iod, ioh, ifbuf->length); 1780308696Sshurd } 1781308696Sshurd 1782308696Sshurd rc = 0; 1783308696Sshurd goto exit; 1784308696Sshurd } 1785308696Sshurd case BNXT_HWRM_NVM_INSTALL_UPDATE: 1786308696Sshurd { 1787308696Sshurd struct bnxt_ioctl_hwrm_nvm_install_update *inst = 1788308696Sshurd &iod->install; 1789308696Sshurd 1790308696Sshurd rc = bnxt_hwrm_nvm_install_update(softc, 1791308696Sshurd inst->install_type, &inst->installed_items, 1792308696Sshurd &inst->result, &inst->problem_item, 1793308696Sshurd &inst->reset_required); 1794308696Sshurd if (rc) { 1795308696Sshurd iod->hdr.rc = rc; 1796308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1797308696Sshurd sizeof(ioh->rc)); 1798308696Sshurd } 1799308696Sshurd else { 1800308696Sshurd iod->hdr.rc = 0; 1801308696Sshurd copyout(iod, ioh, ifbuf->length); 1802308696Sshurd } 1803308696Sshurd 1804308696Sshurd rc = 0; 1805308696Sshurd goto exit; 1806308696Sshurd } 1807308696Sshurd case BNXT_HWRM_NVM_MODIFY: 1808308696Sshurd { 1809308696Sshurd struct bnxt_ioctl_hwrm_nvm_modify *mod = &iod->modify; 1810308696Sshurd 1811308696Sshurd rc = bnxt_hwrm_nvm_modify(softc, mod->index, 1812308696Sshurd mod->offset, mod->data, true, mod->length); 1813308696Sshurd if (rc) { 1814308696Sshurd iod->hdr.rc = rc; 1815308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1816308696Sshurd sizeof(ioh->rc)); 1817308696Sshurd } 1818308696Sshurd else { 1819308696Sshurd iod->hdr.rc = 0; 1820308696Sshurd copyout(iod, ioh, ifbuf->length); 1821308696Sshurd } 1822308696Sshurd 1823308696Sshurd rc = 0; 1824308696Sshurd goto exit; 1825308696Sshurd } 1826308696Sshurd case BNXT_HWRM_FW_GET_TIME: 1827308696Sshurd { 1828308696Sshurd struct bnxt_ioctl_hwrm_fw_get_time *gtm = 1829308696Sshurd &iod->get_time; 1830308696Sshurd 1831308696Sshurd rc = bnxt_hwrm_fw_get_time(softc, >m->year, 1832308696Sshurd >m->month, >m->day, >m->hour, >m->minute, 1833308696Sshurd >m->second, >m->millisecond, >m->zone); 1834308696Sshurd if (rc) { 1835308696Sshurd iod->hdr.rc = rc; 1836308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1837308696Sshurd sizeof(ioh->rc)); 1838308696Sshurd } 1839308696Sshurd else { 1840308696Sshurd iod->hdr.rc = 0; 1841308696Sshurd copyout(iod, ioh, ifbuf->length); 1842308696Sshurd } 1843308696Sshurd 1844308696Sshurd rc = 0; 1845308696Sshurd goto exit; 1846308696Sshurd } 1847308696Sshurd case BNXT_HWRM_FW_SET_TIME: 1848308696Sshurd { 1849308696Sshurd struct bnxt_ioctl_hwrm_fw_set_time *stm = 1850308696Sshurd &iod->set_time; 1851308696Sshurd 1852308696Sshurd rc = bnxt_hwrm_fw_set_time(softc, stm->year, 1853308696Sshurd stm->month, stm->day, stm->hour, stm->minute, 1854308696Sshurd stm->second, stm->millisecond, stm->zone); 1855308696Sshurd if (rc) { 1856308696Sshurd iod->hdr.rc = rc; 1857308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1858308696Sshurd sizeof(ioh->rc)); 1859308696Sshurd } 1860308696Sshurd else { 1861308696Sshurd iod->hdr.rc = 0; 1862308696Sshurd copyout(iod, ioh, ifbuf->length); 1863308696Sshurd } 1864308696Sshurd 1865308696Sshurd rc = 0; 1866308696Sshurd goto exit; 1867308696Sshurd } 1868308696Sshurd } 1869308696Sshurd break; 1870308696Sshurd } 1871308696Sshurd 1872308696Sshurdexit: 1873308696Sshurd if (iod) 1874308696Sshurd free(iod, M_DEVBUF); 1875308696Sshurd return rc; 1876308696Sshurd} 1877308696Sshurd 1878308696Sshurd/* 1879308696Sshurd * Support functions 1880308696Sshurd */ 1881308696Sshurdstatic int 1882308696Sshurdbnxt_probe_phy(struct bnxt_softc *softc) 1883308696Sshurd{ 1884308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 1885308696Sshurd int rc = 0; 1886308696Sshurd 1887308696Sshurd rc = bnxt_update_link(softc, false); 1888308696Sshurd if (rc) { 1889308696Sshurd device_printf(softc->dev, 1890308696Sshurd "Probe phy can't update link (rc: %x)\n", rc); 1891308696Sshurd return (rc); 1892308696Sshurd } 1893308696Sshurd 1894308696Sshurd /*initialize the ethool setting copy with NVM settings */ 1895308696Sshurd if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE) 1896308696Sshurd link_info->autoneg |= BNXT_AUTONEG_SPEED; 1897308696Sshurd 1898308696Sshurd if (link_info->auto_pause & (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | 1899308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) { 1900308696Sshurd if (link_info->auto_pause == ( 1901308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | 1902308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) 1903308696Sshurd link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; 1904308696Sshurd link_info->req_flow_ctrl = link_info->auto_pause; 1905308696Sshurd } else if (link_info->force_pause & ( 1906308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | 1907308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) { 1908308696Sshurd link_info->req_flow_ctrl = link_info->force_pause; 1909308696Sshurd } 1910308696Sshurd link_info->req_duplex = link_info->duplex_setting; 1911308696Sshurd if (link_info->autoneg & BNXT_AUTONEG_SPEED) 1912308696Sshurd link_info->req_link_speed = link_info->auto_link_speed; 1913308696Sshurd else 1914308696Sshurd link_info->req_link_speed = link_info->force_link_speed; 1915308696Sshurd return (rc); 1916308696Sshurd} 1917308696Sshurd 1918308696Sshurdstatic void 1919308696Sshurdbnxt_add_media_types(struct bnxt_softc *softc) 1920308696Sshurd{ 1921308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 1922308696Sshurd uint16_t supported; 1923308696Sshurd uint8_t phy_type = get_phy_type(softc); 1924308696Sshurd 1925308696Sshurd supported = link_info->support_speeds; 1926308696Sshurd 1927308696Sshurd /* Auto is always supported */ 1928308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); 1929308696Sshurd 1930308696Sshurd if (softc->flags & BNXT_FLAG_NPAR) 1931308696Sshurd return; 1932308696Sshurd 1933308696Sshurd switch (phy_type) { 1934308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: 1935308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) 1936308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_100G_CR4, 0, 1937308696Sshurd NULL); 1938308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB) 1939308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_50G_CR2, 0, 1940308696Sshurd NULL); 1941308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) 1942308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_40G_CR4, 0, 1943308696Sshurd NULL); 1944308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) 1945308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_25G_CR, 0, 1946308696Sshurd NULL); 1947308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) 1948308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_10G_CR1, 0, 1949308696Sshurd NULL); 1950308696Sshurd break; 1951308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN: 1952308696Sshurd /* Auto only */ 1953308696Sshurd break; 1954308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: 1955308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: 1956308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: 1957308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) 1958308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_100G_KR4, 0, 1959308696Sshurd NULL); 1960308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB) 1961308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_50G_KR2, 0, 1962308696Sshurd NULL); 1963308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) 1964308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_40G_KR4, 0, 1965308696Sshurd NULL); 1966308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) 1967308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_25G_KR, 0, 1968308696Sshurd NULL); 1969308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB) 1970308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_20G_KR2, 0, 1971308696Sshurd NULL); 1972308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) 1973308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KR, 0, 1974308696Sshurd NULL); 1975309377Sshurd break; 1976308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: 1977308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) 1978308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_100G_LR4, 0, 1979308696Sshurd NULL); 1980308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) 1981308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_40G_LR4, 0, 1982308696Sshurd NULL); 1983308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) 1984308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_10G_LR, 0, 1985308696Sshurd NULL); 1986308696Sshurd break; 1987308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: 1988308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB) 1989308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_100G_SR4, 0, 1990308696Sshurd NULL); 1991308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB) 1992308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_40G_SR4, 0, 1993308696Sshurd NULL); 1994308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB) 1995308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_25G_SR, 0, 1996308696Sshurd NULL); 1997308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) 1998308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_10G_SR, 0, 1999308696Sshurd NULL); 2000308696Sshurd break; 2001308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: 2002308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) 2003308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KX4, 0, 2004308696Sshurd NULL); 2005308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) 2006308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_2500_KX, 0, 2007308696Sshurd NULL); 2008308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) 2009308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_1000_KX, 0, 2010308696Sshurd NULL); 2011308696Sshurd break; 2012308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: 2013308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE: 2014308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MB) 2015308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_10_T, 0, 2016308696Sshurd NULL); 2017308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MB) 2018308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_100_T, 0, 2019308696Sshurd NULL); 2020308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) 2021308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_1000_T, 0, 2022308696Sshurd NULL); 2023308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) 2024308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_2500_T, 0, 2025308696Sshurd NULL); 2026308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB) 2027308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_10G_T, 0, 2028308696Sshurd NULL); 2029308696Sshurd break; 2030308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: 2031308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB) 2032308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_1000_SGMII, 0, 2033308696Sshurd NULL); 2034308696Sshurd break; 2035308696Sshurd } 2036308696Sshurd 2037308696Sshurd return; 2038308696Sshurd} 2039308696Sshurd 2040308696Sshurdstatic int 2041308696Sshurdbnxt_map_bar(struct bnxt_softc *softc, struct bnxt_bar_info *bar, int bar_num, bool shareable) 2042308696Sshurd{ 2043308696Sshurd uint32_t flag; 2044308696Sshurd 2045308696Sshurd if (bar->res != NULL) { 2046308696Sshurd device_printf(softc->dev, "Bar %d already mapped\n", bar_num); 2047308696Sshurd return EDOOFUS; 2048308696Sshurd } 2049308696Sshurd 2050308696Sshurd bar->rid = PCIR_BAR(bar_num); 2051308696Sshurd flag = RF_ACTIVE; 2052308696Sshurd if (shareable) 2053308696Sshurd flag |= RF_SHAREABLE; 2054308696Sshurd 2055308696Sshurd if ((bar->res = 2056308696Sshurd bus_alloc_resource_any(softc->dev, 2057308696Sshurd SYS_RES_MEMORY, 2058308696Sshurd &bar->rid, 2059308696Sshurd flag)) == NULL) { 2060308696Sshurd device_printf(softc->dev, 2061308696Sshurd "PCI BAR%d mapping failure\n", bar_num); 2062308696Sshurd return (ENXIO); 2063308696Sshurd } 2064308696Sshurd bar->tag = rman_get_bustag(bar->res); 2065308696Sshurd bar->handle = rman_get_bushandle(bar->res); 2066308696Sshurd bar->size = rman_get_size(bar->res); 2067308696Sshurd 2068308696Sshurd return 0; 2069308696Sshurd} 2070308696Sshurd 2071308696Sshurdstatic int 2072308696Sshurdbnxt_pci_mapping(struct bnxt_softc *softc) 2073308696Sshurd{ 2074308696Sshurd int rc; 2075308696Sshurd 2076308696Sshurd rc = bnxt_map_bar(softc, &softc->hwrm_bar, 0, true); 2077308696Sshurd if (rc) 2078308696Sshurd return rc; 2079308696Sshurd 2080308696Sshurd rc = bnxt_map_bar(softc, &softc->doorbell_bar, 2, false); 2081308696Sshurd 2082308696Sshurd return rc; 2083308696Sshurd} 2084308696Sshurd 2085308696Sshurdstatic void 2086308696Sshurdbnxt_pci_mapping_free(struct bnxt_softc *softc) 2087308696Sshurd{ 2088308696Sshurd if (softc->hwrm_bar.res != NULL) 2089308696Sshurd bus_release_resource(softc->dev, SYS_RES_MEMORY, 2090308696Sshurd softc->hwrm_bar.rid, softc->hwrm_bar.res); 2091308696Sshurd softc->hwrm_bar.res = NULL; 2092308696Sshurd 2093308696Sshurd if (softc->doorbell_bar.res != NULL) 2094308696Sshurd bus_release_resource(softc->dev, SYS_RES_MEMORY, 2095308696Sshurd softc->doorbell_bar.rid, softc->doorbell_bar.res); 2096308696Sshurd softc->doorbell_bar.res = NULL; 2097308696Sshurd} 2098308696Sshurd 2099308696Sshurdstatic int 2100308696Sshurdbnxt_update_link(struct bnxt_softc *softc, bool chng_link_state) 2101308696Sshurd{ 2102308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 2103308696Sshurd uint8_t link_up = link_info->link_up; 2104308696Sshurd int rc = 0; 2105308696Sshurd 2106308696Sshurd rc = bnxt_hwrm_port_phy_qcfg(softc); 2107308696Sshurd if (rc) 2108308696Sshurd goto exit; 2109308696Sshurd 2110308696Sshurd /* TODO: need to add more logic to report VF link */ 2111308696Sshurd if (chng_link_state) { 2112308696Sshurd if (link_info->phy_link_status == 2113308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) 2114308696Sshurd link_info->link_up = 1; 2115308696Sshurd else 2116308696Sshurd link_info->link_up = 0; 2117308696Sshurd if (link_up != link_info->link_up) 2118308696Sshurd bnxt_report_link(softc); 2119308696Sshurd } else { 2120308696Sshurd /* always link down if not require to update link state */ 2121308696Sshurd link_info->link_up = 0; 2122308696Sshurd } 2123308696Sshurd 2124308696Sshurdexit: 2125308696Sshurd return rc; 2126308696Sshurd} 2127308696Sshurd 2128308696Sshurdvoid 2129308696Sshurdbnxt_report_link(struct bnxt_softc *softc) 2130308696Sshurd{ 2131308696Sshurd const char *duplex = NULL, *flow_ctrl = NULL; 2132308696Sshurd 2133308696Sshurd if (softc->link_info.link_up == softc->link_info.last_link_up) { 2134308696Sshurd if (!softc->link_info.link_up) 2135308696Sshurd return; 2136308696Sshurd if (softc->link_info.pause == softc->link_info.last_pause && 2137308696Sshurd softc->link_info.duplex == softc->link_info.last_duplex) 2138308696Sshurd return; 2139308696Sshurd } 2140308696Sshurd 2141308696Sshurd if (softc->link_info.link_up) { 2142308696Sshurd if (softc->link_info.duplex == 2143308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL) 2144308696Sshurd duplex = "full duplex"; 2145308696Sshurd else 2146308696Sshurd duplex = "half duplex"; 2147308696Sshurd if (softc->link_info.pause == ( 2148308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX | 2149308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) 2150308696Sshurd flow_ctrl = "FC - receive & transmit"; 2151308696Sshurd else if (softc->link_info.pause == 2152308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX) 2153308696Sshurd flow_ctrl = "FC - transmit"; 2154308696Sshurd else if (softc->link_info.pause == 2155308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) 2156308696Sshurd flow_ctrl = "FC - receive"; 2157308696Sshurd else 2158308696Sshurd flow_ctrl = "none"; 2159308696Sshurd iflib_link_state_change(softc->ctx, LINK_STATE_UP, 2160308696Sshurd IF_Gbps(100)); 2161308696Sshurd device_printf(softc->dev, "Link is UP %s, %s\n", duplex, 2162308696Sshurd flow_ctrl); 2163308696Sshurd } else { 2164308696Sshurd iflib_link_state_change(softc->ctx, LINK_STATE_DOWN, 2165308696Sshurd bnxt_get_baudrate(&softc->link_info)); 2166308696Sshurd device_printf(softc->dev, "Link is Down\n"); 2167308696Sshurd } 2168308696Sshurd 2169308696Sshurd softc->link_info.last_link_up = softc->link_info.link_up; 2170308696Sshurd softc->link_info.last_pause = softc->link_info.pause; 2171308696Sshurd softc->link_info.last_duplex = softc->link_info.duplex; 2172308696Sshurd} 2173308696Sshurd 2174308696Sshurdstatic int 2175308696Sshurdbnxt_handle_rx_cp(void *arg) 2176308696Sshurd{ 2177308696Sshurd struct bnxt_cp_ring *cpr = arg; 2178308696Sshurd 2179308696Sshurd /* Disable further interrupts for this queue */ 2180308696Sshurd BNXT_CP_DISABLE_DB(&cpr->ring); 2181308696Sshurd return FILTER_SCHEDULE_THREAD; 2182308696Sshurd} 2183308696Sshurd 2184308696Sshurdstatic int 2185308696Sshurdbnxt_handle_def_cp(void *arg) 2186308696Sshurd{ 2187308696Sshurd struct bnxt_softc *softc = arg; 2188308696Sshurd 2189308696Sshurd BNXT_CP_DISABLE_DB(&softc->def_cp_ring.ring); 2190308696Sshurd GROUPTASK_ENQUEUE(&softc->def_cp_task); 2191308696Sshurd return FILTER_HANDLED; 2192308696Sshurd} 2193308696Sshurd 2194308696Sshurdstatic void 2195308696Sshurdbnxt_clear_ids(struct bnxt_softc *softc) 2196308696Sshurd{ 2197308696Sshurd int i; 2198308696Sshurd 2199308696Sshurd softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE; 2200308696Sshurd softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; 2201308696Sshurd for (i = 0; i < softc->ntxqsets; i++) { 2202308696Sshurd softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; 2203308696Sshurd softc->tx_cp_rings[i].ring.phys_id = 2204308696Sshurd (uint16_t)HWRM_NA_SIGNATURE; 2205308696Sshurd softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 2206308696Sshurd } 2207308696Sshurd for (i = 0; i < softc->nrxqsets; i++) { 2208308696Sshurd softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; 2209308696Sshurd softc->rx_cp_rings[i].ring.phys_id = 2210308696Sshurd (uint16_t)HWRM_NA_SIGNATURE; 2211308696Sshurd softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 2212308696Sshurd softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 2213308696Sshurd softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE; 2214308696Sshurd } 2215308696Sshurd softc->vnic_info.filter_id = -1; 2216308696Sshurd softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE; 2217308696Sshurd softc->vnic_info.rss_id = (uint16_t)HWRM_NA_SIGNATURE; 2218308696Sshurd memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff, 2219308696Sshurd softc->vnic_info.rss_grp_tbl.idi_size); 2220308696Sshurd} 2221308696Sshurd 2222308696Sshurdstatic void 2223308696Sshurdbnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr) 2224308696Sshurd{ 2225308696Sshurd struct cmpl_base *cmp = (void *)cpr->ring.vaddr; 2226308696Sshurd int i; 2227308696Sshurd 2228308696Sshurd for (i = 0; i < cpr->ring.ring_size; i++) 2229308696Sshurd cmp[i].info3_v = !cpr->v_bit; 2230308696Sshurd} 2231308696Sshurd 2232308696Sshurdstatic void 2233308696Sshurdbnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl) 2234308696Sshurd{ 2235308696Sshurd struct hwrm_async_event_cmpl *ae = (void *)cmpl; 2236308696Sshurd uint16_t async_id = le16toh(ae->event_id); 2237308696Sshurd struct ifmediareq ifmr; 2238308696Sshurd 2239308696Sshurd switch (async_id) { 2240308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: 2241308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: 2242308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: 2243308696Sshurd bnxt_media_status(softc->ctx, &ifmr); 2244308696Sshurd break; 2245308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE: 2246308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE: 2247308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: 2248308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED: 2249308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD: 2250308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD: 2251308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD: 2252308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD: 2253308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR: 2254308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE: 2255308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE: 2256308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE: 2257308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR: 2258308696Sshurd device_printf(softc->dev, 2259308696Sshurd "Unhandled async completion type %u\n", async_id); 2260308696Sshurd break; 2261308696Sshurd default: 2262308696Sshurd device_printf(softc->dev, 2263308696Sshurd "Unknown async completion type %u\n", async_id); 2264308696Sshurd break; 2265308696Sshurd } 2266308696Sshurd} 2267308696Sshurd 2268308696Sshurdstatic void 2269308696Sshurdbnxt_def_cp_task(void *context) 2270308696Sshurd{ 2271308696Sshurd if_ctx_t ctx = context; 2272308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 2273308696Sshurd struct bnxt_cp_ring *cpr = &softc->def_cp_ring; 2274308696Sshurd 2275308696Sshurd /* Handle completions on the default completion ring */ 2276308696Sshurd struct cmpl_base *cmpl; 2277308696Sshurd uint32_t cons = cpr->cons; 2278308696Sshurd bool v_bit = cpr->v_bit; 2279308696Sshurd bool last_v_bit; 2280308696Sshurd uint32_t last_cons; 2281308696Sshurd uint16_t type; 2282308696Sshurd 2283308696Sshurd for (;;) { 2284308696Sshurd last_cons = cons; 2285308696Sshurd last_v_bit = v_bit; 2286308696Sshurd NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); 2287308696Sshurd cmpl = &((struct cmpl_base *)cpr->ring.vaddr)[cons]; 2288308696Sshurd 2289308696Sshurd if (!CMP_VALID(cmpl, v_bit)) 2290308696Sshurd break; 2291308696Sshurd 2292308696Sshurd type = le16toh(cmpl->type) & CMPL_BASE_TYPE_MASK; 2293308696Sshurd switch (type) { 2294308696Sshurd case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: 2295308696Sshurd bnxt_handle_async_event(softc, cmpl); 2296308696Sshurd break; 2297308696Sshurd case CMPL_BASE_TYPE_TX_L2: 2298308696Sshurd case CMPL_BASE_TYPE_RX_L2: 2299308696Sshurd case CMPL_BASE_TYPE_RX_AGG: 2300308696Sshurd case CMPL_BASE_TYPE_RX_TPA_START: 2301308696Sshurd case CMPL_BASE_TYPE_RX_TPA_END: 2302308696Sshurd case CMPL_BASE_TYPE_STAT_EJECT: 2303308696Sshurd case CMPL_BASE_TYPE_HWRM_DONE: 2304308696Sshurd case CMPL_BASE_TYPE_HWRM_FWD_REQ: 2305308696Sshurd case CMPL_BASE_TYPE_HWRM_FWD_RESP: 2306308696Sshurd case CMPL_BASE_TYPE_CQ_NOTIFICATION: 2307308696Sshurd case CMPL_BASE_TYPE_SRQ_EVENT: 2308308696Sshurd case CMPL_BASE_TYPE_DBQ_EVENT: 2309308696Sshurd case CMPL_BASE_TYPE_QP_EVENT: 2310308696Sshurd case CMPL_BASE_TYPE_FUNC_EVENT: 2311308696Sshurd device_printf(softc->dev, 2312308696Sshurd "Unhandled completion type %u\n", type); 2313308696Sshurd break; 2314308696Sshurd default: 2315308696Sshurd device_printf(softc->dev, 2316308696Sshurd "Unknown completion type %u\n", type); 2317308696Sshurd break; 2318308696Sshurd } 2319308696Sshurd } 2320308696Sshurd 2321308696Sshurd cpr->cons = last_cons; 2322308696Sshurd cpr->v_bit = last_v_bit; 2323308696Sshurd BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons); 2324308696Sshurd} 2325308696Sshurd 2326308696Sshurdstatic uint8_t 2327308696Sshurdget_phy_type(struct bnxt_softc *softc) 2328308696Sshurd{ 2329308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 2330308696Sshurd uint8_t phy_type = link_info->phy_type; 2331308696Sshurd uint16_t supported; 2332308696Sshurd 2333308696Sshurd if (phy_type != HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN) 2334308696Sshurd return phy_type; 2335308696Sshurd 2336308696Sshurd /* Deduce the phy type from the media type and supported speeds */ 2337308696Sshurd supported = link_info->support_speeds; 2338308696Sshurd 2339308696Sshurd if (link_info->media_type == 2340308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP) 2341308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET; 2342308696Sshurd if (link_info->media_type == 2343308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_DAC) { 2344308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) 2345308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX; 2346308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB) 2347308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR; 2348308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR; 2349308696Sshurd } 2350308696Sshurd if (link_info->media_type == 2351308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_FIBRE) 2352308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR; 2353308696Sshurd 2354308696Sshurd return phy_type; 2355308696Sshurd} 2356308696Sshurd 2357308696Sshurdbool 2358308696Sshurdbnxt_check_hwrm_version(struct bnxt_softc *softc) 2359308696Sshurd{ 2360308696Sshurd char buf[16]; 2361308696Sshurd 2362308696Sshurd sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major, 2363308696Sshurd softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update); 2364308696Sshurd if (softc->ver_info->hwrm_min_major > softc->ver_info->hwrm_if_major) { 2365308696Sshurd device_printf(softc->dev, 2366308696Sshurd "WARNING: HWRM version %s is too old (older than %s)\n", 2367308696Sshurd softc->ver_info->hwrm_if_ver, buf); 2368308696Sshurd return false; 2369308696Sshurd } 2370308696Sshurd else if(softc->ver_info->hwrm_min_major == 2371308696Sshurd softc->ver_info->hwrm_if_major) { 2372308696Sshurd if (softc->ver_info->hwrm_min_minor > 2373308696Sshurd softc->ver_info->hwrm_if_minor) { 2374308696Sshurd device_printf(softc->dev, 2375308696Sshurd "WARNING: HWRM version %s is too old (older than %s)\n", 2376308696Sshurd softc->ver_info->hwrm_if_ver, buf); 2377308696Sshurd return false; 2378308696Sshurd } 2379308696Sshurd else if (softc->ver_info->hwrm_min_minor == 2380308696Sshurd softc->ver_info->hwrm_if_minor) { 2381308696Sshurd if (softc->ver_info->hwrm_min_update > 2382308696Sshurd softc->ver_info->hwrm_if_update) { 2383308696Sshurd device_printf(softc->dev, 2384308696Sshurd "WARNING: HWRM version %s is too old (older than %s)\n", 2385308696Sshurd softc->ver_info->hwrm_if_ver, buf); 2386308696Sshurd return false; 2387308696Sshurd } 2388308696Sshurd } 2389308696Sshurd } 2390308696Sshurd return true; 2391308696Sshurd} 2392308696Sshurd 2393308696Sshurdstatic uint64_t 2394308696Sshurdbnxt_get_baudrate(struct bnxt_link_info *link) 2395308696Sshurd{ 2396308696Sshurd switch (link->link_speed) { 2397308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB: 2398308696Sshurd return IF_Mbps(100); 2399308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB: 2400308696Sshurd return IF_Gbps(1); 2401308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB: 2402308696Sshurd return IF_Gbps(2); 2403308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB: 2404308696Sshurd return IF_Mbps(2500); 2405308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB: 2406308696Sshurd return IF_Gbps(10); 2407308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB: 2408308696Sshurd return IF_Gbps(20); 2409308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB: 2410308696Sshurd return IF_Gbps(25); 2411308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB: 2412308696Sshurd return IF_Gbps(40); 2413308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: 2414308696Sshurd return IF_Gbps(50); 2415308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: 2416308696Sshurd return IF_Gbps(100); 2417308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB: 2418308696Sshurd return IF_Mbps(10); 2419308696Sshurd } 2420308696Sshurd return IF_Gbps(100); 2421308696Sshurd} 2422