> Date: Mon, 9 Jul 2018 14:23:43 +1000
> From: Jonathan Matthew <jonat...@d14n.org>
> 
> This started out as a port of freebsd's bnxt driver, but along the way I
> had to rewrite the interesting bits.
> 
> NetXtreme-C/E (BCM573xx and BCM574xx) is a different line of chips to
> NetXtreme II 10G (BCM577xx, which mje was working on), and luckily for me it's
> much easier to talk to.  The reason these ones are interesting to me is that
> they're the only 10G mezzanine option for Dell's Epyc based servers.
> 
> I've got it to the point where I could commit to cvs over it, so I'd
> like to get it into the tree.  Lots of stuff is still missing -
> media types, multicast, jumbos, any of the vast array of offloads,
> and it's not particularly fast yet, only slightly over a gigabit in
> iperf/tcpbench type tests.  Lots of work to do still.
> 
> The current code is below, only I'm not including bnxtreg.h as it's
> fairly large (>30k lines) and it came unmodified from freebsd:
> https://svnweb.freebsd.org/base/head/sys/dev/bnxt/hsi_struct_def.h?revision=323233&view=markup
> 
> ok?

ok kettenis@

> /*    $OpenBSD$       */
> /*-
>  * Broadcom NetXtreme-C/E network driver.
>  *
>  * Copyright (c) 2016 Broadcom, All Rights Reserved.
>  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
>  *
>  * Redistribution and use in source and binary forms, with or without
>  * modification, are permitted provided that the following conditions
>  * are met:
>  * 1. Redistributions of source code must retain the above copyright
>  *    notice, this list of conditions and the following disclaimer.
>  * 2. Redistributions in binary form must reproduce the above copyright
>  *    notice, this list of conditions and the following disclaimer in the
>  *    documentation and/or other materials provided with the distribution.
>  *
>  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
>  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
>  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
>  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
>  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
>  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
>  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
>  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
>  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
>  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
>  * THE POSSIBILITY OF SUCH DAMAGE.
>  */
> 
> /*
>  * Copyright (c) 2018 Jonathan Matthew <jmatt...@openbsd.org>
>  *
>  * Permission to use, copy, modify, and distribute this software for any
>  * purpose with or without fee is hereby granted, provided that the above
>  * copyright notice and this permission notice appear in all copies.
>  *
>  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
>  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
>  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
>  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
>  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
>  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>  */
> 
> 
> #include "bpfilter.h"
> 
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/mbuf.h>
> #include <sys/kernel.h>
> #include <sys/malloc.h>
> #include <sys/device.h>
> #include <sys/stdint.h>
> #include <sys/sockio.h>
> #include <sys/atomic.h>
> 
> #include <machine/bus.h>
> 
> #include <dev/pci/pcireg.h>
> #include <dev/pci/pcivar.h>
> #include <dev/pci/pcidevs.h>
> 
> #define __FBSDID(x)
> #include <dev/pci/bnxtreg.h>
> 
> #include <net/if.h>
> #include <net/if_media.h>
> 
> #if NBPFILTER > 0
> #include <net/bpf.h>
> #endif
> 
> #include <netinet/in.h>
> #include <netinet/if_ether.h>
> 
> #define BNXT_HWRM_BAR         0x10
> #define BNXT_DOORBELL_BAR     0x18
> 
> #define BNXT_RX_RING_ID               0
> #define BNXT_AG_RING_ID               1
> #define BNXT_TX_RING_ID               3
> 
> #define BNXT_MAX_QUEUE                8
> #define BNXT_MAX_MTU          9000
> 
> #define BNXT_MAX_TX_SEGS      32      /* a bit much? */
> 
> #define BNXT_HWRM_SHORT_REQ_LEN       sizeof(struct hwrm_short_input)
> 
> #define BNXT_HWRM_LOCK_INIT(_sc, _name)       \
>       mtx_init_flags(&sc->sc_lock, IPL_NET, _name, 0)
> #define BNXT_HWRM_LOCK(_sc)           mtx_enter(&_sc->sc_lock)
> #define BNXT_HWRM_UNLOCK(_sc)                 mtx_leave(&_sc->sc_lock)
> #define BNXT_HWRM_LOCK_DESTROY(_sc)   /* nothing */
> #define BNXT_HWRM_LOCK_ASSERT(_sc)    MUTEX_ASSERT_LOCKED(&_sc->sc_lock)
> 
> #define BNXT_FLAG_VF            0x0001
> #define BNXT_FLAG_NPAR          0x0002
> #define BNXT_FLAG_WOL_CAP       0x0004
> #define BNXT_FLAG_SHORT_CMD     0x0008
> 
> #define NEXT_CP_CONS_V(_ring, _cons, _v_bit)          \
> do {                                                  \
>       if (++(_cons) == (_ring)->ring_size)            \
>               ((_cons) = 0, (_v_bit) = !_v_bit);      \
> } while (0);
> 
> struct bnxt_cos_queue {
>       uint8_t                 id;
>       uint8_t                 profile;
> };
> 
> struct bnxt_ring {
>       uint64_t                paddr;
>       uint64_t                doorbell;
>       caddr_t                 vaddr;
>       uint32_t                ring_size;
>       uint16_t                id;
>       uint16_t                phys_id;
>       struct bnxt_full_tpa_start *tpa_start;
> };
> 
> struct bnxt_cp_ring {
>       struct bnxt_ring        ring;
>       void                    *irq;
>       struct bnxt_softc       *softc;
>       uint32_t                cons;
>       int                     v_bit;
>       struct ctx_hw_stats     *stats;
>       uint32_t                stats_ctx_id;
>       uint32_t                last_idx;
> };
> 
> struct bnxt_grp_info {
>       uint32_t                grp_id;
>       uint16_t                stats_ctx;
>       uint16_t                rx_ring_id;
>       uint16_t                cp_ring_id;
>       uint16_t                ag_ring_id;
> };
> 
> struct bnxt_vnic_info {
>       uint16_t                id;
>       uint16_t                def_ring_grp;
>       uint16_t                cos_rule;
>       uint16_t                lb_rule;
>       uint16_t                mru;
> 
>       uint32_t                rx_mask;
>       /* multicast things */
> 
>       uint32_t                flags;
> #define BNXT_VNIC_FLAG_DEFAULT                0x01
> #define BNXT_VNIC_FLAG_BD_STALL               0x02
> #define BNXT_VNIC_FLAG_VLAN_STRIP     0x04
> 
>       uint64_t                filter_id;
>       uint32_t                flow_id;
> 
>       uint16_t                rss_id;
>       /* rss things */
> 
>       /* vlan things */
> };
> 
> struct bnxt_slot {
>       bus_dmamap_t            bs_map;
>       struct mbuf             *bs_m;
> };
> 
> struct bnxt_dmamem {
>       bus_dmamap_t            bdm_map;
>       bus_dma_segment_t       bdm_seg;
>       size_t                  bdm_size;
>       caddr_t                 bdm_kva;
> };
> #define BNXT_DMA_MAP(_bdm)    ((_bdm)->bdm_map)
> #define BNXT_DMA_LEN(_bdm)    ((_bdm)->bdm_size)
> #define BNXT_DMA_DVA(_bdm)    ((u_int64_t)(_bdm)->bdm_map->dm_segs[0].ds_addr)
> #define BNXT_DMA_KVA(_bdm)    ((void *)(_bdm)->bdm_kva)
> 
> struct bnxt_softc {
>       struct device           sc_dev;
>       struct arpcom           sc_ac;
>       struct ifmedia          sc_media;
> 
>       struct mutex            sc_lock;
> 
>       pci_chipset_tag_t       sc_pc;
>       pcitag_t                sc_tag;
>       bus_dma_tag_t           sc_dmat;
> 
>       bus_space_tag_t         sc_hwrm_t;
>       bus_space_handle_t      sc_hwrm_h;
>       bus_size_t              sc_hwrm_s;
> 
>       struct bnxt_dmamem      *sc_cmd_resp;
>       uint16_t                sc_cmd_seq;
>       uint16_t                sc_max_req_len;
>       uint32_t                sc_cmd_timeo;
>       uint32_t                sc_flags;
> 
>       bus_space_tag_t         sc_db_t;
>       bus_space_handle_t      sc_db_h;
>       bus_size_t              sc_db_s;
> 
>       void                    *sc_ih;
> 
>       int                     sc_max_tc;
>       struct bnxt_cos_queue   sc_q_info[BNXT_MAX_QUEUE];
> 
>       struct bnxt_vnic_info   sc_vnic;
>       struct bnxt_dmamem      *sc_stats_ctx_mem;
> 
>       struct bnxt_cp_ring     sc_cp_ring;
>       struct bnxt_dmamem      *sc_cp_ring_mem;
> 
>       /* rx */
>       struct bnxt_dmamem      *sc_rx_ring_mem;        /* rx and ag */
>       struct bnxt_ring        sc_rx_ring;
>       /* struct bnxt_ring     sc_rx_ag_ring; */
>       struct bnxt_grp_info    sc_ring_group;
>       struct if_rxring        sc_rxr;
>       struct bnxt_slot        *sc_rx_slots;
>       int                     sc_rx_prod;
>       int                     sc_rx_cons;
>       struct timeout          sc_rx_refill;
> 
>       /* tx */
>       struct bnxt_dmamem      *sc_tx_ring_mem;
>       struct bnxt_ring        sc_tx_ring;
>       struct bnxt_slot        *sc_tx_slots;
>       int                     sc_tx_prod;
>       int                     sc_tx_cons;
>       int                     sc_tx_ring_prod;
>       int                     sc_tx_ring_cons;
> };
> #define DEVNAME(_sc)  ((_sc)->sc_dev.dv_xname)
> 
> const struct pci_matchid bnxt_devices[] = {
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57301 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57302 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57304 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57311 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57312 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57314 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57402 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57404 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57406 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57407 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57412 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57414 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57416 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57416_SFP },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57417 },
>       { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57417_SFP }
> };
> 
> int           bnxt_match(struct device *, void *, void *);
> void          bnxt_attach(struct device *, struct device *, void *);
> 
> void          bnxt_up(struct bnxt_softc *);
> void          bnxt_down(struct bnxt_softc *);
> void          bnxt_iff(struct bnxt_softc *);
> int           bnxt_ioctl(struct ifnet *, u_long, caddr_t);
> int           bnxt_rxrinfo(struct bnxt_softc *, struct if_rxrinfo *);
> void          bnxt_start(struct ifqueue *);
> int           bnxt_intr(void *);
> void          bnxt_watchdog(struct ifnet *);
> void          bnxt_media_status(struct ifnet *, struct ifmediareq *);
> int           bnxt_media_change(struct ifnet *);
> 
> void          bnxt_mark_cpr_invalid(struct bnxt_cp_ring *);
> void          bnxt_write_cp_doorbell(struct bnxt_softc *, struct bnxt_ring *,
>                   int);
> void          bnxt_write_cp_doorbell_index(struct bnxt_softc *,
>                   struct bnxt_ring *, uint32_t, int);
> void          bnxt_write_rx_doorbell(struct bnxt_softc *, struct bnxt_ring *,
>                   int);
> void          bnxt_write_tx_doorbell(struct bnxt_softc *, struct bnxt_ring *,
>                   int);
> 
> int           bnxt_rx_fill(struct bnxt_softc *);
> u_int         bnxt_rx_fill_slots(struct bnxt_softc *, u_int);
> void          bnxt_refill(void *);
> void          bnxt_rx(struct bnxt_softc *, struct mbuf_list *, int *,
>                   struct cmpl_base *, struct cmpl_base *);
> 
> int           bnxt_txeof(struct bnxt_softc *, struct cmpl_base *);
> 
> 
> /* HWRM Function Prototypes */
> int           bnxt_hwrm_ring_alloc(struct bnxt_softc *, uint8_t,
>                   struct bnxt_ring *, uint16_t, uint32_t, int);
> int           bnxt_hwrm_ring_free(struct bnxt_softc *, uint8_t,
>                   struct bnxt_ring *);
> int           bnxt_hwrm_ver_get(struct bnxt_softc *);
> int           bnxt_hwrm_queue_qportcfg(struct bnxt_softc *);
> int           bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *);
> int           bnxt_hwrm_func_qcaps(struct bnxt_softc *);
> int           bnxt_hwrm_func_qcfg(struct bnxt_softc *);
> int           bnxt_hwrm_func_reset(struct bnxt_softc *);
> int           bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *, uint16_t *);
> int           bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *, uint16_t *);
> int           bnxt_hwrm_vnic_cfg(struct bnxt_softc *,
>                   struct bnxt_vnic_info *);
> int           bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *,
>                   struct bnxt_cp_ring *, uint64_t);
> int           bnxt_hwrm_stat_ctx_free(struct bnxt_softc *,
>                   struct bnxt_cp_ring *);
> int           bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *,
>                   struct bnxt_grp_info *);
> int           bnxt_hwrm_ring_grp_free(struct bnxt_softc *,
>                   struct bnxt_grp_info *);
> int           bnxt_hwrm_vnic_alloc(struct bnxt_softc *,
>                   struct bnxt_vnic_info *);
> int           bnxt_hwrm_vnic_free(struct bnxt_softc *,
>                   struct bnxt_vnic_info *);
> int           bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *,
>                   struct bnxt_vnic_info *vnic);
> int           bnxt_hwrm_set_filter(struct bnxt_softc *,
>                   struct bnxt_vnic_info *);
> int           bnxt_hwrm_free_filter(struct bnxt_softc *,
>                   struct bnxt_vnic_info *);
> int           bnxt_cfg_async_cr(struct bnxt_softc *);
> int           bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *, uint16_t *,
>                   uint16_t *, uint32_t *, uint32_t *, uint32_t *, uint32_t *);
> int           bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *,
>                   struct ifmediareq *);
> int           bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *);
> 
> /* not used yet: */
> #if 0
> int bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown);
> 
> int bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
>     bool set_eee, bool set_link); 
> int bnxt_hwrm_set_pause(struct bnxt_softc *softc);
> 
> int bnxt_hwrm_port_qstats(struct bnxt_softc *softc);
> 
> int bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
>     uint32_t hash_type);
> 
> int bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc);
> void bnxt_validate_hw_lro_settings(struct bnxt_softc *softc);
> int bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
>     uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
>     uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
>     uint32_t *fw_ver);
> int bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index,
>     uint32_t offset, uint32_t length, struct iflib_dma_info *data);
> int bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index,
>     uint32_t offset, void *data, bool cpyin, uint32_t length);
> int bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
>     uint8_t *selfreset);
> int bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type,
>     uint8_t *selfreset);
> int bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
>     uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
>     uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
>     uint16_t *index);
> int bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index);
> int bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
>     uint32_t *entry_length);
> int bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc,
>     uint32_t *entries, uint32_t *entry_length, struct iflib_dma_info 
> *dma_data);
> 
> int bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
>     uint32_t install_type, uint64_t *installed_items, uint8_t *result,
>     uint8_t *problem_item, uint8_t *reset_required);
> int bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
>     uint16_t ordinal, uint16_t ext);
> int bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year,
>     uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute,
>     uint8_t *second, uint16_t *millisecond, uint16_t *zone);
> int bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year,
>     uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
>     uint16_t millisecond, uint16_t zone);
> 
> uint16_t bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle);
> int bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc);
> int bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc);
> int bnxt_hwrm_set_coal(struct bnxt_softc *softc);
> 
> #endif
> 
> 
> struct cfattach bnxt_ca = {
>       sizeof(struct bnxt_softc), bnxt_match, bnxt_attach
> };
> 
> struct cfdriver bnxt_cd = {
>       NULL, "bnxt", DV_IFNET
> };
> 
> struct bnxt_dmamem *
> bnxt_dmamem_alloc(struct bnxt_softc *sc, size_t size)
> {
>       struct bnxt_dmamem *m;
>       int nsegs;
> 
>       m = malloc(sizeof(*m), M_DEVBUF, M_NOWAIT | M_ZERO);
>       if (m == NULL)
>               return (NULL);
> 
>       m->bdm_size = size;
> 
>       if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
>           BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &m->bdm_map) != 0)
>               goto bdmfree;
> 
>       if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &m->bdm_seg, 1,
>           &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
>               goto destroy;
> 
>       if (bus_dmamem_map(sc->sc_dmat, &m->bdm_seg, nsegs, size, &m->bdm_kva,
>           BUS_DMA_NOWAIT) != 0)
>               goto free;
> 
>       if (bus_dmamap_load(sc->sc_dmat, m->bdm_map, m->bdm_kva, size, NULL,
>           BUS_DMA_NOWAIT) != 0)
>               goto unmap;
> 
>       return (m);
> 
> unmap:
>       bus_dmamem_unmap(sc->sc_dmat, m->bdm_kva, m->bdm_size);
> free:
>       bus_dmamem_free(sc->sc_dmat, &m->bdm_seg, 1);
> destroy:
>       bus_dmamap_destroy(sc->sc_dmat, m->bdm_map);
> bdmfree:
>       free(m, M_DEVBUF, sizeof *m);
> 
>       return (NULL);
> }
> 
> void
> bnxt_dmamem_free(struct bnxt_softc *sc, struct bnxt_dmamem *m)
> {
>       bus_dmamem_unmap(sc->sc_dmat, m->bdm_kva, m->bdm_size);
>       bus_dmamem_free(sc->sc_dmat, &m->bdm_seg, 1);
>       bus_dmamap_destroy(sc->sc_dmat, m->bdm_map);
>       free(m, M_DEVBUF, sizeof *m);
> }
> 
> int
> bnxt_match(struct device *parent, void *match, void *aux)
> {
>       return (pci_matchbyid(aux, bnxt_devices, nitems(bnxt_devices)));
> }
> 
> void
> bnxt_attach(struct device *parent, struct device *self, void *aux)
> {
>       struct bnxt_softc *sc = (struct bnxt_softc *)self;
>       struct ifnet *ifp = &sc->sc_ac.ac_if;
>       struct pci_attach_args *pa = aux;
>       pci_intr_handle_t ih;
>       const char *intrstr;
>       u_int memtype;
> 
>       /* enable busmaster? */
> 
>       sc->sc_pc = pa->pa_pc;
>       sc->sc_tag = pa->pa_tag;
>       sc->sc_dmat = pa->pa_dmat;
> 
>       memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BNXT_HWRM_BAR);
>       if (pci_mapreg_map(pa, BNXT_HWRM_BAR, memtype, 0, &sc->sc_hwrm_t,
>           &sc->sc_hwrm_h, NULL, &sc->sc_hwrm_s, 0)) {
>               printf(": failed to map hwrm\n");
>               return;
>       }
> 
>       memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BNXT_DOORBELL_BAR);
>       if (pci_mapreg_map(pa, BNXT_DOORBELL_BAR, memtype, 0, &sc->sc_db_t,
>           &sc->sc_db_h, NULL, &sc->sc_db_s, 0)) {
>               printf(": failed to map doorbell\n");
>               goto unmap_1;
>       }
> 
>       BNXT_HWRM_LOCK_INIT(sc, DEVNAME(sc));
>       sc->sc_cmd_resp = bnxt_dmamem_alloc(sc, PAGE_SIZE);
>       if (sc->sc_cmd_resp == NULL) {
>               printf(": failed to allocate command response buffer\n");
>               goto unmap_2;
>       }
> 
>       if (bnxt_hwrm_ver_get(sc) != 0) {
>               printf(": failed to query version info\n");
>               goto free_resp;
>       }
> 
>       if (bnxt_hwrm_nvm_get_dev_info(sc, NULL, NULL, NULL, NULL, NULL, NULL)
>           != 0) {
>               printf(": failed to get nvram info\n");
>               goto free_resp;
>       }
> 
>       if (bnxt_hwrm_func_drv_rgtr(sc) != 0) {
>               printf(": failed to register driver with firmware\n");
>               goto free_resp;
>       }
> 
>       if (bnxt_hwrm_func_rgtr_async_events(sc) != 0) {
>               printf(": failed to register async events\n");
>               goto free_resp;
>       }
> 
>       if (bnxt_hwrm_func_qcaps(sc) != 0) {
>               printf(": failed to get queue capabilities\n");
>               goto free_resp;
>       }
> 
>       /*
>        * devices advertise msi support, but there's no way to tell a
>        * completion queue to use msi mode, only legacy or msi-x.
>        */
>       if (/*pci_intr_map_msi(pa, &ih) != 0 && */ pci_intr_map(pa, &ih) != 0) {
>               printf(": unable to map interrupt\n");
>               goto free_resp;
>       }
>       intrstr = pci_intr_string(sc->sc_pc, ih);
>       sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET | IPL_MPSAFE,
>           bnxt_intr, sc, DEVNAME(sc));
>       if (sc->sc_ih == NULL) {
>               printf(": unable to establish interrupt");
>               if (intrstr != NULL)
>                       printf(" at %s", intrstr);
>               printf("\n");
>               goto deintr;
>       }
>       printf("%s, address %s\n", intrstr, ether_sprintf(sc->sc_ac.ac_enaddr));
> 
>       if (bnxt_hwrm_func_qcfg(sc) != 0) {
>               printf("%s: failed to query function config\n", DEVNAME(sc));
>               goto deintr;
>       }
> 
>       if (bnxt_hwrm_queue_qportcfg(sc) != 0) {
>               printf("%s: failed to query port config\n", DEVNAME(sc));
>               goto deintr;
>       }
> 
>       if (bnxt_hwrm_func_reset(sc) != 0) {
>               printf("%s: reset failed\n", DEVNAME(sc));
>               goto deintr;
>       }
> 
>       sc->sc_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE;
>       sc->sc_cp_ring.ring.phys_id = HWRM_NA_SIGNATURE;
>       sc->sc_cp_ring.softc = sc;
>       sc->sc_cp_ring.ring.id = 0;
>       sc->sc_cp_ring.ring.doorbell = sc->sc_cp_ring.ring.id * 0x80;
>       sc->sc_cp_ring.ring.ring_size = PAGE_SIZE / sizeof(struct cmpl_base);
>       sc->sc_cp_ring_mem = bnxt_dmamem_alloc(sc, PAGE_SIZE);
>       if (sc->sc_cp_ring_mem == NULL) {
>               printf("%s: failed to allocate completion queue memory\n",
>                   DEVNAME(sc));
>               goto deintr;
>       }
>       sc->sc_cp_ring.ring.vaddr = BNXT_DMA_KVA(sc->sc_cp_ring_mem);
>       sc->sc_cp_ring.ring.paddr = BNXT_DMA_DVA(sc->sc_cp_ring_mem);
>       sc->sc_cp_ring.cons = UINT32_MAX;
>       sc->sc_cp_ring.v_bit = 1;
>       bnxt_mark_cpr_invalid(&sc->sc_cp_ring);
>       if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL,
>           &sc->sc_cp_ring.ring, (uint16_t)HWRM_NA_SIGNATURE,
>           HWRM_NA_SIGNATURE, 1) != 0) {
>               printf("%s: failed to allocate completion queue\n",
>                   DEVNAME(sc));
>               goto free_cp_mem;
>       }
>       if (bnxt_cfg_async_cr(sc) != 0) {
>               printf("%s: failed to set async completion ring\n",
>                   DEVNAME(sc));
>               goto free_cp_mem;
>       }
>       bnxt_write_cp_doorbell(sc, &sc->sc_cp_ring.ring, 1);
> 
>       strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
>       ifp->if_softc = sc;
>       ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
>       ifp->if_xflags = IFXF_MPSAFE;
>       ifp->if_ioctl = bnxt_ioctl;
>       ifp->if_qstart = bnxt_start;
>       ifp->if_watchdog = bnxt_watchdog;
>       ifp->if_hardmtu = BNXT_MAX_MTU;
>       ifp->if_capabilities = IFCAP_VLAN_MTU;   /* ? */
>       /* checksum flags, hwtagging? */
>       IFQ_SET_MAXLEN(&ifp->if_snd, 1024);     /* ? */
> 
>       ifmedia_init(&sc->sc_media, IFM_IMASK, bnxt_media_change,
>           bnxt_media_status);
>       ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_AUTO, 0, NULL);
>       ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
> 
>       if_attach(ifp);
>       ether_ifattach(ifp);
> 
>       timeout_set(&sc->sc_rx_refill, bnxt_refill, sc);
> 
>       bnxt_hwrm_port_phy_qcfg(sc, NULL);
>       return;
> 
> free_cp_mem:
>       bnxt_dmamem_free(sc, sc->sc_cp_ring_mem);
> deintr:
>       pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
>       sc->sc_ih = NULL;
> free_resp:
>       bnxt_dmamem_free(sc, sc->sc_cmd_resp);
> unmap_2:
>       bus_space_unmap(sc->sc_hwrm_t, sc->sc_hwrm_h, sc->sc_hwrm_s);
>       sc->sc_hwrm_s = 0;
> unmap_1:
>       bus_space_unmap(sc->sc_db_t, sc->sc_db_h, sc->sc_db_s);
>       sc->sc_db_s = 0;
> }
> 
> void
> bnxt_free_slots(struct bnxt_softc *sc, struct bnxt_slot *slots, int allocated,
>     int total)
> {
>       struct bnxt_slot *bs;
> 
>       int i = allocated;
>       while (i-- > 0) {
>               bs = &slots[i];
>               bus_dmamap_destroy(sc->sc_dmat, bs->bs_map);
>       }
>       free(slots, M_DEVBUF, total * sizeof(*bs));
> }
> 
> void
> bnxt_up(struct bnxt_softc *sc)
> {
>       struct ifnet *ifp = &sc->sc_ac.ac_if;
>       struct bnxt_slot *bs;
>       int i;
> 
>       sc->sc_stats_ctx_mem = bnxt_dmamem_alloc(sc,
>           sizeof(struct ctx_hw_stats));
>       if (sc->sc_stats_ctx_mem == NULL) {
>               printf("%s: failed to allocate stats contexts\n", DEVNAME(sc));
>               return;
>       }
> 
>       sc->sc_tx_ring_mem = bnxt_dmamem_alloc(sc, PAGE_SIZE);
>       if (sc->sc_tx_ring_mem == NULL) {
>               printf("%s: failed to allocate tx ring\n", DEVNAME(sc));
>               goto free_stats;
>       }
> 
>       sc->sc_rx_ring_mem = bnxt_dmamem_alloc(sc, PAGE_SIZE * 2);
>       if (sc->sc_rx_ring_mem == NULL) {
>               printf("%s: failed to allocate rx ring\n", DEVNAME(sc));
>               goto free_tx;
>       }
> 
>       if (bnxt_hwrm_stat_ctx_alloc(sc, &sc->sc_cp_ring,
>           BNXT_DMA_DVA(sc->sc_stats_ctx_mem)) != 0) {
>               printf("%s: failed to set up stats context\n", DEVNAME(sc));
>               goto free_rx;
>       }
> 
>       sc->sc_tx_ring.phys_id = HWRM_NA_SIGNATURE;
>       sc->sc_tx_ring.id = BNXT_TX_RING_ID;
>       sc->sc_tx_ring.doorbell = sc->sc_tx_ring.id * 0x80;
>       sc->sc_tx_ring.ring_size = PAGE_SIZE / sizeof(struct tx_bd_short);
>       sc->sc_tx_ring.vaddr = BNXT_DMA_KVA(sc->sc_tx_ring_mem);
>       sc->sc_tx_ring.paddr = BNXT_DMA_DVA(sc->sc_tx_ring_mem);
>       if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
>           &sc->sc_tx_ring, sc->sc_cp_ring.ring.phys_id,
>           HWRM_NA_SIGNATURE, 1) != 0) {
>               printf("%s: failed to set up tx ring\n",
>                   DEVNAME(sc));
>               goto dealloc_stats;
>       }
>       bnxt_write_tx_doorbell(sc, &sc->sc_tx_ring, 0);
> 
>       sc->sc_rx_ring.phys_id = HWRM_NA_SIGNATURE;
>       sc->sc_rx_ring.id = BNXT_RX_RING_ID;
>       sc->sc_rx_ring.doorbell = sc->sc_rx_ring.id * 0x80;
>       sc->sc_rx_ring.ring_size = PAGE_SIZE / sizeof(struct rx_prod_pkt_bd);
>       sc->sc_rx_ring.vaddr = BNXT_DMA_KVA(sc->sc_rx_ring_mem);
>       sc->sc_rx_ring.paddr = BNXT_DMA_DVA(sc->sc_rx_ring_mem);
>       if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
>           &sc->sc_rx_ring, sc->sc_cp_ring.ring.phys_id,
>           HWRM_NA_SIGNATURE, 1) != 0) {
>               printf("%s: failed to set up rx ring\n",
>                   DEVNAME(sc));
>               goto dealloc_tx;
>       }
>       bnxt_write_rx_doorbell(sc, &sc->sc_rx_ring, 0);
> 
> #if 0
>       sc->sc_rx_ag_ring.phys_id = HWRM_NA_SIGNATURE;
>       sc->sc_rx_ag_ring.id = BNXT_AG_RING_ID;
>       sc->sc_rx_ag_ring.doorbell = sc->sc_rx_ring.id * 0x80;
>       sc->sc_rx_ag_ring.ring_size = PAGE_SIZE / sizeof(struct rx_prod_pkt_bd);
>       sc->sc_rx_ag_ring.vaddr = BNXT_DMA_KVA(sc->sc_rx_ring_mem) + PAGE_SIZE;
>       sc->sc_rx_ag_ring.paddr = BNXT_DMA_DVA(sc->sc_rx_ring_mem) + PAGE_SIZE;
>       if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
>           &sc->sc_rx_ag_ring, sc->sc_cp_ring.ring.phys_id,
>           HWRM_NA_SIGNATURE, 1) != 0) {
>               printf("%s: failed to set up rx ag ring\n",
>                   DEVNAME(sc));
>               goto dealloc_rx;
>       }
> #endif
> 
>       sc->sc_ring_group.grp_id = HWRM_NA_SIGNATURE;
>       sc->sc_ring_group.stats_ctx = sc->sc_cp_ring.stats_ctx_id;
>       sc->sc_ring_group.rx_ring_id = sc->sc_rx_ring.phys_id;
>       sc->sc_ring_group.ag_ring_id = HWRM_NA_SIGNATURE;
>       sc->sc_ring_group.cp_ring_id = sc->sc_cp_ring.ring.phys_id;
>       if (bnxt_hwrm_ring_grp_alloc(sc, &sc->sc_ring_group) != 0) {
>               printf("%s: failed to allocate ring group\n",
>                   DEVNAME(sc));
>               goto dealloc_rx;
>       }
> 
>       sc->sc_vnic.rss_id = HWRM_NA_SIGNATURE;
>       if (bnxt_hwrm_vnic_ctx_alloc(sc, &sc->sc_vnic.rss_id) != 0) {
>               printf("%s: failed to allocate vnic rss context\n",
>                   DEVNAME(sc));
>               goto dealloc_ring_group;
>       }
> 
>       sc->sc_vnic.id = HWRM_NA_SIGNATURE;
>       sc->sc_vnic.def_ring_grp = sc->sc_ring_group.grp_id;
>       sc->sc_vnic.mru = MCLBYTES;
>       sc->sc_vnic.cos_rule = (uint16_t)HWRM_NA_SIGNATURE;
>       sc->sc_vnic.lb_rule = (uint16_t)HWRM_NA_SIGNATURE;
>       sc->sc_vnic.rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST;
>       /* sc->sc_vnic.mc_list_count = 0; */
>       sc->sc_vnic.flags = BNXT_VNIC_FLAG_DEFAULT;
>       if (bnxt_hwrm_vnic_alloc(sc, &sc->sc_vnic) != 0) {
>               printf("%s: failed to allocate vnic\n", DEVNAME(sc));
>               goto dealloc_vnic_ctx;
>       }
> 
>       if (bnxt_hwrm_vnic_cfg(sc, &sc->sc_vnic) != 0) {
>               printf("%s: failed to configure vnic\n", DEVNAME(sc));
>               goto dealloc_vnic;
>       }
> 
>       sc->sc_vnic.filter_id = -1;
>       if (bnxt_hwrm_set_filter(sc, &sc->sc_vnic) != 0) {
>               printf("%s: failed to set vnic filter\n", DEVNAME(sc));
>               goto dealloc_vnic;
>       }
> 
>       /* don't configure rss or tpa yet */
> 
>       sc->sc_rx_slots = mallocarray(sizeof(*bs), sc->sc_rx_ring.ring_size,
>           M_DEVBUF, M_WAITOK | M_ZERO);
>       if (sc->sc_rx_slots == NULL) {
>               printf("%s: failed to allocate rx slots\n", DEVNAME(sc));
>               goto dealloc_filter;
>       }
> 
>       for (i = 0; i < sc->sc_rx_ring.ring_size; i++) {
>               bs = &sc->sc_rx_slots[i];
>               if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
>                   BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &bs->bs_map) != 0) {
>                       printf("%s: failed to allocate rx dma maps\n",
>                           DEVNAME(sc));
>                       goto destroy_rx_slots;
>               }
>       }
> 
>       sc->sc_tx_slots = mallocarray(sizeof(*bs), sc->sc_tx_ring.ring_size,
>           M_DEVBUF, M_WAITOK | M_ZERO);
>       if (sc->sc_tx_slots == NULL) {
>               printf("%s: failed to allocate tx slots\n", DEVNAME(sc));
>               goto destroy_rx_slots;
>       }
> 
>       for (i = 0; i < sc->sc_tx_ring.ring_size; i++) {
>               bs = &sc->sc_tx_slots[i];
>               if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, BNXT_MAX_TX_SEGS,
>                   MCLBYTES, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
>                   &bs->bs_map) != 0) {
>                       printf("%s: failed to allocate tx dma maps\n",
>                           DEVNAME(sc));
>                       goto destroy_tx_slots;
>               }
>       }
> 
>       bnxt_iff(sc);
> 
>       /*
>        * initially, the rx ring must be filled at least some distance beyond
>        * the current consumer index, as it looks like the firmware assumes the
>        * ring is full on creation, but doesn't prefetch the whole thing.
>        * once the whole ring has been used once, we should be able to back off
>        * to 2 or so slots, but we currently don't have a way of doing that.
>        */
>       if_rxr_init(&sc->sc_rxr, 32, sc->sc_rx_ring.ring_size - 1);
>       sc->sc_rx_prod = 0;
>       sc->sc_rx_cons = 0;
>       bnxt_rx_fill(sc);
> 
>       SET(ifp->if_flags, IFF_RUNNING);
> 
>       sc->sc_tx_cons = 0;
>       sc->sc_tx_prod = 0;
>       sc->sc_tx_ring_cons = 0;
>       sc->sc_tx_ring_prod = 0;
>       ifq_clr_oactive(&ifp->if_snd);
>       ifq_restart(&ifp->if_snd);
> 
>       return;
> 
> destroy_tx_slots:
>       bnxt_free_slots(sc, sc->sc_tx_slots, i, sc->sc_tx_ring.ring_size);
>       sc->sc_tx_slots = NULL;
> 
>       i = sc->sc_rx_ring.ring_size;
> destroy_rx_slots:
>       bnxt_free_slots(sc, sc->sc_rx_slots, i, sc->sc_rx_ring.ring_size);
>       sc->sc_rx_slots = NULL;
> dealloc_filter:
>       bnxt_hwrm_free_filter(sc, &sc->sc_vnic);
> dealloc_vnic:
>       bnxt_hwrm_vnic_free(sc, &sc->sc_vnic);
> dealloc_vnic_ctx:
>       bnxt_hwrm_vnic_ctx_free(sc, &sc->sc_vnic.rss_id);
> dealloc_ring_group:
>       bnxt_hwrm_ring_grp_free(sc, &sc->sc_ring_group);
> /* dealloc_ag: */
> dealloc_tx:
>       bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
>           &sc->sc_tx_ring);
> dealloc_rx:
>       bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
>           &sc->sc_rx_ring);
> dealloc_stats:
>       bnxt_hwrm_stat_ctx_free(sc, &sc->sc_cp_ring);
> free_rx:
>       bnxt_dmamem_free(sc, sc->sc_rx_ring_mem);
>       sc->sc_rx_ring_mem = NULL;
> free_tx:
>       bnxt_dmamem_free(sc, sc->sc_tx_ring_mem);
>       sc->sc_tx_ring_mem = NULL;
> free_stats:
>       bnxt_dmamem_free(sc, sc->sc_stats_ctx_mem);
>       sc->sc_stats_ctx_mem = NULL;
> }
> 
> void
> bnxt_down(struct bnxt_softc *sc)
> {
>       struct ifnet *ifp = &sc->sc_ac.ac_if;
>       
>       CLR(ifp->if_flags, IFF_RUNNING);
> 
>       ifq_clr_oactive(&ifp->if_snd);
>       ifq_barrier(&ifp->if_snd);
> 
>       timeout_del(&sc->sc_rx_refill);
> 
>       /* empty rx ring first i guess */
> 
>       bnxt_free_slots(sc, sc->sc_tx_slots, sc->sc_tx_ring.ring_size,
>           sc->sc_tx_ring.ring_size);
>       sc->sc_tx_slots = NULL;
> 
>       bnxt_free_slots(sc, sc->sc_rx_slots, sc->sc_rx_ring.ring_size,
>           sc->sc_rx_ring.ring_size);
>       sc->sc_rx_slots = NULL;
> 
>       bnxt_hwrm_free_filter(sc, &sc->sc_vnic);
>       bnxt_hwrm_vnic_free(sc, &sc->sc_vnic);
>       bnxt_hwrm_vnic_ctx_free(sc, &sc->sc_vnic.rss_id);
>       bnxt_hwrm_ring_grp_free(sc, &sc->sc_ring_group);
>       bnxt_hwrm_stat_ctx_free(sc, &sc->sc_cp_ring);
> 
>       /* may need to wait for 500ms here before we can free the rings */
> 
>       bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
>           &sc->sc_tx_ring);
>       bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
>           &sc->sc_rx_ring);
> 
>       bnxt_dmamem_free(sc, sc->sc_rx_ring_mem);
>       sc->sc_rx_ring_mem = NULL;
> 
>       bnxt_dmamem_free(sc, sc->sc_tx_ring_mem);
>       sc->sc_tx_ring_mem = NULL;
> 
>       bnxt_dmamem_free(sc, sc->sc_stats_ctx_mem);
>       sc->sc_stats_ctx_mem = NULL;
> }
> 
> void
> bnxt_iff(struct bnxt_softc *sc)
> {
>       struct ifnet *ifp = &sc->sc_ac.ac_if;
> 
>       if (ifp->if_flags & IFF_ALLMULTI)
>               sc->sc_vnic.rx_mask |=
>                   HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
>       else
>               sc->sc_vnic.rx_mask &=
>                   ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
> 
>       if (ifp->if_flags & IFF_PROMISC)
>               sc->sc_vnic.rx_mask |=
>                   HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS |
>                   HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN;
>       else
>               sc->sc_vnic.rx_mask &=
>                   ~(HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS |
>                   HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN);
> 
>       bnxt_hwrm_cfa_l2_set_rx_mask(sc, &sc->sc_vnic);
> }
> 
> int
> bnxt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
> {
>       struct bnxt_softc       *sc = (struct bnxt_softc *)ifp->if_softc;
>       struct ifreq            *ifr = (struct ifreq *)data;
>       int                     s, error = 0;
> 
>       s = splnet();
>       switch (cmd) {
>       case SIOCSIFADDR:
>               ifp->if_flags |= IFF_UP;
>               /* FALLTHROUGH */
> 
>       case SIOCSIFFLAGS:
>               if (ISSET(ifp->if_flags, IFF_UP)) {
>                       if (ISSET(ifp->if_flags, IFF_RUNNING))
>                               error = ENETRESET;
>                       else
>                               bnxt_up(sc);
>               } else {
>                       if (ISSET(ifp->if_flags, IFF_RUNNING))
>                               bnxt_down(sc);
>               }
>               break;
> 
>       case SIOCGIFMEDIA:
>       case SIOCSIFMEDIA:
>               error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
>               break;
> 
>       case SIOCGIFRXR:
>               error = bnxt_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data);
>               break;
> 
>       default:
>               error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
>       }
> 
>       if (error == ENETRESET) {
>               if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
>                   (IFF_UP | IFF_RUNNING))
>                       bnxt_iff(sc);
>               error = 0;
>       }
> 
>       splx(s);
> 
>       return (error);
> }
> 
> int
> bnxt_rxrinfo(struct bnxt_softc *sc, struct if_rxrinfo *ifri)
> {
>       struct if_rxring_info ifr;
> 
>       memset(&ifr, 0, sizeof(ifr));
>       ifr.ifr_size = MCLBYTES;
>       ifr.ifr_info = sc->sc_rxr;
> 
>       return (if_rxr_info_ioctl(ifri, 1, &ifr));
> }
> 
> int
> bnxt_load_mbuf(struct bnxt_softc *sc, struct bnxt_slot *bs, struct mbuf *m)
> {
>       switch (bus_dmamap_load_mbuf(sc->sc_dmat, bs->bs_map, m,
>           BUS_DMA_STREAMING | BUS_DMA_NOWAIT)) {
>       case 0:
>               break;
> 
>       case EFBIG:
>               if (m_defrag(m, M_DONTWAIT) == 0 &&
>                   bus_dmamap_load_mbuf(sc->sc_dmat, bs->bs_map, m,
>                   BUS_DMA_STREAMING | BUS_DMA_NOWAIT) == 0)
>                       break;
> 
>       default:
>               return (1);
>       }
> 
>       bs->bs_m = m;
>       return (0);
> }
> 
> void
> bnxt_start(struct ifqueue *ifq)
> {
>       struct ifnet *ifp = ifq->ifq_if;
>       struct tx_bd_short *txring;
>       struct bnxt_softc *sc = ifp->if_softc;
>       struct bnxt_slot *bs;
>       bus_dmamap_t map;
>       struct mbuf *m;
>       u_int idx, free, used;
>       uint16_t txflags;
>       int i;
> 
>       txring = (struct tx_bd_short *)BNXT_DMA_KVA(sc->sc_tx_ring_mem);
> 
>       idx = sc->sc_tx_ring_prod;
>       free = sc->sc_tx_ring_cons;
>       if (free <= idx)
>               free += sc->sc_tx_ring.ring_size;
>       free -= idx;
> 
>       used = 0;
> 
>       for (;;) {
>               if (used + BNXT_MAX_TX_SEGS > free) {
>                       ifq_set_oactive(ifq);
>                       break;
>               }
> 
>               m = ifq_dequeue(ifq);
>               if (m == NULL)
>                       break;
> 
>               bs = &sc->sc_tx_slots[sc->sc_tx_prod];
>               if (bnxt_load_mbuf(sc, bs, m) != 0) {
>                       m_freem(m);
>                       ifp->if_oerrors++;
>                       continue;
>               }
> 
> #if NBPFILTER > 0
>               if (ifp->if_bpf)
>                       bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
> #endif
>               map = bs->bs_map;
>               bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
>                   BUS_DMASYNC_PREWRITE);
>               used += map->dm_nsegs;
> 
>               if (map->dm_mapsize < 512)
>                       txflags = TX_BD_SHORT_FLAGS_LHINT_LT512;
>               else if (map->dm_mapsize < 1024)
>                       txflags = TX_BD_SHORT_FLAGS_LHINT_LT1K;
>               else if (map->dm_mapsize < 2048)
>                       txflags = TX_BD_SHORT_FLAGS_LHINT_LT2K;
>               else
>                       txflags = TX_BD_SHORT_FLAGS_LHINT_GTE2K;
> 
>               txflags |= TX_BD_SHORT_TYPE_TX_BD_SHORT |
>                   (map->dm_nsegs << TX_BD_SHORT_FLAGS_BD_CNT_SFT);
> 
>               for (i = 0; i < map->dm_nsegs; i++) {
>                       txring[idx].flags_type = htole16(txflags);
>                       if (i == map->dm_nsegs - 1)
>                               txring[idx].flags_type |=
>                                   TX_BD_SHORT_FLAGS_PACKET_END;
>                       txflags = TX_BD_SHORT_TYPE_TX_BD_SHORT;
> 
>                       txring[idx].len =
>                           htole16(bs->bs_map->dm_segs[i].ds_len);
>                       txring[idx].opaque = sc->sc_tx_prod;
>                       txring[idx].addr =
>                           htole64(bs->bs_map->dm_segs[i].ds_addr);
> 
>                       idx++;
>                       if (idx == sc->sc_tx_ring.ring_size)
>                               idx = 0;
>               }
> 
>               if (++sc->sc_tx_prod >= sc->sc_tx_ring.ring_size)
>                       sc->sc_tx_prod = 0;
>       }
> 
>       bnxt_write_tx_doorbell(sc, &sc->sc_tx_ring, idx);
>       sc->sc_tx_ring_prod = idx;
> }
> 
> void
> bnxt_handle_async_event(struct bnxt_softc *sc, struct cmpl_base *cmpl)
> {
>       struct hwrm_async_event_cmpl *ae = (struct hwrm_async_event_cmpl *)cmpl;
>       uint16_t type = le16toh(ae->event_id);
> 
>       switch (type) {
>       case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
>       case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE:
>       case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE:
>               bnxt_hwrm_port_phy_qcfg(sc, NULL);
>               break;
> 
>       default:
>               printf("%s: unexpected async event %x\n", DEVNAME(sc), type);
>               break;
>       }
> }
> 
> int
> bnxt_intr(void *xsc)
> {
>       struct bnxt_softc *sc = (struct bnxt_softc *)xsc;
>       struct ifnet *ifp = &sc->sc_ac.ac_if;
>       struct bnxt_cp_ring *cpr = &sc->sc_cp_ring;
>       struct cmpl_base *cmpl, *cmpl2;
>       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
>       uint32_t cons, last_cons;
>       int v_bit, last_v_bit;
>       uint16_t type;
>       int rxfree, txfree;
> 
>       cons = cpr->cons;
>       v_bit = cpr->v_bit;
> 
>       bnxt_write_cp_doorbell(sc, &cpr->ring, 0);
>       rxfree = 0;
>       txfree = 0;
>       for (;;) {
>               last_cons = cons;
>               last_v_bit = v_bit;
>               NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
>               cmpl = &((struct cmpl_base *)cpr->ring.vaddr)[cons];
> 
>               if ((!!(cmpl->info3_v & htole32(CMPL_BASE_V))) != (!!v_bit))
>                       break;
> 
>               type = le16toh(cmpl->type) & CMPL_BASE_TYPE_MASK;
>               switch (type) {
>               case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT:
>                       bnxt_handle_async_event(sc, cmpl);
>                       break;
>               case CMPL_BASE_TYPE_RX_L2:
>                       /* rx takes two slots */
>                       last_cons = cons;
>                       last_v_bit = v_bit;
>                       NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
>                       cmpl2 = &((struct cmpl_base *)cpr->ring.vaddr)[cons];
>                       bnxt_rx(sc, &ml, &rxfree, cmpl, cmpl2);
>                       break;
>               case CMPL_BASE_TYPE_TX_L2:
>                       txfree += bnxt_txeof(sc, cmpl);
>                       break;
>               default:
>                       printf("%s: unexpected completion type %u\n",
>                           DEVNAME(sc), type);
>               }
>       }
> 
>       cpr->cons = last_cons;
>       cpr->v_bit = last_v_bit;
> 
>       /*
>        * comments in bnxtreg.h suggest we should be writing cpr->cons here,
>        * but writing cpr->cons + 1 makes it stop interrupting.
>        */
>       bnxt_write_cp_doorbell_index(sc, &cpr->ring,
>           (cpr->cons+1) % cpr->ring.ring_size, 1);
> 
>       if (rxfree != 0) {
>               sc->sc_rx_cons += rxfree;
>               if (sc->sc_rx_cons >= sc->sc_rx_ring.ring_size)
>                       sc->sc_rx_cons -= sc->sc_rx_ring.ring_size;
> 
>               if_rxr_put(&sc->sc_rxr, rxfree);
> 
>               bnxt_rx_fill(sc);
>               if (sc->sc_rx_cons == sc->sc_rx_prod)
>                       timeout_add(&sc->sc_rx_refill, 0);
> 
>               if_input(&sc->sc_ac.ac_if, &ml);
>       }
>       if (txfree != 0) {
>               if (ifq_is_oactive(&ifp->if_snd))
>                       ifq_restart(&ifp->if_snd);
>       }
>       return (1);
> }
> 
> void
> bnxt_watchdog(struct ifnet *ifp)
> {
> }
> 
> void
> bnxt_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
> {
>       struct bnxt_softc *sc = (struct bnxt_softc *)ifp->if_softc;
>       bnxt_hwrm_port_phy_qcfg(sc, ifmr);
> }
> 
> int
> bnxt_media_change(struct ifnet *ifp)
> {
>       return 0;
> }
> 
> void
> bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr)
> {
>       struct cmpl_base *cmp = (void *)cpr->ring.vaddr;
>       int i;
> 
>       for (i = 0; i < cpr->ring.ring_size; i++)
>               cmp[i].info3_v = !cpr->v_bit;
> }
> 
> void
> bnxt_write_cp_doorbell(struct bnxt_softc *sc, struct bnxt_ring *ring,
>     int enable)
> {
>       uint32_t val = CMPL_DOORBELL_KEY_CMPL;
>       if (enable == 0)
>               val |= CMPL_DOORBELL_MASK;
> 
>       bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
>           BUS_SPACE_BARRIER_WRITE);
>       bus_space_barrier(sc->sc_db_t, sc->sc_db_h, 0, sc->sc_db_s,
>           BUS_SPACE_BARRIER_WRITE);
>       bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
>           htole32(val));
> }
> 
> void
> bnxt_write_cp_doorbell_index(struct bnxt_softc *sc, struct bnxt_ring *ring,
>     uint32_t index, int enable)
> {
>       uint32_t val = CMPL_DOORBELL_KEY_CMPL | CMPL_DOORBELL_IDX_VALID |
>           (index & CMPL_DOORBELL_IDX_MASK);
>       if (enable == 0)
>               val |= CMPL_DOORBELL_MASK;
>       bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
>           BUS_SPACE_BARRIER_WRITE);
>       bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
>           htole32(val));
>       bus_space_barrier(sc->sc_db_t, sc->sc_db_h, 0, sc->sc_db_s,
>           BUS_SPACE_BARRIER_WRITE);
> }
> 
> void
> bnxt_write_rx_doorbell(struct bnxt_softc *sc, struct bnxt_ring *ring, int 
> index)
> {
>       uint32_t val = RX_DOORBELL_KEY_RX | index;
>       bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
>           BUS_SPACE_BARRIER_WRITE);
>       bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
>           htole32(val));
> 
>       /* second write isn't necessary on all hardware */
>       bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
>           BUS_SPACE_BARRIER_WRITE);
>       bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
>           htole32(val));
> }
> 
> void
> bnxt_write_tx_doorbell(struct bnxt_softc *sc, struct bnxt_ring *ring, int 
> index)
> {
>       uint32_t val = TX_DOORBELL_KEY_TX | index;
>       bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
>           BUS_SPACE_BARRIER_WRITE);
>       bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
>           htole32(val));
> 
>       /* second write isn't necessary on all hardware */
>       bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
>           BUS_SPACE_BARRIER_WRITE);
>       bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
>           htole32(val));
> }
> 
> u_int
> bnxt_rx_fill_slots(struct bnxt_softc *sc, u_int slots)
> {
>       struct rx_prod_pkt_bd *rxring;
>       struct bnxt_slot *bs;
>       struct mbuf *m;
>       uint p, fills;
>       uint16_t type;
> 
>       type = RX_PROD_PKT_BD_TYPE_RX_PROD_PKT;
> 
>       rxring = (struct rx_prod_pkt_bd *)BNXT_DMA_KVA(sc->sc_rx_ring_mem);
>       p = sc->sc_rx_prod;
>       for (fills = 0; fills < slots; fills++) {
>               bs = &sc->sc_rx_slots[p];
>               m = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
>               if (m == NULL)
>                       break;
> 
>               m->m_len = m->m_pkthdr.len = MCLBYTES;
>               if (bus_dmamap_load_mbuf(sc->sc_dmat, bs->bs_map, m,
>                   BUS_DMA_NOWAIT) != 0) {
>                       m_freem(m);
>                       break;
>               }
>               bs->bs_m = m;
> 
>               rxring[p].flags_type = htole16(type);
>               rxring[p].len = htole16(MCLBYTES);
>               rxring[p].opaque = p;
>               rxring[p].addr = htole64(bs->bs_map->dm_segs[0].ds_addr);
> 
>               if (++p >= sc->sc_rx_ring.ring_size)
>                       p = 0;
>       }
> 
>       if (fills != 0)
>               bnxt_write_rx_doorbell(sc, &sc->sc_rx_ring, p);
>       sc->sc_rx_prod = p;
> 
>       return (slots - fills);
> }
> 
> int
> bnxt_rx_fill(struct bnxt_softc *sc)
> {
>       u_int slots;
> 
>       slots = if_rxr_get(&sc->sc_rxr, sc->sc_rx_ring.ring_size);
>       if (slots == 0)
>               return (1);
> 
>       slots = bnxt_rx_fill_slots(sc, slots);
>       if_rxr_put(&sc->sc_rxr, slots);
> 
>       return (0);
> }
> 
> void
> bnxt_refill(void *xsc)
> {
>       struct bnxt_softc *sc = xsc;
> 
>       bnxt_rx_fill(sc);
> 
>       if (sc->sc_rx_cons == sc->sc_rx_prod)
>               timeout_add(&sc->sc_rx_refill, 1);
> }
> 
> void
> bnxt_rx(struct bnxt_softc *sc, struct mbuf_list *ml, int *slots,
>     struct cmpl_base *cmpl, struct cmpl_base *cmpl2)
> {
>       struct mbuf *m;
>       struct bnxt_slot *bs;
>       struct rx_pkt_cmpl *rx = (struct rx_pkt_cmpl *)cmpl;
>       /* struct rx_pkt_cmpl_hi *rxhi = (struct rx_pkt_cmpl_hi *)cmpl2; */
> 
>       if (rx->opaque != sc->sc_rx_cons)
>               printf("%s: expected rx %d, got %d\n", DEVNAME(sc), 
> sc->sc_rx_cons, rx->opaque);
>       bs = &sc->sc_rx_slots[rx->opaque];
> 
>       bus_dmamap_sync(sc->sc_dmat, bs->bs_map, 0, bs->bs_map->dm_mapsize,
>           BUS_DMASYNC_POSTREAD);
>       bus_dmamap_unload(sc->sc_dmat, bs->bs_map);
> 
>       m = bs->bs_m;
>       bs->bs_m = NULL;
>       m->m_pkthdr.len = m->m_len = letoh16(rx->len);
>       ml_enqueue(ml, m);
>       (*slots)++;
> }
> 
> int
> bnxt_txeof(struct bnxt_softc *sc, struct cmpl_base *cmpl)
> {
>       struct tx_cmpl *txcmpl = (struct tx_cmpl *)cmpl;
>       struct bnxt_slot *bs;
>       bus_dmamap_t map;
>       u_int idx, freed;
> 
>       if (txcmpl->opaque != sc->sc_tx_cons)
>               printf("%s: txeof for %d, expected %d?\n",
>                   DEVNAME(sc), txcmpl->opaque, sc->sc_tx_cons);
>       idx = sc->sc_tx_ring_cons;
> 
>       bs = &sc->sc_tx_slots[sc->sc_tx_cons];
>       map = bs->bs_map;
> 
>       freed = map->dm_nsegs;
>       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
>           BUS_DMASYNC_POSTWRITE);
>       bus_dmamap_unload(sc->sc_dmat, map);
>       m_freem(bs->bs_m);
>       bs->bs_m = NULL;
> 
>       idx += freed;
>       if (idx >= sc->sc_tx_ring.ring_size)
>               idx -= sc->sc_tx_ring.ring_size;
>       sc->sc_tx_ring_cons = idx;
> 
>       if (++sc->sc_tx_cons >= sc->sc_tx_ring.ring_size)
>               sc->sc_tx_cons = 0;
> 
>       return (freed);
> }
> 
> /* bnxt_hwrm.c */
> 
> static int bnxt_hwrm_err_map(uint16_t err);
> #if 0
> static void   bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
>                   struct hwrm_port_phy_cfg_input *req);
> static void   bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
>                   struct hwrm_port_phy_cfg_input *req);
> static void   bnxt_hwrm_set_eee(struct bnxt_softc *softc,
>                   struct hwrm_port_phy_cfg_input *req);
> #endif
> 
> static int    _hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
> static int    hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
> static void bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
> 
> /* NVRam stuff has a five minute timeout */
> #define BNXT_NVM_TIMEO        (5 * 60 * 1000)
> 
> static int
> bnxt_hwrm_err_map(uint16_t err)
> {
>       int rc;
> 
>       switch (err) {
>       case HWRM_ERR_CODE_SUCCESS:
>               return 0;
>       case HWRM_ERR_CODE_INVALID_PARAMS:
>       case HWRM_ERR_CODE_INVALID_FLAGS:
>       case HWRM_ERR_CODE_INVALID_ENABLES:
>               return EINVAL;
>       case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
>               return EACCES;
>       case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
>               return ENOMEM;
>       case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
>               return ENOSYS;
>       case HWRM_ERR_CODE_FAIL:
>               return EIO;
>       case HWRM_ERR_CODE_HWRM_ERROR:
>       case HWRM_ERR_CODE_UNKNOWN_ERR:
>       default:
>               return EIO;
>       }
> 
>       return rc;
> }
> 
> static void
> bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
>     uint16_t req_type)
> {
>       struct input *req = request;
> 
>       req->req_type = htole16(req_type);
>       req->cmpl_ring = 0xffff;
>       req->target_id = 0xffff;
>       req->resp_addr = htole64(BNXT_DMA_DVA(softc->sc_cmd_resp));
> }
> 
> static int
> _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
> {
>       struct input *req = msg;
>       struct hwrm_err_output *resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
>       uint32_t *data = msg;
>       int i;
>       uint16_t cp_ring_id;
>       uint8_t *valid;
>       uint16_t err;
>       uint16_t max_req_len = HWRM_MAX_REQ_LEN;
>       struct hwrm_short_input short_input = {0};
> 
>       /* TODO: DMASYNC in here. */
>       req->seq_id = htole16(softc->sc_cmd_seq++);
>       memset(resp, 0, PAGE_SIZE);
>       cp_ring_id = le16toh(req->cmpl_ring);
> 
>       if (softc->sc_flags & BNXT_FLAG_SHORT_CMD) {
>               void *short_cmd_req = BNXT_DMA_KVA(softc->sc_cmd_resp);
> 
>               memcpy(short_cmd_req, req, msg_len);
>               memset((uint8_t *) short_cmd_req + msg_len, 0,
>                   softc->sc_max_req_len - msg_len);
> 
>               short_input.req_type = req->req_type;
>               short_input.signature =
>                   htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
>               short_input.size = htole16(msg_len);
>               short_input.req_addr =
>                   htole64(BNXT_DMA_DVA(softc->sc_cmd_resp));
> 
>               data = (uint32_t *)&short_input;
>               msg_len = sizeof(short_input);
> 
>               /* Sync memory write before updating doorbell */
>               membar_sync();
> 
>               max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
>       }
> 
>       /* Write request msg to hwrm channel */
>       for (i = 0; i < msg_len; i += 4) {
>               bus_space_write_4(softc->sc_hwrm_t,
>                                 softc->sc_hwrm_h,
>                                 i, *data);
>               data++;
>       }
> 
>       /* Clear to the end of the request buffer */
>       for (i = msg_len; i < max_req_len; i += 4)
>               bus_space_write_4(softc->sc_hwrm_t, softc->sc_hwrm_h,
>                   i, 0);
> 
>       /* Ring channel doorbell */
>       bus_space_write_4(softc->sc_hwrm_t, softc->sc_hwrm_h, 0x100,
>           htole32(1));
> 
>       /* Check if response len is updated */
>       for (i = 0; i < softc->sc_cmd_timeo; i++) {
>               if (resp->resp_len && resp->resp_len <= 4096)
>                       break;
>               DELAY(1000);
>       }
>       if (i >= softc->sc_cmd_timeo) {
>               printf("%s: timeout sending %s: (timeout: %u) seq: %d\n",
>                   DEVNAME(softc), GET_HWRM_REQ_TYPE(req->req_type),
>                   softc->sc_cmd_timeo,
>                   le16toh(req->seq_id));
>               return ETIMEDOUT;
>       }
>       /* Last byte of resp contains the valid key */
>       valid = (uint8_t *)resp + resp->resp_len - 1;
>       for (i = 0; i < softc->sc_cmd_timeo; i++) {
>               if (*valid == HWRM_RESP_VALID_KEY)
>                       break;
>               DELAY(1000);
>       }
>       if (i >= softc->sc_cmd_timeo) {
>               printf("%s: timeout sending %s: "
>                   "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
>                   DEVNAME(softc), GET_HWRM_REQ_TYPE(req->req_type),
>                   softc->sc_cmd_timeo, le16toh(req->req_type),
>                   le16toh(req->seq_id), msg_len,
>                   *valid);
>               return ETIMEDOUT;
>       }
> 
>       err = le16toh(resp->error_code);
>       if (err) {
>               /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
>               if (err != HWRM_ERR_CODE_FAIL) {
>                       printf("%s: %s command returned %s error.\n",
>                           DEVNAME(softc),
>                           GET_HWRM_REQ_TYPE(req->req_type),
>                           GET_HWRM_ERROR_CODE(err));
>               }
>               return bnxt_hwrm_err_map(err);
>       }
> 
>       return 0;
> }
> 
> 
> static int
> hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
> {
>       int rc;
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, msg, msg_len);
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> 
> int
> bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
> {
>       struct hwrm_queue_qportcfg_input req = {0};
>       struct hwrm_queue_qportcfg_output *resp =
>           BNXT_DMA_KVA(softc->sc_cmd_resp);
> 
>       int     rc = 0;
>       uint8_t *qptr;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto qportcfg_exit;
> 
>       if (!resp->max_configurable_queues) {
>               rc = -EINVAL;
>               goto qportcfg_exit;
>       }
>       softc->sc_max_tc = resp->max_configurable_queues;
>       if (softc->sc_max_tc > BNXT_MAX_QUEUE)
>               softc->sc_max_tc = BNXT_MAX_QUEUE;
> 
>       qptr = &resp->queue_id0;
>       for (int i = 0; i < softc->sc_max_tc; i++) {
>               softc->sc_q_info[i].id = *qptr++;
>               softc->sc_q_info[i].profile = *qptr++;
>       }
> 
> qportcfg_exit:
>       BNXT_HWRM_UNLOCK(softc);
>       return (rc);
> }
> 
> int
> bnxt_hwrm_ver_get(struct bnxt_softc *softc)
> {
>       struct hwrm_ver_get_input       req = {0};
>       struct hwrm_ver_get_output      *resp =
>           BNXT_DMA_KVA(softc->sc_cmd_resp);
>       int                             rc;
> #if 0
>       const char nastr[] = "<not installed>";
>       const char naver[] = "<N/A>";
> #endif
>       uint32_t dev_caps_cfg;
> 
>       softc->sc_max_req_len = HWRM_MAX_REQ_LEN;
>       softc->sc_cmd_timeo = 1000;
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
> 
>       req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
>       req.hwrm_intf_min = HWRM_VERSION_MINOR;
>       req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       printf(": fw ver %d.%d.%d, ", resp->hwrm_fw_maj, resp->hwrm_fw_min,
>           resp->hwrm_fw_bld);
> #if 0
>       snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
>           resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
>       softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
>       softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
>       softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
>       snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
>           resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
>       strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
>           BNXT_VERSTR_SIZE);
>       strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
>           BNXT_NAME_SIZE);
> 
>       if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
>           resp->mgmt_fw_bld == 0) {
>               strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
>               strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
>       }
>       else {
>               snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
>                   "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
>                   resp->mgmt_fw_bld);
>               strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
>                   BNXT_NAME_SIZE);
>       }
>       if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
>           resp->netctrl_fw_bld == 0) {
>               strlcpy(softc->ver_info->netctrl_fw_ver, naver,
>                   BNXT_VERSTR_SIZE);
>               strlcpy(softc->ver_info->netctrl_fw_name, nastr,
>                   BNXT_NAME_SIZE);
>       }
>       else {
>               snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
>                   "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
>                   resp->netctrl_fw_bld);
>               strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
>                   BNXT_NAME_SIZE);
>       }
>       if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
>           resp->roce_fw_bld == 0) {
>               strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
>               strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
>       }
>       else {
>               snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
>                   "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
>                   resp->roce_fw_bld);
>               strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
>                   BNXT_NAME_SIZE);
>       }
>       softc->ver_info->chip_num = le16toh(resp->chip_num);
>       softc->ver_info->chip_rev = resp->chip_rev;
>       softc->ver_info->chip_metal = resp->chip_metal;
>       softc->ver_info->chip_bond_id = resp->chip_bond_id;
>       softc->ver_info->chip_type = resp->chip_platform_type;
> #endif
> 
>       if (resp->max_req_win_len)
>               softc->sc_max_req_len = le16toh(resp->max_req_win_len);
>       if (resp->def_req_timeout)
>               softc->sc_cmd_timeo = le16toh(resp->def_req_timeout);
> 
>       dev_caps_cfg = le32toh(resp->dev_caps_cfg);
>       if ((dev_caps_cfg & 
> HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
>           (dev_caps_cfg & 
> HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
>               softc->sc_flags |= BNXT_FLAG_SHORT_CMD;
> 
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> 
> int
> bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
> {
>       struct hwrm_func_drv_rgtr_input req = {0};
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
> 
>       req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
>           HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
>       req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
> 
>       req.ver_maj = 6;
>       req.ver_min = 4;
>       req.ver_upd = 0;
> 
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> #if 0
> 
> int
> bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
> {
>       struct hwrm_func_drv_unrgtr_input req = {0};
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
>       if (shutdown == true)
>               req.flags |=
>                   HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> #endif
> 
> int
> bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
> {
>       int rc = 0;
>       struct hwrm_func_qcaps_input req = {0};
>       struct hwrm_func_qcaps_output *resp =
>           BNXT_DMA_KVA(softc->sc_cmd_resp);
>       /* struct bnxt_func_info *func = &softc->func; */
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
>       req.fid = htole16(0xffff);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       if (resp->flags &
>           htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
>               softc->sc_flags |= BNXT_FLAG_WOL_CAP;
> 
>       memcpy(softc->sc_ac.ac_enaddr, resp->mac_address, 6);
>       /*
>       func->fw_fid = le16toh(resp->fid);
>       memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
>       func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
>       func->max_cp_rings = le16toh(resp->max_cmpl_rings);
>       func->max_tx_rings = le16toh(resp->max_tx_rings);
>       func->max_rx_rings = le16toh(resp->max_rx_rings);
>       func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
>       if (!func->max_hw_ring_grps)
>               func->max_hw_ring_grps = func->max_tx_rings;
>       func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
>       func->max_vnics = le16toh(resp->max_vnics);
>       func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
>       if (BNXT_PF(softc)) {
>               struct bnxt_pf_info *pf = &softc->pf;
> 
>               pf->port_id = le16toh(resp->port_id);
>               pf->first_vf_id = le16toh(resp->first_vf_id);
>               pf->max_vfs = le16toh(resp->max_vfs);
>               pf->max_encap_records = le32toh(resp->max_encap_records);
>               pf->max_decap_records = le32toh(resp->max_decap_records);
>               pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
>               pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
>               pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
>               pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
>       }
>       if (!_is_valid_ether_addr(func->mac_addr)) {
>               device_printf(softc->dev, "Invalid ethernet address, generating 
> random locally administered address\n");
>               get_random_ether_addr(func->mac_addr);
>       }
>       */
> 
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> 
> int 
> bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
> {
>         struct hwrm_func_qcfg_input req = {0};
>         /* struct hwrm_func_qcfg_output *resp =
>           BNXT_DMA_KVA(softc->sc_cmd_resp);
>       struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg; */
>         int rc;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
>         req.fid = htole16(0xffff);
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>         if (rc)
>               goto fail;
> 
>       /*
>       fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
>       fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
>       fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
>       fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
>       */
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>         return rc;
> }
> 
> 
> int
> bnxt_hwrm_func_reset(struct bnxt_softc *softc)
> {
>       struct hwrm_func_reset_input req = {0};
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
>       req.enables = 0;
> 
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> #if 0
> static void
> bnxt_hwrm_set_link_common(struct bnxt_softc *softc,
>     struct hwrm_port_phy_cfg_input *req)
> {
>       uint8_t autoneg = softc->link_info.autoneg;
>       uint16_t fw_link_speed = softc->link_info.req_link_speed;
> 
>       if (autoneg & BNXT_AUTONEG_SPEED) {
>               req->auto_mode |=
>                   HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
> 
>               req->enables |=
>                   htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
>               req->flags |=
>                   htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
>       } else {
>               req->force_link_speed = htole16(fw_link_speed);
>               req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
>       }
> 
>       /* tell chimp that the setting takes effect immediately */
>       req->flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
> }
> 
> 
> static void
> bnxt_hwrm_set_pause_common(struct bnxt_softc *softc,
>     struct hwrm_port_phy_cfg_input *req)
> {
>       struct bnxt_link_info *link_info = &softc->link_info;
> 
>       if (link_info->flow_ctrl.autoneg) {
>               req->auto_pause =
>                   HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
>               if (link_info->flow_ctrl.rx)
>                       req->auto_pause |=
>                           HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
>               if (link_info->flow_ctrl.tx)
>                       req->auto_pause |=
>                           HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
>               req->enables |=
>                   htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
>       } else {
>               if (link_info->flow_ctrl.rx)
>                       req->force_pause |=
>                           HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
>               if (link_info->flow_ctrl.tx)
>                       req->force_pause |=
>                           HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
>               req->enables |=
>                       htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
>       }
> }
> 
> 
> /* JFV this needs interface connection */
> static void
> bnxt_hwrm_set_eee(struct bnxt_softc *softc, struct hwrm_port_phy_cfg_input 
> *req)
> {
>       /* struct ethtool_eee *eee = &softc->eee; */
>       bool    eee_enabled = false;
> 
>       if (eee_enabled) {
> # i f 0
>               uint16_t eee_speeds;
>               uint32_t flags = HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_ENABLE;
> 
>               if (eee->tx_lpi_enabled)
>                       flags |= HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_TX_LPI;
> 
>               req->flags |= htole32(flags);
>               eee_speeds = bnxt_get_fw_auto_link_speeds(eee->advertised);
>               req->eee_link_speed_mask = htole16(eee_speeds);
>               req->tx_lpi_timer = htole32(eee->tx_lpi_timer);
> # e n d i f
>       } else {
>               req->flags |=
>                   htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_EEE_DISABLE);
>       }
> }
> 
> 
> int
> bnxt_hwrm_set_link_setting(struct bnxt_softc *softc, bool set_pause,
>     bool set_eee, bool set_link)
> {
>       struct hwrm_port_phy_cfg_input req = {0};
>       int rc;
> 
>       if (softc->sc_flags & BNXT_FLAG_NPAR)
>               return ENOTSUP;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_CFG);
>       
>       if (set_pause) {
>               bnxt_hwrm_set_pause_common(softc, &req);
> 
>               if (softc->link_info.flow_ctrl.autoneg)
>                       set_link = true;
>       }
> 
>       if (set_link)
>               bnxt_hwrm_set_link_common(softc, &req);
>       
>       if (set_eee)
>               bnxt_hwrm_set_eee(softc, &req);
>       
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
> 
>       if (!rc) {
>               if (set_pause) {
>                       /* since changing of 'force pause' setting doesn't 
>                        * trigger any link change event, the driver needs to
>                        * update the current pause result upon successfully i
>                        * return of the phy_cfg command */
>                       if (!softc->link_info.flow_ctrl.autoneg) 
>                               bnxt_report_link(softc);
>               }
>       }
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> #endif
> 
> int
> bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
> {
>       struct hwrm_vnic_cfg_input req = {0};
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
> 
>       if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
>               req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
>       if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
>               req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
>       if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
>               req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
>       req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
>           HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
>           HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
>       req.vnic_id = htole16(vnic->id);
>       req.dflt_ring_grp = htole16(vnic->def_ring_grp);
>       req.rss_rule = htole16(vnic->rss_id);
>       req.cos_rule = htole16(vnic->cos_rule);
>       req.lb_rule = htole16(vnic->lb_rule);
>       req.mru = htole16(vnic->mru);
> 
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> int
> bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
> {
>       struct hwrm_vnic_alloc_input req = {0};
>       struct hwrm_vnic_alloc_output *resp =
>           BNXT_DMA_KVA(softc->sc_cmd_resp);
>       int rc;
> 
>       if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to re-allocate vnic %04x\n",
>                   DEVNAME(softc), vnic->id);
>               return EINVAL;
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
> 
>       if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
>               req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       vnic->id = le32toh(resp->vnic_id);
> 
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>       return (rc);
> }
> 
> int
> bnxt_hwrm_vnic_free(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
> {
>       struct hwrm_vnic_free_input req = {0};
>       int rc;
> 
>       if (vnic->id == (uint16_t)HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to deallocate vnic %04x\n",
>                   DEVNAME(softc), vnic->id);
>               return (EINVAL);
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_FREE);
>       req.vnic_id = htole16(vnic->id);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc == 0)
>               vnic->id = (uint16_t)HWRM_NA_SIGNATURE;
>       BNXT_HWRM_UNLOCK(softc);
> 
>       return (rc);
> }
> 
> int
> bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
> {
>       struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
>       struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
>           BNXT_DMA_KVA(softc->sc_cmd_resp);
>       int rc;
> 
>       if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to re-allocate vnic ctx %04x\n",
>                   DEVNAME(softc), *ctx_id);
>               return EINVAL;
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       *ctx_id = letoh16(resp->rss_cos_lb_ctx_id);
> 
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>       return (rc);
> }
> 
> int
> bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *softc, uint16_t *ctx_id)
> {
>       struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0};
>       int rc;
> 
>       if (*ctx_id == (uint16_t)HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to deallocate vnic ctx %04x\n",
>                   DEVNAME(softc), *ctx_id);
>               return (EINVAL);
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE);
>       req.rss_cos_lb_ctx_id = htole32(*ctx_id);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc == 0)
>               *ctx_id = (uint16_t)HWRM_NA_SIGNATURE;
>       BNXT_HWRM_UNLOCK(softc);
>       return (rc);
> }
> 
> int
> bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
> {
>       struct hwrm_ring_grp_alloc_input req = {0};
>       struct hwrm_ring_grp_alloc_output *resp;
>       int rc = 0;
> 
>       if (grp->grp_id != HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to re-allocate ring group %04x\n",
>                   DEVNAME(softc), grp->grp_id);
>               return EINVAL;
>       }
> 
>       resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
>       req.cr = htole16(grp->cp_ring_id);
>       req.rr = htole16(grp->rx_ring_id);
>       req.ar = htole16(grp->ag_ring_id);
>       req.sc = htole16(grp->stats_ctx);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       grp->grp_id = letoh32(resp->ring_group_id);
> 
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
> {
>       struct hwrm_ring_grp_free_input req = {0};
>       int rc = 0;
> 
>       if (grp->grp_id == HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to free ring group %04x\n",
>                   DEVNAME(softc), grp->grp_id);
>               return EINVAL;
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_FREE);
>       req.ring_group_id = htole32(grp->grp_id);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc == 0)
>               grp->grp_id = HWRM_NA_SIGNATURE;
> 
>       BNXT_HWRM_UNLOCK(softc);
>       return (rc);
> }
> 
> /*
>  * Ring allocation message to the firmware
>  */
> int
> bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
>     struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
>     int irq)
> {
>       struct hwrm_ring_alloc_input req = {0};
>       struct hwrm_ring_alloc_output *resp;
>       int rc;
> 
>       if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to re-allocate ring %04x\n",
>                   DEVNAME(softc), ring->phys_id);
>               return EINVAL;
>       }
> 
>       resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
>       req.enables = htole32(0);
>       req.fbo = htole32(0);
> 
>       if (stat_ctx_id != HWRM_NA_SIGNATURE) {
>               req.enables |= htole32(
>                   HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
>               req.stat_ctx_id = htole32(stat_ctx_id);
>       }
>       req.ring_type = type;
>       req.page_tbl_addr = htole64(ring->paddr);
>       req.length = htole32(ring->ring_size);
>       req.logical_id = htole16(ring->id);
>       req.cmpl_ring_id = htole16(cmpl_ring_id);
>       req.queue_id = htole16(softc->sc_q_info[0].id);
>       req.int_mode = 0;
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       ring->phys_id = le16toh(resp->ring_id);
> 
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_ring_free(struct bnxt_softc *softc, uint8_t type, struct bnxt_ring 
> *ring)
> {
>       struct hwrm_ring_free_input req = {0};
>       int rc;
> 
>       if (ring->phys_id == (uint16_t)HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to deallocate ring %04x\n",
>                   DEVNAME(softc), ring->phys_id);
>               return (EINVAL);
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_FREE);
>       req.ring_type = type;
>       req.ring_id = htole16(ring->phys_id);
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       ring->phys_id = (uint16_t)HWRM_NA_SIGNATURE;
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>       return (rc);
> }
> 
> 
> int
> bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
>     uint64_t paddr)
> {
>       struct hwrm_stat_ctx_alloc_input req = {0};
>       struct hwrm_stat_ctx_alloc_output *resp;
>       int rc = 0;
> 
>       if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to re-allocate stats ctx %08x\n",
>                   DEVNAME(softc), cpr->stats_ctx_id);
>               return EINVAL;
>       }
> 
>       resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
> 
>       req.update_period_ms = htole32(1000);
>       req.stats_dma_addr = htole64(paddr);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
> 
> fail:
>       BNXT_HWRM_UNLOCK(softc);
> 
>       return rc;
> }
> 
> int
> bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr)
> {
>       struct hwrm_stat_ctx_free_input req = {0};
>       int rc = 0;
> 
>       if (cpr->stats_ctx_id == HWRM_NA_SIGNATURE) {
>               printf("%s: attempt to free stats ctx %08x\n",
>                   DEVNAME(softc), cpr->stats_ctx_id);
>               return EINVAL;
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_FREE);
>       req.stat_ctx_id = htole32(cpr->stats_ctx_id);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       BNXT_HWRM_UNLOCK(softc);
> 
>       if (rc == 0)
>               cpr->stats_ctx_id = HWRM_NA_SIGNATURE;
> 
>       return (rc);
> }
> 
> #if 0
> 
> int
> bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
> {
>       struct hwrm_port_qstats_input req = {0};
>       int rc = 0;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
> 
>       req.port_id = htole16(softc->pf.port_id);
>       req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
>       req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       BNXT_HWRM_UNLOCK(softc);
> 
>       return rc;
> }
> 
> #endif
> 
> int
> bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
>     struct bnxt_vnic_info *vnic)
> {
>       struct hwrm_cfa_l2_set_rx_mask_input req = {0};
>       uint32_t mask = vnic->rx_mask;
> 
> #if 0
>       struct bnxt_vlan_tag *tag;
>       uint32_t *tags;
>       uint32_t num_vlan_tags = 0;;
>       uint32_t i;
>       int rc;
> 
>       SLIST_FOREACH(tag, &vnic->vlan_tags, next)
>               num_vlan_tags++;
> 
>       if (num_vlan_tags) {
>               if (!(mask &
>                   HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN)) {
>                       if (!vnic->vlan_only)
>                               mask |= 
> HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN;
>                       else
>                               mask |=
>                                   HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
>               }
>               if (vnic->vlan_tag_list.idi_vaddr) {
>                       iflib_dma_free(&vnic->vlan_tag_list);
>                       vnic->vlan_tag_list.idi_vaddr = NULL;
>               }
>               rc = iflib_dma_alloc(softc->ctx, 4 * num_vlan_tags,
>                   &vnic->vlan_tag_list, BUS_DMA_NOWAIT);
>               if (rc)
>                       return rc;
>               tags = (uint32_t *)vnic->vlan_tag_list.idi_vaddr;
> 
>               i = 0;
>               SLIST_FOREACH(tag, &vnic->vlan_tags, next) {
>                       tags[i] = htole32((tag->tpid << 16) | tag->tag);
>                       i++;
>               }
>       }
> #endif
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
> 
>       req.vnic_id = htole32(vnic->id);
>       req.mask = htole32(mask);
> #if 0
>       req.mc_tbl_addr = htole64(vnic->mc_list.idi_paddr);
>       req.num_mc_entries = htole32(vnic->mc_list_count);
>       req.vlan_tag_tbl_addr = htole64(vnic->vlan_tag_list.idi_paddr);
>       req.num_vlan_tags = htole32(num_vlan_tags);
> #endif
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> int
> bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
> {
>       struct hwrm_cfa_l2_filter_alloc_input   req = {0};
>       struct hwrm_cfa_l2_filter_alloc_output  *resp;
>       uint32_t enables = 0;
>       int rc = 0;
> 
>       if (vnic->filter_id != -1) {
>               printf("%s: attempt to re-allocate l2 ctx filter\n",
>                   DEVNAME(softc));
>               return EINVAL;
>       }
> 
>       resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
> 
>       req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
>       enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
>           | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
>           | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
>       req.enables = htole32(enables);
>       req.dst_id = htole16(vnic->id);
>       memcpy(req.l2_addr, softc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
>       memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto fail;
> 
>       vnic->filter_id = le64toh(resp->l2_filter_id);
>       vnic->flow_id = le64toh(resp->flow_id);
> 
> fail:
>       BNXT_HWRM_UNLOCK(softc);
>       return (rc);
> }
> 
> int
> bnxt_hwrm_free_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
> {
>       struct hwrm_cfa_l2_filter_free_input req = {0};
>       int rc = 0;
> 
>       if (vnic->filter_id == -1) {
>               printf("%s: attempt to deallocate filter %llx\n",
>                    DEVNAME(softc), vnic->filter_id);
>               return (EINVAL);
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_FREE);
>       req.l2_filter_id = htole64(vnic->filter_id);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc == 0)
>               vnic->filter_id = -1;
>       BNXT_HWRM_UNLOCK(softc);
> 
>       return (rc);
> }
> 
> 
> #if 0
> 
> int
> bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
>     uint32_t hash_type)
> {
>       struct hwrm_vnic_rss_cfg_input  req = {0};
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
> 
>       req.hash_type = htole32(hash_type);
>       req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
>       req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
>       req.rss_ctx_idx = htole16(vnic->rss_id);
> 
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> #endif
> 
> int
> bnxt_cfg_async_cr(struct bnxt_softc *softc)
> {
>       int rc = 0;
>       
>       if (1 /* BNXT_PF(softc) */) {
>               struct hwrm_func_cfg_input req = {0};
> 
>               bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
> 
>               req.fid = htole16(0xffff);
>               req.enables = 
> htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
>               req.async_event_cr = htole16(softc->sc_cp_ring.ring.phys_id);
> 
>               rc = hwrm_send_message(softc, &req, sizeof(req));
>       } else {
>               struct hwrm_func_vf_cfg_input req = {0};
> 
>               bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_VF_CFG);
> 
>               req.enables = 
> htole32(HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
>               req.async_event_cr = htole16(softc->sc_cp_ring.ring.phys_id);
> 
>               rc = hwrm_send_message(softc, &req, sizeof(req));
>       }
>       return rc;
> }
> 
> #if 0
> 
> void
> bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
> {
>       softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
> 
>         softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
> 
>       softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
>               HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
> 
>       softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
>               HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
> 
>       softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, 
> BNXT_MAX_MTU);
> }
> 
> int
> bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
> {
>       struct hwrm_vnic_tpa_cfg_input req = {0};
>       uint32_t flags;
> 
>       if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
>               return 0;
>       }
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
> 
>       if (softc->hw_lro.enable) {
>               flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
>                       HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
>                       HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
>                       HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
>               
>               if (softc->hw_lro.is_mode_gro)
>                       flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
>               else
>                       flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
>                       
>               req.flags = htole32(flags);
> 
>               req.enables = 
> htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
>                               HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
>                               HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
> 
>               req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
>               req.max_aggs = htole16(softc->hw_lro.max_aggs);
>               req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
>       }
> 
>       req.vnic_id = htole16(softc->vnic_info.id);
> 
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> int
> bnxt_hwrm_nvm_find_dir_entry(struct bnxt_softc *softc, uint16_t type,
>     uint16_t *ordinal, uint16_t ext, uint16_t *index, bool use_index,
>     uint8_t search_opt, uint32_t *data_length, uint32_t *item_length,
>     uint32_t *fw_ver)
> {
>       struct hwrm_nvm_find_dir_entry_input req = {0};
>       struct hwrm_nvm_find_dir_entry_output *resp =
>           (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       int     rc = 0;
>       uint32_t old_timeo;
> 
>       MPASS(ordinal);
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_FIND_DIR_ENTRY);
>       if (use_index) {
>               req.enables = htole32(
>                   HWRM_NVM_FIND_DIR_ENTRY_INPUT_ENABLES_DIR_IDX_VALID);
>               req.dir_idx = htole16(*index);
>       }
>       req.dir_type = htole16(type);
>       req.dir_ordinal = htole16(*ordinal);
>       req.dir_ext = htole16(ext);
>       req.opt_ordinal = search_opt;
> 
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       if (rc)
>               goto exit;
> 
>       if (item_length)
>               *item_length = le32toh(resp->dir_item_length);
>       if (data_length)
>               *data_length = le32toh(resp->dir_data_length);
>       if (fw_ver)
>               *fw_ver = le32toh(resp->fw_ver);
>       *ordinal = le16toh(resp->dir_ordinal);
>       if (index)
>               *index = le16toh(resp->dir_idx);
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
>       return (rc);
> }
> 
> int
> bnxt_hwrm_nvm_read(struct bnxt_softc *softc, uint16_t index, uint32_t offset,
>     uint32_t length, struct iflib_dma_info *data)
> {
>       struct hwrm_nvm_read_input req = {0};
>       int rc;
>       uint32_t old_timeo;
> 
>       if (length > data->idi_size) {
>               rc = EINVAL;
>               goto exit;
>       }
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_READ);
>       req.host_dest_addr = htole64(data->idi_paddr);
>       req.dir_idx = htole16(index);
>       req.offset = htole32(offset);
>       req.len = htole32(length);
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       BNXT_HWRM_UNLOCK(softc);
>       if (rc)
>               goto exit;
>       bus_dmamap_sync(data->idi_tag, data->idi_map, BUS_DMASYNC_POSTREAD);
> 
>       goto exit;
> 
> exit:
>       return rc;
> }
> 
> int
> bnxt_hwrm_nvm_modify(struct bnxt_softc *softc, uint16_t index, uint32_t 
> offset,
>     void *data, bool cpyin, uint32_t length)
> {
>       struct hwrm_nvm_modify_input req = {0};
>       struct iflib_dma_info dma_data;
>       int rc;
>       uint32_t old_timeo;
> 
>       if (length == 0 || !data)
>               return EINVAL;
>       rc = iflib_dma_alloc(softc->ctx, length, &dma_data,
>           BUS_DMA_NOWAIT);
>       if (rc)
>               return ENOMEM;
>       if (cpyin) {
>               rc = copyin(data, dma_data.idi_vaddr, length);
>               if (rc)
>                       goto exit;
>       }
>       else
>               memcpy(dma_data.idi_vaddr, data, length);
>       bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
>           BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_MODIFY);
>       req.host_src_addr = htole64(dma_data.idi_paddr);
>       req.dir_idx = htole16(index);
>       req.offset = htole32(offset);
>       req.len = htole32(length);
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       BNXT_HWRM_UNLOCK(softc);
> 
> exit:
>       iflib_dma_free(&dma_data);
>       return rc;
> }
> 
> int
> bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
>     uint8_t *selfreset)
> {
>       struct hwrm_fw_reset_input req = {0};
>       struct hwrm_fw_reset_output *resp =
>           (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       int rc;
> 
>       MPASS(selfreset);
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
>       req.embedded_proc_type = processor;
>       req.selfrst_status = *selfreset;
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto exit;
>       *selfreset = resp->selfrst_status;
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t 
> *selfreset)
> {
>       struct hwrm_fw_qstatus_input req = {0};
>       struct hwrm_fw_qstatus_output *resp =
>           (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       int rc;
> 
>       MPASS(selfreset);
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
>       req.embedded_proc_type = type;
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto exit;
>       *selfreset = resp->selfrst_status;
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_nvm_write(struct bnxt_softc *softc, void *data, bool cpyin,
>     uint16_t type, uint16_t ordinal, uint16_t ext, uint16_t attr,
>     uint16_t option, uint32_t data_length, bool keep, uint32_t *item_length,
>     uint16_t *index)
> {
>       struct hwrm_nvm_write_input req = {0};
>       struct hwrm_nvm_write_output *resp =
>           (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       struct iflib_dma_info dma_data;
>       int rc;
>       uint32_t old_timeo;
> 
>       if (data_length) {
>               rc = iflib_dma_alloc(softc->ctx, data_length, &dma_data,
>                   BUS_DMA_NOWAIT);
>               if (rc)
>                       return ENOMEM;
>               if (cpyin) {
>                       rc = copyin(data, dma_data.idi_vaddr, data_length);
>                       if (rc)
>                               goto early_exit;
>               }
>               else
>                       memcpy(dma_data.idi_vaddr, data, data_length);
>               bus_dmamap_sync(dma_data.idi_tag, dma_data.idi_map,
>                   BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
>       }
>       else
>               dma_data.idi_paddr = 0;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_WRITE);
> 
>       req.host_src_addr = htole64(dma_data.idi_paddr);
>       req.dir_type = htole16(type);
>       req.dir_ordinal = htole16(ordinal);
>       req.dir_ext = htole16(ext);
>       req.dir_attr = htole16(attr);
>       req.dir_data_length = htole32(data_length);
>       req.option = htole16(option);
>       if (keep) {
>               req.flags =
>                   htole16(HWRM_NVM_WRITE_INPUT_FLAGS_KEEP_ORIG_ACTIVE_IMG);
>       }
>       if (item_length)
>               req.dir_item_length = htole32(*item_length);
> 
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       if (rc)
>               goto exit;
>       if (item_length)
>               *item_length = le32toh(resp->dir_item_length);
>       if (index)
>               *index = le16toh(resp->dir_idx);
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
> early_exit:
>       if (data_length)
>               iflib_dma_free(&dma_data);
>       return rc;
> }
> 
> int
> bnxt_hwrm_nvm_erase_dir_entry(struct bnxt_softc *softc, uint16_t index)
> {
>       struct hwrm_nvm_erase_dir_entry_input req = {0};
>       uint32_t old_timeo;
>       int rc;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_ERASE_DIR_ENTRY);
>       req.dir_idx = htole16(index);
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_nvm_get_dir_info(struct bnxt_softc *softc, uint32_t *entries,
>     uint32_t *entry_length)
> {
>       struct hwrm_nvm_get_dir_info_input req = {0};
>       struct hwrm_nvm_get_dir_info_output *resp =
>           (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       int rc;
>       uint32_t old_timeo;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_INFO);
> 
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       if (rc)
>               goto exit;
> 
>       if (entries)
>               *entries = le32toh(resp->entries);
>       if (entry_length)
>               *entry_length = le32toh(resp->entry_length);
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_nvm_get_dir_entries(struct bnxt_softc *softc, uint32_t *entries,
>     uint32_t *entry_length, struct iflib_dma_info *dma_data)
> {
>       struct hwrm_nvm_get_dir_entries_input req = {0};
>       uint32_t ent;
>       uint32_t ent_len;
>       int rc;
>       uint32_t old_timeo;
> 
>       if (!entries)
>               entries = &ent;
>       if (!entry_length)
>               entry_length = &ent_len;
> 
>       rc = bnxt_hwrm_nvm_get_dir_info(softc, entries, entry_length);
>       if (rc)
>               goto exit;
>       if (*entries * *entry_length > dma_data->idi_size) {
>               rc = EINVAL;
>               goto exit;
>       }
> 
>       /*
>        * TODO: There's a race condition here that could blow up DMA memory...
>        *       we need to allocate the max size, not the currently in use
>        *       size.  The command should totally have a max size here.
>        */
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DIR_ENTRIES);
>       req.host_dest_addr = htole64(dma_data->idi_paddr);
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       BNXT_HWRM_UNLOCK(softc);
>       if (rc)
>               goto exit;
>       bus_dmamap_sync(dma_data->idi_tag, dma_data->idi_map,
>           BUS_DMASYNC_POSTWRITE);
> 
> exit:
>       return rc;
> }
> 
> #endif
> 
> int
> bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
>     uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
>     uint32_t *reserved_size, uint32_t *available_size)
> {
>       struct hwrm_nvm_get_dev_info_input req = {0};
>       struct hwrm_nvm_get_dev_info_output *resp =
>           BNXT_DMA_KVA(softc->sc_cmd_resp);
>       int rc;
>       uint32_t old_timeo;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
> 
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->sc_cmd_timeo;
>       softc->sc_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->sc_cmd_timeo = old_timeo;
>       if (rc)
>               goto exit;
> 
>       if (mfg_id)
>               *mfg_id = le16toh(resp->manufacturer_id);
>       if (device_id)
>               *device_id = le16toh(resp->device_id);
>       if (sector_size)
>               *sector_size = le32toh(resp->sector_size);
>       if (nvram_size)
>               *nvram_size = le32toh(resp->nvram_size);
>       if (reserved_size)
>               *reserved_size = le32toh(resp->reserved_size);
>       if (available_size)
>               *available_size = le32toh(resp->available_size);
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> #if 0
> 
> int
> bnxt_hwrm_nvm_install_update(struct bnxt_softc *softc,
>     uint32_t install_type, uint64_t *installed_items, uint8_t *result,
>     uint8_t *problem_item, uint8_t *reset_required)
> {
>       struct hwrm_nvm_install_update_input req = {0};
>       struct hwrm_nvm_install_update_output *resp =
>           (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       int rc;
>       uint32_t old_timeo;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_INSTALL_UPDATE);
>       req.install_type = htole32(install_type);
> 
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       if (rc)
>               goto exit;
> 
>       if (installed_items)
>               *installed_items = le32toh(resp->installed_items);
>       if (result)
>               *result = resp->result;
>       if (problem_item)
>               *problem_item = resp->problem_item;
>       if (reset_required)
>               *reset_required = resp->reset_required;
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_nvm_verify_update(struct bnxt_softc *softc, uint16_t type,
>     uint16_t ordinal, uint16_t ext)
> {
>       struct hwrm_nvm_verify_update_input req = {0};
>       uint32_t old_timeo;
>       int rc;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_VERIFY_UPDATE);
> 
>       req.dir_type = htole16(type);
>       req.dir_ordinal = htole16(ordinal);
>       req.dir_ext = htole16(ext);
> 
>       BNXT_HWRM_LOCK(softc);
>       old_timeo = softc->hwrm_cmd_timeo;
>       softc->hwrm_cmd_timeo = BNXT_NVM_TIMEO;
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       softc->hwrm_cmd_timeo = old_timeo;
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t 
> *month,
>     uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
>     uint16_t *millisecond, uint16_t *zone)
> {
>       struct hwrm_fw_get_time_input req = {0};
>       struct hwrm_fw_get_time_output *resp =
>           (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       int rc;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
> 
>       BNXT_HWRM_LOCK(softc);
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc)
>               goto exit;
> 
>       if (year)
>               *year = le16toh(resp->year);
>       if (month)
>               *month = resp->month;
>       if (day)
>               *day = resp->day;
>       if (hour)
>               *hour = resp->hour;
>       if (minute)
>               *minute = resp->minute;
>       if (second)
>               *second = resp->second;
>       if (millisecond)
>               *millisecond = le16toh(resp->millisecond);
>       if (zone)
>               *zone = le16toh(resp->zone);
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
>       return rc;
> }
> 
> int
> bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
>     uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
>     uint16_t millisecond, uint16_t zone)
> {
>       struct hwrm_fw_set_time_input req = {0};
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
> 
>       req.year = htole16(year);
>       req.month = month;
>       req.day = day;
>       req.hour = hour;
>       req.minute = minute;
>       req.second = second;
>       req.millisecond = htole16(millisecond);
>       req.zone = htole16(zone);
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> #endif
> 
> int
> bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc, struct ifmediareq *ifmr)
> {
>       struct ifnet *ifp = &softc->sc_ac.ac_if;
>       struct hwrm_port_phy_qcfg_input req = {0};
>       struct hwrm_port_phy_qcfg_output *resp =
>           BNXT_DMA_KVA(softc->sc_cmd_resp);
>       int rc = 0;
>       int link_state = LINK_STATE_DOWN;
> 
>       BNXT_HWRM_LOCK(softc);
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
> 
>       rc = _hwrm_send_message(softc, &req, sizeof(req));
>       if (rc) {
>               printf("%s: failed to query port phy config\n", DEVNAME(softc));
>               goto exit;
>       }
> 
>       if (resp->link == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) {
>               if (resp->duplex_state == 
> HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_STATE_HALF)
>                       link_state = LINK_STATE_HALF_DUPLEX;
>               else
>                       link_state = LINK_STATE_FULL_DUPLEX;
> 
>               switch (resp->link_speed) {
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB:
>                       ifp->if_baudrate = IF_Mbps(10);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB:
>                       ifp->if_baudrate = IF_Mbps(100);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB:
>                       ifp->if_baudrate = IF_Gbps(1);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB:
>                       ifp->if_baudrate = IF_Gbps(2);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB:
>                       ifp->if_baudrate = IF_Mbps(2500);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB:
>                       ifp->if_baudrate = IF_Gbps(10);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB:
>                       ifp->if_baudrate = IF_Gbps(20);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB:
>                       ifp->if_baudrate = IF_Gbps(25);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB:
>                       ifp->if_baudrate = IF_Gbps(40);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB:
>                       ifp->if_baudrate = IF_Gbps(50);
>                       break;
>               case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB:
>                       ifp->if_baudrate = IF_Gbps(100);
>                       break;
>               }
>       }
> 
>       if (ifmr != NULL) {
>               ifmr->ifm_status = IFM_AVALID;
>               if (LINK_STATE_IS_UP(ifp->if_link_state)) {
>                       ifmr->ifm_status |= IFM_ACTIVE;
>                       ifmr->ifm_active = IFM_ETHER | IFM_AUTO;
>                       if (resp->pause & HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
>                               ifmr->ifm_active |= IFM_ETH_TXPAUSE;
>                       if (resp->pause & HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
>                               ifmr->ifm_active |= IFM_ETH_RXPAUSE;
>                       if (resp->duplex_state == 
> HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_STATE_HALF)
>                               ifmr->ifm_active |= IFM_HDX;
>                       else
>                               ifmr->ifm_active |= IFM_FDX;
>               }
>       }
> 
> exit:
>       BNXT_HWRM_UNLOCK(softc);
> 
>       if (rc == 0 && (link_state != ifp->if_link_state)) {
>               ifp->if_link_state = link_state;
>               if_link_state_change(ifp);
>       }
> 
>       return rc;
> }
> 
> #if 0
> 
> uint16_t
> bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle)
> {
>       struct hwrm_wol_filter_qcfg_input req = {0};
>       struct hwrm_wol_filter_qcfg_output *resp =
>                       (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       uint16_t next_handle = 0;
>       int rc;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_QCFG);
>       req.port_id = htole16(softc->pf.port_id);
>       req.handle = htole16(handle);
>       rc = hwrm_send_message(softc, &req, sizeof(req));
>       if (!rc) {
>               next_handle = le16toh(resp->next_handle);
>               if (next_handle != 0) {
>                       if (resp->wol_type ==
>                               HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT) {
>                               softc->wol = 1;
>                               softc->wol_filter_id = resp->wol_filter_id;
>                       }
>               }
>       }
>       return next_handle;
> }
> 
> int
> bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc)
> {
>       struct hwrm_wol_filter_alloc_input req = {0};
>       struct hwrm_wol_filter_alloc_output *resp =
>               (void *)softc->hwrm_cmd_resp.idi_vaddr;
>       int rc;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_ALLOC);
>       req.port_id = htole16(softc->pf.port_id);
>       req.wol_type = HWRM_WOL_FILTER_ALLOC_INPUT_WOL_TYPE_MAGICPKT;
>       req.enables =
>               htole32(HWRM_WOL_FILTER_ALLOC_INPUT_ENABLES_MAC_ADDRESS);
>       memcpy(req.mac_address, softc->func.mac_addr, ETHER_ADDR_LEN);
>       rc = hwrm_send_message(softc, &req, sizeof(req));
>       if (!rc)
>               softc->wol_filter_id = resp->wol_filter_id;
> 
>       return rc;
> }
> 
> int
> bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
> {
>       struct hwrm_wol_filter_free_input req = {0};
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_WOL_FILTER_FREE);
>       req.port_id = htole16(softc->pf.port_id);
>       req.enables =
>               htole32(HWRM_WOL_FILTER_FREE_INPUT_ENABLES_WOL_FILTER_ID);
>       req.wol_filter_id = softc->wol_filter_id;
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t 
> max_frames,
>         uint32_t buf_tmrs, uint16_t flags,
>         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
> {
>         req->flags = htole16(flags);
>         req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
>         req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
>         req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
>         req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
>         /* Minimum time between 2 interrupts set to buf_tmr x 2 */
>         req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
>         req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
>         req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
> }
> 
> 
> int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
> {
>         int i, rc = 0;
>         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
>                                                            req_tx = {0}, *req;
>         uint16_t max_buf, max_buf_irq;
>         uint16_t buf_tmr, buf_tmr_irq;
>         uint32_t flags;
> 
>         bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
>                                HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
>         bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
>                                HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
> 
>         /* Each rx completion (2 records) should be DMAed immediately.
>          * DMA 1/4 of the completion buffers at a time.
>          */
>         max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
>         /* max_buf must not be zero */
>         max_buf = clamp_t(uint16_t, max_buf, 1, 63);
>         max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
>         buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
>         /* buf timer set to 1/4 of interrupt timer */
>         buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
>         buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
>         buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
> 
>         flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
> 
>         /* RING_IDLE generates more IRQs for lower latency.  Enable it only
>          * if coal_usecs is less than 25 us.
>          */
>         if (softc->rx_coal_usecs < 25)
>                 flags |= 
> HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
> 
>         bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
>                                   buf_tmr_irq << 16 | buf_tmr, flags, 
> &req_rx);
> 
>         /* max_buf must not be zero */
>         max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
>         max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
>         buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
>         /* buf timer set to 1/4 of interrupt timer */
>         buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
>         buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
>         buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
>         flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
>         bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
>                                   buf_tmr_irq << 16 | buf_tmr, flags, 
> &req_tx);
> 
>         for (i = 0; i < softc->nrxqsets; i++) {
> 
>                 
>               req = &req_rx;
>                 /*
>                  * TBD:
>                *      Check if Tx also needs to be done
>                  *      So far, Tx processing has been done in softirq contest
>                  *
>                * req = &req_tx;
>                */
>               req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
> 
>                 rc = hwrm_send_message(softc, req, sizeof(*req));
>                 if (rc)
>                         break;
>         }
>         return rc;
> }
> 
> #endif
> 
> void
> _bnxt_hwrm_set_async_event_bit(struct hwrm_func_drv_rgtr_input *req, int bit)
> {
>       req->async_event_fwd[bit/32] |= (1 << (bit % 32));
> }
> 
> int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc)
> {
>       struct hwrm_func_drv_rgtr_input req = {0};
>       int events[] = {
>               HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
>               HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
>               HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
>               HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
>               HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE
>       };
>       int i;
> 
>       bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
> 
>       req.enables =
>               htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
> 
>       for (i = 0; i < nitems(events); i++)
>               _bnxt_hwrm_set_async_event_bit(&req, events[i]);
> 
>       return hwrm_send_message(softc, &req, sizeof(req));
> }
> 
> 

Reply via email to