LCOV - code coverage report
Current view: top level - dev/pci - if_bnxt.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1306 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_bnxt.c,v 1.15 2018/09/10 04:59:32 jmatthew Exp $   */
       2             : /*-
       3             :  * Broadcom NetXtreme-C/E network driver.
       4             :  *
       5             :  * Copyright (c) 2016 Broadcom, All Rights Reserved.
       6             :  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
      18             :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
      21             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      22             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      23             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      24             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      25             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      26             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      27             :  * THE POSSIBILITY OF SUCH DAMAGE.
      28             :  */
      29             : 
      30             : /*
      31             :  * Copyright (c) 2018 Jonathan Matthew <jmatthew@openbsd.org>
      32             :  *
      33             :  * Permission to use, copy, modify, and distribute this software for any
      34             :  * purpose with or without fee is hereby granted, provided that the above
      35             :  * copyright notice and this permission notice appear in all copies.
      36             :  *
      37             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      38             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      39             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      40             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      41             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      42             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      43             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      44             :  */
      45             : 
      46             : 
      47             : #include "bpfilter.h"
      48             : 
      49             : #include <sys/param.h>
      50             : #include <sys/systm.h>
      51             : #include <sys/mbuf.h>
      52             : #include <sys/kernel.h>
      53             : #include <sys/malloc.h>
      54             : #include <sys/device.h>
      55             : #include <sys/stdint.h>
      56             : #include <sys/sockio.h>
      57             : #include <sys/atomic.h>
      58             : 
      59             : #include <machine/bus.h>
      60             : 
      61             : #include <dev/pci/pcireg.h>
      62             : #include <dev/pci/pcivar.h>
      63             : #include <dev/pci/pcidevs.h>
      64             : 
      65             : #define __FBSDID(x)
      66             : #include <dev/pci/if_bnxtreg.h>
      67             : 
      68             : #include <net/if.h>
      69             : #include <net/if_media.h>
      70             : 
      71             : #if NBPFILTER > 0
      72             : #include <net/bpf.h>
      73             : #endif
      74             : 
      75             : #include <netinet/in.h>
      76             : #include <netinet/if_ether.h>
      77             : 
      78             : #define BNXT_HWRM_BAR           0x10
      79             : #define BNXT_DOORBELL_BAR       0x18
      80             : 
      81             : #define BNXT_RX_RING_ID         0
      82             : #define BNXT_AG_RING_ID         1
      83             : #define BNXT_TX_RING_ID         3
      84             : 
      85             : #define BNXT_MAX_QUEUE          8
      86             : #define BNXT_MAX_MTU            9000
      87             : #define BNXT_AG_BUFFER_SIZE     8192
      88             : 
      89             : #define BNXT_CP_PAGES           4
      90             : 
      91             : #define BNXT_MAX_TX_SEGS        32      /* a bit much? */
      92             : 
      93             : #define BNXT_HWRM_SHORT_REQ_LEN sizeof(struct hwrm_short_input)
      94             : 
      95             : #define BNXT_HWRM_LOCK_INIT(_sc, _name) \
      96             :         mtx_init_flags(&sc->sc_lock, IPL_NET, _name, 0)
      97             : #define BNXT_HWRM_LOCK(_sc)             mtx_enter(&_sc->sc_lock)
      98             : #define BNXT_HWRM_UNLOCK(_sc)           mtx_leave(&_sc->sc_lock)
      99             : #define BNXT_HWRM_LOCK_DESTROY(_sc)     /* nothing */
     100             : #define BNXT_HWRM_LOCK_ASSERT(_sc)      MUTEX_ASSERT_LOCKED(&_sc->sc_lock)
     101             : 
     102             : #define BNXT_FLAG_VF            0x0001
     103             : #define BNXT_FLAG_NPAR          0x0002
     104             : #define BNXT_FLAG_WOL_CAP       0x0004
     105             : #define BNXT_FLAG_SHORT_CMD     0x0008
     106             : 
     107             : /* NVRam stuff has a five minute timeout */
     108             : #define BNXT_NVM_TIMEO  (5 * 60 * 1000)
     109             : 
     110             : #define NEXT_CP_CONS_V(_ring, _cons, _v_bit)            \
     111             : do {                                                    \
     112             :         if (++(_cons) == (_ring)->ring_size)         \
     113             :                 ((_cons) = 0, (_v_bit) = !_v_bit);      \
     114             : } while (0);
     115             : 
     116             : struct bnxt_cos_queue {
     117             :         uint8_t                 id;
     118             :         uint8_t                 profile;
     119             : };
     120             : 
     121             : struct bnxt_ring {
     122             :         uint64_t                paddr;
     123             :         uint64_t                doorbell;
     124             :         caddr_t                 vaddr;
     125             :         uint32_t                ring_size;
     126             :         uint16_t                id;
     127             :         uint16_t                phys_id;
     128             : };
     129             : 
     130             : struct bnxt_cp_ring {
     131             :         struct bnxt_ring        ring;
     132             :         void                    *irq;
     133             :         struct bnxt_softc       *softc;
     134             :         uint32_t                cons;
     135             :         int                     v_bit;
     136             :         uint32_t                commit_cons;
     137             :         int                     commit_v_bit;
     138             :         struct ctx_hw_stats     *stats;
     139             :         uint32_t                stats_ctx_id;
     140             : };
     141             : 
     142             : struct bnxt_grp_info {
     143             :         uint32_t                grp_id;
     144             :         uint16_t                stats_ctx;
     145             :         uint16_t                rx_ring_id;
     146             :         uint16_t                cp_ring_id;
     147             :         uint16_t                ag_ring_id;
     148             : };
     149             : 
     150             : struct bnxt_vnic_info {
     151             :         uint16_t                id;
     152             :         uint16_t                def_ring_grp;
     153             :         uint16_t                cos_rule;
     154             :         uint16_t                lb_rule;
     155             :         uint16_t                mru;
     156             : 
     157             :         uint32_t                flags;
     158             : #define BNXT_VNIC_FLAG_DEFAULT          0x01
     159             : #define BNXT_VNIC_FLAG_BD_STALL         0x02
     160             : #define BNXT_VNIC_FLAG_VLAN_STRIP       0x04
     161             : 
     162             :         uint64_t                filter_id;
     163             :         uint32_t                flow_id;
     164             : 
     165             :         uint16_t                rss_id;
     166             :         /* rss things */
     167             : };
     168             : 
     169             : struct bnxt_slot {
     170             :         bus_dmamap_t            bs_map;
     171             :         struct mbuf             *bs_m;
     172             : };
     173             : 
     174             : struct bnxt_dmamem {
     175             :         bus_dmamap_t            bdm_map;
     176             :         bus_dma_segment_t       bdm_seg;
     177             :         size_t                  bdm_size;
     178             :         caddr_t                 bdm_kva;
     179             : };
     180             : #define BNXT_DMA_MAP(_bdm)      ((_bdm)->bdm_map)
     181             : #define BNXT_DMA_LEN(_bdm)      ((_bdm)->bdm_size)
     182             : #define BNXT_DMA_DVA(_bdm)      ((u_int64_t)(_bdm)->bdm_map->dm_segs[0].ds_addr)
     183             : #define BNXT_DMA_KVA(_bdm)      ((void *)(_bdm)->bdm_kva)
     184             : 
     185             : struct bnxt_softc {
     186             :         struct device           sc_dev;
     187             :         struct arpcom           sc_ac;
     188             :         struct ifmedia          sc_media;
     189             : 
     190             :         struct mutex            sc_lock;
     191             : 
     192             :         pci_chipset_tag_t       sc_pc;
     193             :         pcitag_t                sc_tag;
     194             :         bus_dma_tag_t           sc_dmat;
     195             : 
     196             :         bus_space_tag_t         sc_hwrm_t;
     197             :         bus_space_handle_t      sc_hwrm_h;
     198             :         bus_size_t              sc_hwrm_s;
     199             : 
     200             :         struct bnxt_dmamem      *sc_cmd_resp;
     201             :         uint16_t                sc_cmd_seq;
     202             :         uint16_t                sc_max_req_len;
     203             :         uint32_t                sc_cmd_timeo;
     204             :         uint32_t                sc_flags;
     205             : 
     206             :         bus_space_tag_t         sc_db_t;
     207             :         bus_space_handle_t      sc_db_h;
     208             :         bus_size_t              sc_db_s;
     209             : 
     210             :         void                    *sc_ih;
     211             : 
     212             :         int                     sc_max_tc;
     213             :         struct bnxt_cos_queue   sc_q_info[BNXT_MAX_QUEUE];
     214             : 
     215             :         struct bnxt_vnic_info   sc_vnic;
     216             :         struct bnxt_dmamem      *sc_stats_ctx_mem;
     217             : 
     218             :         struct bnxt_cp_ring     sc_cp_ring;
     219             :         struct bnxt_dmamem      *sc_cp_ring_mem;
     220             : 
     221             :         /* rx */
     222             :         struct bnxt_dmamem      *sc_rx_ring_mem;        /* rx and ag */
     223             :         struct bnxt_dmamem      *sc_rx_mcast;
     224             :         struct bnxt_ring        sc_rx_ring;
     225             :         struct bnxt_ring        sc_rx_ag_ring;
     226             :         struct bnxt_grp_info    sc_ring_group;
     227             :         struct if_rxring        sc_rxr[2];
     228             :         struct bnxt_slot        *sc_rx_slots;
     229             :         struct bnxt_slot        *sc_rx_ag_slots;
     230             :         int                     sc_rx_prod;
     231             :         int                     sc_rx_cons;
     232             :         int                     sc_rx_ag_prod;
     233             :         int                     sc_rx_ag_cons;
     234             :         struct timeout          sc_rx_refill;
     235             : 
     236             :         /* tx */
     237             :         struct bnxt_dmamem      *sc_tx_ring_mem;
     238             :         struct bnxt_ring        sc_tx_ring;
     239             :         struct bnxt_slot        *sc_tx_slots;
     240             :         int                     sc_tx_prod;
     241             :         int                     sc_tx_cons;
     242             :         int                     sc_tx_ring_prod;
     243             :         int                     sc_tx_ring_cons;
     244             : };
     245             : #define DEVNAME(_sc)    ((_sc)->sc_dev.dv_xname)
     246             : 
     247             : const struct pci_matchid bnxt_devices[] = {
     248             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57301 },
     249             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57302 },
     250             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57304 },
     251             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57311 },
     252             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57312 },
     253             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57314 },
     254             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57402 },
     255             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57404 },
     256             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57406 },
     257             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57407 },
     258             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57412 },
     259             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57414 },
     260             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57416 },
     261             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57416_SFP },
     262             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57417 },
     263             :         { PCI_VENDOR_BROADCOM,  PCI_PRODUCT_BROADCOM_BCM57417_SFP }
     264             : };
     265             : 
     266             : int             bnxt_match(struct device *, void *, void *);
     267             : void            bnxt_attach(struct device *, struct device *, void *);
     268             : 
     269             : void            bnxt_up(struct bnxt_softc *);
     270             : void            bnxt_down(struct bnxt_softc *);
     271             : void            bnxt_iff(struct bnxt_softc *);
     272             : int             bnxt_ioctl(struct ifnet *, u_long, caddr_t);
     273             : int             bnxt_rxrinfo(struct bnxt_softc *, struct if_rxrinfo *);
     274             : void            bnxt_start(struct ifqueue *);
     275             : int             bnxt_intr(void *);
     276             : void            bnxt_watchdog(struct ifnet *);
     277             : void            bnxt_media_status(struct ifnet *, struct ifmediareq *);
     278             : int             bnxt_media_change(struct ifnet *);
     279             : int             bnxt_media_autonegotiate(struct bnxt_softc *);
     280             : 
     281             : struct cmpl_base *bnxt_cpr_next_cmpl(struct bnxt_softc *, struct bnxt_cp_ring *);
     282             : void            bnxt_cpr_commit(struct bnxt_softc *, struct bnxt_cp_ring *);
     283             : void            bnxt_cpr_rollback(struct bnxt_softc *, struct bnxt_cp_ring *);
     284             : 
     285             : void            bnxt_mark_cpr_invalid(struct bnxt_cp_ring *);
     286             : void            bnxt_write_cp_doorbell(struct bnxt_softc *, struct bnxt_ring *,
     287             :                     int);
     288             : void            bnxt_write_cp_doorbell_index(struct bnxt_softc *,
     289             :                     struct bnxt_ring *, uint32_t, int);
     290             : void            bnxt_write_rx_doorbell(struct bnxt_softc *, struct bnxt_ring *,
     291             :                     int);
     292             : void            bnxt_write_tx_doorbell(struct bnxt_softc *, struct bnxt_ring *,
     293             :                     int);
     294             : 
     295             : int             bnxt_rx_fill(struct bnxt_softc *);
     296             : u_int           bnxt_rx_fill_slots(struct bnxt_softc *, struct bnxt_ring *, void *,
     297             :                     struct bnxt_slot *, uint *, int, uint16_t, u_int);
     298             : void            bnxt_refill(void *);
     299             : int             bnxt_rx(struct bnxt_softc *, struct bnxt_cp_ring *,
     300             :                     struct mbuf_list *, int *, int *, struct cmpl_base *);
     301             : 
     302             : void            bnxt_txeof(struct bnxt_softc *, int *, struct cmpl_base *);
     303             : 
     304             : int             _hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
     305             : int             hwrm_send_message(struct bnxt_softc *, void *, uint32_t);
     306             : void            bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *, void *, uint16_t);
     307             : int             bnxt_hwrm_err_map(uint16_t err);
     308             : 
     309             : /* HWRM Function Prototypes */
     310             : int             bnxt_hwrm_ring_alloc(struct bnxt_softc *, uint8_t,
     311             :                     struct bnxt_ring *, uint16_t, uint32_t, int);
     312             : int             bnxt_hwrm_ring_free(struct bnxt_softc *, uint8_t,
     313             :                     struct bnxt_ring *);
     314             : int             bnxt_hwrm_ver_get(struct bnxt_softc *);
     315             : int             bnxt_hwrm_queue_qportcfg(struct bnxt_softc *);
     316             : int             bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *);
     317             : int             bnxt_hwrm_func_qcaps(struct bnxt_softc *);
     318             : int             bnxt_hwrm_func_qcfg(struct bnxt_softc *);
     319             : int             bnxt_hwrm_func_reset(struct bnxt_softc *);
     320             : int             bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *, uint16_t *);
     321             : int             bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *, uint16_t *);
     322             : int             bnxt_hwrm_vnic_cfg(struct bnxt_softc *,
     323             :                     struct bnxt_vnic_info *);
     324             : int             bnxt_hwrm_vnic_cfg_placement(struct bnxt_softc *,
     325             :                     struct bnxt_vnic_info *vnic);
     326             : int             bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *,
     327             :                     struct bnxt_cp_ring *, uint64_t);
     328             : int             bnxt_hwrm_stat_ctx_free(struct bnxt_softc *,
     329             :                     struct bnxt_cp_ring *);
     330             : int             bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *,
     331             :                     struct bnxt_grp_info *);
     332             : int             bnxt_hwrm_ring_grp_free(struct bnxt_softc *,
     333             :                     struct bnxt_grp_info *);
     334             : int             bnxt_hwrm_vnic_alloc(struct bnxt_softc *,
     335             :                     struct bnxt_vnic_info *);
     336             : int             bnxt_hwrm_vnic_free(struct bnxt_softc *,
     337             :                     struct bnxt_vnic_info *);
     338             : int             bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *,
     339             :                     uint32_t, uint32_t, uint64_t, uint32_t);
     340             : int             bnxt_hwrm_set_filter(struct bnxt_softc *,
     341             :                     struct bnxt_vnic_info *);
     342             : int             bnxt_hwrm_free_filter(struct bnxt_softc *,
     343             :                     struct bnxt_vnic_info *);
     344             : int             bnxt_cfg_async_cr(struct bnxt_softc *);
     345             : int             bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *, uint16_t *,
     346             :                     uint16_t *, uint32_t *, uint32_t *, uint32_t *, uint32_t *);
     347             : int             bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *,
     348             :                     struct ifmediareq *);
     349             : int             bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *);
     350             : 
     351             : /* not used yet: */
     352             : #if 0
     353             : int bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown);
     354             : 
     355             : int bnxt_hwrm_port_qstats(struct bnxt_softc *softc);
     356             : 
     357             : int bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
     358             :     uint32_t hash_type);
     359             : 
     360             : int bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc);
     361             : void bnxt_validate_hw_lro_settings(struct bnxt_softc *softc);
     362             : int bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
     363             :     uint8_t *selfreset);
     364             : int bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type,
     365             :     uint8_t *selfreset);
     366             : int bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year,
     367             :     uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute,
     368             :     uint8_t *second, uint16_t *millisecond, uint16_t *zone);
     369             : int bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year,
     370             :     uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
     371             :     uint16_t millisecond, uint16_t zone);
     372             : 
     373             : #endif
     374             : 
     375             : 
     376             : struct cfattach bnxt_ca = {
     377             :         sizeof(struct bnxt_softc), bnxt_match, bnxt_attach
     378             : };
     379             : 
     380             : struct cfdriver bnxt_cd = {
     381             :         NULL, "bnxt", DV_IFNET
     382             : };
     383             : 
     384             : struct bnxt_dmamem *
     385           0 : bnxt_dmamem_alloc(struct bnxt_softc *sc, size_t size)
     386             : {
     387             :         struct bnxt_dmamem *m;
     388           0 :         int nsegs;
     389             : 
     390           0 :         m = malloc(sizeof(*m), M_DEVBUF, M_NOWAIT | M_ZERO);
     391           0 :         if (m == NULL)
     392           0 :                 return (NULL);
     393             : 
     394           0 :         m->bdm_size = size;
     395             : 
     396           0 :         if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
     397           0 :             BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &m->bdm_map) != 0)
     398             :                 goto bdmfree;
     399             : 
     400           0 :         if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &m->bdm_seg, 1,
     401           0 :             &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO) != 0)
     402             :                 goto destroy;
     403             : 
     404           0 :         if (bus_dmamem_map(sc->sc_dmat, &m->bdm_seg, nsegs, size, &m->bdm_kva,
     405           0 :             BUS_DMA_NOWAIT) != 0)
     406             :                 goto free;
     407             : 
     408           0 :         if (bus_dmamap_load(sc->sc_dmat, m->bdm_map, m->bdm_kva, size, NULL,
     409           0 :             BUS_DMA_NOWAIT) != 0)
     410             :                 goto unmap;
     411             : 
     412           0 :         return (m);
     413             : 
     414             : unmap:
     415           0 :         bus_dmamem_unmap(sc->sc_dmat, m->bdm_kva, m->bdm_size);
     416             : free:
     417           0 :         bus_dmamem_free(sc->sc_dmat, &m->bdm_seg, 1);
     418             : destroy:
     419           0 :         bus_dmamap_destroy(sc->sc_dmat, m->bdm_map);
     420             : bdmfree:
     421           0 :         free(m, M_DEVBUF, sizeof *m);
     422             : 
     423           0 :         return (NULL);
     424           0 : }
     425             : 
     426             : void
     427           0 : bnxt_dmamem_free(struct bnxt_softc *sc, struct bnxt_dmamem *m)
     428             : {
     429           0 :         bus_dmamem_unmap(sc->sc_dmat, m->bdm_kva, m->bdm_size);
     430           0 :         bus_dmamem_free(sc->sc_dmat, &m->bdm_seg, 1);
     431           0 :         bus_dmamap_destroy(sc->sc_dmat, m->bdm_map);
     432           0 :         free(m, M_DEVBUF, sizeof *m);
     433           0 : }
     434             : 
     435             : int
     436           0 : bnxt_match(struct device *parent, void *match, void *aux)
     437             : {
     438           0 :         return (pci_matchbyid(aux, bnxt_devices, nitems(bnxt_devices)));
     439             : }
     440             : 
     441             : void
     442           0 : bnxt_attach(struct device *parent, struct device *self, void *aux)
     443             : {
     444           0 :         struct bnxt_softc *sc = (struct bnxt_softc *)self;
     445           0 :         struct hwrm_ring_cmpl_ring_cfg_aggint_params_input aggint;
     446           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
     447           0 :         struct pci_attach_args *pa = aux;
     448           0 :         pci_intr_handle_t ih;
     449             :         const char *intrstr;
     450             :         u_int memtype;
     451             : 
     452             :         /* enable busmaster? */
     453             : 
     454           0 :         sc->sc_pc = pa->pa_pc;
     455           0 :         sc->sc_tag = pa->pa_tag;
     456           0 :         sc->sc_dmat = pa->pa_dmat;
     457             : 
     458           0 :         memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BNXT_HWRM_BAR);
     459           0 :         if (pci_mapreg_map(pa, BNXT_HWRM_BAR, memtype, 0, &sc->sc_hwrm_t,
     460           0 :             &sc->sc_hwrm_h, NULL, &sc->sc_hwrm_s, 0)) {
     461           0 :                 printf(": failed to map hwrm\n");
     462           0 :                 return;
     463             :         }
     464             : 
     465           0 :         memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BNXT_DOORBELL_BAR);
     466           0 :         if (pci_mapreg_map(pa, BNXT_DOORBELL_BAR, memtype, 0, &sc->sc_db_t,
     467           0 :             &sc->sc_db_h, NULL, &sc->sc_db_s, 0)) {
     468           0 :                 printf(": failed to map doorbell\n");
     469           0 :                 goto unmap_1;
     470             :         }
     471             : 
     472           0 :         BNXT_HWRM_LOCK_INIT(sc, DEVNAME(sc));
     473           0 :         sc->sc_cmd_resp = bnxt_dmamem_alloc(sc, PAGE_SIZE);
     474           0 :         if (sc->sc_cmd_resp == NULL) {
     475           0 :                 printf(": failed to allocate command response buffer\n");
     476           0 :                 goto unmap_2;
     477             :         }
     478             : 
     479           0 :         if (bnxt_hwrm_ver_get(sc) != 0) {
     480           0 :                 printf(": failed to query version info\n");
     481           0 :                 goto free_resp;
     482             :         }
     483             : 
     484           0 :         if (bnxt_hwrm_nvm_get_dev_info(sc, NULL, NULL, NULL, NULL, NULL, NULL)
     485           0 :             != 0) {
     486           0 :                 printf(": failed to get nvram info\n");
     487           0 :                 goto free_resp;
     488             :         }
     489             : 
     490           0 :         if (bnxt_hwrm_func_drv_rgtr(sc) != 0) {
     491           0 :                 printf(": failed to register driver with firmware\n");
     492           0 :                 goto free_resp;
     493             :         }
     494             : 
     495           0 :         if (bnxt_hwrm_func_rgtr_async_events(sc) != 0) {
     496           0 :                 printf(": failed to register async events\n");
     497           0 :                 goto free_resp;
     498             :         }
     499             : 
     500           0 :         if (bnxt_hwrm_func_qcaps(sc) != 0) {
     501           0 :                 printf(": failed to get queue capabilities\n");
     502           0 :                 goto free_resp;
     503             :         }
     504             : 
     505             :         /*
     506             :          * devices advertise msi support, but there's no way to tell a
     507             :          * completion queue to use msi mode, only legacy or msi-x.
     508             :          */
     509           0 :         if (/*pci_intr_map_msi(pa, &ih) != 0 && */ pci_intr_map(pa, &ih) != 0) {
     510           0 :                 printf(": unable to map interrupt\n");
     511           0 :                 goto free_resp;
     512             :         }
     513           0 :         intrstr = pci_intr_string(sc->sc_pc, ih);
     514           0 :         sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_NET | IPL_MPSAFE,
     515           0 :             bnxt_intr, sc, DEVNAME(sc));
     516           0 :         if (sc->sc_ih == NULL) {
     517           0 :                 printf(": unable to establish interrupt");
     518           0 :                 if (intrstr != NULL)
     519           0 :                         printf(" at %s", intrstr);
     520           0 :                 printf("\n");
     521           0 :                 goto deintr;
     522             :         }
     523           0 :         printf("%s, address %s\n", intrstr, ether_sprintf(sc->sc_ac.ac_enaddr));
     524             : 
     525           0 :         if (bnxt_hwrm_func_qcfg(sc) != 0) {
     526           0 :                 printf("%s: failed to query function config\n", DEVNAME(sc));
     527           0 :                 goto deintr;
     528             :         }
     529             : 
     530           0 :         if (bnxt_hwrm_queue_qportcfg(sc) != 0) {
     531           0 :                 printf("%s: failed to query port config\n", DEVNAME(sc));
     532           0 :                 goto deintr;
     533             :         }
     534             : 
     535           0 :         if (bnxt_hwrm_func_reset(sc) != 0) {
     536           0 :                 printf("%s: reset failed\n", DEVNAME(sc));
     537           0 :                 goto deintr;
     538             :         }
     539             : 
     540           0 :         sc->sc_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE;
     541           0 :         sc->sc_cp_ring.ring.phys_id = HWRM_NA_SIGNATURE;
     542           0 :         sc->sc_cp_ring.softc = sc;
     543           0 :         sc->sc_cp_ring.ring.id = 0;
     544           0 :         sc->sc_cp_ring.ring.doorbell = sc->sc_cp_ring.ring.id * 0x80;
     545           0 :         sc->sc_cp_ring.ring.ring_size = (PAGE_SIZE * BNXT_CP_PAGES) /
     546             :             sizeof(struct cmpl_base);
     547           0 :         sc->sc_cp_ring_mem = bnxt_dmamem_alloc(sc, PAGE_SIZE * BNXT_CP_PAGES);
     548           0 :         if (sc->sc_cp_ring_mem == NULL) {
     549           0 :                 printf("%s: failed to allocate completion queue memory\n",
     550             :                     DEVNAME(sc));
     551           0 :                 goto deintr;
     552             :         }
     553           0 :         sc->sc_cp_ring.ring.vaddr = BNXT_DMA_KVA(sc->sc_cp_ring_mem);
     554           0 :         sc->sc_cp_ring.ring.paddr = BNXT_DMA_DVA(sc->sc_cp_ring_mem);
     555           0 :         sc->sc_cp_ring.cons = UINT32_MAX;
     556           0 :         sc->sc_cp_ring.v_bit = 1;
     557           0 :         bnxt_mark_cpr_invalid(&sc->sc_cp_ring);
     558           0 :         if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL,
     559             :             &sc->sc_cp_ring.ring, (uint16_t)HWRM_NA_SIGNATURE,
     560           0 :             HWRM_NA_SIGNATURE, 1) != 0) {
     561           0 :                 printf("%s: failed to allocate completion queue\n",
     562             :                     DEVNAME(sc));
     563           0 :                 goto free_cp_mem;
     564             :         }
     565           0 :         if (bnxt_cfg_async_cr(sc) != 0) {
     566           0 :                 printf("%s: failed to set async completion ring\n",
     567             :                     DEVNAME(sc));
     568           0 :                 goto free_cp_mem;
     569             :         }
     570           0 :         bnxt_write_cp_doorbell(sc, &sc->sc_cp_ring.ring, 1);
     571             : 
     572             :         /*
     573             :          * set interrupt aggregation parameters for around 10k interrupts
     574             :          * per second.  the timers are in units of 80usec, and the counters
     575             :          * are based on the minimum rx ring size of 32.
     576             :          */
     577           0 :         memset(&aggint, 0, sizeof(aggint));
     578           0 :         bnxt_hwrm_cmd_hdr_init(sc, &aggint,
     579             :             HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
     580           0 :         aggint.ring_id = htole16(sc->sc_cp_ring.ring.phys_id);
     581           0 :         aggint.num_cmpl_dma_aggr = htole16(32);
     582           0 :         aggint.num_cmpl_dma_aggr_during_int  = aggint.num_cmpl_dma_aggr;
     583           0 :         aggint.cmpl_aggr_dma_tmr = htole16((1000000000 / 20000) / 80);
     584           0 :         aggint.cmpl_aggr_dma_tmr_during_int = aggint.cmpl_aggr_dma_tmr;
     585           0 :         aggint.int_lat_tmr_min = htole16((1000000000 / 20000) / 80);
     586           0 :         aggint.int_lat_tmr_max = htole16((1000000000 / 10000) / 80);
     587           0 :         aggint.num_cmpl_aggr_int = htole16(16);
     588           0 :         if (hwrm_send_message(sc, &aggint, sizeof(aggint)))
     589             :                 goto free_cp_mem;
     590             : 
     591           0 :         strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
     592           0 :         ifp->if_softc = sc;
     593           0 :         ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
     594           0 :         ifp->if_xflags = IFXF_MPSAFE;
     595           0 :         ifp->if_ioctl = bnxt_ioctl;
     596           0 :         ifp->if_qstart = bnxt_start;
     597           0 :         ifp->if_watchdog = bnxt_watchdog;
     598           0 :         ifp->if_hardmtu = BNXT_MAX_MTU;
     599           0 :         ifp->if_capabilities = IFCAP_VLAN_MTU;        /* ? */
     600             :         /* checksum flags, hwtagging? */
     601           0 :         IFQ_SET_MAXLEN(&ifp->if_snd, 1024);      /* ? */
     602             : 
     603           0 :         ifmedia_init(&sc->sc_media, IFM_IMASK, bnxt_media_change,
     604             :             bnxt_media_status);
     605             : 
     606           0 :         if_attach(ifp);
     607           0 :         ether_ifattach(ifp);
     608             : 
     609           0 :         timeout_set(&sc->sc_rx_refill, bnxt_refill, sc);
     610             : 
     611           0 :         bnxt_media_autonegotiate(sc);
     612           0 :         bnxt_hwrm_port_phy_qcfg(sc, NULL);
     613           0 :         return;
     614             : 
     615             : free_cp_mem:
     616           0 :         bnxt_dmamem_free(sc, sc->sc_cp_ring_mem);
     617             : deintr:
     618           0 :         pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
     619           0 :         sc->sc_ih = NULL;
     620             : free_resp:
     621           0 :         bnxt_dmamem_free(sc, sc->sc_cmd_resp);
     622             : unmap_2:
     623           0 :         bus_space_unmap(sc->sc_hwrm_t, sc->sc_hwrm_h, sc->sc_hwrm_s);
     624           0 :         sc->sc_hwrm_s = 0;
     625             : unmap_1:
     626           0 :         bus_space_unmap(sc->sc_db_t, sc->sc_db_h, sc->sc_db_s);
     627           0 :         sc->sc_db_s = 0;
     628           0 : }
     629             : 
     630             : void
     631           0 : bnxt_free_slots(struct bnxt_softc *sc, struct bnxt_slot *slots, int allocated,
     632             :     int total)
     633             : {
     634             :         struct bnxt_slot *bs;
     635             : 
     636             :         int i = allocated;
     637           0 :         while (i-- > 0) {
     638           0 :                 bs = &slots[i];
     639           0 :                 bus_dmamap_destroy(sc->sc_dmat, bs->bs_map);
     640             :         }
     641           0 :         free(slots, M_DEVBUF, total * sizeof(*bs));
     642           0 : }
     643             : 
     644             : void
     645           0 : bnxt_up(struct bnxt_softc *sc)
     646             : {
     647           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
     648             :         struct bnxt_slot *bs;
     649             :         int i;
     650             : 
     651           0 :         sc->sc_stats_ctx_mem = bnxt_dmamem_alloc(sc,
     652             :             sizeof(struct ctx_hw_stats));
     653           0 :         if (sc->sc_stats_ctx_mem == NULL) {
     654           0 :                 printf("%s: failed to allocate stats contexts\n", DEVNAME(sc));
     655           0 :                 return;
     656             :         }
     657             : 
     658           0 :         sc->sc_tx_ring_mem = bnxt_dmamem_alloc(sc, PAGE_SIZE);
     659           0 :         if (sc->sc_tx_ring_mem == NULL) {
     660           0 :                 printf("%s: failed to allocate tx ring\n", DEVNAME(sc));
     661           0 :                 goto free_stats;
     662             :         }
     663             : 
     664           0 :         sc->sc_rx_ring_mem = bnxt_dmamem_alloc(sc, PAGE_SIZE * 2);
     665           0 :         if (sc->sc_rx_ring_mem == NULL) {
     666           0 :                 printf("%s: failed to allocate rx ring\n", DEVNAME(sc));
     667           0 :                 goto free_tx;
     668             :         }
     669             : 
     670           0 :         sc->sc_rx_mcast = bnxt_dmamem_alloc(sc, PAGE_SIZE);
     671           0 :         if (sc->sc_rx_mcast == NULL) {
     672           0 :                 printf("%s: failed to allocate multicast address table\n",
     673           0 :                     DEVNAME(sc));
     674           0 :                 goto free_rx;
     675             :         }
     676             : 
     677           0 :         if (bnxt_hwrm_stat_ctx_alloc(sc, &sc->sc_cp_ring,
     678           0 :             BNXT_DMA_DVA(sc->sc_stats_ctx_mem)) != 0) {
     679           0 :                 printf("%s: failed to set up stats context\n", DEVNAME(sc));
     680           0 :                 goto free_mc;
     681             :         }
     682             : 
     683           0 :         sc->sc_tx_ring.phys_id = HWRM_NA_SIGNATURE;
     684           0 :         sc->sc_tx_ring.id = BNXT_TX_RING_ID;
     685           0 :         sc->sc_tx_ring.doorbell = sc->sc_tx_ring.id * 0x80;
     686           0 :         sc->sc_tx_ring.ring_size = PAGE_SIZE / sizeof(struct tx_bd_short);
     687           0 :         sc->sc_tx_ring.vaddr = BNXT_DMA_KVA(sc->sc_tx_ring_mem);
     688           0 :         sc->sc_tx_ring.paddr = BNXT_DMA_DVA(sc->sc_tx_ring_mem);
     689           0 :         if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
     690           0 :             &sc->sc_tx_ring, sc->sc_cp_ring.ring.phys_id,
     691           0 :             HWRM_NA_SIGNATURE, 1) != 0) {
     692           0 :                 printf("%s: failed to set up tx ring\n",
     693           0 :                     DEVNAME(sc));
     694           0 :                 goto dealloc_stats;
     695             :         }
     696           0 :         bnxt_write_tx_doorbell(sc, &sc->sc_tx_ring, 0);
     697             : 
     698           0 :         sc->sc_rx_ring.phys_id = HWRM_NA_SIGNATURE;
     699           0 :         sc->sc_rx_ring.id = BNXT_RX_RING_ID;
     700           0 :         sc->sc_rx_ring.doorbell = sc->sc_rx_ring.id * 0x80;
     701           0 :         sc->sc_rx_ring.ring_size = PAGE_SIZE / sizeof(struct rx_prod_pkt_bd);
     702           0 :         sc->sc_rx_ring.vaddr = BNXT_DMA_KVA(sc->sc_rx_ring_mem);
     703           0 :         sc->sc_rx_ring.paddr = BNXT_DMA_DVA(sc->sc_rx_ring_mem);
     704           0 :         if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
     705           0 :             &sc->sc_rx_ring, sc->sc_cp_ring.ring.phys_id,
     706           0 :             HWRM_NA_SIGNATURE, 1) != 0) {
     707           0 :                 printf("%s: failed to set up rx ring\n",
     708           0 :                     DEVNAME(sc));
     709           0 :                 goto dealloc_tx;
     710             :         }
     711           0 :         bnxt_write_rx_doorbell(sc, &sc->sc_rx_ring, 0);
     712             : 
     713           0 :         sc->sc_rx_ag_ring.phys_id = HWRM_NA_SIGNATURE;
     714           0 :         sc->sc_rx_ag_ring.id = BNXT_AG_RING_ID;
     715           0 :         sc->sc_rx_ag_ring.doorbell = sc->sc_rx_ag_ring.id * 0x80;
     716           0 :         sc->sc_rx_ag_ring.ring_size = PAGE_SIZE / sizeof(struct rx_prod_pkt_bd);
     717           0 :         sc->sc_rx_ag_ring.vaddr = BNXT_DMA_KVA(sc->sc_rx_ring_mem) + PAGE_SIZE;
     718           0 :         sc->sc_rx_ag_ring.paddr = BNXT_DMA_DVA(sc->sc_rx_ring_mem) + PAGE_SIZE;
     719           0 :         if (bnxt_hwrm_ring_alloc(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
     720           0 :             &sc->sc_rx_ag_ring, sc->sc_cp_ring.ring.phys_id,
     721           0 :             HWRM_NA_SIGNATURE, 1) != 0) {
     722           0 :                 printf("%s: failed to set up rx ag ring\n",
     723           0 :                     DEVNAME(sc));
     724           0 :                 goto dealloc_rx;
     725             :         }
     726           0 :         bnxt_write_rx_doorbell(sc, &sc->sc_rx_ag_ring, 0);
     727             : 
     728           0 :         sc->sc_ring_group.grp_id = HWRM_NA_SIGNATURE;
     729           0 :         sc->sc_ring_group.stats_ctx = sc->sc_cp_ring.stats_ctx_id;
     730           0 :         sc->sc_ring_group.rx_ring_id = sc->sc_rx_ring.phys_id;
     731           0 :         sc->sc_ring_group.ag_ring_id = sc->sc_rx_ag_ring.phys_id;
     732           0 :         sc->sc_ring_group.cp_ring_id = sc->sc_cp_ring.ring.phys_id;
     733           0 :         if (bnxt_hwrm_ring_grp_alloc(sc, &sc->sc_ring_group) != 0) {
     734           0 :                 printf("%s: failed to allocate ring group\n",
     735           0 :                     DEVNAME(sc));
     736           0 :                 goto dealloc_ag;
     737             :         }
     738             : 
     739           0 :         sc->sc_vnic.rss_id = HWRM_NA_SIGNATURE;
     740           0 :         if (bnxt_hwrm_vnic_ctx_alloc(sc, &sc->sc_vnic.rss_id) != 0) {
     741           0 :                 printf("%s: failed to allocate vnic rss context\n",
     742           0 :                     DEVNAME(sc));
     743           0 :                 goto dealloc_ring_group;
     744             :         }
     745             : 
     746           0 :         sc->sc_vnic.id = HWRM_NA_SIGNATURE;
     747           0 :         sc->sc_vnic.def_ring_grp = sc->sc_ring_group.grp_id;
     748           0 :         sc->sc_vnic.mru = BNXT_MAX_MTU;
     749           0 :         sc->sc_vnic.cos_rule = (uint16_t)HWRM_NA_SIGNATURE;
     750           0 :         sc->sc_vnic.lb_rule = (uint16_t)HWRM_NA_SIGNATURE;
     751           0 :         sc->sc_vnic.flags = BNXT_VNIC_FLAG_DEFAULT;
     752           0 :         if (bnxt_hwrm_vnic_alloc(sc, &sc->sc_vnic) != 0) {
     753           0 :                 printf("%s: failed to allocate vnic\n", DEVNAME(sc));
     754           0 :                 goto dealloc_vnic_ctx;
     755             :         }
     756             : 
     757           0 :         if (bnxt_hwrm_vnic_cfg(sc, &sc->sc_vnic) != 0) {
     758           0 :                 printf("%s: failed to configure vnic\n", DEVNAME(sc));
     759           0 :                 goto dealloc_vnic;
     760             :         }
     761             : 
     762           0 :         if (bnxt_hwrm_vnic_cfg_placement(sc, &sc->sc_vnic) != 0) {
     763           0 :                 printf("%s: failed to configure vnic placement mode\n",
     764           0 :                     DEVNAME(sc));
     765           0 :                 goto dealloc_vnic;
     766             :         }
     767             : 
     768           0 :         sc->sc_vnic.filter_id = -1;
     769           0 :         if (bnxt_hwrm_set_filter(sc, &sc->sc_vnic) != 0) {
     770           0 :                 printf("%s: failed to set vnic filter\n", DEVNAME(sc));
     771           0 :                 goto dealloc_vnic;
     772             :         }
     773             : 
     774             :         /* don't configure rss or tpa yet */
     775             : 
     776           0 :         sc->sc_rx_slots = mallocarray(sizeof(*bs), sc->sc_rx_ring.ring_size,
     777             :             M_DEVBUF, M_WAITOK | M_ZERO);
     778           0 :         if (sc->sc_rx_slots == NULL) {
     779           0 :                 printf("%s: failed to allocate rx slots\n", DEVNAME(sc));
     780           0 :                 goto dealloc_filter;
     781             :         }
     782             : 
     783           0 :         for (i = 0; i < sc->sc_rx_ring.ring_size; i++) {
     784           0 :                 bs = &sc->sc_rx_slots[i];
     785           0 :                 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
     786           0 :                     BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &bs->bs_map) != 0) {
     787           0 :                         printf("%s: failed to allocate rx dma maps\n",
     788           0 :                             DEVNAME(sc));
     789           0 :                         goto destroy_rx_slots;
     790             :                 }
     791             :         }
     792             : 
     793           0 :         sc->sc_rx_ag_slots = mallocarray(sizeof(*bs), sc->sc_rx_ag_ring.ring_size,
     794             :             M_DEVBUF, M_WAITOK | M_ZERO);
     795           0 :         if (sc->sc_rx_ag_slots == NULL) {
     796           0 :                 printf("%s: failed to allocate rx ag slots\n", DEVNAME(sc));
     797           0 :                 goto destroy_rx_slots;
     798             :         }
     799             : 
     800           0 :         for (i = 0; i < sc->sc_rx_ag_ring.ring_size; i++) {
     801           0 :                 bs = &sc->sc_rx_ag_slots[i];
     802           0 :                 if (bus_dmamap_create(sc->sc_dmat, BNXT_AG_BUFFER_SIZE, 1,
     803             :                     BNXT_AG_BUFFER_SIZE, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
     804           0 :                     &bs->bs_map) != 0) {
     805           0 :                         printf("%s: failed to allocate rx ag dma maps\n",
     806           0 :                             DEVNAME(sc));
     807           0 :                         goto destroy_rx_ag_slots;
     808             :                 }
     809             :         }
     810             : 
     811           0 :         sc->sc_tx_slots = mallocarray(sizeof(*bs), sc->sc_tx_ring.ring_size,
     812             :             M_DEVBUF, M_WAITOK | M_ZERO);
     813           0 :         if (sc->sc_tx_slots == NULL) {
     814           0 :                 printf("%s: failed to allocate tx slots\n", DEVNAME(sc));
     815           0 :                 goto destroy_rx_ag_slots;
     816             :         }
     817             : 
     818           0 :         for (i = 0; i < sc->sc_tx_ring.ring_size; i++) {
     819           0 :                 bs = &sc->sc_tx_slots[i];
     820           0 :                 if (bus_dmamap_create(sc->sc_dmat, BNXT_MAX_MTU, BNXT_MAX_TX_SEGS,
     821             :                     BNXT_MAX_MTU, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
     822           0 :                     &bs->bs_map) != 0) {
     823           0 :                         printf("%s: failed to allocate tx dma maps\n",
     824           0 :                             DEVNAME(sc));
     825             :                         goto destroy_tx_slots;
     826             :                 }
     827             :         }
     828             : 
     829           0 :         bnxt_iff(sc);
     830             : 
     831             :         /*
     832             :          * initially, the rx ring must be filled at least some distance beyond
     833             :          * the current consumer index, as it looks like the firmware assumes the
     834             :          * ring is full on creation, but doesn't prefetch the whole thing.
     835             :          * once the whole ring has been used once, we should be able to back off
     836             :          * to 2 or so slots, but we currently don't have a way of doing that.
     837             :          */
     838           0 :         if_rxr_init(&sc->sc_rxr[0], 32, sc->sc_rx_ring.ring_size - 1);
     839           0 :         if_rxr_init(&sc->sc_rxr[1], 32, sc->sc_rx_ag_ring.ring_size - 1);
     840           0 :         sc->sc_rx_prod = 0;
     841           0 :         sc->sc_rx_cons = 0;
     842           0 :         sc->sc_rx_ag_prod = 0;
     843           0 :         sc->sc_rx_ag_cons = 0;
     844           0 :         bnxt_rx_fill(sc);
     845             : 
     846           0 :         SET(ifp->if_flags, IFF_RUNNING);
     847             : 
     848           0 :         sc->sc_tx_cons = 0;
     849           0 :         sc->sc_tx_prod = 0;
     850           0 :         sc->sc_tx_ring_cons = 0;
     851           0 :         sc->sc_tx_ring_prod = 0;
     852           0 :         ifq_clr_oactive(&ifp->if_snd);
     853           0 :         ifq_restart(&ifp->if_snd);
     854             : 
     855           0 :         return;
     856             : 
     857             : destroy_tx_slots:
     858           0 :         bnxt_free_slots(sc, sc->sc_tx_slots, i, sc->sc_tx_ring.ring_size);
     859           0 :         sc->sc_tx_slots = NULL;
     860             : 
     861           0 :         i = sc->sc_rx_ag_ring.ring_size;
     862             : destroy_rx_ag_slots:
     863           0 :         bnxt_free_slots(sc, sc->sc_rx_ag_slots, i, sc->sc_rx_ag_ring.ring_size);
     864           0 :         sc->sc_rx_ag_slots = NULL;
     865             : 
     866           0 :         i = sc->sc_rx_ring.ring_size;
     867             : destroy_rx_slots:
     868           0 :         bnxt_free_slots(sc, sc->sc_rx_slots, i, sc->sc_rx_ring.ring_size);
     869           0 :         sc->sc_rx_slots = NULL;
     870             : dealloc_filter:
     871           0 :         bnxt_hwrm_free_filter(sc, &sc->sc_vnic);
     872             : dealloc_vnic:
     873           0 :         bnxt_hwrm_vnic_free(sc, &sc->sc_vnic);
     874             : dealloc_vnic_ctx:
     875           0 :         bnxt_hwrm_vnic_ctx_free(sc, &sc->sc_vnic.rss_id);
     876             : dealloc_ring_group:
     877           0 :         bnxt_hwrm_ring_grp_free(sc, &sc->sc_ring_group);
     878             : dealloc_ag:
     879           0 :         bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
     880             :             &sc->sc_rx_ag_ring);
     881             : dealloc_tx:
     882           0 :         bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
     883             :             &sc->sc_tx_ring);
     884             : dealloc_rx:
     885           0 :         bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
     886             :             &sc->sc_rx_ring);
     887             : dealloc_stats:
     888           0 :         bnxt_hwrm_stat_ctx_free(sc, &sc->sc_cp_ring);
     889             : free_mc:
     890           0 :         bnxt_dmamem_free(sc, sc->sc_rx_mcast);
     891           0 :         sc->sc_rx_mcast = NULL;
     892             : free_rx:
     893           0 :         bnxt_dmamem_free(sc, sc->sc_rx_ring_mem);
     894           0 :         sc->sc_rx_ring_mem = NULL;
     895             : free_tx:
     896           0 :         bnxt_dmamem_free(sc, sc->sc_tx_ring_mem);
     897           0 :         sc->sc_tx_ring_mem = NULL;
     898             : free_stats:
     899           0 :         bnxt_dmamem_free(sc, sc->sc_stats_ctx_mem);
     900           0 :         sc->sc_stats_ctx_mem = NULL;
     901           0 : }
     902             : 
     903             : void
     904           0 : bnxt_down(struct bnxt_softc *sc)
     905             : {
     906           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
     907             :         
     908           0 :         CLR(ifp->if_flags, IFF_RUNNING);
     909             : 
     910           0 :         ifq_clr_oactive(&ifp->if_snd);
     911           0 :         ifq_barrier(&ifp->if_snd);
     912             : 
     913           0 :         timeout_del(&sc->sc_rx_refill);
     914             : 
     915             :         /* empty rx ring first i guess */
     916             : 
     917           0 :         bnxt_free_slots(sc, sc->sc_tx_slots, sc->sc_tx_ring.ring_size,
     918             :             sc->sc_tx_ring.ring_size);
     919           0 :         sc->sc_tx_slots = NULL;
     920             : 
     921           0 :         bnxt_free_slots(sc, sc->sc_rx_ag_slots, sc->sc_rx_ag_ring.ring_size,
     922             :             sc->sc_rx_ag_ring.ring_size);
     923           0 :         sc->sc_rx_ag_slots = NULL;
     924             : 
     925           0 :         bnxt_free_slots(sc, sc->sc_rx_slots, sc->sc_rx_ring.ring_size,
     926             :             sc->sc_rx_ring.ring_size);
     927           0 :         sc->sc_rx_slots = NULL;
     928             : 
     929           0 :         bnxt_hwrm_free_filter(sc, &sc->sc_vnic);
     930           0 :         bnxt_hwrm_vnic_free(sc, &sc->sc_vnic);
     931           0 :         bnxt_hwrm_vnic_ctx_free(sc, &sc->sc_vnic.rss_id);
     932           0 :         bnxt_hwrm_ring_grp_free(sc, &sc->sc_ring_group);
     933           0 :         bnxt_hwrm_stat_ctx_free(sc, &sc->sc_cp_ring);
     934             : 
     935             :         /* may need to wait for 500ms here before we can free the rings */
     936             : 
     937           0 :         bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
     938             :             &sc->sc_tx_ring);
     939           0 :         bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
     940             :             &sc->sc_rx_ag_ring);
     941           0 :         bnxt_hwrm_ring_free(sc, HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
     942             :             &sc->sc_rx_ring);
     943             : 
     944           0 :         bnxt_dmamem_free(sc, sc->sc_rx_mcast);
     945           0 :         sc->sc_rx_mcast = NULL;
     946             : 
     947           0 :         bnxt_dmamem_free(sc, sc->sc_rx_ring_mem);
     948           0 :         sc->sc_rx_ring_mem = NULL;
     949             : 
     950           0 :         bnxt_dmamem_free(sc, sc->sc_tx_ring_mem);
     951           0 :         sc->sc_tx_ring_mem = NULL;
     952             : 
     953           0 :         bnxt_dmamem_free(sc, sc->sc_stats_ctx_mem);
     954           0 :         sc->sc_stats_ctx_mem = NULL;
     955           0 : }
     956             : 
     957             : void
     958           0 : bnxt_iff(struct bnxt_softc *sc)
     959             : {
     960           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
     961             :         struct ether_multi *enm;
     962             :         struct ether_multistep step;
     963             :         char *mc_list;
     964             :         uint32_t rx_mask, mc_count;
     965             : 
     966             :         rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST
     967             :             | HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST
     968             :             | HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN;
     969             : 
     970           0 :         mc_list = BNXT_DMA_KVA(sc->sc_rx_mcast);
     971             :         mc_count = 0;
     972             : 
     973           0 :         if (ifp->if_flags & IFF_PROMISC) {
     974           0 :                 SET(ifp->if_flags, IFF_ALLMULTI);
     975             :                 rx_mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS;
     976           0 :         } else if ((sc->sc_ac.ac_multirangecnt > 0) ||
     977           0 :             (sc->sc_ac.ac_multicnt > (PAGE_SIZE / ETHER_ADDR_LEN))) {
     978           0 :                 SET(ifp->if_flags, IFF_ALLMULTI);
     979             :                 rx_mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
     980           0 :         } else {
     981           0 :                 CLR(ifp->if_flags, IFF_ALLMULTI);
     982           0 :                 ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
     983           0 :                 while (enm != NULL) {
     984           0 :                         memcpy(mc_list, enm->enm_addrlo, ETHER_ADDR_LEN);
     985           0 :                         mc_list += ETHER_ADDR_LEN;
     986           0 :                         mc_count++;
     987             : 
     988           0 :                         ETHER_NEXT_MULTI(step, enm);
     989             :                 }
     990             :         }
     991             : 
     992           0 :         bnxt_hwrm_cfa_l2_set_rx_mask(sc, sc->sc_vnic.id, rx_mask,
     993           0 :             BNXT_DMA_DVA(sc->sc_rx_mcast), mc_count);
     994           0 : }
     995             : 
     996             : int
     997           0 : bnxt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
     998             : {
     999           0 :         struct bnxt_softc       *sc = (struct bnxt_softc *)ifp->if_softc;
    1000           0 :         struct ifreq            *ifr = (struct ifreq *)data;
    1001             :         int                     s, error = 0;
    1002             : 
    1003           0 :         s = splnet();
    1004           0 :         switch (cmd) {
    1005             :         case SIOCSIFADDR:
    1006           0 :                 ifp->if_flags |= IFF_UP;
    1007             :                 /* FALLTHROUGH */
    1008             : 
    1009             :         case SIOCSIFFLAGS:
    1010           0 :                 if (ISSET(ifp->if_flags, IFF_UP)) {
    1011           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    1012           0 :                                 error = ENETRESET;
    1013             :                         else
    1014           0 :                                 bnxt_up(sc);
    1015             :                 } else {
    1016           0 :                         if (ISSET(ifp->if_flags, IFF_RUNNING))
    1017           0 :                                 bnxt_down(sc);
    1018             :                 }
    1019             :                 break;
    1020             : 
    1021             :         case SIOCGIFMEDIA:
    1022             :         case SIOCSIFMEDIA:
    1023           0 :                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
    1024           0 :                 break;
    1025             : 
    1026             :         case SIOCGIFRXR:
    1027           0 :                 error = bnxt_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data);
    1028           0 :                 break;
    1029             : 
    1030             :         default:
    1031           0 :                 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
    1032           0 :         }
    1033             : 
    1034           0 :         if (error == ENETRESET) {
    1035           0 :                 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
    1036             :                     (IFF_UP | IFF_RUNNING))
    1037           0 :                         bnxt_iff(sc);
    1038             :                 error = 0;
    1039           0 :         }
    1040             : 
    1041           0 :         splx(s);
    1042             : 
    1043           0 :         return (error);
    1044             : }
    1045             : 
    1046             : int
    1047           0 : bnxt_rxrinfo(struct bnxt_softc *sc, struct if_rxrinfo *ifri)
    1048             : {
    1049           0 :         struct if_rxring_info ifr[2];
    1050             : 
    1051           0 :         memset(&ifr, 0, sizeof(ifr));
    1052           0 :         ifr[0].ifr_size = MCLBYTES;
    1053           0 :         ifr[0].ifr_info = sc->sc_rxr[0];
    1054             : 
    1055           0 :         ifr[1].ifr_size = BNXT_AG_BUFFER_SIZE;
    1056           0 :         ifr[1].ifr_info = sc->sc_rxr[1];
    1057             : 
    1058           0 :         return (if_rxr_info_ioctl(ifri, nitems(ifr), ifr));
    1059           0 : }
    1060             : 
    1061             : int
    1062           0 : bnxt_load_mbuf(struct bnxt_softc *sc, struct bnxt_slot *bs, struct mbuf *m)
    1063             : {
    1064           0 :         switch (bus_dmamap_load_mbuf(sc->sc_dmat, bs->bs_map, m,
    1065             :             BUS_DMA_STREAMING | BUS_DMA_NOWAIT)) {
    1066             :         case 0:
    1067             :                 break;
    1068             : 
    1069             :         case EFBIG:
    1070           0 :                 if (m_defrag(m, M_DONTWAIT) == 0 &&
    1071           0 :                     bus_dmamap_load_mbuf(sc->sc_dmat, bs->bs_map, m,
    1072           0 :                     BUS_DMA_STREAMING | BUS_DMA_NOWAIT) == 0)
    1073             :                         break;
    1074             : 
    1075             :         default:
    1076           0 :                 return (1);
    1077             :         }
    1078             : 
    1079           0 :         bs->bs_m = m;
    1080           0 :         return (0);
    1081           0 : }
    1082             : 
    1083             : void
    1084           0 : bnxt_start(struct ifqueue *ifq)
    1085             : {
    1086           0 :         struct ifnet *ifp = ifq->ifq_if;
    1087             :         struct tx_bd_short *txring;
    1088           0 :         struct bnxt_softc *sc = ifp->if_softc;
    1089             :         struct bnxt_slot *bs;
    1090             :         bus_dmamap_t map;
    1091             :         struct mbuf *m;
    1092             :         u_int idx, free, used, laststart;
    1093             :         uint16_t txflags;
    1094             :         int i;
    1095             : 
    1096           0 :         txring = (struct tx_bd_short *)BNXT_DMA_KVA(sc->sc_tx_ring_mem);
    1097             : 
    1098           0 :         idx = sc->sc_tx_ring_prod;
    1099           0 :         free = sc->sc_tx_ring_cons;
    1100           0 :         if (free <= idx)
    1101           0 :                 free += sc->sc_tx_ring.ring_size;
    1102           0 :         free -= idx;
    1103             : 
    1104             :         used = 0;
    1105             : 
    1106           0 :         for (;;) {
    1107           0 :                 if (used + BNXT_MAX_TX_SEGS > free) {
    1108           0 :                         ifq_set_oactive(ifq);
    1109           0 :                         break;
    1110             :                 }
    1111             : 
    1112           0 :                 m = ifq_dequeue(ifq);
    1113           0 :                 if (m == NULL)
    1114             :                         break;
    1115             : 
    1116           0 :                 bs = &sc->sc_tx_slots[sc->sc_tx_prod];
    1117           0 :                 if (bnxt_load_mbuf(sc, bs, m) != 0) {
    1118           0 :                         m_freem(m);
    1119           0 :                         ifp->if_oerrors++;
    1120           0 :                         continue;
    1121             :                 }
    1122             : 
    1123             : #if NBPFILTER > 0
    1124           0 :                 if (ifp->if_bpf)
    1125           0 :                         bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
    1126             : #endif
    1127           0 :                 map = bs->bs_map;
    1128           0 :                 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
    1129             :                     BUS_DMASYNC_PREWRITE);
    1130           0 :                 used += map->dm_nsegs;
    1131             : 
    1132           0 :                 if (map->dm_mapsize < 512)
    1133           0 :                         txflags = TX_BD_SHORT_FLAGS_LHINT_LT512;
    1134           0 :                 else if (map->dm_mapsize < 1024)
    1135           0 :                         txflags = TX_BD_SHORT_FLAGS_LHINT_LT1K;
    1136           0 :                 else if (map->dm_mapsize < 2048)
    1137           0 :                         txflags = TX_BD_SHORT_FLAGS_LHINT_LT2K;
    1138             :                 else
    1139             :                         txflags = TX_BD_SHORT_FLAGS_LHINT_GTE2K;
    1140             : 
    1141           0 :                 txflags |= TX_BD_SHORT_TYPE_TX_BD_SHORT |
    1142           0 :                     TX_BD_SHORT_FLAGS_NO_CMPL |
    1143           0 :                     (map->dm_nsegs << TX_BD_SHORT_FLAGS_BD_CNT_SFT);
    1144             :                 laststart = idx;
    1145             : 
    1146           0 :                 for (i = 0; i < map->dm_nsegs; i++) {
    1147           0 :                         txring[idx].flags_type = htole16(txflags);
    1148           0 :                         if (i == map->dm_nsegs - 1)
    1149           0 :                                 txring[idx].flags_type |=
    1150             :                                     TX_BD_SHORT_FLAGS_PACKET_END;
    1151             :                         txflags = TX_BD_SHORT_TYPE_TX_BD_SHORT;
    1152             : 
    1153           0 :                         txring[idx].len =
    1154           0 :                             htole16(bs->bs_map->dm_segs[i].ds_len);
    1155           0 :                         txring[idx].opaque = sc->sc_tx_prod;
    1156           0 :                         txring[idx].addr =
    1157           0 :                             htole64(bs->bs_map->dm_segs[i].ds_addr);
    1158             : 
    1159           0 :                         idx++;
    1160           0 :                         if (idx == sc->sc_tx_ring.ring_size)
    1161             :                                 idx = 0;
    1162             :                 }
    1163             : 
    1164           0 :                 if (++sc->sc_tx_prod >= sc->sc_tx_ring.ring_size)
    1165           0 :                         sc->sc_tx_prod = 0;
    1166             :         }
    1167             : 
    1168             :         /* unset NO_CMPL on the first bd of the last packet */
    1169           0 :         if (used != 0) {
    1170           0 :                 txring[laststart].flags_type &=
    1171             :                     ~htole16(TX_BD_SHORT_FLAGS_NO_CMPL);
    1172           0 :         }
    1173             : 
    1174           0 :         bnxt_write_tx_doorbell(sc, &sc->sc_tx_ring, idx);
    1175           0 :         sc->sc_tx_ring_prod = idx;
    1176           0 : }
    1177             : 
    1178             : void
    1179           0 : bnxt_handle_async_event(struct bnxt_softc *sc, struct cmpl_base *cmpl)
    1180             : {
    1181           0 :         struct hwrm_async_event_cmpl *ae = (struct hwrm_async_event_cmpl *)cmpl;
    1182           0 :         uint16_t type = le16toh(ae->event_id);
    1183             : 
    1184           0 :         switch (type) {
    1185             :         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
    1186             :         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE:
    1187             :         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE:
    1188           0 :                 bnxt_hwrm_port_phy_qcfg(sc, NULL);
    1189           0 :                 break;
    1190             : 
    1191             :         default:
    1192           0 :                 printf("%s: unexpected async event %x\n", DEVNAME(sc), type);
    1193           0 :                 break;
    1194             :         }
    1195           0 : }
    1196             : 
    1197             : struct cmpl_base *
    1198           0 : bnxt_cpr_next_cmpl(struct bnxt_softc *sc, struct bnxt_cp_ring *cpr)
    1199             : {
    1200             :         struct cmpl_base *cmpl;
    1201             :         uint32_t cons;
    1202             :         int v_bit;
    1203             : 
    1204           0 :         cons = cpr->cons + 1;
    1205           0 :         v_bit = cpr->v_bit;
    1206           0 :         if (cons == cpr->ring.ring_size) {
    1207             :                 cons = 0;
    1208           0 :                 v_bit = !v_bit;
    1209           0 :         }
    1210           0 :         cmpl = &((struct cmpl_base *)cpr->ring.vaddr)[cons];
    1211             : 
    1212           0 :         if ((!!(cmpl->info3_v & htole32(CMPL_BASE_V))) != (!!v_bit))
    1213           0 :                 return (NULL);
    1214             : 
    1215           0 :         cpr->cons = cons;
    1216           0 :         cpr->v_bit = v_bit;
    1217           0 :         return (cmpl);
    1218           0 : }
    1219             : 
    1220             : void
    1221           0 : bnxt_cpr_commit(struct bnxt_softc *sc, struct bnxt_cp_ring *cpr)
    1222             : {
    1223           0 :         cpr->commit_cons = cpr->cons;
    1224           0 :         cpr->commit_v_bit = cpr->v_bit;
    1225           0 : }
    1226             : 
    1227             : void
    1228           0 : bnxt_cpr_rollback(struct bnxt_softc *sc, struct bnxt_cp_ring *cpr)
    1229             : {
    1230           0 :         cpr->cons = cpr->commit_cons;
    1231           0 :         cpr->v_bit = cpr->commit_v_bit;
    1232           0 : }
    1233             : 
    1234             : 
    1235             : int
    1236           0 : bnxt_intr(void *xsc)
    1237             : {
    1238           0 :         struct bnxt_softc *sc = (struct bnxt_softc *)xsc;
    1239           0 :         struct ifnet *ifp = &sc->sc_ac.ac_if;
    1240           0 :         struct bnxt_cp_ring *cpr = &sc->sc_cp_ring;
    1241             :         struct cmpl_base *cmpl;
    1242           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    1243             :         uint16_t type;
    1244           0 :         int rxfree, txfree, agfree, rv, rollback;
    1245             : 
    1246           0 :         bnxt_write_cp_doorbell(sc, &cpr->ring, 0);
    1247           0 :         rxfree = 0;
    1248           0 :         txfree = 0;
    1249           0 :         agfree = 0;
    1250             :         rv = -1;
    1251           0 :         cmpl = bnxt_cpr_next_cmpl(sc, cpr);
    1252           0 :         while (cmpl != NULL) {
    1253           0 :                 type = le16toh(cmpl->type) & CMPL_BASE_TYPE_MASK;
    1254             :                 rollback = 0;
    1255           0 :                 switch (type) {
    1256             :                 case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT:
    1257           0 :                         bnxt_handle_async_event(sc, cmpl);
    1258           0 :                         break;
    1259             :                 case CMPL_BASE_TYPE_RX_L2:
    1260           0 :                         rollback = bnxt_rx(sc, cpr, &ml, &rxfree, &agfree, cmpl);
    1261           0 :                         break;
    1262             :                 case CMPL_BASE_TYPE_TX_L2:
    1263           0 :                         bnxt_txeof(sc, &txfree, cmpl);
    1264           0 :                         break;
    1265             :                 default:
    1266           0 :                         printf("%s: unexpected completion type %u\n",
    1267           0 :                             DEVNAME(sc), type);
    1268           0 :                 }
    1269             : 
    1270           0 :                 if (rollback) {
    1271           0 :                         bnxt_cpr_rollback(sc, cpr);
    1272           0 :                         break;
    1273             :                 }
    1274             :                 rv = 1;
    1275           0 :                 bnxt_cpr_commit(sc, cpr);
    1276           0 :                 cmpl = bnxt_cpr_next_cmpl(sc, cpr);
    1277             :         }
    1278             : 
    1279             :         /*
    1280             :          * comments in bnxtreg.h suggest we should be writing cpr->cons here,
    1281             :          * but writing cpr->cons + 1 makes it stop interrupting.
    1282             :          */
    1283           0 :         bnxt_write_cp_doorbell_index(sc, &cpr->ring,
    1284           0 :             (cpr->commit_cons+1) % cpr->ring.ring_size, 1);
    1285             : 
    1286           0 :         if (rxfree != 0) {
    1287           0 :                 sc->sc_rx_cons += rxfree;
    1288           0 :                 if (sc->sc_rx_cons >= sc->sc_rx_ring.ring_size)
    1289           0 :                         sc->sc_rx_cons -= sc->sc_rx_ring.ring_size;
    1290             : 
    1291           0 :                 sc->sc_rx_ag_cons += agfree;
    1292           0 :                 if (sc->sc_rx_ag_cons >= sc->sc_rx_ag_ring.ring_size)
    1293           0 :                         sc->sc_rx_ag_cons -= sc->sc_rx_ag_ring.ring_size;
    1294             : 
    1295           0 :                 if_rxr_put(&sc->sc_rxr[0], rxfree);
    1296           0 :                 if_rxr_put(&sc->sc_rxr[1], agfree);
    1297             : 
    1298           0 :                 bnxt_rx_fill(sc);
    1299           0 :                 if ((sc->sc_rx_cons == sc->sc_rx_prod) ||
    1300           0 :                     (sc->sc_rx_ag_cons == sc->sc_rx_ag_prod))
    1301           0 :                         timeout_add(&sc->sc_rx_refill, 0);
    1302             : 
    1303           0 :                 if_input(&sc->sc_ac.ac_if, &ml);
    1304           0 :         }
    1305           0 :         if (txfree != 0) {
    1306           0 :                 if (ifq_is_oactive(&ifp->if_snd))
    1307           0 :                         ifq_restart(&ifp->if_snd);
    1308             :         }
    1309           0 :         return (rv);
    1310           0 : }
    1311             : 
    1312             : void
    1313           0 : bnxt_watchdog(struct ifnet *ifp)
    1314             : {
    1315           0 : }
    1316             : 
    1317             : void
    1318           0 : bnxt_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
    1319             : {
    1320           0 :         struct bnxt_softc *sc = (struct bnxt_softc *)ifp->if_softc;
    1321           0 :         bnxt_hwrm_port_phy_qcfg(sc, ifmr);
    1322           0 : }
    1323             : 
    1324             : uint64_t
    1325           0 : bnxt_get_media_type(uint64_t speed, int phy_type)
    1326             : {
    1327           0 :         switch (phy_type) {
    1328             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN:
    1329             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
    1330             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_L:
    1331             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_S:
    1332             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASECR_CA_N:
    1333             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASECR4:
    1334             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASECR4:
    1335           0 :                 switch (speed) {
    1336             :                 case IF_Gbps(1):
    1337           0 :                         return IFM_1000_T;
    1338             :                 case IF_Gbps(10):
    1339           0 :                         return IFM_10G_SFP_CU;
    1340             :                 case IF_Gbps(25):
    1341           0 :                         return IFM_25G_CR;
    1342             :                 case IF_Gbps(40):
    1343           0 :                         return IFM_40G_CR4;
    1344             :                 case IF_Gbps(50):
    1345           0 :                         return IFM_50G_CR2;
    1346             :                 case IF_Gbps(100):
    1347           0 :                         return IFM_100G_CR4;
    1348             :                 }
    1349             :                 break;
    1350             : 
    1351             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
    1352             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASELR4:
    1353             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASELR4:
    1354           0 :                 switch (speed) {
    1355             :                 case IF_Gbps(1):
    1356           0 :                         return IFM_1000_LX;
    1357             :                 case IF_Gbps(10):
    1358           0 :                         return IFM_10G_LR;
    1359             :                 case IF_Gbps(25):
    1360           0 :                         return IFM_25G_LR;
    1361             :                 case IF_Gbps(40):
    1362           0 :                         return IFM_40G_LR4;
    1363             :                 case IF_Gbps(100):
    1364           0 :                         return IFM_100G_LR4;
    1365             :                 }
    1366             :                 break;
    1367             : 
    1368             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
    1369             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_25G_BASESR:
    1370             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR4:
    1371             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASESR10:
    1372             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASESX:
    1373           0 :                 switch (speed) {
    1374             :                 case IF_Gbps(1):
    1375           0 :                         return IFM_1000_SX;
    1376             :                 case IF_Gbps(10):
    1377           0 :                         return IFM_10G_SR;
    1378             :                 case IF_Gbps(25):
    1379           0 :                         return IFM_25G_SR;
    1380             :                 case IF_Gbps(40):
    1381           0 :                         return IFM_40G_SR4;
    1382             :                 case IF_Gbps(100):
    1383           0 :                         return IFM_100G_SR4;
    1384             :                 }
    1385             :                 break;
    1386             : 
    1387             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_100G_BASEER4:
    1388             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_BASEER4:
    1389           0 :                 switch (speed) {
    1390             :                 case IF_Gbps(10):
    1391           0 :                         return IFM_10G_ER;
    1392             :                 case IF_Gbps(25):
    1393           0 :                         return IFM_25G_ER;
    1394             :                 }
    1395             :                 /* missing IFM_40G_ER4, IFM_100G_ER4 */
    1396             :                 break;
    1397             : 
    1398             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
    1399             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
    1400             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
    1401           0 :                 switch (speed) {
    1402             :                 case IF_Gbps(10):
    1403           0 :                         return IFM_10G_KR;
    1404             :                 case IF_Gbps(20):
    1405           0 :                         return IFM_20G_KR2;
    1406             :                 case IF_Gbps(25):
    1407           0 :                         return IFM_25G_KR;
    1408             :                 case IF_Gbps(40):
    1409           0 :                         return IFM_40G_KR4;
    1410             :                 case IF_Gbps(50):
    1411           0 :                         return IFM_50G_KR2;
    1412             :                 case IF_Gbps(100):
    1413           0 :                         return IFM_100G_KR4;
    1414             :                 }
    1415             :                 break;
    1416             : 
    1417             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
    1418           0 :                 switch (speed) {
    1419             :                 case IF_Gbps(1):
    1420           0 :                         return IFM_1000_KX;
    1421             :                 case IF_Mbps(2500):
    1422           0 :                         return IFM_2500_KX;
    1423             :                 case IF_Gbps(10):
    1424           0 :                         return IFM_10G_KX4;
    1425             :                 }
    1426             :                 break;
    1427             : 
    1428             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
    1429             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE:
    1430             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_1G_BASET:
    1431           0 :                 switch (speed) {
    1432             :                 case IF_Mbps(10):
    1433           0 :                         return IFM_10_T;
    1434             :                 case IF_Mbps(100):
    1435           0 :                         return IFM_100_TX;
    1436             :                 case IF_Gbps(1):
    1437           0 :                         return IFM_1000_T;
    1438             :                 case IF_Mbps(2500):
    1439           0 :                         return IFM_2500_T;
    1440             :                 case IF_Gbps(10):
    1441           0 :                         return IFM_10G_T;
    1442             :                 }
    1443             :                 break;
    1444             : 
    1445             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY:
    1446           0 :                 switch (speed) {
    1447             :                 case IF_Gbps(1):
    1448           0 :                         return IFM_1000_SGMII;
    1449             :                 }
    1450             :                 break;
    1451             : 
    1452             :         case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_40G_ACTIVE_CABLE:
    1453           0 :                 switch (speed) {
    1454             :                 case IF_Gbps(10):
    1455           0 :                         return IFM_10G_AOC;
    1456             :                 case IF_Gbps(25):
    1457           0 :                         return IFM_25G_AOC;
    1458             :                 case IF_Gbps(40):
    1459           0 :                         return IFM_40G_AOC;
    1460             :                 case IF_Gbps(100):
    1461           0 :                         return IFM_100G_AOC;
    1462             :                 }
    1463             :                 break;
    1464             :         }
    1465             : 
    1466           0 :         return 0;
    1467           0 : }
    1468             : 
    1469             : void
    1470           0 : bnxt_add_media_type(struct bnxt_softc *sc, int supported_speeds, uint64_t speed, uint64_t ifmt)
    1471             : {
    1472             :         int speed_bit = 0;
    1473           0 :         switch (speed) {
    1474             :         case IF_Gbps(1):
    1475             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB;
    1476           0 :                 break;
    1477             :         case IF_Gbps(2):
    1478             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2GB;
    1479           0 :                 break;
    1480             :         case IF_Mbps(2500):
    1481             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB;
    1482           0 :                 break;
    1483             :         case IF_Gbps(10):
    1484             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB;
    1485           0 :                 break;
    1486             :         case IF_Gbps(20):
    1487             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB;
    1488           0 :                 break;
    1489             :         case IF_Gbps(25):
    1490             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB;
    1491           0 :                 break;
    1492             :         case IF_Gbps(40):
    1493             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB;
    1494           0 :                 break;
    1495             :         case IF_Gbps(50):
    1496             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB;
    1497           0 :                 break;
    1498             :         case IF_Gbps(100):
    1499             :                 speed_bit = HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB;
    1500           0 :                 break;
    1501             :         }
    1502           0 :         if (supported_speeds & speed_bit)
    1503           0 :                 ifmedia_add(&sc->sc_media, IFM_ETHER | ifmt, 0, NULL);
    1504           0 : }
    1505             : 
    1506             : int
    1507           0 : bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc, struct ifmediareq *ifmr)
    1508             : {
    1509           0 :         struct ifnet *ifp = &softc->sc_ac.ac_if;
    1510           0 :         struct hwrm_port_phy_qcfg_input req = {0};
    1511             :         struct hwrm_port_phy_qcfg_output *resp =
    1512           0 :             BNXT_DMA_KVA(softc->sc_cmd_resp);
    1513             :         int link_state = LINK_STATE_DOWN;
    1514           0 :         uint64_t speeds[] = {
    1515             :                 IF_Gbps(1), IF_Gbps(2), IF_Mbps(2500), IF_Gbps(10), IF_Gbps(20),
    1516             :                 IF_Gbps(25), IF_Gbps(40), IF_Gbps(50), IF_Gbps(100)
    1517             :         };
    1518             :         uint64_t media_type;
    1519             :         int rc = 0;
    1520             :         int i;
    1521             : 
    1522           0 :         BNXT_HWRM_LOCK(softc);
    1523           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_PHY_QCFG);
    1524             : 
    1525           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    1526           0 :         if (rc) {
    1527           0 :                 printf("%s: failed to query port phy config\n", DEVNAME(softc));
    1528           0 :                 goto exit;
    1529             :         }
    1530             : 
    1531           0 :         if (resp->link == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) {
    1532           0 :                 if (resp->duplex_state == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_STATE_HALF)
    1533           0 :                         link_state = LINK_STATE_HALF_DUPLEX;
    1534             :                 else
    1535             :                         link_state = LINK_STATE_FULL_DUPLEX;
    1536             : 
    1537           0 :                 switch (resp->link_speed) {
    1538             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB:
    1539           0 :                         ifp->if_baudrate = IF_Mbps(10);
    1540           0 :                         break;
    1541             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB:
    1542           0 :                         ifp->if_baudrate = IF_Mbps(100);
    1543           0 :                         break;
    1544             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB:
    1545           0 :                         ifp->if_baudrate = IF_Gbps(1);
    1546           0 :                         break;
    1547             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB:
    1548           0 :                         ifp->if_baudrate = IF_Gbps(2);
    1549           0 :                         break;
    1550             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB:
    1551           0 :                         ifp->if_baudrate = IF_Mbps(2500);
    1552           0 :                         break;
    1553             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB:
    1554           0 :                         ifp->if_baudrate = IF_Gbps(10);
    1555           0 :                         break;
    1556             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB:
    1557           0 :                         ifp->if_baudrate = IF_Gbps(20);
    1558           0 :                         break;
    1559             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB:
    1560           0 :                         ifp->if_baudrate = IF_Gbps(25);
    1561           0 :                         break;
    1562             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB:
    1563           0 :                         ifp->if_baudrate = IF_Gbps(40);
    1564           0 :                         break;
    1565             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB:
    1566           0 :                         ifp->if_baudrate = IF_Gbps(50);
    1567           0 :                         break;
    1568             :                 case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB:
    1569           0 :                         ifp->if_baudrate = IF_Gbps(100);
    1570           0 :                         break;
    1571             :                 }
    1572             :         }
    1573             : 
    1574           0 :         ifmedia_delete_instance(&softc->sc_media, IFM_INST_ANY);
    1575           0 :         for (i = 0; i < nitems(speeds); i++) {
    1576           0 :                 media_type = bnxt_get_media_type(speeds[i], resp->phy_type);
    1577           0 :                 if (media_type != 0)
    1578           0 :                         bnxt_add_media_type(softc, resp->support_speeds,
    1579           0 :                             speeds[i], media_type);
    1580             :         }
    1581           0 :         ifmedia_add(&softc->sc_media, IFM_ETHER|IFM_AUTO, 0, NULL);
    1582           0 :         ifmedia_set(&softc->sc_media, IFM_ETHER|IFM_AUTO);
    1583             : 
    1584           0 :         if (ifmr != NULL) {
    1585           0 :                 ifmr->ifm_status = IFM_AVALID;
    1586           0 :                 if (LINK_STATE_IS_UP(ifp->if_link_state)) {
    1587           0 :                         ifmr->ifm_status |= IFM_ACTIVE;
    1588           0 :                         ifmr->ifm_active = IFM_ETHER | IFM_AUTO;
    1589           0 :                         if (resp->pause & HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
    1590           0 :                                 ifmr->ifm_active |= IFM_ETH_TXPAUSE;
    1591           0 :                         if (resp->pause & HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
    1592           0 :                                 ifmr->ifm_active |= IFM_ETH_RXPAUSE;
    1593           0 :                         if (resp->duplex_state == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_STATE_HALF)
    1594           0 :                                 ifmr->ifm_active |= IFM_HDX;
    1595             :                         else
    1596           0 :                                 ifmr->ifm_active |= IFM_FDX;
    1597             : 
    1598           0 :                         media_type = bnxt_get_media_type(ifp->if_baudrate, resp->phy_type);
    1599           0 :                         if (media_type != 0)
    1600           0 :                                 ifmr->ifm_active |= media_type;
    1601             :                 }
    1602             :         }
    1603             : 
    1604             : exit:
    1605           0 :         BNXT_HWRM_UNLOCK(softc);
    1606             : 
    1607           0 :         if (rc == 0 && (link_state != ifp->if_link_state)) {
    1608           0 :                 ifp->if_link_state = link_state;
    1609           0 :                 if_link_state_change(ifp);
    1610           0 :         }
    1611             : 
    1612           0 :         return rc;
    1613           0 : }
    1614             : 
    1615             : int
    1616           0 : bnxt_media_change(struct ifnet *ifp)
    1617             : {
    1618           0 :         struct bnxt_softc *sc = (struct bnxt_softc *)ifp->if_softc;
    1619           0 :         struct hwrm_port_phy_cfg_input req = {0};
    1620             :         uint64_t link_speed;
    1621             : 
    1622           0 :         if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER)
    1623           0 :                 return EINVAL;
    1624             : 
    1625           0 :         if (sc->sc_flags & BNXT_FLAG_NPAR)
    1626           0 :                 return ENODEV;
    1627             : 
    1628           0 :         bnxt_hwrm_cmd_hdr_init(sc, &req, HWRM_PORT_PHY_CFG);
    1629             : 
    1630           0 :         switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) {
    1631             :         case IFM_100G_CR4:
    1632             :         case IFM_100G_SR4:
    1633             :         case IFM_100G_KR4:
    1634             :         case IFM_100G_LR4:
    1635             :         case IFM_100G_AOC:
    1636             :                 link_speed = HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_100GB;
    1637           0 :                 break;
    1638             : 
    1639             :         case IFM_50G_CR2:
    1640             :         case IFM_50G_KR2:
    1641             :                 link_speed = HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_50GB;
    1642           0 :                 break;
    1643             : 
    1644             :         case IFM_40G_CR4:
    1645             :         case IFM_40G_SR4:
    1646             :         case IFM_40G_LR4:
    1647             :         case IFM_40G_KR4:
    1648             :         case IFM_40G_AOC:
    1649             :                 link_speed = HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_40GB;
    1650           0 :                 break;
    1651             : 
    1652             :         case IFM_25G_CR:
    1653             :         case IFM_25G_KR:
    1654             :         case IFM_25G_SR:
    1655             :         case IFM_25G_LR:
    1656             :         case IFM_25G_ER:
    1657             :         case IFM_25G_AOC:
    1658             :                 link_speed = HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_25GB;
    1659           0 :                 break;
    1660             : 
    1661             :         case IFM_10G_LR:
    1662             :         case IFM_10G_SR:
    1663             :         case IFM_10G_CX4:
    1664             :         case IFM_10G_T:
    1665             :         case IFM_10G_SFP_CU:
    1666             :         case IFM_10G_LRM:
    1667             :         case IFM_10G_KX4:
    1668             :         case IFM_10G_KR:
    1669             :         case IFM_10G_CR1:
    1670             :         case IFM_10G_ER:
    1671             :         case IFM_10G_AOC:
    1672             :                 link_speed = HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_10GB;
    1673           0 :                 break;
    1674             : 
    1675             :         case IFM_2500_SX:
    1676             :         case IFM_2500_KX:
    1677             :         case IFM_2500_T:
    1678             :                 link_speed = HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_2_5GB;
    1679           0 :                 break;
    1680             : 
    1681             :         case IFM_1000_T:
    1682             :         case IFM_1000_LX:
    1683             :         case IFM_1000_SX:
    1684             :         case IFM_1000_CX:
    1685             :         case IFM_1000_KX:
    1686             :                 link_speed = HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_1GB;
    1687           0 :                 break;
    1688             : 
    1689             :         case IFM_100_TX:
    1690             :                 link_speed = HWRM_PORT_PHY_QCFG_OUTPUT_FORCE_LINK_SPEED_100MB;
    1691           0 :                 break;
    1692             : 
    1693             :         default:
    1694             :                 link_speed = 0;
    1695           0 :         }
    1696             : 
    1697           0 :         if (link_speed == 0) {
    1698           0 :                 req.auto_mode |=
    1699             :                     HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
    1700           0 :                 req.flags |=
    1701             :                     htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
    1702           0 :                 req.enables |=
    1703             :                     htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
    1704           0 :         } else {
    1705           0 :                 req.force_link_speed = htole16(link_speed);
    1706           0 :                 req.flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
    1707             :         }
    1708           0 :         req.flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
    1709             : 
    1710           0 :         return hwrm_send_message(sc, &req, sizeof(req));
    1711           0 : }
    1712             : 
    1713             : int
    1714           0 : bnxt_media_autonegotiate(struct bnxt_softc *sc)
    1715             : {
    1716           0 :         struct hwrm_port_phy_cfg_input req = {0};
    1717             : 
    1718           0 :         if (sc->sc_flags & BNXT_FLAG_NPAR)
    1719           0 :                 return ENODEV;
    1720             : 
    1721           0 :         bnxt_hwrm_cmd_hdr_init(sc, &req, HWRM_PORT_PHY_CFG);
    1722           0 :         req.auto_mode |= HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_ALL_SPEEDS;
    1723           0 :         req.enables |= htole32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE);
    1724           0 :         req.flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
    1725           0 :         req.flags |= htole32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
    1726             : 
    1727           0 :         return hwrm_send_message(sc, &req, sizeof(req));
    1728           0 : }
    1729             : 
    1730             : 
    1731             : void
    1732           0 : bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr)
    1733             : {
    1734           0 :         struct cmpl_base *cmp = (void *)cpr->ring.vaddr;
    1735             :         int i;
    1736             : 
    1737           0 :         for (i = 0; i < cpr->ring.ring_size; i++)
    1738           0 :                 cmp[i].info3_v = !cpr->v_bit;
    1739           0 : }
    1740             : 
    1741             : void
    1742           0 : bnxt_write_cp_doorbell(struct bnxt_softc *sc, struct bnxt_ring *ring,
    1743             :     int enable)
    1744             : {
    1745             :         uint32_t val = CMPL_DOORBELL_KEY_CMPL;
    1746           0 :         if (enable == 0)
    1747           0 :                 val |= CMPL_DOORBELL_MASK;
    1748             : 
    1749           0 :         bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
    1750             :             BUS_SPACE_BARRIER_WRITE);
    1751           0 :         bus_space_barrier(sc->sc_db_t, sc->sc_db_h, 0, sc->sc_db_s,
    1752             :             BUS_SPACE_BARRIER_WRITE);
    1753           0 :         bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
    1754             :             htole32(val));
    1755           0 : }
    1756             : 
    1757             : void
    1758           0 : bnxt_write_cp_doorbell_index(struct bnxt_softc *sc, struct bnxt_ring *ring,
    1759             :     uint32_t index, int enable)
    1760             : {
    1761           0 :         uint32_t val = CMPL_DOORBELL_KEY_CMPL | CMPL_DOORBELL_IDX_VALID |
    1762           0 :             (index & CMPL_DOORBELL_IDX_MASK);
    1763           0 :         if (enable == 0)
    1764           0 :                 val |= CMPL_DOORBELL_MASK;
    1765           0 :         bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
    1766             :             BUS_SPACE_BARRIER_WRITE);
    1767           0 :         bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
    1768             :             htole32(val));
    1769           0 :         bus_space_barrier(sc->sc_db_t, sc->sc_db_h, 0, sc->sc_db_s,
    1770             :             BUS_SPACE_BARRIER_WRITE);
    1771           0 : }
    1772             : 
    1773             : void
    1774           0 : bnxt_write_rx_doorbell(struct bnxt_softc *sc, struct bnxt_ring *ring, int index)
    1775             : {
    1776           0 :         uint32_t val = RX_DOORBELL_KEY_RX | index;
    1777           0 :         bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
    1778             :             BUS_SPACE_BARRIER_WRITE);
    1779           0 :         bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
    1780             :             htole32(val));
    1781             : 
    1782             :         /* second write isn't necessary on all hardware */
    1783           0 :         bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
    1784             :             BUS_SPACE_BARRIER_WRITE);
    1785           0 :         bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
    1786             :             htole32(val));
    1787           0 : }
    1788             : 
    1789             : void
    1790           0 : bnxt_write_tx_doorbell(struct bnxt_softc *sc, struct bnxt_ring *ring, int index)
    1791             : {
    1792             :         uint32_t val = TX_DOORBELL_KEY_TX | index;
    1793           0 :         bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
    1794             :             BUS_SPACE_BARRIER_WRITE);
    1795           0 :         bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
    1796             :             htole32(val));
    1797             : 
    1798             :         /* second write isn't necessary on all hardware */
    1799           0 :         bus_space_barrier(sc->sc_db_t, sc->sc_db_h, ring->doorbell, 4,
    1800             :             BUS_SPACE_BARRIER_WRITE);
    1801           0 :         bus_space_write_4(sc->sc_db_t, sc->sc_db_h, ring->doorbell,
    1802             :             htole32(val));
    1803           0 : }
    1804             : 
    1805             : u_int
    1806           0 : bnxt_rx_fill_slots(struct bnxt_softc *sc, struct bnxt_ring *ring, void *ring_mem,
    1807             :     struct bnxt_slot *slots, uint *prod, int bufsize, uint16_t bdtype,
    1808             :     u_int nslots)
    1809             : {
    1810             :         struct rx_prod_pkt_bd *rxring;
    1811             :         struct bnxt_slot *bs;
    1812             :         struct mbuf *m;
    1813             :         uint p, fills;
    1814             : 
    1815           0 :         rxring = (struct rx_prod_pkt_bd *)ring_mem;
    1816           0 :         p = *prod;
    1817           0 :         for (fills = 0; fills < nslots; fills++) {
    1818           0 :                 bs = &slots[p];
    1819           0 :                 m = MCLGETI(NULL, M_DONTWAIT, NULL, bufsize);
    1820           0 :                 if (m == NULL)
    1821             :                         break;
    1822             : 
    1823           0 :                 m->m_len = m->m_pkthdr.len = bufsize;
    1824           0 :                 if (bus_dmamap_load_mbuf(sc->sc_dmat, bs->bs_map, m,
    1825           0 :                     BUS_DMA_NOWAIT) != 0) {
    1826           0 :                         m_freem(m);
    1827           0 :                         break;
    1828             :                 }
    1829           0 :                 bs->bs_m = m;
    1830             : 
    1831           0 :                 rxring[p].flags_type = htole16(bdtype);
    1832           0 :                 rxring[p].len = htole16(bufsize);
    1833           0 :                 rxring[p].opaque = p;
    1834           0 :                 rxring[p].addr = htole64(bs->bs_map->dm_segs[0].ds_addr);
    1835             : 
    1836           0 :                 if (++p >= ring->ring_size)
    1837             :                         p = 0;
    1838             :         }
    1839             : 
    1840           0 :         if (fills != 0)
    1841           0 :                 bnxt_write_rx_doorbell(sc, ring, p);
    1842           0 :         *prod = p;
    1843             : 
    1844           0 :         return (nslots - fills);
    1845             : }
    1846             : 
    1847             : int
    1848           0 : bnxt_rx_fill(struct bnxt_softc *sc)
    1849             : {
    1850             :         u_int slots;
    1851             :         int rv = 0;
    1852             : 
    1853           0 :         slots = if_rxr_get(&sc->sc_rxr[0], sc->sc_rx_ring.ring_size);
    1854           0 :         if (slots > 0) {
    1855           0 :                 slots = bnxt_rx_fill_slots(sc, &sc->sc_rx_ring,
    1856           0 :                     BNXT_DMA_KVA(sc->sc_rx_ring_mem), sc->sc_rx_slots,
    1857           0 :                     &sc->sc_rx_prod, MCLBYTES,
    1858             :                     RX_PROD_PKT_BD_TYPE_RX_PROD_PKT, slots);
    1859           0 :                 if_rxr_put(&sc->sc_rxr[0], slots);
    1860           0 :         } else
    1861             :                 rv = 1;
    1862             : 
    1863           0 :         slots = if_rxr_get(&sc->sc_rxr[1],  sc->sc_rx_ag_ring.ring_size);
    1864           0 :         if (slots > 0) {
    1865           0 :                 slots = bnxt_rx_fill_slots(sc, &sc->sc_rx_ag_ring,
    1866           0 :                     BNXT_DMA_KVA(sc->sc_rx_ring_mem) + PAGE_SIZE,
    1867           0 :                     sc->sc_rx_ag_slots, &sc->sc_rx_ag_prod,
    1868             :                     BNXT_AG_BUFFER_SIZE,
    1869             :                     RX_PROD_AGG_BD_TYPE_RX_PROD_AGG, slots);
    1870           0 :                 if_rxr_put(&sc->sc_rxr[1], slots);
    1871           0 :         } else
    1872             :                 rv = 1;
    1873             : 
    1874           0 :         return (rv);
    1875             : }
    1876             : 
    1877             : void
    1878           0 : bnxt_refill(void *xsc)
    1879             : {
    1880           0 :         struct bnxt_softc *sc = xsc;
    1881             : 
    1882           0 :         bnxt_rx_fill(sc);
    1883             : 
    1884           0 :         if (sc->sc_rx_cons == sc->sc_rx_prod)
    1885           0 :                 timeout_add(&sc->sc_rx_refill, 1);
    1886           0 : }
    1887             : 
    1888             : int
    1889           0 : bnxt_rx(struct bnxt_softc *sc, struct bnxt_cp_ring *cpr, struct mbuf_list *ml,
    1890             :     int *slots, int *agslots, struct cmpl_base *cmpl)
    1891             : {
    1892             :         struct mbuf *m, *am;
    1893             :         struct bnxt_slot *bs;
    1894           0 :         struct rx_pkt_cmpl *rx = (struct rx_pkt_cmpl *)cmpl;
    1895             :         struct rx_pkt_cmpl_hi *rxhi;
    1896             :         struct rx_abuf_cmpl *ag;
    1897             : 
    1898             :         /* second part of the rx completion */
    1899           0 :         rxhi = (struct rx_pkt_cmpl_hi *)bnxt_cpr_next_cmpl(sc, cpr);
    1900           0 :         if (rxhi == NULL) {
    1901           0 :                 return (1);
    1902             :         }
    1903             : 
    1904             :         /* packets over 2k in size use an aggregation buffer completion too */
    1905             :         ag = NULL;
    1906           0 :         if ((rx->agg_bufs_v1 >> RX_PKT_CMPL_AGG_BUFS_SFT) != 0) {
    1907           0 :                 ag = (struct rx_abuf_cmpl *)bnxt_cpr_next_cmpl(sc, cpr);
    1908           0 :                 if (ag == NULL) {
    1909           0 :                         return (1);
    1910             :                 }
    1911             :         }
    1912             : 
    1913           0 :         bs = &sc->sc_rx_slots[rx->opaque];
    1914           0 :         bus_dmamap_sync(sc->sc_dmat, bs->bs_map, 0, bs->bs_map->dm_mapsize,
    1915             :             BUS_DMASYNC_POSTREAD);
    1916           0 :         bus_dmamap_unload(sc->sc_dmat, bs->bs_map);
    1917             : 
    1918           0 :         m = bs->bs_m;
    1919           0 :         bs->bs_m = NULL;
    1920           0 :         m->m_pkthdr.len = m->m_len = letoh16(rx->len);
    1921           0 :         (*slots)++;
    1922             : 
    1923           0 :         if (ag != NULL) {
    1924           0 :                 bs = &sc->sc_rx_ag_slots[ag->opaque];
    1925           0 :                 bus_dmamap_sync(sc->sc_dmat, bs->bs_map, 0,
    1926             :                     bs->bs_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
    1927           0 :                 bus_dmamap_unload(sc->sc_dmat, bs->bs_map);
    1928             : 
    1929           0 :                 am = bs->bs_m;
    1930           0 :                 bs->bs_m = NULL;
    1931           0 :                 am->m_len = letoh16(ag->len);
    1932           0 :                 m->m_next = am;
    1933           0 :                 m->m_pkthdr.len += am->m_len;
    1934           0 :                 (*agslots)++;
    1935           0 :         }
    1936             : 
    1937           0 :         ml_enqueue(ml, m);
    1938           0 :         return (0);
    1939           0 : }
    1940             : 
    1941             : void
    1942           0 : bnxt_txeof(struct bnxt_softc *sc, int *txfree, struct cmpl_base *cmpl)
    1943             : {
    1944           0 :         struct tx_cmpl *txcmpl = (struct tx_cmpl *)cmpl;
    1945             :         struct bnxt_slot *bs;
    1946             :         bus_dmamap_t map;
    1947             :         u_int idx, segs, last;
    1948             : 
    1949           0 :         idx = sc->sc_tx_ring_cons;
    1950           0 :         last = sc->sc_tx_cons;
    1951           0 :         do {
    1952           0 :                 bs = &sc->sc_tx_slots[sc->sc_tx_cons];
    1953           0 :                 map = bs->bs_map;
    1954             : 
    1955           0 :                 segs = map->dm_nsegs;
    1956           0 :                 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
    1957             :                     BUS_DMASYNC_POSTWRITE);
    1958           0 :                 bus_dmamap_unload(sc->sc_dmat, map);
    1959           0 :                 m_freem(bs->bs_m);
    1960           0 :                 bs->bs_m = NULL;
    1961             : 
    1962           0 :                 idx += segs;
    1963           0 :                 (*txfree) += segs;
    1964           0 :                 if (idx >= sc->sc_tx_ring.ring_size)
    1965           0 :                         idx -= sc->sc_tx_ring.ring_size;
    1966             : 
    1967           0 :                 last = sc->sc_tx_cons;
    1968           0 :                 if (++sc->sc_tx_cons >= sc->sc_tx_ring.ring_size)
    1969           0 :                         sc->sc_tx_cons = 0;
    1970             : 
    1971           0 :         } while (last != txcmpl->opaque);
    1972           0 :         sc->sc_tx_ring_cons = idx;
    1973           0 : }
    1974             : 
    1975             : /* bnxt_hwrm.c */
    1976             : 
    1977             : int
    1978           0 : bnxt_hwrm_err_map(uint16_t err)
    1979             : {
    1980             :         int rc;
    1981             : 
    1982           0 :         switch (err) {
    1983             :         case HWRM_ERR_CODE_SUCCESS:
    1984           0 :                 return 0;
    1985             :         case HWRM_ERR_CODE_INVALID_PARAMS:
    1986             :         case HWRM_ERR_CODE_INVALID_FLAGS:
    1987             :         case HWRM_ERR_CODE_INVALID_ENABLES:
    1988           0 :                 return EINVAL;
    1989             :         case HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED:
    1990           0 :                 return EACCES;
    1991             :         case HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR:
    1992           0 :                 return ENOMEM;
    1993             :         case HWRM_ERR_CODE_CMD_NOT_SUPPORTED:
    1994           0 :                 return ENOSYS;
    1995             :         case HWRM_ERR_CODE_FAIL:
    1996           0 :                 return EIO;
    1997             :         case HWRM_ERR_CODE_HWRM_ERROR:
    1998             :         case HWRM_ERR_CODE_UNKNOWN_ERR:
    1999             :         default:
    2000           0 :                 return EIO;
    2001             :         }
    2002             : 
    2003             :         return rc;
    2004           0 : }
    2005             : 
    2006             : void
    2007           0 : bnxt_hwrm_cmd_hdr_init(struct bnxt_softc *softc, void *request,
    2008             :     uint16_t req_type)
    2009             : {
    2010           0 :         struct input *req = request;
    2011             : 
    2012           0 :         req->req_type = htole16(req_type);
    2013           0 :         req->cmpl_ring = 0xffff;
    2014           0 :         req->target_id = 0xffff;
    2015           0 :         req->resp_addr = htole64(BNXT_DMA_DVA(softc->sc_cmd_resp));
    2016           0 : }
    2017             : 
    2018             : int
    2019           0 : _hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
    2020             : {
    2021           0 :         struct input *req = msg;
    2022           0 :         struct hwrm_err_output *resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
    2023           0 :         uint32_t *data = msg;
    2024             :         int i;
    2025             :         uint8_t *valid;
    2026             :         uint16_t err;
    2027             :         uint16_t max_req_len = HWRM_MAX_REQ_LEN;
    2028           0 :         struct hwrm_short_input short_input = {0};
    2029             : 
    2030             :         /* TODO: DMASYNC in here. */
    2031           0 :         req->seq_id = htole16(softc->sc_cmd_seq++);
    2032           0 :         memset(resp, 0, PAGE_SIZE);
    2033             : 
    2034           0 :         if (softc->sc_flags & BNXT_FLAG_SHORT_CMD) {
    2035           0 :                 void *short_cmd_req = BNXT_DMA_KVA(softc->sc_cmd_resp);
    2036             : 
    2037           0 :                 memcpy(short_cmd_req, req, msg_len);
    2038           0 :                 memset((uint8_t *) short_cmd_req + msg_len, 0,
    2039             :                     softc->sc_max_req_len - msg_len);
    2040             : 
    2041           0 :                 short_input.req_type = req->req_type;
    2042           0 :                 short_input.signature =
    2043             :                     htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD);
    2044           0 :                 short_input.size = htole16(msg_len);
    2045           0 :                 short_input.req_addr =
    2046           0 :                     htole64(BNXT_DMA_DVA(softc->sc_cmd_resp));
    2047             : 
    2048           0 :                 data = (uint32_t *)&short_input;
    2049             :                 msg_len = sizeof(short_input);
    2050             : 
    2051             :                 /* Sync memory write before updating doorbell */
    2052           0 :                 membar_sync();
    2053             : 
    2054             :                 max_req_len = BNXT_HWRM_SHORT_REQ_LEN;
    2055           0 :         }
    2056             : 
    2057             :         /* Write request msg to hwrm channel */
    2058           0 :         for (i = 0; i < msg_len; i += 4) {
    2059           0 :                 bus_space_write_4(softc->sc_hwrm_t,
    2060             :                                   softc->sc_hwrm_h,
    2061             :                                   i, *data);
    2062           0 :                 data++;
    2063             :         }
    2064             : 
    2065             :         /* Clear to the end of the request buffer */
    2066           0 :         for (i = msg_len; i < max_req_len; i += 4)
    2067           0 :                 bus_space_write_4(softc->sc_hwrm_t, softc->sc_hwrm_h,
    2068             :                     i, 0);
    2069             : 
    2070             :         /* Ring channel doorbell */
    2071           0 :         bus_space_write_4(softc->sc_hwrm_t, softc->sc_hwrm_h, 0x100,
    2072             :             htole32(1));
    2073             : 
    2074             :         /* Check if response len is updated */
    2075           0 :         for (i = 0; i < softc->sc_cmd_timeo; i++) {
    2076           0 :                 if (resp->resp_len && resp->resp_len <= 4096)
    2077             :                         break;
    2078           0 :                 DELAY(1000);
    2079             :         }
    2080           0 :         if (i >= softc->sc_cmd_timeo) {
    2081           0 :                 printf("%s: timeout sending %s: (timeout: %u) seq: %d\n",
    2082           0 :                     DEVNAME(softc), GET_HWRM_REQ_TYPE(req->req_type),
    2083           0 :                     softc->sc_cmd_timeo,
    2084           0 :                     le16toh(req->seq_id));
    2085           0 :                 return ETIMEDOUT;
    2086             :         }
    2087             :         /* Last byte of resp contains the valid key */
    2088           0 :         valid = (uint8_t *)resp + resp->resp_len - 1;
    2089           0 :         for (i = 0; i < softc->sc_cmd_timeo; i++) {
    2090           0 :                 if (*valid == HWRM_RESP_VALID_KEY)
    2091             :                         break;
    2092           0 :                 DELAY(1000);
    2093             :         }
    2094           0 :         if (i >= softc->sc_cmd_timeo) {
    2095           0 :                 printf("%s: timeout sending %s: "
    2096             :                     "(timeout: %u) msg {0x%x 0x%x} len:%d v: %d\n",
    2097           0 :                     DEVNAME(softc), GET_HWRM_REQ_TYPE(req->req_type),
    2098           0 :                     softc->sc_cmd_timeo, le16toh(req->req_type),
    2099           0 :                     le16toh(req->seq_id), msg_len,
    2100           0 :                     *valid);
    2101           0 :                 return ETIMEDOUT;
    2102             :         }
    2103             : 
    2104           0 :         err = le16toh(resp->error_code);
    2105           0 :         if (err) {
    2106             :                 /* HWRM_ERR_CODE_FAIL is a "normal" error, don't log */
    2107           0 :                 if (err != HWRM_ERR_CODE_FAIL) {
    2108           0 :                         printf("%s: %s command returned %s error.\n",
    2109           0 :                             DEVNAME(softc),
    2110           0 :                             GET_HWRM_REQ_TYPE(req->req_type),
    2111           0 :                             GET_HWRM_ERROR_CODE(err));
    2112           0 :                 }
    2113           0 :                 return bnxt_hwrm_err_map(err);
    2114             :         }
    2115             : 
    2116           0 :         return 0;
    2117           0 : }
    2118             : 
    2119             : 
    2120             : int
    2121           0 : hwrm_send_message(struct bnxt_softc *softc, void *msg, uint32_t msg_len)
    2122             : {
    2123             :         int rc;
    2124             : 
    2125           0 :         BNXT_HWRM_LOCK(softc);
    2126           0 :         rc = _hwrm_send_message(softc, msg, msg_len);
    2127           0 :         BNXT_HWRM_UNLOCK(softc);
    2128           0 :         return rc;
    2129             : }
    2130             : 
    2131             : 
    2132             : int
    2133           0 : bnxt_hwrm_queue_qportcfg(struct bnxt_softc *softc)
    2134             : {
    2135           0 :         struct hwrm_queue_qportcfg_input req = {0};
    2136             :         struct hwrm_queue_qportcfg_output *resp =
    2137           0 :             BNXT_DMA_KVA(softc->sc_cmd_resp);
    2138             : 
    2139             :         int     i, rc = 0;
    2140             :         uint8_t *qptr;
    2141             : 
    2142           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_QUEUE_QPORTCFG);
    2143             : 
    2144           0 :         BNXT_HWRM_LOCK(softc);
    2145           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2146           0 :         if (rc)
    2147             :                 goto qportcfg_exit;
    2148             : 
    2149           0 :         if (!resp->max_configurable_queues) {
    2150             :                 rc = -EINVAL;
    2151           0 :                 goto qportcfg_exit;
    2152             :         }
    2153           0 :         softc->sc_max_tc = resp->max_configurable_queues;
    2154           0 :         if (softc->sc_max_tc > BNXT_MAX_QUEUE)
    2155           0 :                 softc->sc_max_tc = BNXT_MAX_QUEUE;
    2156             : 
    2157           0 :         qptr = &resp->queue_id0;
    2158           0 :         for (i = 0; i < softc->sc_max_tc; i++) {
    2159           0 :                 softc->sc_q_info[i].id = *qptr++;
    2160           0 :                 softc->sc_q_info[i].profile = *qptr++;
    2161             :         }
    2162             : 
    2163             : qportcfg_exit:
    2164           0 :         BNXT_HWRM_UNLOCK(softc);
    2165           0 :         return rc;
    2166           0 : }
    2167             : 
    2168             : int
    2169           0 : bnxt_hwrm_ver_get(struct bnxt_softc *softc)
    2170             : {
    2171           0 :         struct hwrm_ver_get_input       req = {0};
    2172             :         struct hwrm_ver_get_output      *resp =
    2173           0 :             BNXT_DMA_KVA(softc->sc_cmd_resp);
    2174             :         int                             rc;
    2175             : #if 0
    2176             :         const char nastr[] = "<not installed>";
    2177             :         const char naver[] = "<N/A>";
    2178             : #endif
    2179             :         uint32_t dev_caps_cfg;
    2180             : 
    2181           0 :         softc->sc_max_req_len = HWRM_MAX_REQ_LEN;
    2182           0 :         softc->sc_cmd_timeo = 1000;
    2183           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VER_GET);
    2184             : 
    2185           0 :         req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
    2186           0 :         req.hwrm_intf_min = HWRM_VERSION_MINOR;
    2187           0 :         req.hwrm_intf_upd = HWRM_VERSION_UPDATE;
    2188             : 
    2189           0 :         BNXT_HWRM_LOCK(softc);
    2190           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2191           0 :         if (rc)
    2192             :                 goto fail;
    2193             : 
    2194           0 :         printf(": fw ver %d.%d.%d, ", resp->hwrm_fw_maj, resp->hwrm_fw_min,
    2195           0 :             resp->hwrm_fw_bld);
    2196             : #if 0
    2197             :         snprintf(softc->ver_info->hwrm_if_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
    2198             :             resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd);
    2199             :         softc->ver_info->hwrm_if_major = resp->hwrm_intf_maj;
    2200             :         softc->ver_info->hwrm_if_minor = resp->hwrm_intf_min;
    2201             :         softc->ver_info->hwrm_if_update = resp->hwrm_intf_upd;
    2202             :         snprintf(softc->ver_info->hwrm_fw_ver, BNXT_VERSTR_SIZE, "%d.%d.%d",
    2203             :             resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld);
    2204             :         strlcpy(softc->ver_info->driver_hwrm_if_ver, HWRM_VERSION_STR,
    2205             :             BNXT_VERSTR_SIZE);
    2206             :         strlcpy(softc->ver_info->hwrm_fw_name, resp->hwrm_fw_name,
    2207             :             BNXT_NAME_SIZE);
    2208             : 
    2209             :         if (resp->mgmt_fw_maj == 0 && resp->mgmt_fw_min == 0 &&
    2210             :             resp->mgmt_fw_bld == 0) {
    2211             :                 strlcpy(softc->ver_info->mgmt_fw_ver, naver, BNXT_VERSTR_SIZE);
    2212             :                 strlcpy(softc->ver_info->mgmt_fw_name, nastr, BNXT_NAME_SIZE);
    2213             :         }
    2214             :         else {
    2215             :                 snprintf(softc->ver_info->mgmt_fw_ver, BNXT_VERSTR_SIZE,
    2216             :                     "%d.%d.%d", resp->mgmt_fw_maj, resp->mgmt_fw_min,
    2217             :                     resp->mgmt_fw_bld);
    2218             :                 strlcpy(softc->ver_info->mgmt_fw_name, resp->mgmt_fw_name,
    2219             :                     BNXT_NAME_SIZE);
    2220             :         }
    2221             :         if (resp->netctrl_fw_maj == 0 && resp->netctrl_fw_min == 0 &&
    2222             :             resp->netctrl_fw_bld == 0) {
    2223             :                 strlcpy(softc->ver_info->netctrl_fw_ver, naver,
    2224             :                     BNXT_VERSTR_SIZE);
    2225             :                 strlcpy(softc->ver_info->netctrl_fw_name, nastr,
    2226             :                     BNXT_NAME_SIZE);
    2227             :         }
    2228             :         else {
    2229             :                 snprintf(softc->ver_info->netctrl_fw_ver, BNXT_VERSTR_SIZE,
    2230             :                     "%d.%d.%d", resp->netctrl_fw_maj, resp->netctrl_fw_min,
    2231             :                     resp->netctrl_fw_bld);
    2232             :                 strlcpy(softc->ver_info->netctrl_fw_name, resp->netctrl_fw_name,
    2233             :                     BNXT_NAME_SIZE);
    2234             :         }
    2235             :         if (resp->roce_fw_maj == 0 && resp->roce_fw_min == 0 &&
    2236             :             resp->roce_fw_bld == 0) {
    2237             :                 strlcpy(softc->ver_info->roce_fw_ver, naver, BNXT_VERSTR_SIZE);
    2238             :                 strlcpy(softc->ver_info->roce_fw_name, nastr, BNXT_NAME_SIZE);
    2239             :         }
    2240             :         else {
    2241             :                 snprintf(softc->ver_info->roce_fw_ver, BNXT_VERSTR_SIZE,
    2242             :                     "%d.%d.%d", resp->roce_fw_maj, resp->roce_fw_min,
    2243             :                     resp->roce_fw_bld);
    2244             :                 strlcpy(softc->ver_info->roce_fw_name, resp->roce_fw_name,
    2245             :                     BNXT_NAME_SIZE);
    2246             :         }
    2247             :         softc->ver_info->chip_num = le16toh(resp->chip_num);
    2248             :         softc->ver_info->chip_rev = resp->chip_rev;
    2249             :         softc->ver_info->chip_metal = resp->chip_metal;
    2250             :         softc->ver_info->chip_bond_id = resp->chip_bond_id;
    2251             :         softc->ver_info->chip_type = resp->chip_platform_type;
    2252             : #endif
    2253             : 
    2254           0 :         if (resp->max_req_win_len)
    2255           0 :                 softc->sc_max_req_len = le16toh(resp->max_req_win_len);
    2256           0 :         if (resp->def_req_timeout)
    2257           0 :                 softc->sc_cmd_timeo = le16toh(resp->def_req_timeout);
    2258             : 
    2259           0 :         dev_caps_cfg = le32toh(resp->dev_caps_cfg);
    2260           0 :         if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) &&
    2261           0 :             (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED))
    2262           0 :                 softc->sc_flags |= BNXT_FLAG_SHORT_CMD;
    2263             : 
    2264             : fail:
    2265           0 :         BNXT_HWRM_UNLOCK(softc);
    2266           0 :         return rc;
    2267           0 : }
    2268             : 
    2269             : 
    2270             : int
    2271           0 : bnxt_hwrm_func_drv_rgtr(struct bnxt_softc *softc)
    2272             : {
    2273           0 :         struct hwrm_func_drv_rgtr_input req = {0};
    2274             : 
    2275           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
    2276             : 
    2277           0 :         req.enables = htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_VER |
    2278             :             HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_OS_TYPE);
    2279           0 :         req.os_type = htole16(HWRM_FUNC_DRV_RGTR_INPUT_OS_TYPE_FREEBSD);
    2280             : 
    2281           0 :         req.ver_maj = 6;
    2282           0 :         req.ver_min = 4;
    2283           0 :         req.ver_upd = 0;
    2284             : 
    2285           0 :         return hwrm_send_message(softc, &req, sizeof(req));
    2286           0 : }
    2287             : 
    2288             : #if 0
    2289             : 
    2290             : int
    2291             : bnxt_hwrm_func_drv_unrgtr(struct bnxt_softc *softc, bool shutdown)
    2292             : {
    2293             :         struct hwrm_func_drv_unrgtr_input req = {0};
    2294             : 
    2295             :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_UNRGTR);
    2296             :         if (shutdown == true)
    2297             :                 req.flags |=
    2298             :                     HWRM_FUNC_DRV_UNRGTR_INPUT_FLAGS_PREPARE_FOR_SHUTDOWN;
    2299             :         return hwrm_send_message(softc, &req, sizeof(req));
    2300             : }
    2301             : 
    2302             : #endif
    2303             : 
    2304             : int
    2305           0 : bnxt_hwrm_func_qcaps(struct bnxt_softc *softc)
    2306             : {
    2307             :         int rc = 0;
    2308           0 :         struct hwrm_func_qcaps_input req = {0};
    2309             :         struct hwrm_func_qcaps_output *resp =
    2310           0 :             BNXT_DMA_KVA(softc->sc_cmd_resp);
    2311             :         /* struct bnxt_func_info *func = &softc->func; */
    2312             : 
    2313           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCAPS);
    2314           0 :         req.fid = htole16(0xffff);
    2315             : 
    2316           0 :         BNXT_HWRM_LOCK(softc);
    2317           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2318           0 :         if (rc)
    2319             :                 goto fail;
    2320             : 
    2321           0 :         if (resp->flags &
    2322             :             htole32(HWRM_FUNC_QCAPS_OUTPUT_FLAGS_WOL_MAGICPKT_SUPPORTED))
    2323           0 :                 softc->sc_flags |= BNXT_FLAG_WOL_CAP;
    2324             : 
    2325           0 :         memcpy(softc->sc_ac.ac_enaddr, resp->mac_address, 6);
    2326             :         /*
    2327             :         func->fw_fid = le16toh(resp->fid);
    2328             :         memcpy(func->mac_addr, resp->mac_address, ETHER_ADDR_LEN);
    2329             :         func->max_rsscos_ctxs = le16toh(resp->max_rsscos_ctx);
    2330             :         func->max_cp_rings = le16toh(resp->max_cmpl_rings);
    2331             :         func->max_tx_rings = le16toh(resp->max_tx_rings);
    2332             :         func->max_rx_rings = le16toh(resp->max_rx_rings);
    2333             :         func->max_hw_ring_grps = le32toh(resp->max_hw_ring_grps);
    2334             :         if (!func->max_hw_ring_grps)
    2335             :                 func->max_hw_ring_grps = func->max_tx_rings;
    2336             :         func->max_l2_ctxs = le16toh(resp->max_l2_ctxs);
    2337             :         func->max_vnics = le16toh(resp->max_vnics);
    2338             :         func->max_stat_ctxs = le16toh(resp->max_stat_ctx);
    2339             :         if (BNXT_PF(softc)) {
    2340             :                 struct bnxt_pf_info *pf = &softc->pf;
    2341             : 
    2342             :                 pf->port_id = le16toh(resp->port_id);
    2343             :                 pf->first_vf_id = le16toh(resp->first_vf_id);
    2344             :                 pf->max_vfs = le16toh(resp->max_vfs);
    2345             :                 pf->max_encap_records = le32toh(resp->max_encap_records);
    2346             :                 pf->max_decap_records = le32toh(resp->max_decap_records);
    2347             :                 pf->max_tx_em_flows = le32toh(resp->max_tx_em_flows);
    2348             :                 pf->max_tx_wm_flows = le32toh(resp->max_tx_wm_flows);
    2349             :                 pf->max_rx_em_flows = le32toh(resp->max_rx_em_flows);
    2350             :                 pf->max_rx_wm_flows = le32toh(resp->max_rx_wm_flows);
    2351             :         }
    2352             :         if (!_is_valid_ether_addr(func->mac_addr)) {
    2353             :                 device_printf(softc->dev, "Invalid ethernet address, generating random locally administered address\n");
    2354             :                 get_random_ether_addr(func->mac_addr);
    2355             :         }
    2356             :         */
    2357             : 
    2358             : fail:
    2359           0 :         BNXT_HWRM_UNLOCK(softc);
    2360           0 :         return rc;
    2361           0 : }
    2362             : 
    2363             : 
    2364             : int 
    2365           0 : bnxt_hwrm_func_qcfg(struct bnxt_softc *softc)
    2366             : {
    2367           0 :         struct hwrm_func_qcfg_input req = {0};
    2368             :         /* struct hwrm_func_qcfg_output *resp =
    2369             :             BNXT_DMA_KVA(softc->sc_cmd_resp);
    2370             :         struct bnxt_func_qcfg *fn_qcfg = &softc->fn_qcfg; */
    2371             :         int rc;
    2372             : 
    2373           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_QCFG);
    2374           0 :         req.fid = htole16(0xffff);
    2375           0 :         BNXT_HWRM_LOCK(softc);
    2376           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2377             :         if (rc)
    2378             :                 goto fail;
    2379             : 
    2380             :         /*
    2381             :         fn_qcfg->alloc_completion_rings = le16toh(resp->alloc_cmpl_rings);
    2382             :         fn_qcfg->alloc_tx_rings = le16toh(resp->alloc_tx_rings);
    2383             :         fn_qcfg->alloc_rx_rings = le16toh(resp->alloc_rx_rings);
    2384             :         fn_qcfg->alloc_vnics = le16toh(resp->alloc_vnics);
    2385             :         */
    2386             : fail:
    2387           0 :         BNXT_HWRM_UNLOCK(softc);
    2388           0 :         return rc;
    2389           0 : }
    2390             : 
    2391             : 
    2392             : int
    2393           0 : bnxt_hwrm_func_reset(struct bnxt_softc *softc)
    2394             : {
    2395           0 :         struct hwrm_func_reset_input req = {0};
    2396             : 
    2397           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_RESET);
    2398           0 :         req.enables = 0;
    2399             : 
    2400           0 :         return hwrm_send_message(softc, &req, sizeof(req));
    2401           0 : }
    2402             : 
    2403             : int
    2404           0 : bnxt_hwrm_vnic_cfg_placement(struct bnxt_softc *softc,
    2405             :     struct bnxt_vnic_info *vnic)
    2406             : {
    2407           0 :         struct hwrm_vnic_plcmodes_cfg_input req = {0};
    2408             : 
    2409           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_PLCMODES_CFG);
    2410             : 
    2411           0 :         req.flags = htole32(
    2412             :             HWRM_VNIC_PLCMODES_CFG_INPUT_FLAGS_JUMBO_PLACEMENT);
    2413           0 :         req.enables = htole32(
    2414             :             HWRM_VNIC_PLCMODES_CFG_INPUT_ENABLES_JUMBO_THRESH_VALID);
    2415           0 :         req.vnic_id = htole16(vnic->id);
    2416           0 :         req.jumbo_thresh = htole16(MCLBYTES);
    2417             : 
    2418           0 :         return hwrm_send_message(softc, &req, sizeof(req));
    2419           0 : }
    2420             : 
    2421             : int
    2422           0 : bnxt_hwrm_vnic_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
    2423             : {
    2424           0 :         struct hwrm_vnic_cfg_input req = {0};
    2425             : 
    2426           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_CFG);
    2427             : 
    2428           0 :         if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
    2429           0 :                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_DEFAULT);
    2430           0 :         if (vnic->flags & BNXT_VNIC_FLAG_BD_STALL)
    2431           0 :                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_BD_STALL_MODE);
    2432           0 :         if (vnic->flags & BNXT_VNIC_FLAG_VLAN_STRIP)
    2433           0 :                 req.flags |= htole32(HWRM_VNIC_CFG_INPUT_FLAGS_VLAN_STRIP_MODE);
    2434           0 :         req.enables = htole32(HWRM_VNIC_CFG_INPUT_ENABLES_DFLT_RING_GRP |
    2435             :             HWRM_VNIC_CFG_INPUT_ENABLES_RSS_RULE |
    2436             :             HWRM_VNIC_CFG_INPUT_ENABLES_MRU);
    2437           0 :         req.vnic_id = htole16(vnic->id);
    2438           0 :         req.dflt_ring_grp = htole16(vnic->def_ring_grp);
    2439           0 :         req.rss_rule = htole16(vnic->rss_id);
    2440           0 :         req.cos_rule = htole16(vnic->cos_rule);
    2441           0 :         req.lb_rule = htole16(vnic->lb_rule);
    2442           0 :         req.mru = htole16(vnic->mru);
    2443             : 
    2444           0 :         return hwrm_send_message(softc, &req, sizeof(req));
    2445           0 : }
    2446             : 
    2447             : int
    2448           0 : bnxt_hwrm_vnic_alloc(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
    2449             : {
    2450           0 :         struct hwrm_vnic_alloc_input req = {0};
    2451             :         struct hwrm_vnic_alloc_output *resp =
    2452           0 :             BNXT_DMA_KVA(softc->sc_cmd_resp);
    2453             :         int rc;
    2454             : 
    2455           0 :         if (vnic->id != (uint16_t)HWRM_NA_SIGNATURE) {
    2456           0 :                 printf("%s: attempt to re-allocate vnic %04x\n",
    2457           0 :                     DEVNAME(softc), vnic->id);
    2458           0 :                 return EINVAL;
    2459             :         }
    2460             : 
    2461           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_ALLOC);
    2462             : 
    2463           0 :         if (vnic->flags & BNXT_VNIC_FLAG_DEFAULT)
    2464           0 :                 req.flags = htole32(HWRM_VNIC_ALLOC_INPUT_FLAGS_DEFAULT);
    2465             : 
    2466           0 :         BNXT_HWRM_LOCK(softc);
    2467           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2468           0 :         if (rc)
    2469             :                 goto fail;
    2470             : 
    2471           0 :         vnic->id = le32toh(resp->vnic_id);
    2472             : 
    2473             : fail:
    2474           0 :         BNXT_HWRM_UNLOCK(softc);
    2475           0 :         return rc;
    2476           0 : }
    2477             : 
    2478             : int
    2479           0 : bnxt_hwrm_vnic_free(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
    2480             : {
    2481           0 :         struct hwrm_vnic_free_input req = {0};
    2482             :         int rc;
    2483             : 
    2484           0 :         if (vnic->id == (uint16_t)HWRM_NA_SIGNATURE) {
    2485           0 :                 printf("%s: attempt to deallocate vnic %04x\n",
    2486           0 :                     DEVNAME(softc), vnic->id);
    2487           0 :                 return (EINVAL);
    2488             :         }
    2489             : 
    2490           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_FREE);
    2491           0 :         req.vnic_id = htole16(vnic->id);
    2492             : 
    2493           0 :         BNXT_HWRM_LOCK(softc);
    2494           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2495           0 :         if (rc == 0)
    2496           0 :                 vnic->id = (uint16_t)HWRM_NA_SIGNATURE;
    2497           0 :         BNXT_HWRM_UNLOCK(softc);
    2498             : 
    2499           0 :         return (rc);
    2500           0 : }
    2501             : 
    2502             : int
    2503           0 : bnxt_hwrm_vnic_ctx_alloc(struct bnxt_softc *softc, uint16_t *ctx_id)
    2504             : {
    2505           0 :         struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0};
    2506             :         struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp =
    2507           0 :             BNXT_DMA_KVA(softc->sc_cmd_resp);
    2508             :         int rc;
    2509             : 
    2510           0 :         if (*ctx_id != (uint16_t)HWRM_NA_SIGNATURE) {
    2511           0 :                 printf("%s: attempt to re-allocate vnic ctx %04x\n",
    2512           0 :                     DEVNAME(softc), *ctx_id);
    2513           0 :                 return EINVAL;
    2514             :         }
    2515             : 
    2516           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC);
    2517             : 
    2518           0 :         BNXT_HWRM_LOCK(softc);
    2519           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2520           0 :         if (rc)
    2521             :                 goto fail;
    2522             : 
    2523           0 :         *ctx_id = letoh16(resp->rss_cos_lb_ctx_id);
    2524             : 
    2525             : fail:
    2526           0 :         BNXT_HWRM_UNLOCK(softc);
    2527           0 :         return (rc);
    2528           0 : }
    2529             : 
    2530             : int
    2531           0 : bnxt_hwrm_vnic_ctx_free(struct bnxt_softc *softc, uint16_t *ctx_id)
    2532             : {
    2533           0 :         struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0};
    2534             :         int rc;
    2535             : 
    2536           0 :         if (*ctx_id == (uint16_t)HWRM_NA_SIGNATURE) {
    2537           0 :                 printf("%s: attempt to deallocate vnic ctx %04x\n",
    2538           0 :                     DEVNAME(softc), *ctx_id);
    2539           0 :                 return (EINVAL);
    2540             :         }
    2541             : 
    2542           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE);
    2543           0 :         req.rss_cos_lb_ctx_id = htole32(*ctx_id);
    2544             : 
    2545           0 :         BNXT_HWRM_LOCK(softc);
    2546           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2547           0 :         if (rc == 0)
    2548           0 :                 *ctx_id = (uint16_t)HWRM_NA_SIGNATURE;
    2549           0 :         BNXT_HWRM_UNLOCK(softc);
    2550           0 :         return (rc);
    2551           0 : }
    2552             : 
    2553             : int
    2554           0 : bnxt_hwrm_ring_grp_alloc(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
    2555             : {
    2556           0 :         struct hwrm_ring_grp_alloc_input req = {0};
    2557             :         struct hwrm_ring_grp_alloc_output *resp;
    2558             :         int rc = 0;
    2559             : 
    2560           0 :         if (grp->grp_id != HWRM_NA_SIGNATURE) {
    2561           0 :                 printf("%s: attempt to re-allocate ring group %04x\n",
    2562           0 :                     DEVNAME(softc), grp->grp_id);
    2563           0 :                 return EINVAL;
    2564             :         }
    2565             : 
    2566           0 :         resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
    2567           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_ALLOC);
    2568           0 :         req.cr = htole16(grp->cp_ring_id);
    2569           0 :         req.rr = htole16(grp->rx_ring_id);
    2570           0 :         req.ar = htole16(grp->ag_ring_id);
    2571           0 :         req.sc = htole16(grp->stats_ctx);
    2572             : 
    2573           0 :         BNXT_HWRM_LOCK(softc);
    2574           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2575           0 :         if (rc)
    2576             :                 goto fail;
    2577             : 
    2578           0 :         grp->grp_id = letoh32(resp->ring_group_id);
    2579             : 
    2580             : fail:
    2581           0 :         BNXT_HWRM_UNLOCK(softc);
    2582           0 :         return rc;
    2583           0 : }
    2584             : 
    2585             : int
    2586           0 : bnxt_hwrm_ring_grp_free(struct bnxt_softc *softc, struct bnxt_grp_info *grp)
    2587             : {
    2588           0 :         struct hwrm_ring_grp_free_input req = {0};
    2589             :         int rc = 0;
    2590             : 
    2591           0 :         if (grp->grp_id == HWRM_NA_SIGNATURE) {
    2592           0 :                 printf("%s: attempt to free ring group %04x\n",
    2593           0 :                     DEVNAME(softc), grp->grp_id);
    2594           0 :                 return EINVAL;
    2595             :         }
    2596             : 
    2597           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_GRP_FREE);
    2598           0 :         req.ring_group_id = htole32(grp->grp_id);
    2599             : 
    2600           0 :         BNXT_HWRM_LOCK(softc);
    2601           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2602           0 :         if (rc == 0)
    2603           0 :                 grp->grp_id = HWRM_NA_SIGNATURE;
    2604             : 
    2605           0 :         BNXT_HWRM_UNLOCK(softc);
    2606           0 :         return (rc);
    2607           0 : }
    2608             : 
    2609             : /*
    2610             :  * Ring allocation message to the firmware
    2611             :  */
    2612             : int
    2613           0 : bnxt_hwrm_ring_alloc(struct bnxt_softc *softc, uint8_t type,
    2614             :     struct bnxt_ring *ring, uint16_t cmpl_ring_id, uint32_t stat_ctx_id,
    2615             :     int irq)
    2616             : {
    2617           0 :         struct hwrm_ring_alloc_input req = {0};
    2618             :         struct hwrm_ring_alloc_output *resp;
    2619             :         int rc;
    2620             : 
    2621           0 :         if (ring->phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
    2622           0 :                 printf("%s: attempt to re-allocate ring %04x\n",
    2623           0 :                     DEVNAME(softc), ring->phys_id);
    2624           0 :                 return EINVAL;
    2625             :         }
    2626             : 
    2627           0 :         resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
    2628           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_ALLOC);
    2629           0 :         req.enables = htole32(0);
    2630           0 :         req.fbo = htole32(0);
    2631             : 
    2632           0 :         if (stat_ctx_id != HWRM_NA_SIGNATURE) {
    2633           0 :                 req.enables |= htole32(
    2634             :                     HWRM_RING_ALLOC_INPUT_ENABLES_STAT_CTX_ID_VALID);
    2635           0 :                 req.stat_ctx_id = htole32(stat_ctx_id);
    2636           0 :         }
    2637           0 :         req.ring_type = type;
    2638           0 :         req.page_tbl_addr = htole64(ring->paddr);
    2639           0 :         req.length = htole32(ring->ring_size);
    2640           0 :         req.logical_id = htole16(ring->id);
    2641           0 :         req.cmpl_ring_id = htole16(cmpl_ring_id);
    2642           0 :         req.queue_id = htole16(softc->sc_q_info[0].id);
    2643           0 :         req.int_mode = 0;
    2644           0 :         BNXT_HWRM_LOCK(softc);
    2645           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2646           0 :         if (rc)
    2647             :                 goto fail;
    2648             : 
    2649           0 :         ring->phys_id = le16toh(resp->ring_id);
    2650             : 
    2651             : fail:
    2652           0 :         BNXT_HWRM_UNLOCK(softc);
    2653           0 :         return rc;
    2654           0 : }
    2655             : 
    2656             : int
    2657           0 : bnxt_hwrm_ring_free(struct bnxt_softc *softc, uint8_t type, struct bnxt_ring *ring)
    2658             : {
    2659           0 :         struct hwrm_ring_free_input req = {0};
    2660             :         int rc;
    2661             : 
    2662           0 :         if (ring->phys_id == (uint16_t)HWRM_NA_SIGNATURE) {
    2663           0 :                 printf("%s: attempt to deallocate ring %04x\n",
    2664           0 :                     DEVNAME(softc), ring->phys_id);
    2665           0 :                 return (EINVAL);
    2666             :         }
    2667             : 
    2668           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_RING_FREE);
    2669           0 :         req.ring_type = type;
    2670           0 :         req.ring_id = htole16(ring->phys_id);
    2671           0 :         BNXT_HWRM_LOCK(softc);
    2672           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2673           0 :         if (rc)
    2674             :                 goto fail;
    2675             : 
    2676           0 :         ring->phys_id = (uint16_t)HWRM_NA_SIGNATURE;
    2677             : fail:
    2678           0 :         BNXT_HWRM_UNLOCK(softc);
    2679           0 :         return (rc);
    2680           0 : }
    2681             : 
    2682             : 
    2683             : int
    2684           0 : bnxt_hwrm_stat_ctx_alloc(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr,
    2685             :     uint64_t paddr)
    2686             : {
    2687           0 :         struct hwrm_stat_ctx_alloc_input req = {0};
    2688             :         struct hwrm_stat_ctx_alloc_output *resp;
    2689             :         int rc = 0;
    2690             : 
    2691           0 :         if (cpr->stats_ctx_id != HWRM_NA_SIGNATURE) {
    2692           0 :                 printf("%s: attempt to re-allocate stats ctx %08x\n",
    2693           0 :                     DEVNAME(softc), cpr->stats_ctx_id);
    2694           0 :                 return EINVAL;
    2695             :         }
    2696             : 
    2697           0 :         resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
    2698           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_ALLOC);
    2699             : 
    2700           0 :         req.update_period_ms = htole32(1000);
    2701           0 :         req.stats_dma_addr = htole64(paddr);
    2702             : 
    2703           0 :         BNXT_HWRM_LOCK(softc);
    2704           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2705           0 :         if (rc)
    2706             :                 goto fail;
    2707             : 
    2708           0 :         cpr->stats_ctx_id = le32toh(resp->stat_ctx_id);
    2709             : 
    2710             : fail:
    2711           0 :         BNXT_HWRM_UNLOCK(softc);
    2712             : 
    2713           0 :         return rc;
    2714           0 : }
    2715             : 
    2716             : int
    2717           0 : bnxt_hwrm_stat_ctx_free(struct bnxt_softc *softc, struct bnxt_cp_ring *cpr)
    2718             : {
    2719           0 :         struct hwrm_stat_ctx_free_input req = {0};
    2720             :         int rc = 0;
    2721             : 
    2722           0 :         if (cpr->stats_ctx_id == HWRM_NA_SIGNATURE) {
    2723           0 :                 printf("%s: attempt to free stats ctx %08x\n",
    2724           0 :                     DEVNAME(softc), cpr->stats_ctx_id);
    2725           0 :                 return EINVAL;
    2726             :         }
    2727             : 
    2728           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_STAT_CTX_FREE);
    2729           0 :         req.stat_ctx_id = htole32(cpr->stats_ctx_id);
    2730             : 
    2731           0 :         BNXT_HWRM_LOCK(softc);
    2732           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2733           0 :         BNXT_HWRM_UNLOCK(softc);
    2734             : 
    2735           0 :         if (rc == 0)
    2736           0 :                 cpr->stats_ctx_id = HWRM_NA_SIGNATURE;
    2737             : 
    2738           0 :         return (rc);
    2739           0 : }
    2740             : 
    2741             : #if 0
    2742             : 
    2743             : int
    2744             : bnxt_hwrm_port_qstats(struct bnxt_softc *softc)
    2745             : {
    2746             :         struct hwrm_port_qstats_input req = {0};
    2747             :         int rc = 0;
    2748             : 
    2749             :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_PORT_QSTATS);
    2750             : 
    2751             :         req.port_id = htole16(softc->pf.port_id);
    2752             :         req.rx_stat_host_addr = htole64(softc->hw_rx_port_stats.idi_paddr);
    2753             :         req.tx_stat_host_addr = htole64(softc->hw_tx_port_stats.idi_paddr);
    2754             : 
    2755             :         BNXT_HWRM_LOCK(softc);
    2756             :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2757             :         BNXT_HWRM_UNLOCK(softc);
    2758             : 
    2759             :         return rc;
    2760             : }
    2761             : 
    2762             : #endif
    2763             : 
    2764             : int
    2765           0 : bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt_softc *softc,
    2766             :     uint32_t vnic_id, uint32_t rx_mask, uint64_t mc_addr, uint32_t mc_count)
    2767             : {
    2768           0 :         struct hwrm_cfa_l2_set_rx_mask_input req = {0};
    2769             : 
    2770           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_SET_RX_MASK);
    2771             : 
    2772           0 :         req.vnic_id = htole32(vnic_id);
    2773           0 :         req.mask = htole32(rx_mask);
    2774           0 :         req.mc_tbl_addr = htole64(mc_addr);
    2775           0 :         req.num_mc_entries = htole32(mc_count);
    2776           0 :         return hwrm_send_message(softc, &req, sizeof(req));
    2777           0 : }
    2778             : 
    2779             : int
    2780           0 : bnxt_hwrm_set_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
    2781             : {
    2782           0 :         struct hwrm_cfa_l2_filter_alloc_input   req = {0};
    2783             :         struct hwrm_cfa_l2_filter_alloc_output  *resp;
    2784             :         uint32_t enables = 0;
    2785             :         int rc = 0;
    2786             : 
    2787           0 :         if (vnic->filter_id != -1) {
    2788           0 :                 printf("%s: attempt to re-allocate l2 ctx filter\n",
    2789           0 :                     DEVNAME(softc));
    2790           0 :                 return EINVAL;
    2791             :         }
    2792             : 
    2793           0 :         resp = BNXT_DMA_KVA(softc->sc_cmd_resp);
    2794           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_ALLOC);
    2795             : 
    2796           0 :         req.flags = htole32(HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX);
    2797             :         enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR
    2798             :             | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK
    2799             :             | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_DST_ID;
    2800           0 :         req.enables = htole32(enables);
    2801           0 :         req.dst_id = htole16(vnic->id);
    2802           0 :         memcpy(req.l2_addr, softc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
    2803           0 :         memset(&req.l2_addr_mask, 0xff, sizeof(req.l2_addr_mask));
    2804             : 
    2805           0 :         BNXT_HWRM_LOCK(softc);
    2806           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2807           0 :         if (rc)
    2808             :                 goto fail;
    2809             : 
    2810           0 :         vnic->filter_id = le64toh(resp->l2_filter_id);
    2811           0 :         vnic->flow_id = le64toh(resp->flow_id);
    2812             : 
    2813             : fail:
    2814           0 :         BNXT_HWRM_UNLOCK(softc);
    2815           0 :         return (rc);
    2816           0 : }
    2817             : 
    2818             : int
    2819           0 : bnxt_hwrm_free_filter(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic)
    2820             : {
    2821           0 :         struct hwrm_cfa_l2_filter_free_input req = {0};
    2822             :         int rc = 0;
    2823             : 
    2824           0 :         if (vnic->filter_id == -1) {
    2825           0 :                 printf("%s: attempt to deallocate filter %llx\n",
    2826           0 :                      DEVNAME(softc), vnic->filter_id);
    2827           0 :                 return (EINVAL);
    2828             :         }
    2829             : 
    2830           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_CFA_L2_FILTER_FREE);
    2831           0 :         req.l2_filter_id = htole64(vnic->filter_id);
    2832             : 
    2833           0 :         BNXT_HWRM_LOCK(softc);
    2834           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2835           0 :         if (rc == 0)
    2836           0 :                 vnic->filter_id = -1;
    2837           0 :         BNXT_HWRM_UNLOCK(softc);
    2838             : 
    2839           0 :         return (rc);
    2840           0 : }
    2841             : 
    2842             : 
    2843             : #if 0
    2844             : 
    2845             : int
    2846             : bnxt_hwrm_rss_cfg(struct bnxt_softc *softc, struct bnxt_vnic_info *vnic,
    2847             :     uint32_t hash_type)
    2848             : {
    2849             :         struct hwrm_vnic_rss_cfg_input  req = {0};
    2850             : 
    2851             :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_RSS_CFG);
    2852             : 
    2853             :         req.hash_type = htole32(hash_type);
    2854             :         req.ring_grp_tbl_addr = htole64(vnic->rss_grp_tbl.idi_paddr);
    2855             :         req.hash_key_tbl_addr = htole64(vnic->rss_hash_key_tbl.idi_paddr);
    2856             :         req.rss_ctx_idx = htole16(vnic->rss_id);
    2857             : 
    2858             :         return hwrm_send_message(softc, &req, sizeof(req));
    2859             : }
    2860             : 
    2861             : #endif
    2862             : 
    2863             : int
    2864           0 : bnxt_cfg_async_cr(struct bnxt_softc *softc)
    2865             : {
    2866             :         int rc = 0;
    2867             :         
    2868             :         if (1 /* BNXT_PF(softc) */) {
    2869           0 :                 struct hwrm_func_cfg_input req = {0};
    2870             : 
    2871           0 :                 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG);
    2872             : 
    2873           0 :                 req.fid = htole16(0xffff);
    2874           0 :                 req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
    2875           0 :                 req.async_event_cr = htole16(softc->sc_cp_ring.ring.phys_id);
    2876             : 
    2877           0 :                 rc = hwrm_send_message(softc, &req, sizeof(req));
    2878           0 :         } else {
    2879             :                 struct hwrm_func_vf_cfg_input req = {0};
    2880             : 
    2881             :                 bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_VF_CFG);
    2882             : 
    2883             :                 req.enables = htole32(HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR);
    2884             :                 req.async_event_cr = htole16(softc->sc_cp_ring.ring.phys_id);
    2885             : 
    2886             :                 rc = hwrm_send_message(softc, &req, sizeof(req));
    2887             :         }
    2888           0 :         return rc;
    2889             : }
    2890             : 
    2891             : #if 0
    2892             : 
    2893             : void
    2894             : bnxt_validate_hw_lro_settings(struct bnxt_softc *softc)
    2895             : {
    2896             :         softc->hw_lro.enable = min(softc->hw_lro.enable, 1);
    2897             : 
    2898             :         softc->hw_lro.is_mode_gro = min(softc->hw_lro.is_mode_gro, 1);
    2899             : 
    2900             :         softc->hw_lro.max_agg_segs = min(softc->hw_lro.max_agg_segs,
    2901             :                 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGG_SEGS_MAX);
    2902             : 
    2903             :         softc->hw_lro.max_aggs = min(softc->hw_lro.max_aggs,
    2904             :                 HWRM_VNIC_TPA_CFG_INPUT_MAX_AGGS_MAX);
    2905             : 
    2906             :         softc->hw_lro.min_agg_len = min(softc->hw_lro.min_agg_len, BNXT_MAX_MTU);
    2907             : }
    2908             : 
    2909             : int
    2910             : bnxt_hwrm_vnic_tpa_cfg(struct bnxt_softc *softc)
    2911             : {
    2912             :         struct hwrm_vnic_tpa_cfg_input req = {0};
    2913             :         uint32_t flags;
    2914             : 
    2915             :         if (softc->vnic_info.id == (uint16_t) HWRM_NA_SIGNATURE) {
    2916             :                 return 0;
    2917             :         }
    2918             : 
    2919             :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_VNIC_TPA_CFG);
    2920             : 
    2921             :         if (softc->hw_lro.enable) {
    2922             :                 flags = HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA |
    2923             :                         HWRM_VNIC_TPA_CFG_INPUT_FLAGS_ENCAP_TPA |
    2924             :                         HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
    2925             :                         HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ;
    2926             :                 
    2927             :                 if (softc->hw_lro.is_mode_gro)
    2928             :                         flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO;
    2929             :                 else
    2930             :                         flags |= HWRM_VNIC_TPA_CFG_INPUT_FLAGS_RSC_WND_UPDATE;
    2931             :                         
    2932             :                 req.flags = htole32(flags);
    2933             : 
    2934             :                 req.enables = htole32(HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGG_SEGS |
    2935             :                                 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MAX_AGGS |
    2936             :                                 HWRM_VNIC_TPA_CFG_INPUT_ENABLES_MIN_AGG_LEN);
    2937             : 
    2938             :                 req.max_agg_segs = htole16(softc->hw_lro.max_agg_segs);
    2939             :                 req.max_aggs = htole16(softc->hw_lro.max_aggs);
    2940             :                 req.min_agg_len = htole32(softc->hw_lro.min_agg_len);
    2941             :         }
    2942             : 
    2943             :         req.vnic_id = htole16(softc->vnic_info.id);
    2944             : 
    2945             :         return hwrm_send_message(softc, &req, sizeof(req));
    2946             : }
    2947             : 
    2948             : 
    2949             : int
    2950             : bnxt_hwrm_fw_reset(struct bnxt_softc *softc, uint8_t processor,
    2951             :     uint8_t *selfreset)
    2952             : {
    2953             :         struct hwrm_fw_reset_input req = {0};
    2954             :         struct hwrm_fw_reset_output *resp =
    2955             :             (void *)softc->hwrm_cmd_resp.idi_vaddr;
    2956             :         int rc;
    2957             : 
    2958             :         MPASS(selfreset);
    2959             : 
    2960             :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_RESET);
    2961             :         req.embedded_proc_type = processor;
    2962             :         req.selfrst_status = *selfreset;
    2963             : 
    2964             :         BNXT_HWRM_LOCK(softc);
    2965             :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2966             :         if (rc)
    2967             :                 goto exit;
    2968             :         *selfreset = resp->selfrst_status;
    2969             : 
    2970             : exit:
    2971             :         BNXT_HWRM_UNLOCK(softc);
    2972             :         return rc;
    2973             : }
    2974             : 
    2975             : int
    2976             : bnxt_hwrm_fw_qstatus(struct bnxt_softc *softc, uint8_t type, uint8_t *selfreset)
    2977             : {
    2978             :         struct hwrm_fw_qstatus_input req = {0};
    2979             :         struct hwrm_fw_qstatus_output *resp =
    2980             :             (void *)softc->hwrm_cmd_resp.idi_vaddr;
    2981             :         int rc;
    2982             : 
    2983             :         MPASS(selfreset);
    2984             : 
    2985             :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_QSTATUS);
    2986             :         req.embedded_proc_type = type;
    2987             : 
    2988             :         BNXT_HWRM_LOCK(softc);
    2989             :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    2990             :         if (rc)
    2991             :                 goto exit;
    2992             :         *selfreset = resp->selfrst_status;
    2993             : 
    2994             : exit:
    2995             :         BNXT_HWRM_UNLOCK(softc);
    2996             :         return rc;
    2997             : }
    2998             : 
    2999             : #endif
    3000             : 
    3001             : int
    3002           0 : bnxt_hwrm_nvm_get_dev_info(struct bnxt_softc *softc, uint16_t *mfg_id,
    3003             :     uint16_t *device_id, uint32_t *sector_size, uint32_t *nvram_size,
    3004             :     uint32_t *reserved_size, uint32_t *available_size)
    3005             : {
    3006           0 :         struct hwrm_nvm_get_dev_info_input req = {0};
    3007             :         struct hwrm_nvm_get_dev_info_output *resp =
    3008           0 :             BNXT_DMA_KVA(softc->sc_cmd_resp);
    3009             :         int rc;
    3010             :         uint32_t old_timeo;
    3011             : 
    3012           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_NVM_GET_DEV_INFO);
    3013             : 
    3014           0 :         BNXT_HWRM_LOCK(softc);
    3015           0 :         old_timeo = softc->sc_cmd_timeo;
    3016           0 :         softc->sc_cmd_timeo = BNXT_NVM_TIMEO;
    3017           0 :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    3018           0 :         softc->sc_cmd_timeo = old_timeo;
    3019           0 :         if (rc)
    3020             :                 goto exit;
    3021             : 
    3022           0 :         if (mfg_id)
    3023           0 :                 *mfg_id = le16toh(resp->manufacturer_id);
    3024           0 :         if (device_id)
    3025           0 :                 *device_id = le16toh(resp->device_id);
    3026           0 :         if (sector_size)
    3027           0 :                 *sector_size = le32toh(resp->sector_size);
    3028           0 :         if (nvram_size)
    3029           0 :                 *nvram_size = le32toh(resp->nvram_size);
    3030           0 :         if (reserved_size)
    3031           0 :                 *reserved_size = le32toh(resp->reserved_size);
    3032           0 :         if (available_size)
    3033           0 :                 *available_size = le32toh(resp->available_size);
    3034             : 
    3035             : exit:
    3036           0 :         BNXT_HWRM_UNLOCK(softc);
    3037           0 :         return rc;
    3038           0 : }
    3039             : 
    3040             : #if 0
    3041             : 
    3042             : int
    3043             : bnxt_hwrm_fw_get_time(struct bnxt_softc *softc, uint16_t *year, uint8_t *month,
    3044             :     uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second,
    3045             :     uint16_t *millisecond, uint16_t *zone)
    3046             : {
    3047             :         struct hwrm_fw_get_time_input req = {0};
    3048             :         struct hwrm_fw_get_time_output *resp =
    3049             :             (void *)softc->hwrm_cmd_resp.idi_vaddr;
    3050             :         int rc;
    3051             : 
    3052             :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_GET_TIME);
    3053             : 
    3054             :         BNXT_HWRM_LOCK(softc);
    3055             :         rc = _hwrm_send_message(softc, &req, sizeof(req));
    3056             :         if (rc)
    3057             :                 goto exit;
    3058             : 
    3059             :         if (year)
    3060             :                 *year = le16toh(resp->year);
    3061             :         if (month)
    3062             :                 *month = resp->month;
    3063             :         if (day)
    3064             :                 *day = resp->day;
    3065             :         if (hour)
    3066             :                 *hour = resp->hour;
    3067             :         if (minute)
    3068             :                 *minute = resp->minute;
    3069             :         if (second)
    3070             :                 *second = resp->second;
    3071             :         if (millisecond)
    3072             :                 *millisecond = le16toh(resp->millisecond);
    3073             :         if (zone)
    3074             :                 *zone = le16toh(resp->zone);
    3075             : 
    3076             : exit:
    3077             :         BNXT_HWRM_UNLOCK(softc);
    3078             :         return rc;
    3079             : }
    3080             : 
    3081             : int
    3082             : bnxt_hwrm_fw_set_time(struct bnxt_softc *softc, uint16_t year, uint8_t month,
    3083             :     uint8_t day, uint8_t hour, uint8_t minute, uint8_t second,
    3084             :     uint16_t millisecond, uint16_t zone)
    3085             : {
    3086             :         struct hwrm_fw_set_time_input req = {0};
    3087             : 
    3088             :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FW_SET_TIME);
    3089             : 
    3090             :         req.year = htole16(year);
    3091             :         req.month = month;
    3092             :         req.day = day;
    3093             :         req.hour = hour;
    3094             :         req.minute = minute;
    3095             :         req.second = second;
    3096             :         req.millisecond = htole16(millisecond);
    3097             :         req.zone = htole16(zone);
    3098             :         return hwrm_send_message(softc, &req, sizeof(req));
    3099             : }
    3100             : 
    3101             : #endif
    3102             : 
    3103             : void
    3104           0 : _bnxt_hwrm_set_async_event_bit(struct hwrm_func_drv_rgtr_input *req, int bit)
    3105             : {
    3106           0 :         req->async_event_fwd[bit/32] |= (1 << (bit % 32));
    3107           0 : }
    3108             : 
    3109           0 : int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc)
    3110             : {
    3111           0 :         struct hwrm_func_drv_rgtr_input req = {0};
    3112           0 :         int events[] = {
    3113             :                 HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
    3114             :                 HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
    3115             :                 HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
    3116             :                 HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
    3117             :                 HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE
    3118             :         };
    3119             :         int i;
    3120             : 
    3121           0 :         bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
    3122             : 
    3123           0 :         req.enables =
    3124             :                 htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
    3125             : 
    3126           0 :         for (i = 0; i < nitems(events); i++)
    3127           0 :                 _bnxt_hwrm_set_async_event_bit(&req, events[i]);
    3128             : 
    3129           0 :         return hwrm_send_message(softc, &req, sizeof(req));
    3130           0 : }

Generated by: LCOV version 1.13