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 361762 2020-06-03 18:09:32Z kp $"); 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); 179333364Sshurdstatic void bnxt_if_timer(if_ctx_t ctx, uint16_t qid); 180308696Sshurd 181308696Sshurd/* Interrupt enable / disable */ 182308696Sshurdstatic void bnxt_intr_enable(if_ctx_t ctx); 183333364Sshurdstatic int bnxt_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid); 184333364Sshurdstatic int bnxt_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid); 185308696Sshurdstatic void bnxt_disable_intr(if_ctx_t ctx); 186308696Sshurdstatic int bnxt_msix_intr_assign(if_ctx_t ctx, int msix); 187308696Sshurd 188308696Sshurd/* vlan support */ 189308696Sshurdstatic void bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag); 190308696Sshurdstatic void bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag); 191308696Sshurd 192308696Sshurd/* ioctl */ 193308696Sshurdstatic int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data); 194308696Sshurd 195333364Sshurdstatic int bnxt_shutdown(if_ctx_t ctx); 196333364Sshurdstatic int bnxt_suspend(if_ctx_t ctx); 197333364Sshurdstatic int bnxt_resume(if_ctx_t ctx); 198333364Sshurd 199308696Sshurd/* Internal support functions */ 200308696Sshurdstatic int bnxt_probe_phy(struct bnxt_softc *softc); 201308696Sshurdstatic void bnxt_add_media_types(struct bnxt_softc *softc); 202308696Sshurdstatic int bnxt_pci_mapping(struct bnxt_softc *softc); 203308696Sshurdstatic void bnxt_pci_mapping_free(struct bnxt_softc *softc); 204308696Sshurdstatic int bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state); 205308696Sshurdstatic int bnxt_handle_def_cp(void *arg); 206308696Sshurdstatic int bnxt_handle_rx_cp(void *arg); 207308696Sshurdstatic void bnxt_clear_ids(struct bnxt_softc *softc); 208308696Sshurdstatic void inline bnxt_do_enable_intr(struct bnxt_cp_ring *cpr); 209308696Sshurdstatic void inline bnxt_do_disable_intr(struct bnxt_cp_ring *cpr); 210308696Sshurdstatic void bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr); 211308696Sshurdstatic void bnxt_def_cp_task(void *context); 212308696Sshurdstatic void bnxt_handle_async_event(struct bnxt_softc *softc, 213308696Sshurd struct cmpl_base *cmpl); 214308696Sshurdstatic uint8_t get_phy_type(struct bnxt_softc *softc); 215308696Sshurdstatic uint64_t bnxt_get_baudrate(struct bnxt_link_info *link); 216333364Sshurdstatic void bnxt_get_wol_settings(struct bnxt_softc *softc); 217333364Sshurdstatic int bnxt_wol_config(if_ctx_t ctx); 218308696Sshurd 219308696Sshurd/* 220308696Sshurd * Device Interface Declaration 221308696Sshurd */ 222308696Sshurd 223308696Sshurdstatic device_method_t bnxt_methods[] = { 224308696Sshurd /* Device interface */ 225308696Sshurd DEVMETHOD(device_register, bnxt_register), 226308696Sshurd DEVMETHOD(device_probe, iflib_device_probe), 227308696Sshurd DEVMETHOD(device_attach, iflib_device_attach), 228308696Sshurd DEVMETHOD(device_detach, iflib_device_detach), 229308696Sshurd DEVMETHOD(device_shutdown, iflib_device_shutdown), 230308696Sshurd DEVMETHOD(device_suspend, iflib_device_suspend), 231308696Sshurd DEVMETHOD(device_resume, iflib_device_resume), 232308696Sshurd DEVMETHOD_END 233308696Sshurd}; 234308696Sshurd 235308696Sshurdstatic driver_t bnxt_driver = { 236308696Sshurd "bnxt", bnxt_methods, sizeof(struct bnxt_softc), 237308696Sshurd}; 238308696Sshurd 239308696Sshurddevclass_t bnxt_devclass; 240308696SshurdDRIVER_MODULE(bnxt, pci, bnxt_driver, bnxt_devclass, 0, 0); 241308696Sshurd 242308696SshurdMODULE_DEPEND(bnxt, pci, 1, 1, 1); 243308696SshurdMODULE_DEPEND(bnxt, ether, 1, 1, 1); 244308696SshurdMODULE_DEPEND(bnxt, iflib, 1, 1, 1); 245308696Sshurd 246333338SshurdIFLIB_PNP_INFO(pci, bnxt, bnxt_vendor_info_array); 247333338Sshurd 248308696Sshurdstatic device_method_t bnxt_iflib_methods[] = { 249308696Sshurd DEVMETHOD(ifdi_tx_queues_alloc, bnxt_tx_queues_alloc), 250308696Sshurd DEVMETHOD(ifdi_rx_queues_alloc, bnxt_rx_queues_alloc), 251308696Sshurd DEVMETHOD(ifdi_queues_free, bnxt_queues_free), 252308696Sshurd 253308696Sshurd DEVMETHOD(ifdi_attach_pre, bnxt_attach_pre), 254308696Sshurd DEVMETHOD(ifdi_attach_post, bnxt_attach_post), 255308696Sshurd DEVMETHOD(ifdi_detach, bnxt_detach), 256308696Sshurd 257308696Sshurd DEVMETHOD(ifdi_init, bnxt_init), 258308696Sshurd DEVMETHOD(ifdi_stop, bnxt_stop), 259308696Sshurd DEVMETHOD(ifdi_multi_set, bnxt_multi_set), 260308696Sshurd DEVMETHOD(ifdi_mtu_set, bnxt_mtu_set), 261308696Sshurd DEVMETHOD(ifdi_media_status, bnxt_media_status), 262308696Sshurd DEVMETHOD(ifdi_media_change, bnxt_media_change), 263308696Sshurd DEVMETHOD(ifdi_promisc_set, bnxt_promisc_set), 264308696Sshurd DEVMETHOD(ifdi_get_counter, bnxt_get_counter), 265308696Sshurd DEVMETHOD(ifdi_update_admin_status, bnxt_update_admin_status), 266333364Sshurd DEVMETHOD(ifdi_timer, bnxt_if_timer), 267308696Sshurd 268308696Sshurd DEVMETHOD(ifdi_intr_enable, bnxt_intr_enable), 269333364Sshurd DEVMETHOD(ifdi_tx_queue_intr_enable, bnxt_tx_queue_intr_enable), 270333364Sshurd DEVMETHOD(ifdi_rx_queue_intr_enable, bnxt_rx_queue_intr_enable), 271308696Sshurd DEVMETHOD(ifdi_intr_disable, bnxt_disable_intr), 272308696Sshurd DEVMETHOD(ifdi_msix_intr_assign, bnxt_msix_intr_assign), 273308696Sshurd 274308696Sshurd DEVMETHOD(ifdi_vlan_register, bnxt_vlan_register), 275308696Sshurd DEVMETHOD(ifdi_vlan_unregister, bnxt_vlan_unregister), 276308696Sshurd 277308696Sshurd DEVMETHOD(ifdi_priv_ioctl, bnxt_priv_ioctl), 278308696Sshurd 279333364Sshurd DEVMETHOD(ifdi_suspend, bnxt_suspend), 280333364Sshurd DEVMETHOD(ifdi_shutdown, bnxt_shutdown), 281333364Sshurd DEVMETHOD(ifdi_resume, bnxt_resume), 282333364Sshurd 283308696Sshurd DEVMETHOD_END 284308696Sshurd}; 285308696Sshurd 286308696Sshurdstatic driver_t bnxt_iflib_driver = { 287308696Sshurd "bnxt", bnxt_iflib_methods, sizeof(struct bnxt_softc) 288308696Sshurd}; 289308696Sshurd 290308696Sshurd/* 291308696Sshurd * iflib shared context 292308696Sshurd */ 293308696Sshurd 294333364Sshurd#define BNXT_DRIVER_VERSION "1.0.0.2" 295333364Sshurdchar bnxt_driver_version[] = BNXT_DRIVER_VERSION; 296308696Sshurdextern struct if_txrx bnxt_txrx; 297308696Sshurdstatic struct if_shared_ctx bnxt_sctx_init = { 298308696Sshurd .isc_magic = IFLIB_MAGIC, 299308696Sshurd .isc_driver = &bnxt_iflib_driver, 300308696Sshurd .isc_nfl = 2, // Number of Free Lists 301333338Sshurd .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ | IFLIB_NEED_ETHER_PAD, 302308696Sshurd .isc_q_align = PAGE_SIZE, 303308696Sshurd .isc_tx_maxsize = BNXT_TSO_SIZE, 304308696Sshurd .isc_tx_maxsegsize = BNXT_TSO_SIZE, 305308696Sshurd .isc_rx_maxsize = BNXT_TSO_SIZE, 306308696Sshurd .isc_rx_maxsegsize = BNXT_TSO_SIZE, 307308696Sshurd 308308696Sshurd // Only use a single segment to avoid page size constraints 309308696Sshurd .isc_rx_nsegments = 1, 310308696Sshurd .isc_ntxqs = 2, 311308696Sshurd .isc_nrxqs = 3, 312308696Sshurd .isc_nrxd_min = {16, 16, 16}, 313308696Sshurd .isc_nrxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 8, 314308696Sshurd PAGE_SIZE / sizeof(struct rx_prod_pkt_bd), 315308696Sshurd PAGE_SIZE / sizeof(struct rx_prod_pkt_bd)}, 316361762Skp .isc_nrxd_max = {BNXT_MAX_RXD, BNXT_MAX_RXD, BNXT_MAX_RXD}, 317308696Sshurd .isc_ntxd_min = {16, 16, 16}, 318308696Sshurd .isc_ntxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 2, 319308696Sshurd PAGE_SIZE / sizeof(struct tx_bd_short)}, 320361762Skp .isc_ntxd_max = {BNXT_MAX_TXD, BNXT_MAX_TXD, BNXT_MAX_TXD}, 321308696Sshurd 322308696Sshurd .isc_admin_intrcnt = 1, 323308696Sshurd .isc_vendor_info = bnxt_vendor_info_array, 324308696Sshurd .isc_driver_version = bnxt_driver_version, 325308696Sshurd}; 326308696Sshurd 327308696Sshurdif_shared_ctx_t bnxt_sctx = &bnxt_sctx_init; 328308696Sshurd 329308696Sshurd/* 330308696Sshurd * Device Methods 331308696Sshurd */ 332308696Sshurd 333308696Sshurdstatic void * 334308696Sshurdbnxt_register(device_t dev) 335308696Sshurd{ 336308696Sshurd return bnxt_sctx; 337308696Sshurd} 338308696Sshurd 339308696Sshurd/* 340308696Sshurd * Device Dependent Configuration Functions 341308696Sshurd*/ 342308696Sshurd 343308696Sshurd/* Soft queue setup and teardown */ 344308696Sshurdstatic int 345308696Sshurdbnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 346308696Sshurd uint64_t *paddrs, int ntxqs, int ntxqsets) 347308696Sshurd{ 348308696Sshurd struct bnxt_softc *softc; 349308696Sshurd int i; 350308696Sshurd int rc; 351308696Sshurd 352308696Sshurd softc = iflib_get_softc(ctx); 353308696Sshurd 354308696Sshurd softc->tx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * ntxqsets, 355308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 356308696Sshurd if (!softc->tx_cp_rings) { 357308696Sshurd device_printf(iflib_get_dev(ctx), 358308696Sshurd "unable to allocate TX completion rings\n"); 359308696Sshurd rc = ENOMEM; 360308696Sshurd goto cp_alloc_fail; 361308696Sshurd } 362308696Sshurd softc->tx_rings = malloc(sizeof(struct bnxt_ring) * ntxqsets, 363308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 364308696Sshurd if (!softc->tx_rings) { 365308696Sshurd device_printf(iflib_get_dev(ctx), 366308696Sshurd "unable to allocate TX rings\n"); 367308696Sshurd rc = ENOMEM; 368308696Sshurd goto ring_alloc_fail; 369308696Sshurd } 370308696Sshurd rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * ntxqsets, 371308696Sshurd &softc->tx_stats, 0); 372308696Sshurd if (rc) 373308696Sshurd goto dma_alloc_fail; 374308696Sshurd bus_dmamap_sync(softc->tx_stats.idi_tag, softc->tx_stats.idi_map, 375308696Sshurd BUS_DMASYNC_PREREAD); 376308696Sshurd 377308696Sshurd for (i = 0; i < ntxqsets; i++) { 378308696Sshurd /* Set up the completion ring */ 379308696Sshurd softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; 380308696Sshurd softc->tx_cp_rings[i].ring.phys_id = 381308696Sshurd (uint16_t)HWRM_NA_SIGNATURE; 382308696Sshurd softc->tx_cp_rings[i].ring.softc = softc; 383308696Sshurd softc->tx_cp_rings[i].ring.id = 384308696Sshurd (softc->scctx->isc_nrxqsets * 2) + 1 + i; 385308696Sshurd softc->tx_cp_rings[i].ring.doorbell = 386308696Sshurd softc->tx_cp_rings[i].ring.id * 0x80; 387308696Sshurd softc->tx_cp_rings[i].ring.ring_size = 388308696Sshurd softc->scctx->isc_ntxd[0]; 389308696Sshurd softc->tx_cp_rings[i].ring.vaddr = vaddrs[i * ntxqs]; 390308696Sshurd softc->tx_cp_rings[i].ring.paddr = paddrs[i * ntxqs]; 391308696Sshurd 392308696Sshurd /* Set up the TX ring */ 393308696Sshurd softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 394308696Sshurd softc->tx_rings[i].softc = softc; 395308696Sshurd softc->tx_rings[i].id = 396308696Sshurd (softc->scctx->isc_nrxqsets * 2) + 1 + i; 397308696Sshurd softc->tx_rings[i].doorbell = softc->tx_rings[i].id * 0x80; 398308696Sshurd softc->tx_rings[i].ring_size = softc->scctx->isc_ntxd[1]; 399308696Sshurd softc->tx_rings[i].vaddr = vaddrs[i * ntxqs + 1]; 400308696Sshurd softc->tx_rings[i].paddr = paddrs[i * ntxqs + 1]; 401308696Sshurd 402308696Sshurd bnxt_create_tx_sysctls(softc, i); 403308696Sshurd } 404308696Sshurd 405308696Sshurd softc->ntxqsets = ntxqsets; 406308696Sshurd return rc; 407308696Sshurd 408308696Sshurddma_alloc_fail: 409308696Sshurd free(softc->tx_rings, M_DEVBUF); 410308696Sshurdring_alloc_fail: 411308696Sshurd free(softc->tx_cp_rings, M_DEVBUF); 412308696Sshurdcp_alloc_fail: 413308696Sshurd return rc; 414308696Sshurd} 415308696Sshurd 416308696Sshurdstatic void 417308696Sshurdbnxt_queues_free(if_ctx_t ctx) 418308696Sshurd{ 419308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 420308696Sshurd 421308696Sshurd // Free TX queues 422308696Sshurd iflib_dma_free(&softc->tx_stats); 423308696Sshurd free(softc->tx_rings, M_DEVBUF); 424308696Sshurd softc->tx_rings = NULL; 425308696Sshurd free(softc->tx_cp_rings, M_DEVBUF); 426308696Sshurd softc->tx_cp_rings = NULL; 427308696Sshurd softc->ntxqsets = 0; 428308696Sshurd 429308696Sshurd // Free RX queues 430308696Sshurd iflib_dma_free(&softc->rx_stats); 431333364Sshurd iflib_dma_free(&softc->hw_tx_port_stats); 432333364Sshurd iflib_dma_free(&softc->hw_rx_port_stats); 433308696Sshurd free(softc->grp_info, M_DEVBUF); 434308696Sshurd free(softc->ag_rings, M_DEVBUF); 435308696Sshurd free(softc->rx_rings, M_DEVBUF); 436308696Sshurd free(softc->rx_cp_rings, M_DEVBUF); 437308696Sshurd} 438308696Sshurd 439308696Sshurdstatic int 440308696Sshurdbnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, 441308696Sshurd uint64_t *paddrs, int nrxqs, int nrxqsets) 442308696Sshurd{ 443308696Sshurd struct bnxt_softc *softc; 444308696Sshurd int i; 445308696Sshurd int rc; 446308696Sshurd 447308696Sshurd softc = iflib_get_softc(ctx); 448308696Sshurd 449308696Sshurd softc->rx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * nrxqsets, 450308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 451308696Sshurd if (!softc->rx_cp_rings) { 452308696Sshurd device_printf(iflib_get_dev(ctx), 453308696Sshurd "unable to allocate RX completion rings\n"); 454308696Sshurd rc = ENOMEM; 455308696Sshurd goto cp_alloc_fail; 456308696Sshurd } 457308696Sshurd softc->rx_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets, 458308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 459308696Sshurd if (!softc->rx_rings) { 460308696Sshurd device_printf(iflib_get_dev(ctx), 461308696Sshurd "unable to allocate RX rings\n"); 462308696Sshurd rc = ENOMEM; 463308696Sshurd goto ring_alloc_fail; 464308696Sshurd } 465308696Sshurd softc->ag_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets, 466308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 467308696Sshurd if (!softc->ag_rings) { 468308696Sshurd device_printf(iflib_get_dev(ctx), 469308696Sshurd "unable to allocate aggregation rings\n"); 470308696Sshurd rc = ENOMEM; 471308696Sshurd goto ag_alloc_fail; 472308696Sshurd } 473308696Sshurd softc->grp_info = malloc(sizeof(struct bnxt_grp_info) * nrxqsets, 474308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 475308696Sshurd if (!softc->grp_info) { 476308696Sshurd device_printf(iflib_get_dev(ctx), 477308696Sshurd "unable to allocate ring groups\n"); 478308696Sshurd rc = ENOMEM; 479308696Sshurd goto grp_alloc_fail; 480308696Sshurd } 481308696Sshurd 482308696Sshurd rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * nrxqsets, 483308696Sshurd &softc->rx_stats, 0); 484308696Sshurd if (rc) 485308696Sshurd goto hw_stats_alloc_fail; 486308696Sshurd bus_dmamap_sync(softc->rx_stats.idi_tag, softc->rx_stats.idi_map, 487308696Sshurd BUS_DMASYNC_PREREAD); 488308696Sshurd 489333364Sshurd/* 490333364Sshurd * Additional 512 bytes for future expansion. 491333364Sshurd * To prevent corruption when loaded with newer firmwares with added counters. 492333364Sshurd * This can be deleted when there will be no further additions of counters. 493333364Sshurd */ 494333364Sshurd#define BNXT_PORT_STAT_PADDING 512 495333364Sshurd 496333364Sshurd rc = iflib_dma_alloc(ctx, sizeof(struct rx_port_stats) + BNXT_PORT_STAT_PADDING, 497333364Sshurd &softc->hw_rx_port_stats, 0); 498333364Sshurd if (rc) 499333364Sshurd goto hw_port_rx_stats_alloc_fail; 500333364Sshurd 501333364Sshurd bus_dmamap_sync(softc->hw_rx_port_stats.idi_tag, 502333364Sshurd softc->hw_rx_port_stats.idi_map, BUS_DMASYNC_PREREAD); 503333364Sshurd 504333364Sshurd rc = iflib_dma_alloc(ctx, sizeof(struct tx_port_stats) + BNXT_PORT_STAT_PADDING, 505333364Sshurd &softc->hw_tx_port_stats, 0); 506333364Sshurd 507333364Sshurd if (rc) 508333364Sshurd goto hw_port_tx_stats_alloc_fail; 509333364Sshurd 510333364Sshurd bus_dmamap_sync(softc->hw_tx_port_stats.idi_tag, 511333364Sshurd softc->hw_tx_port_stats.idi_map, BUS_DMASYNC_PREREAD); 512333364Sshurd 513333364Sshurd softc->rx_port_stats = (void *) softc->hw_rx_port_stats.idi_vaddr; 514333364Sshurd softc->tx_port_stats = (void *) softc->hw_tx_port_stats.idi_vaddr; 515333364Sshurd 516308696Sshurd for (i = 0; i < nrxqsets; i++) { 517308696Sshurd /* Allocation the completion ring */ 518308696Sshurd softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; 519308696Sshurd softc->rx_cp_rings[i].ring.phys_id = 520308696Sshurd (uint16_t)HWRM_NA_SIGNATURE; 521308696Sshurd softc->rx_cp_rings[i].ring.softc = softc; 522308696Sshurd softc->rx_cp_rings[i].ring.id = i + 1; 523308696Sshurd softc->rx_cp_rings[i].ring.doorbell = 524308696Sshurd softc->rx_cp_rings[i].ring.id * 0x80; 525308696Sshurd /* 526308696Sshurd * If this ring overflows, RX stops working. 527308696Sshurd */ 528308696Sshurd softc->rx_cp_rings[i].ring.ring_size = 529308696Sshurd softc->scctx->isc_nrxd[0]; 530308696Sshurd softc->rx_cp_rings[i].ring.vaddr = vaddrs[i * nrxqs]; 531308696Sshurd softc->rx_cp_rings[i].ring.paddr = paddrs[i * nrxqs]; 532308696Sshurd 533308696Sshurd /* Allocate the RX ring */ 534308696Sshurd softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 535308696Sshurd softc->rx_rings[i].softc = softc; 536308696Sshurd softc->rx_rings[i].id = i + 1; 537308696Sshurd softc->rx_rings[i].doorbell = softc->rx_rings[i].id * 0x80; 538308696Sshurd softc->rx_rings[i].ring_size = softc->scctx->isc_nrxd[1]; 539308696Sshurd softc->rx_rings[i].vaddr = vaddrs[i * nrxqs + 1]; 540308696Sshurd softc->rx_rings[i].paddr = paddrs[i * nrxqs + 1]; 541308696Sshurd 542333338Sshurd /* Allocate the TPA start buffer */ 543333338Sshurd softc->rx_rings[i].tpa_start = malloc(sizeof(struct bnxt_full_tpa_start) * 544333338Sshurd (RX_TPA_START_CMPL_AGG_ID_MASK >> RX_TPA_START_CMPL_AGG_ID_SFT), 545333338Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 546333338Sshurd if (softc->rx_rings[i].tpa_start == NULL) { 547333338Sshurd rc = -ENOMEM; 548333338Sshurd device_printf(softc->dev, 549333338Sshurd "Unable to allocate space for TPA\n"); 550333338Sshurd goto tpa_alloc_fail; 551333338Sshurd } 552333338Sshurd 553308696Sshurd /* Allocate the AG ring */ 554308696Sshurd softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 555308696Sshurd softc->ag_rings[i].softc = softc; 556308696Sshurd softc->ag_rings[i].id = nrxqsets + i + 1; 557308696Sshurd softc->ag_rings[i].doorbell = softc->ag_rings[i].id * 0x80; 558308696Sshurd softc->ag_rings[i].ring_size = softc->scctx->isc_nrxd[2]; 559308696Sshurd softc->ag_rings[i].vaddr = vaddrs[i * nrxqs + 2]; 560308696Sshurd softc->ag_rings[i].paddr = paddrs[i * nrxqs + 2]; 561308696Sshurd 562308696Sshurd /* Allocate the ring group */ 563308696Sshurd softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE; 564308696Sshurd softc->grp_info[i].stats_ctx = 565308696Sshurd softc->rx_cp_rings[i].stats_ctx_id; 566308696Sshurd softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id; 567308696Sshurd softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id; 568308696Sshurd softc->grp_info[i].cp_ring_id = 569308696Sshurd softc->rx_cp_rings[i].ring.phys_id; 570308696Sshurd 571308696Sshurd bnxt_create_rx_sysctls(softc, i); 572308696Sshurd } 573308696Sshurd 574333364Sshurd /* 575333364Sshurd * When SR-IOV is enabled, avoid each VF sending PORT_QSTATS 576333364Sshurd * HWRM every sec with which firmware timeouts can happen 577333364Sshurd */ 578333364Sshurd if (BNXT_PF(softc)) 579333364Sshurd bnxt_create_port_stats_sysctls(softc); 580333364Sshurd 581308696Sshurd /* And finally, the VNIC */ 582308696Sshurd softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE; 583308696Sshurd softc->vnic_info.flow_id = (uint16_t)HWRM_NA_SIGNATURE; 584308696Sshurd softc->vnic_info.filter_id = -1; 585308696Sshurd softc->vnic_info.def_ring_grp = (uint16_t)HWRM_NA_SIGNATURE; 586308696Sshurd softc->vnic_info.cos_rule = (uint16_t)HWRM_NA_SIGNATURE; 587308696Sshurd softc->vnic_info.lb_rule = (uint16_t)HWRM_NA_SIGNATURE; 588308696Sshurd softc->vnic_info.rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST; 589308696Sshurd softc->vnic_info.mc_list_count = 0; 590308696Sshurd softc->vnic_info.flags = BNXT_VNIC_FLAG_DEFAULT; 591308696Sshurd rc = iflib_dma_alloc(ctx, BNXT_MAX_MC_ADDRS * ETHER_ADDR_LEN, 592308696Sshurd &softc->vnic_info.mc_list, 0); 593308696Sshurd if (rc) 594308696Sshurd goto mc_list_alloc_fail; 595308696Sshurd 596308696Sshurd /* The VNIC RSS Hash Key */ 597308696Sshurd rc = iflib_dma_alloc(ctx, HW_HASH_KEY_SIZE, 598308696Sshurd &softc->vnic_info.rss_hash_key_tbl, 0); 599308696Sshurd if (rc) 600308696Sshurd goto rss_hash_alloc_fail; 601308696Sshurd bus_dmamap_sync(softc->vnic_info.rss_hash_key_tbl.idi_tag, 602308696Sshurd softc->vnic_info.rss_hash_key_tbl.idi_map, 603308696Sshurd BUS_DMASYNC_PREWRITE); 604308696Sshurd memcpy(softc->vnic_info.rss_hash_key_tbl.idi_vaddr, 605308696Sshurd softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE); 606308696Sshurd 607308696Sshurd /* Allocate the RSS tables */ 608308696Sshurd rc = iflib_dma_alloc(ctx, HW_HASH_INDEX_SIZE * sizeof(uint16_t), 609308696Sshurd &softc->vnic_info.rss_grp_tbl, 0); 610308696Sshurd if (rc) 611308696Sshurd goto rss_grp_alloc_fail; 612308696Sshurd bus_dmamap_sync(softc->vnic_info.rss_grp_tbl.idi_tag, 613308696Sshurd softc->vnic_info.rss_grp_tbl.idi_map, 614308696Sshurd BUS_DMASYNC_PREWRITE); 615308696Sshurd memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff, 616308696Sshurd softc->vnic_info.rss_grp_tbl.idi_size); 617308696Sshurd 618308696Sshurd softc->nrxqsets = nrxqsets; 619308696Sshurd return rc; 620308696Sshurd 621308696Sshurdrss_grp_alloc_fail: 622308696Sshurd iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); 623308696Sshurdrss_hash_alloc_fail: 624308696Sshurd iflib_dma_free(&softc->vnic_info.mc_list); 625333338Sshurdtpa_alloc_fail: 626308696Sshurdmc_list_alloc_fail: 627333338Sshurd for (i = i - 1; i >= 0; i--) 628333338Sshurd free(softc->rx_rings[i].tpa_start, M_DEVBUF); 629333364Sshurd iflib_dma_free(&softc->hw_tx_port_stats); 630333364Sshurdhw_port_tx_stats_alloc_fail: 631333364Sshurd iflib_dma_free(&softc->hw_rx_port_stats); 632333364Sshurdhw_port_rx_stats_alloc_fail: 633308696Sshurd iflib_dma_free(&softc->rx_stats); 634308696Sshurdhw_stats_alloc_fail: 635308696Sshurd free(softc->grp_info, M_DEVBUF); 636308696Sshurdgrp_alloc_fail: 637308696Sshurd free(softc->ag_rings, M_DEVBUF); 638308696Sshurdag_alloc_fail: 639308696Sshurd free(softc->rx_rings, M_DEVBUF); 640308696Sshurdring_alloc_fail: 641308696Sshurd free(softc->rx_cp_rings, M_DEVBUF); 642308696Sshurdcp_alloc_fail: 643308696Sshurd return rc; 644308696Sshurd} 645308696Sshurd 646333364Sshurdstatic void bnxt_free_hwrm_short_cmd_req(struct bnxt_softc *softc) 647333364Sshurd{ 648333364Sshurd if (softc->hwrm_short_cmd_req_addr.idi_vaddr) 649333364Sshurd iflib_dma_free(&softc->hwrm_short_cmd_req_addr); 650333364Sshurd softc->hwrm_short_cmd_req_addr.idi_vaddr = NULL; 651333364Sshurd} 652333364Sshurd 653333364Sshurdstatic int bnxt_alloc_hwrm_short_cmd_req(struct bnxt_softc *softc) 654333364Sshurd{ 655333364Sshurd int rc; 656333364Sshurd 657333364Sshurd rc = iflib_dma_alloc(softc->ctx, softc->hwrm_max_req_len, 658333364Sshurd &softc->hwrm_short_cmd_req_addr, BUS_DMA_NOWAIT); 659333364Sshurd 660333364Sshurd return rc; 661333364Sshurd} 662333364Sshurd 663308696Sshurd/* Device setup and teardown */ 664308696Sshurdstatic int 665308696Sshurdbnxt_attach_pre(if_ctx_t ctx) 666308696Sshurd{ 667308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 668308696Sshurd if_softc_ctx_t scctx; 669308696Sshurd int rc = 0; 670308696Sshurd 671308696Sshurd softc->ctx = ctx; 672308696Sshurd softc->dev = iflib_get_dev(ctx); 673308696Sshurd softc->media = iflib_get_media(ctx); 674308696Sshurd softc->scctx = iflib_get_softc_ctx(ctx); 675308696Sshurd softc->sctx = iflib_get_sctx(ctx); 676308696Sshurd scctx = softc->scctx; 677308696Sshurd 678309377Sshurd /* TODO: Better way of detecting NPAR/VF is needed */ 679333364Sshurd switch (pci_get_device(softc->dev)) { 680308696Sshurd case BCM57402_NPAR: 681308696Sshurd case BCM57404_NPAR: 682308696Sshurd case BCM57406_NPAR: 683309377Sshurd case BCM57407_NPAR: 684309377Sshurd case BCM57412_NPAR1: 685309377Sshurd case BCM57412_NPAR2: 686309377Sshurd case BCM57414_NPAR1: 687309377Sshurd case BCM57414_NPAR2: 688309377Sshurd case BCM57416_NPAR1: 689309377Sshurd case BCM57416_NPAR2: 690308696Sshurd softc->flags |= BNXT_FLAG_NPAR; 691308696Sshurd break; 692309377Sshurd case NETXTREME_C_VF1: 693309377Sshurd case NETXTREME_C_VF2: 694309377Sshurd case NETXTREME_C_VF3: 695309377Sshurd case NETXTREME_E_VF1: 696309377Sshurd case NETXTREME_E_VF2: 697309377Sshurd case NETXTREME_E_VF3: 698308696Sshurd softc->flags |= BNXT_FLAG_VF; 699308696Sshurd break; 700308696Sshurd } 701308696Sshurd 702308696Sshurd pci_enable_busmaster(softc->dev); 703308696Sshurd 704308696Sshurd if (bnxt_pci_mapping(softc)) 705308696Sshurd return (ENXIO); 706308696Sshurd 707308696Sshurd /* HWRM setup/init */ 708308696Sshurd BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev)); 709308696Sshurd rc = bnxt_alloc_hwrm_dma_mem(softc); 710308696Sshurd if (rc) 711308696Sshurd goto dma_fail; 712308696Sshurd 713308696Sshurd 714308696Sshurd /* Get firmware version and compare with driver */ 715308696Sshurd softc->ver_info = malloc(sizeof(struct bnxt_ver_info), 716308696Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 717308696Sshurd if (softc->ver_info == NULL) { 718308696Sshurd rc = ENOMEM; 719308696Sshurd device_printf(softc->dev, 720308696Sshurd "Unable to allocate space for version info\n"); 721308696Sshurd goto ver_alloc_fail; 722308696Sshurd } 723308696Sshurd /* Default minimum required HWRM version */ 724308696Sshurd softc->ver_info->hwrm_min_major = 1; 725308696Sshurd softc->ver_info->hwrm_min_minor = 2; 726308696Sshurd softc->ver_info->hwrm_min_update = 2; 727308696Sshurd 728308696Sshurd rc = bnxt_hwrm_ver_get(softc); 729308696Sshurd if (rc) { 730308696Sshurd device_printf(softc->dev, "attach: hwrm ver get failed\n"); 731308696Sshurd goto ver_fail; 732308696Sshurd } 733308696Sshurd 734333364Sshurd if (softc->flags & BNXT_FLAG_SHORT_CMD) { 735333364Sshurd rc = bnxt_alloc_hwrm_short_cmd_req(softc); 736333364Sshurd if (rc) 737333364Sshurd goto hwrm_short_cmd_alloc_fail; 738333364Sshurd } 739333364Sshurd 740308696Sshurd /* Get NVRAM info */ 741333364Sshurd if (BNXT_PF(softc)) { 742333364Sshurd softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info), 743333364Sshurd M_DEVBUF, M_NOWAIT | M_ZERO); 744333364Sshurd if (softc->nvm_info == NULL) { 745333364Sshurd rc = ENOMEM; 746333364Sshurd device_printf(softc->dev, 747333364Sshurd "Unable to allocate space for NVRAM info\n"); 748333364Sshurd goto nvm_alloc_fail; 749333364Sshurd } 750333364Sshurd 751333364Sshurd rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id, 752333364Sshurd &softc->nvm_info->device_id, &softc->nvm_info->sector_size, 753333364Sshurd &softc->nvm_info->size, &softc->nvm_info->reserved_size, 754333364Sshurd &softc->nvm_info->available_size); 755308696Sshurd } 756308696Sshurd 757308696Sshurd /* Register the driver with the FW */ 758308696Sshurd rc = bnxt_hwrm_func_drv_rgtr(softc); 759308696Sshurd if (rc) { 760308696Sshurd device_printf(softc->dev, "attach: hwrm drv rgtr failed\n"); 761308696Sshurd goto drv_rgtr_fail; 762308696Sshurd } 763308696Sshurd 764333364Sshurd rc = bnxt_hwrm_func_rgtr_async_events(softc, NULL, 0); 765333364Sshurd if (rc) { 766333364Sshurd device_printf(softc->dev, "attach: hwrm rgtr async evts failed\n"); 767333364Sshurd goto drv_rgtr_fail; 768333364Sshurd } 769333364Sshurd 770308696Sshurd /* Get the HW capabilities */ 771308696Sshurd rc = bnxt_hwrm_func_qcaps(softc); 772308696Sshurd if (rc) 773308696Sshurd goto failed; 774333364Sshurd 775333364Sshurd /* Get the current configuration of this function */ 776333364Sshurd rc = bnxt_hwrm_func_qcfg(softc); 777333364Sshurd if (rc) { 778333364Sshurd device_printf(softc->dev, "attach: hwrm func qcfg failed\n"); 779333364Sshurd goto failed; 780333364Sshurd } 781333364Sshurd 782308696Sshurd iflib_set_mac(ctx, softc->func.mac_addr); 783308696Sshurd 784333338Sshurd scctx->isc_txrx = &bnxt_txrx; 785333338Sshurd scctx->isc_tx_csum_flags = (CSUM_IP | CSUM_TCP | CSUM_UDP | 786333338Sshurd CSUM_TCP_IPV6 | CSUM_UDP_IPV6 | CSUM_TSO); 787333338Sshurd scctx->isc_capenable = 788333338Sshurd /* These are translated to hwassit bits */ 789333338Sshurd IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_TSO4 | IFCAP_TSO6 | 790333338Sshurd /* These are checked by iflib */ 791333338Sshurd IFCAP_LRO | IFCAP_VLAN_HWFILTER | 792333338Sshurd /* These are part of the iflib mask */ 793333338Sshurd IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_VLAN_MTU | 794333338Sshurd IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO | 795333338Sshurd /* These likely get lost... */ 796333338Sshurd IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU; 797333338Sshurd 798333364Sshurd if (bnxt_wol_supported(softc)) 799333364Sshurd scctx->isc_capenable |= IFCAP_WOL_MAGIC; 800333364Sshurd 801308696Sshurd /* Get the queue config */ 802308696Sshurd rc = bnxt_hwrm_queue_qportcfg(softc); 803308696Sshurd if (rc) { 804308696Sshurd device_printf(softc->dev, "attach: hwrm qportcfg failed\n"); 805308696Sshurd goto failed; 806308696Sshurd } 807308696Sshurd 808333364Sshurd bnxt_get_wol_settings(softc); 809333364Sshurd 810308696Sshurd /* Now perform a function reset */ 811308696Sshurd rc = bnxt_hwrm_func_reset(softc); 812308696Sshurd bnxt_clear_ids(softc); 813308696Sshurd if (rc) 814308696Sshurd goto failed; 815308696Sshurd 816308696Sshurd /* Now set up iflib sc */ 817308696Sshurd scctx->isc_tx_nsegments = 31, 818308696Sshurd scctx->isc_tx_tso_segments_max = 31; 819308696Sshurd scctx->isc_tx_tso_size_max = BNXT_TSO_SIZE; 820308696Sshurd scctx->isc_tx_tso_segsize_max = BNXT_TSO_SIZE; 821308696Sshurd scctx->isc_vectors = softc->func.max_cp_rings; 822333338Sshurd scctx->isc_min_frame_size = BNXT_MIN_FRAME_SIZE; 823333338Sshurd scctx->isc_txrx = &bnxt_txrx; 824333338Sshurd 825308696Sshurd if (scctx->isc_nrxd[0] < 826308696Sshurd ((scctx->isc_nrxd[1] * 4) + scctx->isc_nrxd[2])) 827308696Sshurd device_printf(softc->dev, 828308696Sshurd "WARNING: nrxd0 (%d) should be at least 4 * nrxd1 (%d) + nrxd2 (%d). Driver may be unstable\n", 829308696Sshurd scctx->isc_nrxd[0], scctx->isc_nrxd[1], scctx->isc_nrxd[2]); 830308696Sshurd if (scctx->isc_ntxd[0] < scctx->isc_ntxd[1] * 2) 831308696Sshurd device_printf(softc->dev, 832308696Sshurd "WARNING: ntxd0 (%d) should be at least 2 * ntxd1 (%d). Driver may be unstable\n", 833308696Sshurd scctx->isc_ntxd[0], scctx->isc_ntxd[1]); 834308696Sshurd scctx->isc_txqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_ntxd[0]; 835308696Sshurd scctx->isc_txqsizes[1] = sizeof(struct tx_bd_short) * 836308696Sshurd scctx->isc_ntxd[1]; 837308696Sshurd scctx->isc_rxqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_nrxd[0]; 838308696Sshurd scctx->isc_rxqsizes[1] = sizeof(struct rx_prod_pkt_bd) * 839308696Sshurd scctx->isc_nrxd[1]; 840308696Sshurd scctx->isc_rxqsizes[2] = sizeof(struct rx_prod_pkt_bd) * 841308696Sshurd scctx->isc_nrxd[2]; 842333364Sshurd 843333338Sshurd scctx->isc_nrxqsets_max = min(pci_msix_count(softc->dev)-1, 844333364Sshurd softc->fn_qcfg.alloc_completion_rings - 1); 845333338Sshurd scctx->isc_nrxqsets_max = min(scctx->isc_nrxqsets_max, 846333364Sshurd softc->fn_qcfg.alloc_rx_rings); 847333364Sshurd scctx->isc_nrxqsets_max = min(scctx->isc_nrxqsets_max, 848333364Sshurd softc->fn_qcfg.alloc_vnics); 849333364Sshurd scctx->isc_ntxqsets_max = min(softc->fn_qcfg.alloc_tx_rings, 850333364Sshurd softc->fn_qcfg.alloc_completion_rings - scctx->isc_nrxqsets_max - 1); 851333364Sshurd 852308696Sshurd scctx->isc_rss_table_size = HW_HASH_INDEX_SIZE; 853308696Sshurd scctx->isc_rss_table_mask = scctx->isc_rss_table_size - 1; 854308696Sshurd 855308696Sshurd /* iflib will map and release this bar */ 856308696Sshurd scctx->isc_msix_bar = pci_msix_table_bar(softc->dev); 857308696Sshurd 858333364Sshurd /* 859333364Sshurd * Default settings for HW LRO (TPA): 860333364Sshurd * Disable HW LRO by default 861333364Sshurd * Can be enabled after taking care of 'packet forwarding' 862333364Sshurd */ 863333364Sshurd softc->hw_lro.enable = 0; 864333364Sshurd softc->hw_lro.is_mode_gro = 0; 865333364Sshurd softc->hw_lro.max_agg_segs = 5; /* 2^5 = 32 segs */ 866333364Sshurd softc->hw_lro.max_aggs = HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX; 867333364Sshurd softc->hw_lro.min_agg_len = 512; 868333364Sshurd 869308696Sshurd /* Allocate the default completion ring */ 870308696Sshurd softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE; 871308696Sshurd softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; 872308696Sshurd softc->def_cp_ring.ring.softc = softc; 873308696Sshurd softc->def_cp_ring.ring.id = 0; 874308696Sshurd softc->def_cp_ring.ring.doorbell = softc->def_cp_ring.ring.id * 0x80; 875308696Sshurd softc->def_cp_ring.ring.ring_size = PAGE_SIZE / 876308696Sshurd sizeof(struct cmpl_base); 877308696Sshurd rc = iflib_dma_alloc(ctx, 878308696Sshurd sizeof(struct cmpl_base) * softc->def_cp_ring.ring.ring_size, 879308696Sshurd &softc->def_cp_ring_mem, 0); 880308696Sshurd softc->def_cp_ring.ring.vaddr = softc->def_cp_ring_mem.idi_vaddr; 881308696Sshurd softc->def_cp_ring.ring.paddr = softc->def_cp_ring_mem.idi_paddr; 882308696Sshurd iflib_config_gtask_init(ctx, &softc->def_cp_task, bnxt_def_cp_task, 883308696Sshurd "dflt_cp"); 884308696Sshurd 885308696Sshurd rc = bnxt_init_sysctl_ctx(softc); 886308696Sshurd if (rc) 887308696Sshurd goto init_sysctl_failed; 888333364Sshurd if (BNXT_PF(softc)) { 889333364Sshurd rc = bnxt_create_nvram_sysctls(softc->nvm_info); 890333364Sshurd if (rc) 891333364Sshurd goto failed; 892333364Sshurd } 893308696Sshurd 894308696Sshurd arc4rand(softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE, 0); 895308696Sshurd softc->vnic_info.rss_hash_type = 896308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 | 897308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 | 898308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 | 899308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 | 900308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 | 901308696Sshurd HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6; 902308696Sshurd rc = bnxt_create_config_sysctls_pre(softc); 903308696Sshurd if (rc) 904308696Sshurd goto failed; 905308696Sshurd 906333364Sshurd rc = bnxt_create_hw_lro_sysctls(softc); 907333364Sshurd if (rc) 908333364Sshurd goto failed; 909333364Sshurd 910333364Sshurd rc = bnxt_create_pause_fc_sysctls(softc); 911333364Sshurd if (rc) 912333364Sshurd goto failed; 913333364Sshurd 914308696Sshurd /* Initialize the vlan list */ 915308696Sshurd SLIST_INIT(&softc->vnic_info.vlan_tags); 916308696Sshurd softc->vnic_info.vlan_tag_list.idi_vaddr = NULL; 917308696Sshurd 918308696Sshurd return (rc); 919308696Sshurd 920308696Sshurdfailed: 921308696Sshurd bnxt_free_sysctl_ctx(softc); 922308696Sshurdinit_sysctl_failed: 923308696Sshurd bnxt_hwrm_func_drv_unrgtr(softc, false); 924308696Sshurddrv_rgtr_fail: 925333364Sshurd if (BNXT_PF(softc)) 926333364Sshurd free(softc->nvm_info, M_DEVBUF); 927308696Sshurdnvm_alloc_fail: 928333364Sshurd bnxt_free_hwrm_short_cmd_req(softc); 929333364Sshurdhwrm_short_cmd_alloc_fail: 930308696Sshurdver_fail: 931308696Sshurd free(softc->ver_info, M_DEVBUF); 932308696Sshurdver_alloc_fail: 933308696Sshurd bnxt_free_hwrm_dma_mem(softc); 934308696Sshurddma_fail: 935308696Sshurd BNXT_HWRM_LOCK_DESTROY(softc); 936308696Sshurd bnxt_pci_mapping_free(softc); 937308696Sshurd pci_disable_busmaster(softc->dev); 938308696Sshurd return (rc); 939308696Sshurd} 940308696Sshurd 941308696Sshurdstatic int 942308696Sshurdbnxt_attach_post(if_ctx_t ctx) 943308696Sshurd{ 944308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 945308696Sshurd if_t ifp = iflib_get_ifp(ctx); 946308696Sshurd int rc; 947308696Sshurd 948308696Sshurd bnxt_create_config_sysctls_post(softc); 949308696Sshurd 950308696Sshurd /* Update link state etc... */ 951308696Sshurd rc = bnxt_probe_phy(softc); 952308696Sshurd if (rc) 953308696Sshurd goto failed; 954308696Sshurd 955308696Sshurd /* Needs to be done after probing the phy */ 956308696Sshurd bnxt_create_ver_sysctls(softc); 957308696Sshurd bnxt_add_media_types(softc); 958308696Sshurd ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); 959308696Sshurd 960308696Sshurd softc->scctx->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN + 961308696Sshurd ETHER_CRC_LEN; 962308696Sshurd 963308696Sshurdfailed: 964308696Sshurd return rc; 965308696Sshurd} 966308696Sshurd 967308696Sshurdstatic int 968308696Sshurdbnxt_detach(if_ctx_t ctx) 969308696Sshurd{ 970308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 971308696Sshurd struct bnxt_vlan_tag *tag; 972308696Sshurd struct bnxt_vlan_tag *tmp; 973308696Sshurd int i; 974308696Sshurd 975333364Sshurd bnxt_wol_config(ctx); 976308696Sshurd bnxt_do_disable_intr(&softc->def_cp_ring); 977308696Sshurd bnxt_free_sysctl_ctx(softc); 978308696Sshurd bnxt_hwrm_func_reset(softc); 979308696Sshurd bnxt_clear_ids(softc); 980308696Sshurd iflib_irq_free(ctx, &softc->def_cp_ring.irq); 981308696Sshurd iflib_config_gtask_deinit(&softc->def_cp_task); 982308696Sshurd /* We need to free() these here... */ 983308696Sshurd for (i = softc->nrxqsets-1; i>=0; i--) { 984308696Sshurd iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); 985308696Sshurd } 986308696Sshurd iflib_dma_free(&softc->vnic_info.mc_list); 987308696Sshurd iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl); 988308696Sshurd iflib_dma_free(&softc->vnic_info.rss_grp_tbl); 989308696Sshurd if (softc->vnic_info.vlan_tag_list.idi_vaddr) 990308696Sshurd iflib_dma_free(&softc->vnic_info.vlan_tag_list); 991308696Sshurd SLIST_FOREACH_SAFE(tag, &softc->vnic_info.vlan_tags, next, tmp) 992308696Sshurd free(tag, M_DEVBUF); 993308696Sshurd iflib_dma_free(&softc->def_cp_ring_mem); 994333338Sshurd for (i = 0; i < softc->nrxqsets; i++) 995333338Sshurd free(softc->rx_rings[i].tpa_start, M_DEVBUF); 996308696Sshurd free(softc->ver_info, M_DEVBUF); 997333364Sshurd if (BNXT_PF(softc)) 998333364Sshurd free(softc->nvm_info, M_DEVBUF); 999308696Sshurd 1000308696Sshurd bnxt_hwrm_func_drv_unrgtr(softc, false); 1001308696Sshurd bnxt_free_hwrm_dma_mem(softc); 1002333364Sshurd bnxt_free_hwrm_short_cmd_req(softc); 1003308696Sshurd BNXT_HWRM_LOCK_DESTROY(softc); 1004308696Sshurd 1005308696Sshurd pci_disable_busmaster(softc->dev); 1006308696Sshurd bnxt_pci_mapping_free(softc); 1007308696Sshurd 1008308696Sshurd return 0; 1009308696Sshurd} 1010308696Sshurd 1011308696Sshurd/* Device configuration */ 1012308696Sshurdstatic void 1013308696Sshurdbnxt_init(if_ctx_t ctx) 1014308696Sshurd{ 1015308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1016309377Sshurd struct ifmediareq ifmr; 1017308696Sshurd int i, j; 1018308696Sshurd int rc; 1019308696Sshurd 1020308696Sshurd rc = bnxt_hwrm_func_reset(softc); 1021308696Sshurd if (rc) 1022308696Sshurd return; 1023308696Sshurd bnxt_clear_ids(softc); 1024308696Sshurd 1025308696Sshurd /* Allocate the default completion ring */ 1026308696Sshurd softc->def_cp_ring.cons = UINT32_MAX; 1027308696Sshurd softc->def_cp_ring.v_bit = 1; 1028308696Sshurd bnxt_mark_cpr_invalid(&softc->def_cp_ring); 1029308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 1030333364Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, 1031308696Sshurd &softc->def_cp_ring.ring, 1032308696Sshurd (uint16_t)HWRM_NA_SIGNATURE, 1033308696Sshurd HWRM_NA_SIGNATURE, true); 1034308696Sshurd if (rc) 1035308696Sshurd goto fail; 1036308696Sshurd 1037308696Sshurd /* And now set the default CP ring as the async CP ring */ 1038333364Sshurd rc = bnxt_cfg_async_cr(softc); 1039308696Sshurd if (rc) 1040308696Sshurd goto fail; 1041308696Sshurd 1042308696Sshurd for (i = 0; i < softc->nrxqsets; i++) { 1043308696Sshurd /* Allocate the statistics context */ 1044308696Sshurd rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i], 1045308696Sshurd softc->rx_stats.idi_paddr + 1046308696Sshurd (sizeof(struct ctx_hw_stats) * i)); 1047308696Sshurd if (rc) 1048308696Sshurd goto fail; 1049308696Sshurd 1050308696Sshurd /* Allocate the completion ring */ 1051308696Sshurd softc->rx_cp_rings[i].cons = UINT32_MAX; 1052308696Sshurd softc->rx_cp_rings[i].v_bit = 1; 1053308696Sshurd softc->rx_cp_rings[i].last_idx = UINT32_MAX; 1054308696Sshurd bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]); 1055308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 1056333364Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, 1057308696Sshurd &softc->rx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, 1058308696Sshurd HWRM_NA_SIGNATURE, true); 1059308696Sshurd if (rc) 1060308696Sshurd goto fail; 1061308696Sshurd 1062308696Sshurd /* Allocate the RX ring */ 1063308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 1064308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, 1065308696Sshurd &softc->rx_rings[i], (uint16_t)HWRM_NA_SIGNATURE, 1066308696Sshurd HWRM_NA_SIGNATURE, false); 1067308696Sshurd if (rc) 1068308696Sshurd goto fail; 1069308696Sshurd BNXT_RX_DB(&softc->rx_rings[i], 0); 1070308696Sshurd /* TODO: Cumulus+ doesn't need the double doorbell */ 1071308696Sshurd BNXT_RX_DB(&softc->rx_rings[i], 0); 1072308696Sshurd 1073308696Sshurd /* Allocate the AG ring */ 1074308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 1075308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_RX, 1076308696Sshurd &softc->ag_rings[i], (uint16_t)HWRM_NA_SIGNATURE, 1077308696Sshurd HWRM_NA_SIGNATURE, false); 1078308696Sshurd if (rc) 1079308696Sshurd goto fail; 1080308696Sshurd BNXT_RX_DB(&softc->rx_rings[i], 0); 1081308696Sshurd /* TODO: Cumulus+ doesn't need the double doorbell */ 1082308696Sshurd BNXT_RX_DB(&softc->ag_rings[i], 0); 1083308696Sshurd 1084308696Sshurd /* Allocate the ring group */ 1085308696Sshurd softc->grp_info[i].stats_ctx = 1086308696Sshurd softc->rx_cp_rings[i].stats_ctx_id; 1087308696Sshurd softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id; 1088308696Sshurd softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id; 1089308696Sshurd softc->grp_info[i].cp_ring_id = 1090308696Sshurd softc->rx_cp_rings[i].ring.phys_id; 1091308696Sshurd rc = bnxt_hwrm_ring_grp_alloc(softc, &softc->grp_info[i]); 1092308696Sshurd if (rc) 1093308696Sshurd goto fail; 1094308696Sshurd 1095308696Sshurd } 1096308696Sshurd 1097308696Sshurd /* Allocate the VNIC RSS context */ 1098308696Sshurd rc = bnxt_hwrm_vnic_ctx_alloc(softc, &softc->vnic_info.rss_id); 1099308696Sshurd if (rc) 1100308696Sshurd goto fail; 1101308696Sshurd 1102308696Sshurd /* Allocate the vnic */ 1103308696Sshurd softc->vnic_info.def_ring_grp = softc->grp_info[0].grp_id; 1104308696Sshurd softc->vnic_info.mru = softc->scctx->isc_max_frame_size; 1105308696Sshurd rc = bnxt_hwrm_vnic_alloc(softc, &softc->vnic_info); 1106308696Sshurd if (rc) 1107308696Sshurd goto fail; 1108308696Sshurd rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info); 1109308696Sshurd if (rc) 1110308696Sshurd goto fail; 1111308696Sshurd rc = bnxt_hwrm_set_filter(softc, &softc->vnic_info); 1112308696Sshurd if (rc) 1113308696Sshurd goto fail; 1114308696Sshurd 1115308696Sshurd /* Enable RSS on the VNICs */ 1116308696Sshurd for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) { 1117308696Sshurd ((uint16_t *) 1118308696Sshurd softc->vnic_info.rss_grp_tbl.idi_vaddr)[i] = 1119308696Sshurd htole16(softc->grp_info[j].grp_id); 1120308696Sshurd if (++j == softc->nrxqsets) 1121308696Sshurd j = 0; 1122308696Sshurd } 1123308696Sshurd 1124308696Sshurd rc = bnxt_hwrm_rss_cfg(softc, &softc->vnic_info, 1125308696Sshurd softc->vnic_info.rss_hash_type); 1126308696Sshurd if (rc) 1127308696Sshurd goto fail; 1128308696Sshurd 1129333364Sshurd rc = bnxt_hwrm_vnic_tpa_cfg(softc); 1130308696Sshurd if (rc) 1131308696Sshurd goto fail; 1132308696Sshurd 1133308696Sshurd for (i = 0; i < softc->ntxqsets; i++) { 1134308696Sshurd /* Allocate the statistics context */ 1135308696Sshurd rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->tx_cp_rings[i], 1136308696Sshurd softc->tx_stats.idi_paddr + 1137308696Sshurd (sizeof(struct ctx_hw_stats) * i)); 1138308696Sshurd if (rc) 1139308696Sshurd goto fail; 1140308696Sshurd 1141308696Sshurd /* Allocate the completion ring */ 1142308696Sshurd softc->tx_cp_rings[i].cons = UINT32_MAX; 1143308696Sshurd softc->tx_cp_rings[i].v_bit = 1; 1144308696Sshurd bnxt_mark_cpr_invalid(&softc->tx_cp_rings[i]); 1145308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 1146333364Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL, 1147308696Sshurd &softc->tx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE, 1148308696Sshurd HWRM_NA_SIGNATURE, false); 1149308696Sshurd if (rc) 1150308696Sshurd goto fail; 1151308696Sshurd 1152308696Sshurd /* Allocate the TX ring */ 1153308696Sshurd rc = bnxt_hwrm_ring_alloc(softc, 1154308696Sshurd HWRM_RING_ALLOC_INPUT_RING_TYPE_TX, 1155308696Sshurd &softc->tx_rings[i], softc->tx_cp_rings[i].ring.phys_id, 1156308696Sshurd softc->tx_cp_rings[i].stats_ctx_id, false); 1157308696Sshurd if (rc) 1158308696Sshurd goto fail; 1159308696Sshurd BNXT_TX_DB(&softc->tx_rings[i], 0); 1160308696Sshurd /* TODO: Cumulus+ doesn't need the double doorbell */ 1161308696Sshurd BNXT_TX_DB(&softc->tx_rings[i], 0); 1162308696Sshurd } 1163308696Sshurd 1164308696Sshurd bnxt_do_enable_intr(&softc->def_cp_ring); 1165309377Sshurd bnxt_media_status(softc->ctx, &ifmr); 1166333364Sshurd bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); 1167308696Sshurd return; 1168308696Sshurd 1169308696Sshurdfail: 1170308696Sshurd bnxt_hwrm_func_reset(softc); 1171308696Sshurd bnxt_clear_ids(softc); 1172308696Sshurd return; 1173308696Sshurd} 1174308696Sshurd 1175308696Sshurdstatic void 1176308696Sshurdbnxt_stop(if_ctx_t ctx) 1177308696Sshurd{ 1178308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1179308696Sshurd 1180308696Sshurd bnxt_do_disable_intr(&softc->def_cp_ring); 1181308696Sshurd bnxt_hwrm_func_reset(softc); 1182308696Sshurd bnxt_clear_ids(softc); 1183308696Sshurd return; 1184308696Sshurd} 1185308696Sshurd 1186308696Sshurdstatic void 1187308696Sshurdbnxt_multi_set(if_ctx_t ctx) 1188308696Sshurd{ 1189308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1190308696Sshurd if_t ifp = iflib_get_ifp(ctx); 1191308696Sshurd uint8_t *mta; 1192308696Sshurd int cnt, mcnt; 1193308696Sshurd 1194308696Sshurd mcnt = if_multiaddr_count(ifp, -1); 1195308696Sshurd 1196308696Sshurd if (mcnt > BNXT_MAX_MC_ADDRS) { 1197308696Sshurd softc->vnic_info.rx_mask |= 1198308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; 1199308696Sshurd bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); 1200308696Sshurd } 1201308696Sshurd else { 1202308696Sshurd softc->vnic_info.rx_mask &= 1203308696Sshurd ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; 1204308696Sshurd mta = softc->vnic_info.mc_list.idi_vaddr; 1205308696Sshurd bzero(mta, softc->vnic_info.mc_list.idi_size); 1206308696Sshurd if_multiaddr_array(ifp, mta, &cnt, mcnt); 1207308696Sshurd bus_dmamap_sync(softc->vnic_info.mc_list.idi_tag, 1208308696Sshurd softc->vnic_info.mc_list.idi_map, BUS_DMASYNC_PREWRITE); 1209308696Sshurd softc->vnic_info.mc_list_count = cnt; 1210308696Sshurd softc->vnic_info.rx_mask |= 1211308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST; 1212308696Sshurd if (bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info)) 1213308696Sshurd device_printf(softc->dev, 1214308696Sshurd "set_multi: rx_mask set failed\n"); 1215308696Sshurd } 1216308696Sshurd} 1217308696Sshurd 1218308696Sshurdstatic int 1219308696Sshurdbnxt_mtu_set(if_ctx_t ctx, uint32_t mtu) 1220308696Sshurd{ 1221308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1222308696Sshurd 1223308696Sshurd if (mtu > BNXT_MAX_MTU) 1224308696Sshurd return EINVAL; 1225308696Sshurd 1226308696Sshurd softc->scctx->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 1227308696Sshurd return 0; 1228308696Sshurd} 1229308696Sshurd 1230308696Sshurdstatic void 1231308696Sshurdbnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) 1232308696Sshurd{ 1233308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1234308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 1235333364Sshurd struct ifmedia_entry *next; 1236333364Sshurd uint64_t target_baudrate = bnxt_get_baudrate(link_info); 1237333364Sshurd int active_media = IFM_UNKNOWN; 1238308696Sshurd 1239333364Sshurd 1240308696Sshurd bnxt_update_link(softc, true); 1241308696Sshurd 1242308696Sshurd ifmr->ifm_status = IFM_AVALID; 1243308696Sshurd ifmr->ifm_active = IFM_ETHER; 1244308696Sshurd 1245308696Sshurd if (link_info->link_up) 1246308696Sshurd ifmr->ifm_status |= IFM_ACTIVE; 1247308696Sshurd else 1248308696Sshurd ifmr->ifm_status &= ~IFM_ACTIVE; 1249308696Sshurd 1250333364Sshurd if (link_info->duplex == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_CFG_FULL) 1251308696Sshurd ifmr->ifm_active |= IFM_FDX; 1252308696Sshurd else 1253308696Sshurd ifmr->ifm_active |= IFM_HDX; 1254308696Sshurd 1255333364Sshurd /* 1256333364Sshurd * Go through the list of supported media which got prepared 1257333364Sshurd * as part of bnxt_add_media_types() using api ifmedia_add(). 1258333364Sshurd */ 1259333364Sshurd LIST_FOREACH(next, &(iflib_get_media(ctx)->ifm_list), ifm_list) { 1260333364Sshurd if (ifmedia_baudrate(next->ifm_media) == target_baudrate) { 1261333364Sshurd active_media = next->ifm_media; 1262308696Sshurd break; 1263308696Sshurd } 1264308696Sshurd } 1265333364Sshurd ifmr->ifm_active |= active_media; 1266308696Sshurd 1267333364Sshurd if (link_info->flow_ctrl.rx) 1268333364Sshurd ifmr->ifm_active |= IFM_ETH_RXPAUSE; 1269333364Sshurd if (link_info->flow_ctrl.tx) 1270308696Sshurd ifmr->ifm_active |= IFM_ETH_TXPAUSE; 1271308696Sshurd 1272308696Sshurd bnxt_report_link(softc); 1273308696Sshurd return; 1274308696Sshurd} 1275308696Sshurd 1276308696Sshurdstatic int 1277308696Sshurdbnxt_media_change(if_ctx_t ctx) 1278308696Sshurd{ 1279308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1280308696Sshurd struct ifmedia *ifm = iflib_get_media(ctx); 1281308696Sshurd struct ifmediareq ifmr; 1282308696Sshurd int rc; 1283308696Sshurd 1284308696Sshurd if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 1285308696Sshurd return EINVAL; 1286308696Sshurd 1287308696Sshurd switch (IFM_SUBTYPE(ifm->ifm_media)) { 1288308696Sshurd case IFM_100_T: 1289308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1290308696Sshurd softc->link_info.req_link_speed = 1291308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100MB; 1292308696Sshurd break; 1293308696Sshurd case IFM_1000_KX: 1294308696Sshurd case IFM_1000_T: 1295308696Sshurd case IFM_1000_SGMII: 1296308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1297308696Sshurd softc->link_info.req_link_speed = 1298308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB; 1299308696Sshurd break; 1300308696Sshurd case IFM_2500_KX: 1301308696Sshurd case IFM_2500_T: 1302308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1303308696Sshurd softc->link_info.req_link_speed = 1304308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2_5GB; 1305308696Sshurd break; 1306308696Sshurd case IFM_10G_CR1: 1307308696Sshurd case IFM_10G_KR: 1308308696Sshurd case IFM_10G_LR: 1309308696Sshurd case IFM_10G_SR: 1310308696Sshurd case IFM_10G_T: 1311308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1312308696Sshurd softc->link_info.req_link_speed = 1313308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB; 1314308696Sshurd break; 1315308696Sshurd case IFM_20G_KR2: 1316308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1317308696Sshurd softc->link_info.req_link_speed = 1318308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_20GB; 1319308696Sshurd break; 1320308696Sshurd case IFM_25G_CR: 1321308696Sshurd case IFM_25G_KR: 1322308696Sshurd case IFM_25G_SR: 1323308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1324308696Sshurd softc->link_info.req_link_speed = 1325308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB; 1326308696Sshurd break; 1327308696Sshurd case IFM_40G_CR4: 1328308696Sshurd case IFM_40G_KR4: 1329308696Sshurd case IFM_40G_LR4: 1330308696Sshurd case IFM_40G_SR4: 1331308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1332308696Sshurd softc->link_info.req_link_speed = 1333308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB; 1334308696Sshurd break; 1335308696Sshurd case IFM_50G_CR2: 1336308696Sshurd case IFM_50G_KR2: 1337308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1338308696Sshurd softc->link_info.req_link_speed = 1339308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB; 1340308696Sshurd break; 1341308696Sshurd case IFM_100G_CR4: 1342308696Sshurd case IFM_100G_KR4: 1343308696Sshurd case IFM_100G_LR4: 1344308696Sshurd case IFM_100G_SR4: 1345308696Sshurd softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED; 1346308696Sshurd softc->link_info.req_link_speed = 1347308696Sshurd HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB; 1348308696Sshurd break; 1349308696Sshurd default: 1350308696Sshurd device_printf(softc->dev, 1351308696Sshurd "Unsupported media type! Using auto\n"); 1352308696Sshurd /* Fall-through */ 1353308696Sshurd case IFM_AUTO: 1354308696Sshurd // Auto 1355308696Sshurd softc->link_info.autoneg |= BNXT_AUTONEG_SPEED; 1356308696Sshurd break; 1357308696Sshurd } 1358333364Sshurd rc = bnxt_hwrm_set_link_setting(softc, true, true, true); 1359308696Sshurd bnxt_media_status(softc->ctx, &ifmr); 1360308696Sshurd return rc; 1361308696Sshurd} 1362308696Sshurd 1363308696Sshurdstatic int 1364308696Sshurdbnxt_promisc_set(if_ctx_t ctx, int flags) 1365308696Sshurd{ 1366308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1367308696Sshurd if_t ifp = iflib_get_ifp(ctx); 1368308696Sshurd int rc; 1369308696Sshurd 1370308696Sshurd if (ifp->if_flags & IFF_ALLMULTI || 1371308696Sshurd if_multiaddr_count(ifp, -1) > BNXT_MAX_MC_ADDRS) 1372308696Sshurd softc->vnic_info.rx_mask |= 1373308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; 1374308696Sshurd else 1375308696Sshurd softc->vnic_info.rx_mask &= 1376308696Sshurd ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST; 1377308696Sshurd 1378308696Sshurd if (ifp->if_flags & IFF_PROMISC) 1379308696Sshurd softc->vnic_info.rx_mask |= 1380308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS | 1381308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN; 1382308696Sshurd else 1383308696Sshurd softc->vnic_info.rx_mask &= 1384308696Sshurd ~(HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS | 1385308696Sshurd HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN); 1386308696Sshurd 1387308696Sshurd rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info); 1388308696Sshurd 1389308696Sshurd return rc; 1390308696Sshurd} 1391308696Sshurd 1392308696Sshurdstatic uint64_t 1393308696Sshurdbnxt_get_counter(if_ctx_t ctx, ift_counter cnt) 1394308696Sshurd{ 1395308696Sshurd if_t ifp = iflib_get_ifp(ctx); 1396308696Sshurd 1397308696Sshurd if (cnt < IFCOUNTERS) 1398308696Sshurd return if_get_counter_default(ifp, cnt); 1399308696Sshurd 1400308696Sshurd return 0; 1401308696Sshurd} 1402308696Sshurd 1403308696Sshurdstatic void 1404308696Sshurdbnxt_update_admin_status(if_ctx_t ctx) 1405308696Sshurd{ 1406333364Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1407333364Sshurd 1408333364Sshurd /* 1409333364Sshurd * When SR-IOV is enabled, avoid each VF sending this HWRM 1410333364Sshurd * request every sec with which firmware timeouts can happen 1411333364Sshurd */ 1412333364Sshurd if (BNXT_PF(softc)) { 1413333364Sshurd bnxt_hwrm_port_qstats(softc); 1414333364Sshurd } 1415333364Sshurd 1416308696Sshurd return; 1417308696Sshurd} 1418308696Sshurd 1419333364Sshurdstatic void 1420333364Sshurdbnxt_if_timer(if_ctx_t ctx, uint16_t qid) 1421333364Sshurd{ 1422333364Sshurd 1423333364Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1424333364Sshurd uint64_t ticks_now = ticks; 1425333364Sshurd 1426333364Sshurd /* Schedule bnxt_update_admin_status() once per sec */ 1427333364Sshurd if (ticks_now - softc->admin_ticks >= hz) { 1428333364Sshurd softc->admin_ticks = ticks_now; 1429333364Sshurd iflib_admin_intr_deferred(ctx); 1430333364Sshurd } 1431333364Sshurd 1432333364Sshurd return; 1433333364Sshurd} 1434333364Sshurd 1435308696Sshurdstatic void inline 1436308696Sshurdbnxt_do_enable_intr(struct bnxt_cp_ring *cpr) 1437308696Sshurd{ 1438308696Sshurd if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) { 1439308696Sshurd /* First time enabling, do not set index */ 1440308696Sshurd if (cpr->cons == UINT32_MAX) 1441308696Sshurd BNXT_CP_ENABLE_DB(&cpr->ring); 1442308696Sshurd else 1443308696Sshurd BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons); 1444308696Sshurd } 1445308696Sshurd} 1446308696Sshurd 1447308696Sshurdstatic void inline 1448308696Sshurdbnxt_do_disable_intr(struct bnxt_cp_ring *cpr) 1449308696Sshurd{ 1450308696Sshurd if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) 1451308696Sshurd BNXT_CP_DISABLE_DB(&cpr->ring); 1452308696Sshurd} 1453308696Sshurd 1454308696Sshurd/* Enable all interrupts */ 1455308696Sshurdstatic void 1456308696Sshurdbnxt_intr_enable(if_ctx_t ctx) 1457308696Sshurd{ 1458308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1459308696Sshurd int i; 1460308696Sshurd 1461308696Sshurd bnxt_do_enable_intr(&softc->def_cp_ring); 1462308696Sshurd for (i = 0; i < softc->nrxqsets; i++) 1463308696Sshurd bnxt_do_enable_intr(&softc->rx_cp_rings[i]); 1464308696Sshurd 1465308696Sshurd return; 1466308696Sshurd} 1467308696Sshurd 1468308696Sshurd/* Enable interrupt for a single queue */ 1469308696Sshurdstatic int 1470333364Sshurdbnxt_tx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) 1471308696Sshurd{ 1472308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1473308696Sshurd 1474333364Sshurd bnxt_do_enable_intr(&softc->tx_cp_rings[qid]); 1475333364Sshurd return 0; 1476333364Sshurd} 1477333364Sshurd 1478333364Sshurdstatic int 1479333364Sshurdbnxt_rx_queue_intr_enable(if_ctx_t ctx, uint16_t qid) 1480333364Sshurd{ 1481333364Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1482333364Sshurd 1483308696Sshurd bnxt_do_enable_intr(&softc->rx_cp_rings[qid]); 1484308696Sshurd return 0; 1485308696Sshurd} 1486308696Sshurd 1487308696Sshurd/* Disable all interrupts */ 1488308696Sshurdstatic void 1489308696Sshurdbnxt_disable_intr(if_ctx_t ctx) 1490308696Sshurd{ 1491308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1492308696Sshurd int i; 1493308696Sshurd 1494308696Sshurd /* 1495308696Sshurd * NOTE: These TX interrupts should never get enabled, so don't 1496308696Sshurd * update the index 1497308696Sshurd */ 1498308696Sshurd for (i = 0; i < softc->ntxqsets; i++) 1499308696Sshurd bnxt_do_disable_intr(&softc->tx_cp_rings[i]); 1500308696Sshurd for (i = 0; i < softc->nrxqsets; i++) 1501308696Sshurd bnxt_do_disable_intr(&softc->rx_cp_rings[i]); 1502308696Sshurd 1503308696Sshurd return; 1504308696Sshurd} 1505308696Sshurd 1506308696Sshurdstatic int 1507308696Sshurdbnxt_msix_intr_assign(if_ctx_t ctx, int msix) 1508308696Sshurd{ 1509308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1510308696Sshurd int rc; 1511308696Sshurd int i; 1512333364Sshurd char irq_name[16]; 1513308696Sshurd 1514308696Sshurd rc = iflib_irq_alloc_generic(ctx, &softc->def_cp_ring.irq, 1515308696Sshurd softc->def_cp_ring.ring.id + 1, IFLIB_INTR_ADMIN, 1516308696Sshurd bnxt_handle_def_cp, softc, 0, "def_cp"); 1517308696Sshurd if (rc) { 1518308696Sshurd device_printf(iflib_get_dev(ctx), 1519308696Sshurd "Failed to register default completion ring handler\n"); 1520308696Sshurd return rc; 1521308696Sshurd } 1522308696Sshurd 1523308696Sshurd for (i=0; i<softc->scctx->isc_nrxqsets; i++) { 1524333364Sshurd snprintf(irq_name, sizeof(irq_name), "rxq%d", i); 1525308696Sshurd rc = iflib_irq_alloc_generic(ctx, &softc->rx_cp_rings[i].irq, 1526333364Sshurd softc->rx_cp_rings[i].ring.id + 1, IFLIB_INTR_RX, 1527333364Sshurd bnxt_handle_rx_cp, &softc->rx_cp_rings[i], i, irq_name); 1528308696Sshurd if (rc) { 1529308696Sshurd device_printf(iflib_get_dev(ctx), 1530308696Sshurd "Failed to register RX completion ring handler\n"); 1531308696Sshurd i--; 1532308696Sshurd goto fail; 1533308696Sshurd } 1534308696Sshurd } 1535308696Sshurd 1536308696Sshurd for (i=0; i<softc->scctx->isc_ntxqsets; i++) 1537333338Sshurd iflib_softirq_alloc_generic(ctx, NULL, IFLIB_INTR_TX, NULL, i, "tx_cp"); 1538308696Sshurd 1539308696Sshurd return rc; 1540308696Sshurd 1541308696Sshurdfail: 1542308696Sshurd for (; i>=0; i--) 1543308696Sshurd iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq); 1544308696Sshurd iflib_irq_free(ctx, &softc->def_cp_ring.irq); 1545308696Sshurd return rc; 1546308696Sshurd} 1547308696Sshurd 1548308696Sshurd/* 1549308696Sshurd * We're explicitly allowing duplicates here. They will need to be 1550308696Sshurd * removed as many times as they are added. 1551308696Sshurd */ 1552308696Sshurdstatic void 1553308696Sshurdbnxt_vlan_register(if_ctx_t ctx, uint16_t vtag) 1554308696Sshurd{ 1555308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1556308696Sshurd struct bnxt_vlan_tag *new_tag; 1557308696Sshurd 1558308696Sshurd new_tag = malloc(sizeof(struct bnxt_vlan_tag), M_DEVBUF, M_NOWAIT); 1559308696Sshurd if (new_tag == NULL) 1560308696Sshurd return; 1561308696Sshurd new_tag->tag = vtag; 1562308696Sshurd new_tag->tpid = 8100; 1563308696Sshurd SLIST_INSERT_HEAD(&softc->vnic_info.vlan_tags, new_tag, next); 1564308696Sshurd}; 1565308696Sshurd 1566308696Sshurdstatic void 1567308696Sshurdbnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag) 1568308696Sshurd{ 1569308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1570308696Sshurd struct bnxt_vlan_tag *vlan_tag; 1571308696Sshurd 1572308696Sshurd SLIST_FOREACH(vlan_tag, &softc->vnic_info.vlan_tags, next) { 1573308696Sshurd if (vlan_tag->tag == vtag) { 1574308696Sshurd SLIST_REMOVE(&softc->vnic_info.vlan_tags, vlan_tag, 1575308696Sshurd bnxt_vlan_tag, next); 1576308696Sshurd free(vlan_tag, M_DEVBUF); 1577308696Sshurd break; 1578308696Sshurd } 1579308696Sshurd } 1580308696Sshurd} 1581308696Sshurd 1582308696Sshurdstatic int 1583333364Sshurdbnxt_wol_config(if_ctx_t ctx) 1584333364Sshurd{ 1585333364Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1586333364Sshurd if_t ifp = iflib_get_ifp(ctx); 1587333364Sshurd 1588333364Sshurd if (!softc) 1589333364Sshurd return -EBUSY; 1590333364Sshurd 1591333364Sshurd if (!bnxt_wol_supported(softc)) 1592333364Sshurd return -ENOTSUP; 1593333364Sshurd 1594333364Sshurd if (if_getcapabilities(ifp) & IFCAP_WOL_MAGIC) { 1595333364Sshurd if (!softc->wol) { 1596333364Sshurd if (bnxt_hwrm_alloc_wol_fltr(softc)) 1597333364Sshurd return -EBUSY; 1598333364Sshurd softc->wol = 1; 1599333364Sshurd } 1600333364Sshurd } else { 1601333364Sshurd if (softc->wol) { 1602333364Sshurd if (bnxt_hwrm_free_wol_fltr(softc)) 1603333364Sshurd return -EBUSY; 1604333364Sshurd softc->wol = 0; 1605333364Sshurd } 1606333364Sshurd } 1607333364Sshurd 1608333364Sshurd return 0; 1609333364Sshurd} 1610333364Sshurd 1611333364Sshurdstatic int 1612333364Sshurdbnxt_shutdown(if_ctx_t ctx) 1613333364Sshurd{ 1614333364Sshurd bnxt_wol_config(ctx); 1615333364Sshurd return 0; 1616333364Sshurd} 1617333364Sshurd 1618333364Sshurdstatic int 1619333364Sshurdbnxt_suspend(if_ctx_t ctx) 1620333364Sshurd{ 1621333364Sshurd bnxt_wol_config(ctx); 1622333364Sshurd return 0; 1623333364Sshurd} 1624333364Sshurd 1625333364Sshurdstatic int 1626333364Sshurdbnxt_resume(if_ctx_t ctx) 1627333364Sshurd{ 1628333364Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1629333364Sshurd 1630333364Sshurd bnxt_get_wol_settings(softc); 1631333364Sshurd return 0; 1632333364Sshurd} 1633333364Sshurd 1634333364Sshurdstatic int 1635308696Sshurdbnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data) 1636308696Sshurd{ 1637308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 1638308696Sshurd struct ifreq *ifr = (struct ifreq *)data; 1639359026Sbrooks struct bnxt_ioctl_header *ioh; 1640359026Sbrooks size_t iol; 1641308696Sshurd int rc = ENOTSUP; 1642359026Sbrooks struct bnxt_ioctl_data iod_storage, *iod = &iod_storage; 1643308696Sshurd 1644359026Sbrooks 1645308696Sshurd switch (command) { 1646308696Sshurd case SIOCGPRIVATE_0: 1647308696Sshurd if ((rc = priv_check(curthread, PRIV_DRIVER)) != 0) 1648308696Sshurd goto exit; 1649308696Sshurd 1650359026Sbrooks ioh = ifr_buffer_get_buffer(ifr); 1651359026Sbrooks iol = ifr_buffer_get_length(ifr); 1652359026Sbrooks if (iol > sizeof(iod_storage)) 1653359026Sbrooks return (EINVAL); 1654359026Sbrooks 1655359026Sbrooks if ((rc = copyin(ioh, iod, iol)) != 0) 1656308696Sshurd goto exit; 1657308696Sshurd 1658359026Sbrooks switch (iod->hdr.type) { 1659308696Sshurd case BNXT_HWRM_NVM_FIND_DIR_ENTRY: 1660308696Sshurd { 1661308696Sshurd struct bnxt_ioctl_hwrm_nvm_find_dir_entry *find = 1662308696Sshurd &iod->find; 1663308696Sshurd 1664308696Sshurd rc = bnxt_hwrm_nvm_find_dir_entry(softc, find->type, 1665308696Sshurd &find->ordinal, find->ext, &find->index, 1666308696Sshurd find->use_index, find->search_opt, 1667308696Sshurd &find->data_length, &find->item_length, 1668308696Sshurd &find->fw_ver); 1669308696Sshurd if (rc) { 1670308696Sshurd iod->hdr.rc = rc; 1671308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1672308696Sshurd sizeof(ioh->rc)); 1673308696Sshurd } 1674308696Sshurd else { 1675308696Sshurd iod->hdr.rc = 0; 1676359026Sbrooks copyout(iod, ioh, iol); 1677308696Sshurd } 1678308696Sshurd 1679308696Sshurd rc = 0; 1680308696Sshurd goto exit; 1681308696Sshurd } 1682308696Sshurd case BNXT_HWRM_NVM_READ: 1683308696Sshurd { 1684308696Sshurd struct bnxt_ioctl_hwrm_nvm_read *rd = &iod->read; 1685308696Sshurd struct iflib_dma_info dma_data; 1686308696Sshurd size_t offset; 1687308696Sshurd size_t remain; 1688308696Sshurd size_t csize; 1689308696Sshurd 1690308696Sshurd /* 1691308696Sshurd * Some HWRM versions can't read more than 0x8000 bytes 1692308696Sshurd */ 1693308696Sshurd rc = iflib_dma_alloc(softc->ctx, 1694308696Sshurd min(rd->length, 0x8000), &dma_data, BUS_DMA_NOWAIT); 1695308696Sshurd if (rc) 1696308696Sshurd break; 1697308696Sshurd for (remain = rd->length, offset = 0; 1698308696Sshurd remain && offset < rd->length; offset += 0x8000) { 1699308696Sshurd csize = min(remain, 0x8000); 1700308696Sshurd rc = bnxt_hwrm_nvm_read(softc, rd->index, 1701308696Sshurd rd->offset + offset, csize, &dma_data); 1702308696Sshurd if (rc) { 1703308696Sshurd iod->hdr.rc = rc; 1704308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1705308696Sshurd sizeof(ioh->rc)); 1706308696Sshurd break; 1707308696Sshurd } 1708308696Sshurd else { 1709308696Sshurd copyout(dma_data.idi_vaddr, 1710308696Sshurd rd->data + offset, csize); 1711308696Sshurd iod->hdr.rc = 0; 1712308696Sshurd } 1713308696Sshurd remain -= csize; 1714308696Sshurd } 1715308696Sshurd if (iod->hdr.rc == 0) 1716359026Sbrooks copyout(iod, ioh, iol); 1717308696Sshurd 1718308696Sshurd iflib_dma_free(&dma_data); 1719308696Sshurd rc = 0; 1720308696Sshurd goto exit; 1721308696Sshurd } 1722308696Sshurd case BNXT_HWRM_FW_RESET: 1723308696Sshurd { 1724308696Sshurd struct bnxt_ioctl_hwrm_fw_reset *rst = 1725308696Sshurd &iod->reset; 1726308696Sshurd 1727308696Sshurd rc = bnxt_hwrm_fw_reset(softc, rst->processor, 1728308696Sshurd &rst->selfreset); 1729308696Sshurd if (rc) { 1730308696Sshurd iod->hdr.rc = rc; 1731308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1732308696Sshurd sizeof(ioh->rc)); 1733308696Sshurd } 1734308696Sshurd else { 1735308696Sshurd iod->hdr.rc = 0; 1736359026Sbrooks copyout(iod, ioh, iol); 1737308696Sshurd } 1738308696Sshurd 1739308696Sshurd rc = 0; 1740308696Sshurd goto exit; 1741308696Sshurd } 1742308696Sshurd case BNXT_HWRM_FW_QSTATUS: 1743308696Sshurd { 1744308696Sshurd struct bnxt_ioctl_hwrm_fw_qstatus *qstat = 1745308696Sshurd &iod->status; 1746308696Sshurd 1747308696Sshurd rc = bnxt_hwrm_fw_qstatus(softc, qstat->processor, 1748308696Sshurd &qstat->selfreset); 1749308696Sshurd if (rc) { 1750308696Sshurd iod->hdr.rc = rc; 1751308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1752308696Sshurd sizeof(ioh->rc)); 1753308696Sshurd } 1754308696Sshurd else { 1755308696Sshurd iod->hdr.rc = 0; 1756359026Sbrooks copyout(iod, ioh, iol); 1757308696Sshurd } 1758308696Sshurd 1759308696Sshurd rc = 0; 1760308696Sshurd goto exit; 1761308696Sshurd } 1762308696Sshurd case BNXT_HWRM_NVM_WRITE: 1763308696Sshurd { 1764308696Sshurd struct bnxt_ioctl_hwrm_nvm_write *wr = 1765308696Sshurd &iod->write; 1766308696Sshurd 1767308696Sshurd rc = bnxt_hwrm_nvm_write(softc, wr->data, true, 1768308696Sshurd wr->type, wr->ordinal, wr->ext, wr->attr, 1769308696Sshurd wr->option, wr->data_length, wr->keep, 1770308696Sshurd &wr->item_length, &wr->index); 1771308696Sshurd if (rc) { 1772308696Sshurd iod->hdr.rc = rc; 1773308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1774308696Sshurd sizeof(ioh->rc)); 1775308696Sshurd } 1776308696Sshurd else { 1777308696Sshurd iod->hdr.rc = 0; 1778359026Sbrooks copyout(iod, ioh, iol); 1779308696Sshurd } 1780308696Sshurd 1781308696Sshurd rc = 0; 1782308696Sshurd goto exit; 1783308696Sshurd } 1784308696Sshurd case BNXT_HWRM_NVM_ERASE_DIR_ENTRY: 1785308696Sshurd { 1786308696Sshurd struct bnxt_ioctl_hwrm_nvm_erase_dir_entry *erase = 1787308696Sshurd &iod->erase; 1788308696Sshurd 1789308696Sshurd rc = bnxt_hwrm_nvm_erase_dir_entry(softc, erase->index); 1790308696Sshurd if (rc) { 1791308696Sshurd iod->hdr.rc = rc; 1792308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1793308696Sshurd sizeof(ioh->rc)); 1794308696Sshurd } 1795308696Sshurd else { 1796308696Sshurd iod->hdr.rc = 0; 1797359026Sbrooks copyout(iod, ioh, iol); 1798308696Sshurd } 1799308696Sshurd 1800308696Sshurd rc = 0; 1801308696Sshurd goto exit; 1802308696Sshurd } 1803308696Sshurd case BNXT_HWRM_NVM_GET_DIR_INFO: 1804308696Sshurd { 1805308696Sshurd struct bnxt_ioctl_hwrm_nvm_get_dir_info *info = 1806308696Sshurd &iod->dir_info; 1807308696Sshurd 1808308696Sshurd rc = bnxt_hwrm_nvm_get_dir_info(softc, &info->entries, 1809308696Sshurd &info->entry_length); 1810308696Sshurd if (rc) { 1811308696Sshurd iod->hdr.rc = rc; 1812308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1813308696Sshurd sizeof(ioh->rc)); 1814308696Sshurd } 1815308696Sshurd else { 1816308696Sshurd iod->hdr.rc = 0; 1817359026Sbrooks copyout(iod, ioh, iol); 1818308696Sshurd } 1819308696Sshurd 1820308696Sshurd rc = 0; 1821308696Sshurd goto exit; 1822308696Sshurd } 1823308696Sshurd case BNXT_HWRM_NVM_GET_DIR_ENTRIES: 1824308696Sshurd { 1825308696Sshurd struct bnxt_ioctl_hwrm_nvm_get_dir_entries *get = 1826308696Sshurd &iod->dir_entries; 1827308696Sshurd struct iflib_dma_info dma_data; 1828308696Sshurd 1829308696Sshurd rc = iflib_dma_alloc(softc->ctx, get->max_size, 1830308696Sshurd &dma_data, BUS_DMA_NOWAIT); 1831308696Sshurd if (rc) 1832308696Sshurd break; 1833308696Sshurd rc = bnxt_hwrm_nvm_get_dir_entries(softc, &get->entries, 1834308696Sshurd &get->entry_length, &dma_data); 1835308696Sshurd if (rc) { 1836308696Sshurd iod->hdr.rc = rc; 1837308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1838308696Sshurd sizeof(ioh->rc)); 1839308696Sshurd } 1840308696Sshurd else { 1841308696Sshurd copyout(dma_data.idi_vaddr, get->data, 1842308696Sshurd get->entry_length * get->entries); 1843308696Sshurd iod->hdr.rc = 0; 1844359026Sbrooks copyout(iod, ioh, iol); 1845308696Sshurd } 1846308696Sshurd iflib_dma_free(&dma_data); 1847308696Sshurd 1848308696Sshurd rc = 0; 1849308696Sshurd goto exit; 1850308696Sshurd } 1851308696Sshurd case BNXT_HWRM_NVM_VERIFY_UPDATE: 1852308696Sshurd { 1853308696Sshurd struct bnxt_ioctl_hwrm_nvm_verify_update *vrfy = 1854308696Sshurd &iod->verify; 1855308696Sshurd 1856308696Sshurd rc = bnxt_hwrm_nvm_verify_update(softc, vrfy->type, 1857308696Sshurd vrfy->ordinal, vrfy->ext); 1858308696Sshurd if (rc) { 1859308696Sshurd iod->hdr.rc = rc; 1860308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1861308696Sshurd sizeof(ioh->rc)); 1862308696Sshurd } 1863308696Sshurd else { 1864308696Sshurd iod->hdr.rc = 0; 1865359026Sbrooks copyout(iod, ioh, iol); 1866308696Sshurd } 1867308696Sshurd 1868308696Sshurd rc = 0; 1869308696Sshurd goto exit; 1870308696Sshurd } 1871308696Sshurd case BNXT_HWRM_NVM_INSTALL_UPDATE: 1872308696Sshurd { 1873308696Sshurd struct bnxt_ioctl_hwrm_nvm_install_update *inst = 1874308696Sshurd &iod->install; 1875308696Sshurd 1876308696Sshurd rc = bnxt_hwrm_nvm_install_update(softc, 1877308696Sshurd inst->install_type, &inst->installed_items, 1878308696Sshurd &inst->result, &inst->problem_item, 1879308696Sshurd &inst->reset_required); 1880308696Sshurd if (rc) { 1881308696Sshurd iod->hdr.rc = rc; 1882308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1883308696Sshurd sizeof(ioh->rc)); 1884308696Sshurd } 1885308696Sshurd else { 1886308696Sshurd iod->hdr.rc = 0; 1887359026Sbrooks copyout(iod, ioh, iol); 1888308696Sshurd } 1889308696Sshurd 1890308696Sshurd rc = 0; 1891308696Sshurd goto exit; 1892308696Sshurd } 1893308696Sshurd case BNXT_HWRM_NVM_MODIFY: 1894308696Sshurd { 1895308696Sshurd struct bnxt_ioctl_hwrm_nvm_modify *mod = &iod->modify; 1896308696Sshurd 1897308696Sshurd rc = bnxt_hwrm_nvm_modify(softc, mod->index, 1898308696Sshurd mod->offset, mod->data, true, mod->length); 1899308696Sshurd if (rc) { 1900308696Sshurd iod->hdr.rc = rc; 1901308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1902308696Sshurd sizeof(ioh->rc)); 1903308696Sshurd } 1904308696Sshurd else { 1905308696Sshurd iod->hdr.rc = 0; 1906359026Sbrooks copyout(iod, ioh, iol); 1907308696Sshurd } 1908308696Sshurd 1909308696Sshurd rc = 0; 1910308696Sshurd goto exit; 1911308696Sshurd } 1912308696Sshurd case BNXT_HWRM_FW_GET_TIME: 1913308696Sshurd { 1914308696Sshurd struct bnxt_ioctl_hwrm_fw_get_time *gtm = 1915308696Sshurd &iod->get_time; 1916308696Sshurd 1917308696Sshurd rc = bnxt_hwrm_fw_get_time(softc, >m->year, 1918308696Sshurd >m->month, >m->day, >m->hour, >m->minute, 1919308696Sshurd >m->second, >m->millisecond, >m->zone); 1920308696Sshurd if (rc) { 1921308696Sshurd iod->hdr.rc = rc; 1922308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1923308696Sshurd sizeof(ioh->rc)); 1924308696Sshurd } 1925308696Sshurd else { 1926308696Sshurd iod->hdr.rc = 0; 1927359026Sbrooks copyout(iod, ioh, iol); 1928308696Sshurd } 1929308696Sshurd 1930308696Sshurd rc = 0; 1931308696Sshurd goto exit; 1932308696Sshurd } 1933308696Sshurd case BNXT_HWRM_FW_SET_TIME: 1934308696Sshurd { 1935308696Sshurd struct bnxt_ioctl_hwrm_fw_set_time *stm = 1936308696Sshurd &iod->set_time; 1937308696Sshurd 1938308696Sshurd rc = bnxt_hwrm_fw_set_time(softc, stm->year, 1939308696Sshurd stm->month, stm->day, stm->hour, stm->minute, 1940308696Sshurd stm->second, stm->millisecond, stm->zone); 1941308696Sshurd if (rc) { 1942308696Sshurd iod->hdr.rc = rc; 1943308696Sshurd copyout(&iod->hdr.rc, &ioh->rc, 1944308696Sshurd sizeof(ioh->rc)); 1945308696Sshurd } 1946308696Sshurd else { 1947308696Sshurd iod->hdr.rc = 0; 1948359026Sbrooks copyout(iod, ioh, iol); 1949308696Sshurd } 1950308696Sshurd 1951308696Sshurd rc = 0; 1952308696Sshurd goto exit; 1953308696Sshurd } 1954308696Sshurd } 1955308696Sshurd break; 1956308696Sshurd } 1957308696Sshurd 1958308696Sshurdexit: 1959308696Sshurd return rc; 1960308696Sshurd} 1961308696Sshurd 1962308696Sshurd/* 1963308696Sshurd * Support functions 1964308696Sshurd */ 1965308696Sshurdstatic int 1966308696Sshurdbnxt_probe_phy(struct bnxt_softc *softc) 1967308696Sshurd{ 1968308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 1969308696Sshurd int rc = 0; 1970308696Sshurd 1971308696Sshurd rc = bnxt_update_link(softc, false); 1972308696Sshurd if (rc) { 1973308696Sshurd device_printf(softc->dev, 1974308696Sshurd "Probe phy can't update link (rc: %x)\n", rc); 1975308696Sshurd return (rc); 1976308696Sshurd } 1977308696Sshurd 1978308696Sshurd /*initialize the ethool setting copy with NVM settings */ 1979308696Sshurd if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE) 1980308696Sshurd link_info->autoneg |= BNXT_AUTONEG_SPEED; 1981308696Sshurd 1982308696Sshurd link_info->req_duplex = link_info->duplex_setting; 1983308696Sshurd if (link_info->autoneg & BNXT_AUTONEG_SPEED) 1984308696Sshurd link_info->req_link_speed = link_info->auto_link_speed; 1985308696Sshurd else 1986308696Sshurd link_info->req_link_speed = link_info->force_link_speed; 1987308696Sshurd return (rc); 1988308696Sshurd} 1989308696Sshurd 1990308696Sshurdstatic void 1991308696Sshurdbnxt_add_media_types(struct bnxt_softc *softc) 1992308696Sshurd{ 1993308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 1994308696Sshurd uint16_t supported; 1995308696Sshurd uint8_t phy_type = get_phy_type(softc); 1996308696Sshurd 1997308696Sshurd supported = link_info->support_speeds; 1998308696Sshurd 1999308696Sshurd /* Auto is always supported */ 2000308696Sshurd ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL); 2001308696Sshurd 2002308696Sshurd if (softc->flags & BNXT_FLAG_NPAR) 2003308696Sshurd return; 2004308696Sshurd 2005308696Sshurd switch (phy_type) { 2006333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR4: 2007333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASECR4: 2008333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_L: 2009333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_S: 2010333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_N: 2011308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR: 2012333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_CR4); 2013333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_CR2); 2014333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_CR4); 2015333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_CR); 2016333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_CR1); 2017333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_T); 2018308696Sshurd break; 2019333364Sshurd 2020333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR4: 2021333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASELR4: 2022333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR: 2023333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_LR4); 2024333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_LR4); 2025333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_LR); 2026333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_LR); 2027333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_LX); 2028308696Sshurd break; 2029333364Sshurd 2030333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR10: 2031333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR4: 2032333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASESR4: 2033333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR: 2034333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASEER4: 2035333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER4: 2036333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASESR: 2037333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASESX: 2038333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_SR4); 2039333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_SR4); 2040333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_SR); 2041333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_SR); 2042333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SX); 2043333364Sshurd break; 2044333364Sshurd 2045308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4: 2046308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2: 2047308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR: 2048333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_100GB, IFM_100G_KR4); 2049333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_50GB, IFM_50G_KR2); 2050333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_40GB, IFM_40G_KR4); 2051333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_KR); 2052333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_20GB, IFM_20G_KR2); 2053333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); 2054333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); 2055309377Sshurd break; 2056333364Sshurd 2057333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_ACTIVE_CABLE: 2058333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_25GB, IFM_25G_ACC); 2059333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_AOC); 2060308696Sshurd break; 2061333364Sshurd 2062333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASECX: 2063333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_1GBHD, IFM_1000_CX); 2064308696Sshurd break; 2065333364Sshurd 2066333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET: 2067308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET: 2068308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE: 2069333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_T); 2070333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_2_5GB, IFM_2500_T); 2071333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_T); 2072333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_100MB, IFM_100_T); 2073333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_10MB, IFM_10_T); 2074308696Sshurd break; 2075333364Sshurd 2076333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX: 2077333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_10GB, IFM_10G_KR); 2078333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_2_5GB, IFM_2500_KX); 2079333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_KX); 2080333364Sshurd break; 2081333364Sshurd 2082308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY: 2083333364Sshurd BNXT_IFMEDIA_ADD(supported, SPEEDS_1GB, IFM_1000_SGMII); 2084308696Sshurd break; 2085333364Sshurd 2086333364Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN: 2087333364Sshurd /* Only Autoneg is supported for TYPE_UNKNOWN */ 2088333364Sshurd device_printf(softc->dev, "Unknown phy type\n"); 2089333364Sshurd break; 2090333364Sshurd 2091333364Sshurd default: 2092333364Sshurd /* Only Autoneg is supported for new phy type values */ 2093333364Sshurd device_printf(softc->dev, "phy type %d not supported by driver\n", phy_type); 2094333364Sshurd break; 2095308696Sshurd } 2096308696Sshurd 2097308696Sshurd return; 2098308696Sshurd} 2099308696Sshurd 2100308696Sshurdstatic int 2101308696Sshurdbnxt_map_bar(struct bnxt_softc *softc, struct bnxt_bar_info *bar, int bar_num, bool shareable) 2102308696Sshurd{ 2103308696Sshurd uint32_t flag; 2104308696Sshurd 2105308696Sshurd if (bar->res != NULL) { 2106308696Sshurd device_printf(softc->dev, "Bar %d already mapped\n", bar_num); 2107308696Sshurd return EDOOFUS; 2108308696Sshurd } 2109308696Sshurd 2110308696Sshurd bar->rid = PCIR_BAR(bar_num); 2111308696Sshurd flag = RF_ACTIVE; 2112308696Sshurd if (shareable) 2113308696Sshurd flag |= RF_SHAREABLE; 2114308696Sshurd 2115308696Sshurd if ((bar->res = 2116308696Sshurd bus_alloc_resource_any(softc->dev, 2117308696Sshurd SYS_RES_MEMORY, 2118308696Sshurd &bar->rid, 2119308696Sshurd flag)) == NULL) { 2120308696Sshurd device_printf(softc->dev, 2121308696Sshurd "PCI BAR%d mapping failure\n", bar_num); 2122308696Sshurd return (ENXIO); 2123308696Sshurd } 2124308696Sshurd bar->tag = rman_get_bustag(bar->res); 2125308696Sshurd bar->handle = rman_get_bushandle(bar->res); 2126308696Sshurd bar->size = rman_get_size(bar->res); 2127308696Sshurd 2128308696Sshurd return 0; 2129308696Sshurd} 2130308696Sshurd 2131308696Sshurdstatic int 2132308696Sshurdbnxt_pci_mapping(struct bnxt_softc *softc) 2133308696Sshurd{ 2134308696Sshurd int rc; 2135308696Sshurd 2136308696Sshurd rc = bnxt_map_bar(softc, &softc->hwrm_bar, 0, true); 2137308696Sshurd if (rc) 2138308696Sshurd return rc; 2139308696Sshurd 2140308696Sshurd rc = bnxt_map_bar(softc, &softc->doorbell_bar, 2, false); 2141308696Sshurd 2142308696Sshurd return rc; 2143308696Sshurd} 2144308696Sshurd 2145308696Sshurdstatic void 2146308696Sshurdbnxt_pci_mapping_free(struct bnxt_softc *softc) 2147308696Sshurd{ 2148308696Sshurd if (softc->hwrm_bar.res != NULL) 2149308696Sshurd bus_release_resource(softc->dev, SYS_RES_MEMORY, 2150308696Sshurd softc->hwrm_bar.rid, softc->hwrm_bar.res); 2151308696Sshurd softc->hwrm_bar.res = NULL; 2152308696Sshurd 2153308696Sshurd if (softc->doorbell_bar.res != NULL) 2154308696Sshurd bus_release_resource(softc->dev, SYS_RES_MEMORY, 2155308696Sshurd softc->doorbell_bar.rid, softc->doorbell_bar.res); 2156308696Sshurd softc->doorbell_bar.res = NULL; 2157308696Sshurd} 2158308696Sshurd 2159308696Sshurdstatic int 2160308696Sshurdbnxt_update_link(struct bnxt_softc *softc, bool chng_link_state) 2161308696Sshurd{ 2162308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 2163308696Sshurd uint8_t link_up = link_info->link_up; 2164308696Sshurd int rc = 0; 2165308696Sshurd 2166308696Sshurd rc = bnxt_hwrm_port_phy_qcfg(softc); 2167308696Sshurd if (rc) 2168308696Sshurd goto exit; 2169308696Sshurd 2170308696Sshurd /* TODO: need to add more logic to report VF link */ 2171308696Sshurd if (chng_link_state) { 2172308696Sshurd if (link_info->phy_link_status == 2173308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) 2174308696Sshurd link_info->link_up = 1; 2175308696Sshurd else 2176308696Sshurd link_info->link_up = 0; 2177308696Sshurd if (link_up != link_info->link_up) 2178308696Sshurd bnxt_report_link(softc); 2179308696Sshurd } else { 2180308696Sshurd /* always link down if not require to update link state */ 2181308696Sshurd link_info->link_up = 0; 2182308696Sshurd } 2183308696Sshurd 2184308696Sshurdexit: 2185308696Sshurd return rc; 2186308696Sshurd} 2187308696Sshurd 2188308696Sshurdvoid 2189308696Sshurdbnxt_report_link(struct bnxt_softc *softc) 2190308696Sshurd{ 2191333364Sshurd struct bnxt_link_info *link_info = &softc->link_info; 2192308696Sshurd const char *duplex = NULL, *flow_ctrl = NULL; 2193308696Sshurd 2194333364Sshurd if (link_info->link_up == link_info->last_link_up) { 2195333364Sshurd if (!link_info->link_up) 2196308696Sshurd return; 2197333364Sshurd if ((link_info->duplex == link_info->last_duplex) && 2198333364Sshurd (!(BNXT_IS_FLOW_CTRL_CHANGED(link_info)))) 2199308696Sshurd return; 2200308696Sshurd } 2201308696Sshurd 2202333364Sshurd if (link_info->link_up) { 2203333364Sshurd if (link_info->duplex == 2204333364Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_CFG_FULL) 2205308696Sshurd duplex = "full duplex"; 2206308696Sshurd else 2207308696Sshurd duplex = "half duplex"; 2208333364Sshurd if (link_info->flow_ctrl.tx & link_info->flow_ctrl.rx) 2209308696Sshurd flow_ctrl = "FC - receive & transmit"; 2210333364Sshurd else if (link_info->flow_ctrl.tx) 2211308696Sshurd flow_ctrl = "FC - transmit"; 2212333364Sshurd else if (link_info->flow_ctrl.rx) 2213308696Sshurd flow_ctrl = "FC - receive"; 2214308696Sshurd else 2215333364Sshurd flow_ctrl = "FC - none"; 2216308696Sshurd iflib_link_state_change(softc->ctx, LINK_STATE_UP, 2217308696Sshurd IF_Gbps(100)); 2218333364Sshurd device_printf(softc->dev, "Link is UP %s, %s - %d Mbps \n", duplex, 2219333364Sshurd flow_ctrl, (link_info->link_speed * 100)); 2220308696Sshurd } else { 2221308696Sshurd iflib_link_state_change(softc->ctx, LINK_STATE_DOWN, 2222308696Sshurd bnxt_get_baudrate(&softc->link_info)); 2223308696Sshurd device_printf(softc->dev, "Link is Down\n"); 2224308696Sshurd } 2225308696Sshurd 2226333364Sshurd link_info->last_link_up = link_info->link_up; 2227333364Sshurd link_info->last_duplex = link_info->duplex; 2228333364Sshurd link_info->last_flow_ctrl.tx = link_info->flow_ctrl.tx; 2229333364Sshurd link_info->last_flow_ctrl.rx = link_info->flow_ctrl.rx; 2230333364Sshurd link_info->last_flow_ctrl.autoneg = link_info->flow_ctrl.autoneg; 2231333364Sshurd /* update media types */ 2232333364Sshurd ifmedia_removeall(softc->media); 2233333364Sshurd bnxt_add_media_types(softc); 2234333364Sshurd ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO); 2235308696Sshurd} 2236308696Sshurd 2237308696Sshurdstatic int 2238308696Sshurdbnxt_handle_rx_cp(void *arg) 2239308696Sshurd{ 2240308696Sshurd struct bnxt_cp_ring *cpr = arg; 2241308696Sshurd 2242308696Sshurd /* Disable further interrupts for this queue */ 2243308696Sshurd BNXT_CP_DISABLE_DB(&cpr->ring); 2244308696Sshurd return FILTER_SCHEDULE_THREAD; 2245308696Sshurd} 2246308696Sshurd 2247308696Sshurdstatic int 2248308696Sshurdbnxt_handle_def_cp(void *arg) 2249308696Sshurd{ 2250308696Sshurd struct bnxt_softc *softc = arg; 2251308696Sshurd 2252308696Sshurd BNXT_CP_DISABLE_DB(&softc->def_cp_ring.ring); 2253308696Sshurd GROUPTASK_ENQUEUE(&softc->def_cp_task); 2254308696Sshurd return FILTER_HANDLED; 2255308696Sshurd} 2256308696Sshurd 2257308696Sshurdstatic void 2258308696Sshurdbnxt_clear_ids(struct bnxt_softc *softc) 2259308696Sshurd{ 2260308696Sshurd int i; 2261308696Sshurd 2262308696Sshurd softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE; 2263308696Sshurd softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE; 2264308696Sshurd for (i = 0; i < softc->ntxqsets; i++) { 2265308696Sshurd softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; 2266308696Sshurd softc->tx_cp_rings[i].ring.phys_id = 2267308696Sshurd (uint16_t)HWRM_NA_SIGNATURE; 2268308696Sshurd softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 2269308696Sshurd } 2270308696Sshurd for (i = 0; i < softc->nrxqsets; i++) { 2271308696Sshurd softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE; 2272308696Sshurd softc->rx_cp_rings[i].ring.phys_id = 2273308696Sshurd (uint16_t)HWRM_NA_SIGNATURE; 2274308696Sshurd softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 2275308696Sshurd softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE; 2276308696Sshurd softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE; 2277308696Sshurd } 2278308696Sshurd softc->vnic_info.filter_id = -1; 2279308696Sshurd softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE; 2280308696Sshurd softc->vnic_info.rss_id = (uint16_t)HWRM_NA_SIGNATURE; 2281308696Sshurd memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff, 2282308696Sshurd softc->vnic_info.rss_grp_tbl.idi_size); 2283308696Sshurd} 2284308696Sshurd 2285308696Sshurdstatic void 2286308696Sshurdbnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr) 2287308696Sshurd{ 2288308696Sshurd struct cmpl_base *cmp = (void *)cpr->ring.vaddr; 2289308696Sshurd int i; 2290308696Sshurd 2291308696Sshurd for (i = 0; i < cpr->ring.ring_size; i++) 2292308696Sshurd cmp[i].info3_v = !cpr->v_bit; 2293308696Sshurd} 2294308696Sshurd 2295308696Sshurdstatic void 2296308696Sshurdbnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl) 2297308696Sshurd{ 2298308696Sshurd struct hwrm_async_event_cmpl *ae = (void *)cmpl; 2299308696Sshurd uint16_t async_id = le16toh(ae->event_id); 2300308696Sshurd struct ifmediareq ifmr; 2301308696Sshurd 2302308696Sshurd switch (async_id) { 2303308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: 2304308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: 2305308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: 2306308696Sshurd bnxt_media_status(softc->ctx, &ifmr); 2307308696Sshurd break; 2308308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE: 2309308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE: 2310308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: 2311308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED: 2312308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD: 2313308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD: 2314308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD: 2315308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD: 2316308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR: 2317308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE: 2318308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE: 2319308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE: 2320308696Sshurd case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR: 2321308696Sshurd device_printf(softc->dev, 2322308696Sshurd "Unhandled async completion type %u\n", async_id); 2323308696Sshurd break; 2324308696Sshurd default: 2325308696Sshurd device_printf(softc->dev, 2326308696Sshurd "Unknown async completion type %u\n", async_id); 2327308696Sshurd break; 2328308696Sshurd } 2329308696Sshurd} 2330308696Sshurd 2331308696Sshurdstatic void 2332308696Sshurdbnxt_def_cp_task(void *context) 2333308696Sshurd{ 2334308696Sshurd if_ctx_t ctx = context; 2335308696Sshurd struct bnxt_softc *softc = iflib_get_softc(ctx); 2336308696Sshurd struct bnxt_cp_ring *cpr = &softc->def_cp_ring; 2337308696Sshurd 2338308696Sshurd /* Handle completions on the default completion ring */ 2339308696Sshurd struct cmpl_base *cmpl; 2340308696Sshurd uint32_t cons = cpr->cons; 2341308696Sshurd bool v_bit = cpr->v_bit; 2342308696Sshurd bool last_v_bit; 2343308696Sshurd uint32_t last_cons; 2344308696Sshurd uint16_t type; 2345308696Sshurd 2346308696Sshurd for (;;) { 2347308696Sshurd last_cons = cons; 2348308696Sshurd last_v_bit = v_bit; 2349308696Sshurd NEXT_CP_CONS_V(&cpr->ring, cons, v_bit); 2350308696Sshurd cmpl = &((struct cmpl_base *)cpr->ring.vaddr)[cons]; 2351308696Sshurd 2352308696Sshurd if (!CMP_VALID(cmpl, v_bit)) 2353308696Sshurd break; 2354308696Sshurd 2355308696Sshurd type = le16toh(cmpl->type) & CMPL_BASE_TYPE_MASK; 2356308696Sshurd switch (type) { 2357308696Sshurd case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: 2358308696Sshurd bnxt_handle_async_event(softc, cmpl); 2359308696Sshurd break; 2360308696Sshurd case CMPL_BASE_TYPE_TX_L2: 2361308696Sshurd case CMPL_BASE_TYPE_RX_L2: 2362308696Sshurd case CMPL_BASE_TYPE_RX_AGG: 2363308696Sshurd case CMPL_BASE_TYPE_RX_TPA_START: 2364308696Sshurd case CMPL_BASE_TYPE_RX_TPA_END: 2365308696Sshurd case CMPL_BASE_TYPE_STAT_EJECT: 2366308696Sshurd case CMPL_BASE_TYPE_HWRM_DONE: 2367308696Sshurd case CMPL_BASE_TYPE_HWRM_FWD_REQ: 2368308696Sshurd case CMPL_BASE_TYPE_HWRM_FWD_RESP: 2369308696Sshurd case CMPL_BASE_TYPE_CQ_NOTIFICATION: 2370308696Sshurd case CMPL_BASE_TYPE_SRQ_EVENT: 2371308696Sshurd case CMPL_BASE_TYPE_DBQ_EVENT: 2372308696Sshurd case CMPL_BASE_TYPE_QP_EVENT: 2373308696Sshurd case CMPL_BASE_TYPE_FUNC_EVENT: 2374308696Sshurd device_printf(softc->dev, 2375308696Sshurd "Unhandled completion type %u\n", type); 2376308696Sshurd break; 2377308696Sshurd default: 2378308696Sshurd device_printf(softc->dev, 2379308696Sshurd "Unknown completion type %u\n", type); 2380308696Sshurd break; 2381308696Sshurd } 2382308696Sshurd } 2383308696Sshurd 2384308696Sshurd cpr->cons = last_cons; 2385308696Sshurd cpr->v_bit = last_v_bit; 2386308696Sshurd BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons); 2387308696Sshurd} 2388308696Sshurd 2389308696Sshurdstatic uint8_t 2390308696Sshurdget_phy_type(struct bnxt_softc *softc) 2391308696Sshurd{ 2392308696Sshurd struct bnxt_link_info *link_info = &softc->link_info; 2393308696Sshurd uint8_t phy_type = link_info->phy_type; 2394308696Sshurd uint16_t supported; 2395308696Sshurd 2396308696Sshurd if (phy_type != HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN) 2397308696Sshurd return phy_type; 2398308696Sshurd 2399308696Sshurd /* Deduce the phy type from the media type and supported speeds */ 2400308696Sshurd supported = link_info->support_speeds; 2401308696Sshurd 2402308696Sshurd if (link_info->media_type == 2403308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP) 2404308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET; 2405308696Sshurd if (link_info->media_type == 2406308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_DAC) { 2407308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB) 2408308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX; 2409308696Sshurd if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB) 2410308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR; 2411308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR; 2412308696Sshurd } 2413308696Sshurd if (link_info->media_type == 2414308696Sshurd HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_FIBRE) 2415308696Sshurd return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR; 2416308696Sshurd 2417308696Sshurd return phy_type; 2418308696Sshurd} 2419308696Sshurd 2420308696Sshurdbool 2421308696Sshurdbnxt_check_hwrm_version(struct bnxt_softc *softc) 2422308696Sshurd{ 2423308696Sshurd char buf[16]; 2424308696Sshurd 2425308696Sshurd sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major, 2426308696Sshurd softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update); 2427308696Sshurd if (softc->ver_info->hwrm_min_major > softc->ver_info->hwrm_if_major) { 2428308696Sshurd device_printf(softc->dev, 2429308696Sshurd "WARNING: HWRM version %s is too old (older than %s)\n", 2430308696Sshurd softc->ver_info->hwrm_if_ver, buf); 2431308696Sshurd return false; 2432308696Sshurd } 2433308696Sshurd else if(softc->ver_info->hwrm_min_major == 2434308696Sshurd softc->ver_info->hwrm_if_major) { 2435308696Sshurd if (softc->ver_info->hwrm_min_minor > 2436308696Sshurd softc->ver_info->hwrm_if_minor) { 2437308696Sshurd device_printf(softc->dev, 2438308696Sshurd "WARNING: HWRM version %s is too old (older than %s)\n", 2439308696Sshurd softc->ver_info->hwrm_if_ver, buf); 2440308696Sshurd return false; 2441308696Sshurd } 2442308696Sshurd else if (softc->ver_info->hwrm_min_minor == 2443308696Sshurd softc->ver_info->hwrm_if_minor) { 2444308696Sshurd if (softc->ver_info->hwrm_min_update > 2445308696Sshurd softc->ver_info->hwrm_if_update) { 2446308696Sshurd device_printf(softc->dev, 2447308696Sshurd "WARNING: HWRM version %s is too old (older than %s)\n", 2448308696Sshurd softc->ver_info->hwrm_if_ver, buf); 2449308696Sshurd return false; 2450308696Sshurd } 2451308696Sshurd } 2452308696Sshurd } 2453308696Sshurd return true; 2454308696Sshurd} 2455308696Sshurd 2456308696Sshurdstatic uint64_t 2457308696Sshurdbnxt_get_baudrate(struct bnxt_link_info *link) 2458308696Sshurd{ 2459308696Sshurd switch (link->link_speed) { 2460308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB: 2461308696Sshurd return IF_Mbps(100); 2462308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB: 2463308696Sshurd return IF_Gbps(1); 2464308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB: 2465308696Sshurd return IF_Gbps(2); 2466308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB: 2467308696Sshurd return IF_Mbps(2500); 2468308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB: 2469308696Sshurd return IF_Gbps(10); 2470308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB: 2471308696Sshurd return IF_Gbps(20); 2472308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB: 2473308696Sshurd return IF_Gbps(25); 2474308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB: 2475308696Sshurd return IF_Gbps(40); 2476308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB: 2477308696Sshurd return IF_Gbps(50); 2478308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB: 2479308696Sshurd return IF_Gbps(100); 2480308696Sshurd case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB: 2481308696Sshurd return IF_Mbps(10); 2482308696Sshurd } 2483308696Sshurd return IF_Gbps(100); 2484308696Sshurd} 2485333364Sshurd 2486333364Sshurdstatic void 2487333364Sshurdbnxt_get_wol_settings(struct bnxt_softc *softc) 2488333364Sshurd{ 2489333364Sshurd uint16_t wol_handle = 0; 2490333364Sshurd 2491333364Sshurd if (!bnxt_wol_supported(softc)) 2492333364Sshurd return; 2493333364Sshurd 2494333364Sshurd do { 2495333364Sshurd wol_handle = bnxt_hwrm_get_wol_fltrs(softc, wol_handle); 2496333364Sshurd } while (wol_handle && wol_handle != BNXT_NO_MORE_WOL_FILTERS); 2497333364Sshurd} 2498