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