if_bnxt.c revision 309377
1/*-
2 * Broadcom NetXtreme-C/E network driver.
3 *
4 * Copyright (c) 2016 Broadcom, All Rights Reserved.
5 * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: stable/11/sys/dev/bnxt/if_bnxt.c 309377 2016-12-01 23:37:17Z shurd $");
31
32#include <sys/param.h>
33#include <sys/socket.h>
34#include <sys/kernel.h>
35#include <sys/bus.h>
36#include <sys/module.h>
37#include <sys/rman.h>
38#include <sys/endian.h>
39#include <sys/sockio.h>
40#include <sys/priv.h>
41
42#include <machine/bus.h>
43#include <machine/resource.h>
44
45#include <dev/pci/pcireg.h>
46#include <dev/pci/pcivar.h>
47
48#include <net/if.h>
49#include <net/if_media.h>
50#include <net/if_var.h>
51#include <net/ethernet.h>
52#include <net/iflib.h>
53
54#include "opt_inet.h"
55#include "opt_inet6.h"
56#include "opt_rss.h"
57
58#include "ifdi_if.h"
59
60#include "bnxt.h"
61#include "bnxt_hwrm.h"
62#include "bnxt_ioctl.h"
63#include "bnxt_sysctl.h"
64#include "hsi_struct_def.h"
65
66/*
67 * PCI Device ID Table
68 */
69
70static pci_vendor_info_t bnxt_vendor_info_array[] =
71{
72    PVID(BROADCOM_VENDOR_ID, BCM57301,
73	"Broadcom BCM57301 NetXtreme-C 10Gb Ethernet Controller"),
74    PVID(BROADCOM_VENDOR_ID, BCM57302,
75	"Broadcom BCM57302 NetXtreme-C 10Gb/25Gb Ethernet Controller"),
76    PVID(BROADCOM_VENDOR_ID, BCM57304,
77	"Broadcom BCM57304 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet Controller"),
78    PVID(BROADCOM_VENDOR_ID, BCM57311,
79	"Broadcom BCM57311 NetXtreme-C 10Gb Ethernet"),
80    PVID(BROADCOM_VENDOR_ID, BCM57312,
81	"Broadcom BCM57312 NetXtreme-C 10Gb/25Gb Ethernet"),
82    PVID(BROADCOM_VENDOR_ID, BCM57314,
83	"Broadcom BCM57314 NetXtreme-C 10Gb/25Gb/40Gb/50Gb Ethernet"),
84    PVID(BROADCOM_VENDOR_ID, BCM57402,
85	"Broadcom BCM57402 NetXtreme-E 10Gb Ethernet Controller"),
86    PVID(BROADCOM_VENDOR_ID, BCM57402_NPAR,
87	"Broadcom BCM57402 NetXtreme-E Partition"),
88    PVID(BROADCOM_VENDOR_ID, BCM57404,
89	"Broadcom BCM57404 NetXtreme-E 10Gb/25Gb Ethernet Controller"),
90    PVID(BROADCOM_VENDOR_ID, BCM57404_NPAR,
91	"Broadcom BCM57404 NetXtreme-E Partition"),
92    PVID(BROADCOM_VENDOR_ID, BCM57406,
93	"Broadcom BCM57406 NetXtreme-E 10GBase-T Ethernet Controller"),
94    PVID(BROADCOM_VENDOR_ID, BCM57406_NPAR,
95	"Broadcom BCM57406 NetXtreme-E Partition"),
96    PVID(BROADCOM_VENDOR_ID, BCM57407,
97	"Broadcom BCM57407 NetXtreme-E 10GBase-T Ethernet Controller"),
98    PVID(BROADCOM_VENDOR_ID, BCM57407_NPAR,
99	"Broadcom BCM57407 NetXtreme-E Ethernet Partition"),
100    PVID(BROADCOM_VENDOR_ID, BCM57407_SFP,
101	"Broadcom BCM57407 NetXtreme-E 25Gb Ethernet Controller"),
102    PVID(BROADCOM_VENDOR_ID, BCM57412,
103	"Broadcom BCM57412 NetXtreme-E 10Gb Ethernet"),
104    PVID(BROADCOM_VENDOR_ID, BCM57412_NPAR1,
105	"Broadcom BCM57412 NetXtreme-E Ethernet Partition"),
106    PVID(BROADCOM_VENDOR_ID, BCM57412_NPAR2,
107	"Broadcom BCM57412 NetXtreme-E Ethernet Partition"),
108    PVID(BROADCOM_VENDOR_ID, BCM57414,
109	"Broadcom BCM57414 NetXtreme-E 10Gb/25Gb Ethernet"),
110    PVID(BROADCOM_VENDOR_ID, BCM57414_NPAR1,
111	"Broadcom BCM57414 NetXtreme-E Ethernet Partition"),
112    PVID(BROADCOM_VENDOR_ID, BCM57414_NPAR2,
113	"Broadcom BCM57414 NetXtreme-E Ethernet Partition"),
114    PVID(BROADCOM_VENDOR_ID, BCM57416,
115	"Broadcom BCM57416 NetXtreme-E 10GBase-T Ethernet"),
116    PVID(BROADCOM_VENDOR_ID, BCM57416_NPAR1,
117	"Broadcom BCM57416 NetXtreme-E Ethernet Partition"),
118    PVID(BROADCOM_VENDOR_ID, BCM57416_NPAR2,
119	"Broadcom BCM57416 NetXtreme-E Ethernet Partition"),
120    PVID(BROADCOM_VENDOR_ID, BCM57416_SFP,
121	"Broadcom BCM57416 NetXtreme-E 10Gb Ethernet"),
122    PVID(BROADCOM_VENDOR_ID, BCM57417,
123	"Broadcom BCM57417 NetXtreme-E 10GBase-T Ethernet"),
124    PVID(BROADCOM_VENDOR_ID, BCM57417_NPAR1,
125	"Broadcom BCM57417 NetXtreme-E Ethernet Partition"),
126    PVID(BROADCOM_VENDOR_ID, BCM57417_NPAR2,
127	"Broadcom BCM57417 NetXtreme-E Ethernet Partition"),
128    PVID(BROADCOM_VENDOR_ID, BCM57417_SFP,
129	"Broadcom BCM57417 NetXtreme-E 10Gb/25Gb Ethernet"),
130    PVID(BROADCOM_VENDOR_ID, BCM58700,
131	"Broadcom BCM58700 Nitro 1Gb/2.5Gb/10Gb Ethernet"),
132    PVID(BROADCOM_VENDOR_ID, NETXTREME_C_VF1,
133	"Broadcom NetXtreme-C Ethernet Virtual Function"),
134    PVID(BROADCOM_VENDOR_ID, NETXTREME_C_VF2,
135	"Broadcom NetXtreme-C Ethernet Virtual Function"),
136    PVID(BROADCOM_VENDOR_ID, NETXTREME_C_VF3,
137	"Broadcom NetXtreme-C Ethernet Virtual Function"),
138    PVID(BROADCOM_VENDOR_ID, NETXTREME_E_VF1,
139	"Broadcom NetXtreme-E Ethernet Virtual Function"),
140    PVID(BROADCOM_VENDOR_ID, NETXTREME_E_VF2,
141	"Broadcom NetXtreme-E Ethernet Virtual Function"),
142    PVID(BROADCOM_VENDOR_ID, NETXTREME_E_VF3,
143	"Broadcom NetXtreme-E Ethernet Virtual Function"),
144    /* required last entry */
145
146    PVID_END
147};
148
149/*
150 * Function prototypes
151 */
152
153static void *bnxt_register(device_t dev);
154
155/* Soft queue setup and teardown */
156static int bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
157    uint64_t *paddrs, int ntxqs, int ntxqsets);
158static int bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
159    uint64_t *paddrs, int nrxqs, int nrxqsets);
160static void bnxt_queues_free(if_ctx_t ctx);
161
162/* Device setup and teardown */
163static int bnxt_attach_pre(if_ctx_t ctx);
164static int bnxt_attach_post(if_ctx_t ctx);
165static int bnxt_detach(if_ctx_t ctx);
166
167/* Device configuration */
168static void bnxt_init(if_ctx_t ctx);
169static void bnxt_stop(if_ctx_t ctx);
170static void bnxt_multi_set(if_ctx_t ctx);
171static int bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu);
172static void bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr);
173static int bnxt_media_change(if_ctx_t ctx);
174static int bnxt_promisc_set(if_ctx_t ctx, int flags);
175static uint64_t	bnxt_get_counter(if_ctx_t, ift_counter);
176static void bnxt_update_admin_status(if_ctx_t ctx);
177
178/* Interrupt enable / disable */
179static void bnxt_intr_enable(if_ctx_t ctx);
180static int bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid);
181static void bnxt_disable_intr(if_ctx_t ctx);
182static int bnxt_msix_intr_assign(if_ctx_t ctx, int msix);
183
184/* vlan support */
185static void bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag);
186static void bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag);
187
188/* ioctl */
189static int bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data);
190
191/* Internal support functions */
192static int bnxt_probe_phy(struct bnxt_softc *softc);
193static void bnxt_add_media_types(struct bnxt_softc *softc);
194static int bnxt_pci_mapping(struct bnxt_softc *softc);
195static void bnxt_pci_mapping_free(struct bnxt_softc *softc);
196static int bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state);
197static int bnxt_handle_def_cp(void *arg);
198static int bnxt_handle_rx_cp(void *arg);
199static void bnxt_clear_ids(struct bnxt_softc *softc);
200static void inline bnxt_do_enable_intr(struct bnxt_cp_ring *cpr);
201static void inline bnxt_do_disable_intr(struct bnxt_cp_ring *cpr);
202static void bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr);
203static void bnxt_def_cp_task(void *context);
204static void bnxt_handle_async_event(struct bnxt_softc *softc,
205    struct cmpl_base *cmpl);
206static uint8_t get_phy_type(struct bnxt_softc *softc);
207static uint64_t bnxt_get_baudrate(struct bnxt_link_info *link);
208
209/*
210 * Device Interface Declaration
211 */
212
213static device_method_t bnxt_methods[] = {
214	/* Device interface */
215	DEVMETHOD(device_register, bnxt_register),
216	DEVMETHOD(device_probe, iflib_device_probe),
217	DEVMETHOD(device_attach, iflib_device_attach),
218	DEVMETHOD(device_detach, iflib_device_detach),
219	DEVMETHOD(device_shutdown, iflib_device_shutdown),
220	DEVMETHOD(device_suspend, iflib_device_suspend),
221	DEVMETHOD(device_resume, iflib_device_resume),
222	DEVMETHOD_END
223};
224
225static driver_t bnxt_driver = {
226	"bnxt", bnxt_methods, sizeof(struct bnxt_softc),
227};
228
229devclass_t bnxt_devclass;
230DRIVER_MODULE(bnxt, pci, bnxt_driver, bnxt_devclass, 0, 0);
231
232MODULE_DEPEND(bnxt, pci, 1, 1, 1);
233MODULE_DEPEND(bnxt, ether, 1, 1, 1);
234MODULE_DEPEND(bnxt, iflib, 1, 1, 1);
235
236static device_method_t bnxt_iflib_methods[] = {
237	DEVMETHOD(ifdi_tx_queues_alloc, bnxt_tx_queues_alloc),
238	DEVMETHOD(ifdi_rx_queues_alloc, bnxt_rx_queues_alloc),
239	DEVMETHOD(ifdi_queues_free, bnxt_queues_free),
240
241	DEVMETHOD(ifdi_attach_pre, bnxt_attach_pre),
242	DEVMETHOD(ifdi_attach_post, bnxt_attach_post),
243	DEVMETHOD(ifdi_detach, bnxt_detach),
244
245	DEVMETHOD(ifdi_init, bnxt_init),
246	DEVMETHOD(ifdi_stop, bnxt_stop),
247	DEVMETHOD(ifdi_multi_set, bnxt_multi_set),
248	DEVMETHOD(ifdi_mtu_set, bnxt_mtu_set),
249	DEVMETHOD(ifdi_media_status, bnxt_media_status),
250	DEVMETHOD(ifdi_media_change, bnxt_media_change),
251	DEVMETHOD(ifdi_promisc_set, bnxt_promisc_set),
252	DEVMETHOD(ifdi_get_counter, bnxt_get_counter),
253	DEVMETHOD(ifdi_update_admin_status, bnxt_update_admin_status),
254
255	DEVMETHOD(ifdi_intr_enable, bnxt_intr_enable),
256	DEVMETHOD(ifdi_queue_intr_enable, bnxt_queue_intr_enable),
257	DEVMETHOD(ifdi_intr_disable, bnxt_disable_intr),
258	DEVMETHOD(ifdi_msix_intr_assign, bnxt_msix_intr_assign),
259
260	DEVMETHOD(ifdi_vlan_register, bnxt_vlan_register),
261	DEVMETHOD(ifdi_vlan_unregister, bnxt_vlan_unregister),
262
263	DEVMETHOD(ifdi_priv_ioctl, bnxt_priv_ioctl),
264
265	DEVMETHOD_END
266};
267
268static driver_t bnxt_iflib_driver = {
269	"bnxt", bnxt_iflib_methods, sizeof(struct bnxt_softc)
270};
271
272/*
273 * iflib shared context
274 */
275
276char bnxt_driver_version[] = "FreeBSD base";
277extern struct if_txrx bnxt_txrx;
278static struct if_shared_ctx bnxt_sctx_init = {
279	.isc_magic = IFLIB_MAGIC,
280	.isc_txrx = &bnxt_txrx,
281	.isc_driver = &bnxt_iflib_driver,
282	.isc_nfl = 2,				// Number of Free Lists
283	.isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ,
284	.isc_q_align = PAGE_SIZE,
285	.isc_tx_maxsize = BNXT_TSO_SIZE,
286	.isc_tx_maxsegsize = BNXT_TSO_SIZE,
287	.isc_rx_maxsize = BNXT_TSO_SIZE,
288	.isc_rx_maxsegsize = BNXT_TSO_SIZE,
289
290	// Only use a single segment to avoid page size constraints
291	.isc_rx_nsegments = 1,
292	.isc_ntxqs = 2,
293	.isc_nrxqs = 3,
294	.isc_nrxd_min = {16, 16, 16},
295	.isc_nrxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 8,
296	    PAGE_SIZE / sizeof(struct rx_prod_pkt_bd),
297	    PAGE_SIZE / sizeof(struct rx_prod_pkt_bd)},
298	.isc_nrxd_max = {INT32_MAX, INT32_MAX, INT32_MAX},
299	.isc_ntxd_min = {16, 16, 16},
300	.isc_ntxd_default = {PAGE_SIZE / sizeof(struct cmpl_base) * 2,
301	    PAGE_SIZE / sizeof(struct tx_bd_short)},
302	.isc_ntxd_max = {INT32_MAX, INT32_MAX, INT32_MAX},
303
304	.isc_admin_intrcnt = 1,
305	.isc_vendor_info = bnxt_vendor_info_array,
306	.isc_driver_version = bnxt_driver_version,
307};
308
309if_shared_ctx_t bnxt_sctx = &bnxt_sctx_init;
310
311/*
312 * Device Methods
313 */
314
315static void *
316bnxt_register(device_t dev)
317{
318	return bnxt_sctx;
319}
320
321/*
322 * Device Dependent Configuration Functions
323*/
324
325/* Soft queue setup and teardown */
326static int
327bnxt_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
328    uint64_t *paddrs, int ntxqs, int ntxqsets)
329{
330	struct bnxt_softc *softc;
331	int i;
332	int rc;
333
334	softc = iflib_get_softc(ctx);
335
336	softc->tx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * ntxqsets,
337	    M_DEVBUF, M_NOWAIT | M_ZERO);
338	if (!softc->tx_cp_rings) {
339		device_printf(iflib_get_dev(ctx),
340		    "unable to allocate TX completion rings\n");
341		rc = ENOMEM;
342		goto cp_alloc_fail;
343	}
344	softc->tx_rings = malloc(sizeof(struct bnxt_ring) * ntxqsets,
345	    M_DEVBUF, M_NOWAIT | M_ZERO);
346	if (!softc->tx_rings) {
347		device_printf(iflib_get_dev(ctx),
348		    "unable to allocate TX rings\n");
349		rc = ENOMEM;
350		goto ring_alloc_fail;
351	}
352	rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * ntxqsets,
353	    &softc->tx_stats, 0);
354	if (rc)
355		goto dma_alloc_fail;
356	bus_dmamap_sync(softc->tx_stats.idi_tag, softc->tx_stats.idi_map,
357	    BUS_DMASYNC_PREREAD);
358
359	for (i = 0; i < ntxqsets; i++) {
360		/* Set up the completion ring */
361		softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE;
362		softc->tx_cp_rings[i].ring.phys_id =
363		    (uint16_t)HWRM_NA_SIGNATURE;
364		softc->tx_cp_rings[i].ring.softc = softc;
365		softc->tx_cp_rings[i].ring.id =
366		    (softc->scctx->isc_nrxqsets * 2) + 1 + i;
367		softc->tx_cp_rings[i].ring.doorbell =
368		    softc->tx_cp_rings[i].ring.id * 0x80;
369		softc->tx_cp_rings[i].ring.ring_size =
370		    softc->scctx->isc_ntxd[0];
371		softc->tx_cp_rings[i].ring.vaddr = vaddrs[i * ntxqs];
372		softc->tx_cp_rings[i].ring.paddr = paddrs[i * ntxqs];
373
374		/* Set up the TX ring */
375		softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
376		softc->tx_rings[i].softc = softc;
377		softc->tx_rings[i].id =
378		    (softc->scctx->isc_nrxqsets * 2) + 1 + i;
379		softc->tx_rings[i].doorbell = softc->tx_rings[i].id * 0x80;
380		softc->tx_rings[i].ring_size = softc->scctx->isc_ntxd[1];
381		softc->tx_rings[i].vaddr = vaddrs[i * ntxqs + 1];
382		softc->tx_rings[i].paddr = paddrs[i * ntxqs + 1];
383
384		bnxt_create_tx_sysctls(softc, i);
385	}
386
387	softc->ntxqsets = ntxqsets;
388	return rc;
389
390dma_alloc_fail:
391	free(softc->tx_rings, M_DEVBUF);
392ring_alloc_fail:
393	free(softc->tx_cp_rings, M_DEVBUF);
394cp_alloc_fail:
395	return rc;
396}
397
398static void
399bnxt_queues_free(if_ctx_t ctx)
400{
401	struct bnxt_softc *softc = iflib_get_softc(ctx);
402
403	// Free TX queues
404	iflib_dma_free(&softc->tx_stats);
405	free(softc->tx_rings, M_DEVBUF);
406	softc->tx_rings = NULL;
407	free(softc->tx_cp_rings, M_DEVBUF);
408	softc->tx_cp_rings = NULL;
409	softc->ntxqsets = 0;
410
411	// Free RX queues
412	iflib_dma_free(&softc->rx_stats);
413	free(softc->grp_info, M_DEVBUF);
414	free(softc->ag_rings, M_DEVBUF);
415	free(softc->rx_rings, M_DEVBUF);
416	free(softc->rx_cp_rings, M_DEVBUF);
417}
418
419static int
420bnxt_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
421    uint64_t *paddrs, int nrxqs, int nrxqsets)
422{
423	struct bnxt_softc *softc;
424	int i;
425	int rc;
426
427	softc = iflib_get_softc(ctx);
428
429	softc->rx_cp_rings = malloc(sizeof(struct bnxt_cp_ring) * nrxqsets,
430	    M_DEVBUF, M_NOWAIT | M_ZERO);
431	if (!softc->rx_cp_rings) {
432		device_printf(iflib_get_dev(ctx),
433		    "unable to allocate RX completion rings\n");
434		rc = ENOMEM;
435		goto cp_alloc_fail;
436	}
437	softc->rx_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets,
438	    M_DEVBUF, M_NOWAIT | M_ZERO);
439	if (!softc->rx_rings) {
440		device_printf(iflib_get_dev(ctx),
441		    "unable to allocate RX rings\n");
442		rc = ENOMEM;
443		goto ring_alloc_fail;
444	}
445	softc->ag_rings = malloc(sizeof(struct bnxt_ring) * nrxqsets,
446	    M_DEVBUF, M_NOWAIT | M_ZERO);
447	if (!softc->ag_rings) {
448		device_printf(iflib_get_dev(ctx),
449		    "unable to allocate aggregation rings\n");
450		rc = ENOMEM;
451		goto ag_alloc_fail;
452	}
453	softc->grp_info = malloc(sizeof(struct bnxt_grp_info) * nrxqsets,
454	    M_DEVBUF, M_NOWAIT | M_ZERO);
455	if (!softc->grp_info) {
456		device_printf(iflib_get_dev(ctx),
457		    "unable to allocate ring groups\n");
458		rc = ENOMEM;
459		goto grp_alloc_fail;
460	}
461
462	rc = iflib_dma_alloc(ctx, sizeof(struct ctx_hw_stats) * nrxqsets,
463	    &softc->rx_stats, 0);
464	if (rc)
465		goto hw_stats_alloc_fail;
466	bus_dmamap_sync(softc->rx_stats.idi_tag, softc->rx_stats.idi_map,
467	    BUS_DMASYNC_PREREAD);
468
469	for (i = 0; i < nrxqsets; i++) {
470		/* Allocation the completion ring */
471		softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE;
472		softc->rx_cp_rings[i].ring.phys_id =
473		    (uint16_t)HWRM_NA_SIGNATURE;
474		softc->rx_cp_rings[i].ring.softc = softc;
475		softc->rx_cp_rings[i].ring.id = i + 1;
476		softc->rx_cp_rings[i].ring.doorbell =
477		    softc->rx_cp_rings[i].ring.id * 0x80;
478		/*
479		 * If this ring overflows, RX stops working.
480		 */
481		softc->rx_cp_rings[i].ring.ring_size =
482		    softc->scctx->isc_nrxd[0];
483		softc->rx_cp_rings[i].ring.vaddr = vaddrs[i * nrxqs];
484		softc->rx_cp_rings[i].ring.paddr = paddrs[i * nrxqs];
485
486		/* Allocate the RX ring */
487		softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
488		softc->rx_rings[i].softc = softc;
489		softc->rx_rings[i].id = i + 1;
490		softc->rx_rings[i].doorbell = softc->rx_rings[i].id * 0x80;
491		softc->rx_rings[i].ring_size = softc->scctx->isc_nrxd[1];
492		softc->rx_rings[i].vaddr = vaddrs[i * nrxqs + 1];
493		softc->rx_rings[i].paddr = paddrs[i * nrxqs + 1];
494
495		/* Allocate the AG ring */
496		softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
497		softc->ag_rings[i].softc = softc;
498		softc->ag_rings[i].id = nrxqsets + i + 1;
499		softc->ag_rings[i].doorbell = softc->ag_rings[i].id * 0x80;
500		softc->ag_rings[i].ring_size = softc->scctx->isc_nrxd[2];
501		softc->ag_rings[i].vaddr = vaddrs[i * nrxqs + 2];
502		softc->ag_rings[i].paddr = paddrs[i * nrxqs + 2];
503
504		/* Allocate the ring group */
505		softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE;
506		softc->grp_info[i].stats_ctx =
507		    softc->rx_cp_rings[i].stats_ctx_id;
508		softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id;
509		softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id;
510		softc->grp_info[i].cp_ring_id =
511		    softc->rx_cp_rings[i].ring.phys_id;
512
513		bnxt_create_rx_sysctls(softc, i);
514	}
515
516	/* And finally, the VNIC */
517	softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE;
518	softc->vnic_info.flow_id = (uint16_t)HWRM_NA_SIGNATURE;
519	softc->vnic_info.filter_id = -1;
520	softc->vnic_info.def_ring_grp = (uint16_t)HWRM_NA_SIGNATURE;
521	softc->vnic_info.cos_rule = (uint16_t)HWRM_NA_SIGNATURE;
522	softc->vnic_info.lb_rule = (uint16_t)HWRM_NA_SIGNATURE;
523	softc->vnic_info.rx_mask = HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_BCAST;
524	softc->vnic_info.mc_list_count = 0;
525	softc->vnic_info.flags = BNXT_VNIC_FLAG_DEFAULT;
526	rc = iflib_dma_alloc(ctx, BNXT_MAX_MC_ADDRS * ETHER_ADDR_LEN,
527	    &softc->vnic_info.mc_list, 0);
528	if (rc)
529		goto mc_list_alloc_fail;
530
531	/* The VNIC RSS Hash Key */
532	rc = iflib_dma_alloc(ctx, HW_HASH_KEY_SIZE,
533	    &softc->vnic_info.rss_hash_key_tbl, 0);
534	if (rc)
535		goto rss_hash_alloc_fail;
536	bus_dmamap_sync(softc->vnic_info.rss_hash_key_tbl.idi_tag,
537	    softc->vnic_info.rss_hash_key_tbl.idi_map,
538	    BUS_DMASYNC_PREWRITE);
539	memcpy(softc->vnic_info.rss_hash_key_tbl.idi_vaddr,
540	    softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE);
541
542	/* Allocate the RSS tables */
543	rc = iflib_dma_alloc(ctx, HW_HASH_INDEX_SIZE * sizeof(uint16_t),
544	    &softc->vnic_info.rss_grp_tbl, 0);
545	if (rc)
546		goto rss_grp_alloc_fail;
547	bus_dmamap_sync(softc->vnic_info.rss_grp_tbl.idi_tag,
548	    softc->vnic_info.rss_grp_tbl.idi_map,
549	    BUS_DMASYNC_PREWRITE);
550	memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff,
551	    softc->vnic_info.rss_grp_tbl.idi_size);
552
553	softc->nrxqsets = nrxqsets;
554	return rc;
555
556rss_grp_alloc_fail:
557	iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl);
558rss_hash_alloc_fail:
559	iflib_dma_free(&softc->vnic_info.mc_list);
560mc_list_alloc_fail:
561	iflib_dma_free(&softc->rx_stats);
562hw_stats_alloc_fail:
563	free(softc->grp_info, M_DEVBUF);
564grp_alloc_fail:
565	free(softc->ag_rings, M_DEVBUF);
566ag_alloc_fail:
567	free(softc->rx_rings, M_DEVBUF);
568ring_alloc_fail:
569	free(softc->rx_cp_rings, M_DEVBUF);
570cp_alloc_fail:
571	return rc;
572}
573
574/* Device setup and teardown */
575static int
576bnxt_attach_pre(if_ctx_t ctx)
577{
578	struct bnxt_softc *softc = iflib_get_softc(ctx);
579	if_softc_ctx_t scctx;
580	int rc = 0;
581
582	softc->ctx = ctx;
583	softc->dev = iflib_get_dev(ctx);
584	softc->media = iflib_get_media(ctx);
585	softc->scctx = iflib_get_softc_ctx(ctx);
586	softc->sctx = iflib_get_sctx(ctx);
587	scctx = softc->scctx;
588
589	/* TODO: Better way of detecting NPAR/VF is needed */
590	switch (softc->sctx->isc_vendor_info->pvi_device_id) {
591	case BCM57402_NPAR:
592	case BCM57404_NPAR:
593	case BCM57406_NPAR:
594	case BCM57407_NPAR:
595	case BCM57412_NPAR1:
596	case BCM57412_NPAR2:
597	case BCM57414_NPAR1:
598	case BCM57414_NPAR2:
599	case BCM57416_NPAR1:
600	case BCM57416_NPAR2:
601		softc->flags |= BNXT_FLAG_NPAR;
602		break;
603	case NETXTREME_C_VF1:
604	case NETXTREME_C_VF2:
605	case NETXTREME_C_VF3:
606	case NETXTREME_E_VF1:
607	case NETXTREME_E_VF2:
608	case NETXTREME_E_VF3:
609		softc->flags |= BNXT_FLAG_VF;
610		break;
611	}
612
613	pci_enable_busmaster(softc->dev);
614
615	if (bnxt_pci_mapping(softc))
616		return (ENXIO);
617
618	/* HWRM setup/init */
619	BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev));
620	rc = bnxt_alloc_hwrm_dma_mem(softc);
621	if (rc)
622		goto dma_fail;
623
624	/* Allocate the TPA start buffer */
625	softc->tpa_start = malloc(sizeof(struct bnxt_full_tpa_start) *
626	    (RX_TPA_START_CMPL_AGG_ID_MASK >> RX_TPA_START_CMPL_AGG_ID_SFT),
627	    M_DEVBUF, M_NOWAIT | M_ZERO);
628	if (softc->tpa_start == NULL) {
629		rc = ENOMEM;
630		device_printf(softc->dev,
631		    "Unable to allocate space for TPA\n");
632		goto tpa_failed;
633	}
634
635	/* Get firmware version and compare with driver */
636	softc->ver_info = malloc(sizeof(struct bnxt_ver_info),
637	    M_DEVBUF, M_NOWAIT | M_ZERO);
638	if (softc->ver_info == NULL) {
639		rc = ENOMEM;
640		device_printf(softc->dev,
641		    "Unable to allocate space for version info\n");
642		goto ver_alloc_fail;
643	}
644	/* Default minimum required HWRM version */
645	softc->ver_info->hwrm_min_major = 1;
646	softc->ver_info->hwrm_min_minor = 2;
647	softc->ver_info->hwrm_min_update = 2;
648
649	rc = bnxt_hwrm_ver_get(softc);
650	if (rc) {
651		device_printf(softc->dev, "attach: hwrm ver get failed\n");
652		goto ver_fail;
653	}
654
655	/* Get NVRAM info */
656	softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info),
657	    M_DEVBUF, M_NOWAIT | M_ZERO);
658	if (softc->nvm_info == NULL) {
659		rc = ENOMEM;
660		device_printf(softc->dev,
661		    "Unable to allocate space for NVRAM info\n");
662		goto nvm_alloc_fail;
663	}
664	rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id,
665	    &softc->nvm_info->device_id, &softc->nvm_info->sector_size,
666	    &softc->nvm_info->size, &softc->nvm_info->reserved_size,
667	    &softc->nvm_info->available_size);
668
669	/* Register the driver with the FW */
670	rc = bnxt_hwrm_func_drv_rgtr(softc);
671	if (rc) {
672		device_printf(softc->dev, "attach: hwrm drv rgtr failed\n");
673		goto drv_rgtr_fail;
674	}
675
676	/* Get the HW capabilities */
677	rc = bnxt_hwrm_func_qcaps(softc);
678	if (rc)
679		goto failed;
680	iflib_set_mac(ctx, softc->func.mac_addr);
681
682	/* Get the queue config */
683	rc = bnxt_hwrm_queue_qportcfg(softc);
684	if (rc) {
685		device_printf(softc->dev, "attach: hwrm qportcfg failed\n");
686		goto failed;
687	}
688
689	/* Now perform a function reset */
690	rc = bnxt_hwrm_func_reset(softc);
691	bnxt_clear_ids(softc);
692	if (rc)
693		goto failed;
694
695	/* Now set up iflib sc */
696	scctx->isc_tx_nsegments = 31,
697	scctx->isc_tx_tso_segments_max = 31;
698	scctx->isc_tx_tso_size_max = BNXT_TSO_SIZE;
699	scctx->isc_tx_tso_segsize_max = BNXT_TSO_SIZE;
700	scctx->isc_vectors = softc->func.max_cp_rings;
701	if (scctx->isc_nrxd[0] <
702	    ((scctx->isc_nrxd[1] * 4) + scctx->isc_nrxd[2]))
703		device_printf(softc->dev,
704		    "WARNING: nrxd0 (%d) should be at least 4 * nrxd1 (%d) + nrxd2 (%d).  Driver may be unstable\n",
705		    scctx->isc_nrxd[0], scctx->isc_nrxd[1], scctx->isc_nrxd[2]);
706	if (scctx->isc_ntxd[0] < scctx->isc_ntxd[1] * 2)
707		device_printf(softc->dev,
708		    "WARNING: ntxd0 (%d) should be at least 2 * ntxd1 (%d).  Driver may be unstable\n",
709		    scctx->isc_ntxd[0], scctx->isc_ntxd[1]);
710	scctx->isc_txqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_ntxd[0];
711	scctx->isc_txqsizes[1] = sizeof(struct tx_bd_short) *
712	    scctx->isc_ntxd[1];
713	scctx->isc_rxqsizes[0] = sizeof(struct cmpl_base) * scctx->isc_nrxd[0];
714	scctx->isc_rxqsizes[1] = sizeof(struct rx_prod_pkt_bd) *
715	    scctx->isc_nrxd[1];
716	scctx->isc_rxqsizes[2] = sizeof(struct rx_prod_pkt_bd) *
717	    scctx->isc_nrxd[2];
718	scctx->isc_max_rxqsets = min(pci_msix_count(softc->dev)-1,
719	    softc->func.max_cp_rings - 1);
720	scctx->isc_max_rxqsets = min(scctx->isc_max_rxqsets,
721	    softc->func.max_rx_rings);
722	scctx->isc_max_txqsets = min(softc->func.max_rx_rings,
723	    softc->func.max_cp_rings - scctx->isc_max_rxqsets - 1);
724	scctx->isc_rss_table_size = HW_HASH_INDEX_SIZE;
725	scctx->isc_rss_table_mask = scctx->isc_rss_table_size - 1;
726
727	/* iflib will map and release this bar */
728	scctx->isc_msix_bar = pci_msix_table_bar(softc->dev);
729
730	/* Allocate the default completion ring */
731	softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE;
732	softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE;
733	softc->def_cp_ring.ring.softc = softc;
734	softc->def_cp_ring.ring.id = 0;
735	softc->def_cp_ring.ring.doorbell = softc->def_cp_ring.ring.id * 0x80;
736	softc->def_cp_ring.ring.ring_size = PAGE_SIZE /
737	    sizeof(struct cmpl_base);
738	rc = iflib_dma_alloc(ctx,
739	    sizeof(struct cmpl_base) * softc->def_cp_ring.ring.ring_size,
740	    &softc->def_cp_ring_mem, 0);
741	softc->def_cp_ring.ring.vaddr = softc->def_cp_ring_mem.idi_vaddr;
742	softc->def_cp_ring.ring.paddr = softc->def_cp_ring_mem.idi_paddr;
743	iflib_config_gtask_init(ctx, &softc->def_cp_task, bnxt_def_cp_task,
744	    "dflt_cp");
745
746	rc = bnxt_init_sysctl_ctx(softc);
747	if (rc)
748		goto init_sysctl_failed;
749	rc = bnxt_create_nvram_sysctls(softc->nvm_info);
750	if (rc)
751		goto failed;
752
753	arc4rand(softc->vnic_info.rss_hash_key, HW_HASH_KEY_SIZE, 0);
754	softc->vnic_info.rss_hash_type =
755	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV4 |
756	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV4 |
757	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV4 |
758	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_IPV6 |
759	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_TCP_IPV6 |
760	    HWRM_VNIC_RSS_CFG_INPUT_HASH_TYPE_UDP_IPV6;
761	rc = bnxt_create_config_sysctls_pre(softc);
762	if (rc)
763		goto failed;
764
765	/* Initialize the vlan list */
766	SLIST_INIT(&softc->vnic_info.vlan_tags);
767	softc->vnic_info.vlan_tag_list.idi_vaddr = NULL;
768
769	return (rc);
770
771failed:
772	bnxt_free_sysctl_ctx(softc);
773init_sysctl_failed:
774	bnxt_hwrm_func_drv_unrgtr(softc, false);
775drv_rgtr_fail:
776	free(softc->nvm_info, M_DEVBUF);
777nvm_alloc_fail:
778ver_fail:
779	free(softc->ver_info, M_DEVBUF);
780ver_alloc_fail:
781	free(softc->tpa_start, M_DEVBUF);
782tpa_failed:
783	bnxt_free_hwrm_dma_mem(softc);
784dma_fail:
785	BNXT_HWRM_LOCK_DESTROY(softc);
786	bnxt_pci_mapping_free(softc);
787	pci_disable_busmaster(softc->dev);
788	return (rc);
789}
790
791static int
792bnxt_attach_post(if_ctx_t ctx)
793{
794	struct bnxt_softc *softc = iflib_get_softc(ctx);
795	if_t ifp = iflib_get_ifp(ctx);
796	int capabilities, enabling;
797	int rc;
798
799	bnxt_create_config_sysctls_post(softc);
800
801	/* Update link state etc... */
802	rc = bnxt_probe_phy(softc);
803	if (rc)
804		goto failed;
805
806	/* Needs to be done after probing the phy */
807	bnxt_create_ver_sysctls(softc);
808	bnxt_add_media_types(softc);
809	ifmedia_set(softc->media, IFM_ETHER | IFM_AUTO);
810
811	if_sethwassist(ifp, (CSUM_TCP | CSUM_UDP | CSUM_TCP_IPV6 |
812	    CSUM_UDP_IPV6 | CSUM_TSO));
813
814	capabilities =
815	    /* These are translated to hwassit bits */
816	    IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_TSO4 | IFCAP_TSO6 |
817	    /* These are checked by iflib */
818	    IFCAP_LRO | IFCAP_VLAN_HWFILTER |
819	    /* These are part of the iflib mask */
820	    IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_VLAN_MTU |
821	    IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWTSO |
822	    /* These likely get lost... */
823	    IFCAP_VLAN_HWCSUM | IFCAP_JUMBO_MTU;
824
825	if_setcapabilities(ifp, capabilities);
826
827	enabling = capabilities;
828
829	if_setcapenable(ifp, enabling);
830
831	softc->scctx->isc_max_frame_size = ifp->if_mtu + ETHER_HDR_LEN +
832	    ETHER_CRC_LEN;
833
834failed:
835	return rc;
836}
837
838static int
839bnxt_detach(if_ctx_t ctx)
840{
841	struct bnxt_softc *softc = iflib_get_softc(ctx);
842	struct bnxt_vlan_tag *tag;
843	struct bnxt_vlan_tag *tmp;
844	int i;
845
846	bnxt_do_disable_intr(&softc->def_cp_ring);
847	bnxt_free_sysctl_ctx(softc);
848	bnxt_hwrm_func_reset(softc);
849	bnxt_clear_ids(softc);
850	iflib_irq_free(ctx, &softc->def_cp_ring.irq);
851	iflib_config_gtask_deinit(&softc->def_cp_task);
852	/* We need to free() these here... */
853	for (i = softc->nrxqsets-1; i>=0; i--) {
854		iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq);
855	}
856	iflib_dma_free(&softc->vnic_info.mc_list);
857	iflib_dma_free(&softc->vnic_info.rss_hash_key_tbl);
858	iflib_dma_free(&softc->vnic_info.rss_grp_tbl);
859	if (softc->vnic_info.vlan_tag_list.idi_vaddr)
860		iflib_dma_free(&softc->vnic_info.vlan_tag_list);
861	SLIST_FOREACH_SAFE(tag, &softc->vnic_info.vlan_tags, next, tmp)
862		free(tag, M_DEVBUF);
863	iflib_dma_free(&softc->def_cp_ring_mem);
864	free(softc->tpa_start, M_DEVBUF);
865	free(softc->ver_info, M_DEVBUF);
866	free(softc->nvm_info, M_DEVBUF);
867
868	bnxt_hwrm_func_drv_unrgtr(softc, false);
869	bnxt_free_hwrm_dma_mem(softc);
870	BNXT_HWRM_LOCK_DESTROY(softc);
871
872	pci_disable_busmaster(softc->dev);
873	bnxt_pci_mapping_free(softc);
874
875	return 0;
876}
877
878/* Device configuration */
879static void
880bnxt_init(if_ctx_t ctx)
881{
882	struct bnxt_softc *softc = iflib_get_softc(ctx);
883	struct ifmediareq ifmr;
884	int i, j;
885	int rc;
886
887	rc = bnxt_hwrm_func_reset(softc);
888	if (rc)
889		return;
890	bnxt_clear_ids(softc);
891
892	/* Allocate the default completion ring */
893	softc->def_cp_ring.cons = UINT32_MAX;
894	softc->def_cp_ring.v_bit = 1;
895	bnxt_mark_cpr_invalid(&softc->def_cp_ring);
896	rc = bnxt_hwrm_ring_alloc(softc,
897	    HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL,
898	    &softc->def_cp_ring.ring,
899	    (uint16_t)HWRM_NA_SIGNATURE,
900	    HWRM_NA_SIGNATURE, true);
901	if (rc)
902		goto fail;
903
904	/* And now set the default CP ring as the async CP ring */
905	rc = bnxt_hwrm_func_cfg(softc);
906	if (rc)
907		goto fail;
908
909	for (i = 0; i < softc->nrxqsets; i++) {
910		/* Allocate the statistics context */
911		rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->rx_cp_rings[i],
912		    softc->rx_stats.idi_paddr +
913		    (sizeof(struct ctx_hw_stats) * i));
914		if (rc)
915			goto fail;
916
917		/* Allocate the completion ring */
918		softc->rx_cp_rings[i].cons = UINT32_MAX;
919		softc->rx_cp_rings[i].v_bit = 1;
920		softc->rx_cp_rings[i].last_idx = UINT32_MAX;
921		bnxt_mark_cpr_invalid(&softc->rx_cp_rings[i]);
922		rc = bnxt_hwrm_ring_alloc(softc,
923		    HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL,
924		    &softc->rx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE,
925		    HWRM_NA_SIGNATURE, true);
926		if (rc)
927			goto fail;
928
929		/* Allocate the RX ring */
930		rc = bnxt_hwrm_ring_alloc(softc,
931		    HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
932		    &softc->rx_rings[i], (uint16_t)HWRM_NA_SIGNATURE,
933		    HWRM_NA_SIGNATURE, false);
934		if (rc)
935			goto fail;
936		BNXT_RX_DB(&softc->rx_rings[i], 0);
937		/* TODO: Cumulus+ doesn't need the double doorbell */
938		BNXT_RX_DB(&softc->rx_rings[i], 0);
939
940		/* Allocate the AG ring */
941		rc = bnxt_hwrm_ring_alloc(softc,
942		    HWRM_RING_ALLOC_INPUT_RING_TYPE_RX,
943		    &softc->ag_rings[i], (uint16_t)HWRM_NA_SIGNATURE,
944		    HWRM_NA_SIGNATURE, false);
945		if (rc)
946			goto fail;
947		BNXT_RX_DB(&softc->rx_rings[i], 0);
948		/* TODO: Cumulus+ doesn't need the double doorbell */
949		BNXT_RX_DB(&softc->ag_rings[i], 0);
950
951		/* Allocate the ring group */
952		softc->grp_info[i].stats_ctx =
953		    softc->rx_cp_rings[i].stats_ctx_id;
954		softc->grp_info[i].rx_ring_id = softc->rx_rings[i].phys_id;
955		softc->grp_info[i].ag_ring_id = softc->ag_rings[i].phys_id;
956		softc->grp_info[i].cp_ring_id =
957		    softc->rx_cp_rings[i].ring.phys_id;
958		rc = bnxt_hwrm_ring_grp_alloc(softc, &softc->grp_info[i]);
959		if (rc)
960			goto fail;
961
962	}
963
964	/* Allocate the VNIC RSS context */
965	rc = bnxt_hwrm_vnic_ctx_alloc(softc, &softc->vnic_info.rss_id);
966	if (rc)
967		goto fail;
968
969	/* Allocate the vnic */
970	softc->vnic_info.def_ring_grp = softc->grp_info[0].grp_id;
971	softc->vnic_info.mru = softc->scctx->isc_max_frame_size;
972	rc = bnxt_hwrm_vnic_alloc(softc, &softc->vnic_info);
973	if (rc)
974		goto fail;
975	rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info);
976	if (rc)
977		goto fail;
978	rc = bnxt_hwrm_set_filter(softc, &softc->vnic_info);
979	if (rc)
980		goto fail;
981
982	/* Enable RSS on the VNICs */
983	for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++) {
984		((uint16_t *)
985		    softc->vnic_info.rss_grp_tbl.idi_vaddr)[i] =
986		    htole16(softc->grp_info[j].grp_id);
987		if (++j == softc->nrxqsets)
988			j = 0;
989	}
990
991	rc = bnxt_hwrm_rss_cfg(softc, &softc->vnic_info,
992	    softc->vnic_info.rss_hash_type);
993	if (rc)
994		goto fail;
995
996#ifdef notyet
997	/* Enable LRO/TPA/GRO */
998	rc = bnxt_hwrm_vnic_tpa_cfg(softc, &softc->vnic_info,
999	    (if_getcapenable(iflib_get_ifp(ctx)) & IFCAP_LRO) ?
1000	    HWRM_VNIC_TPA_CFG_INPUT_FLAGS_TPA : 0);
1001	if (rc)
1002		goto fail;
1003#endif
1004
1005	for (i = 0; i < softc->ntxqsets; i++) {
1006		/* Allocate the statistics context */
1007		rc = bnxt_hwrm_stat_ctx_alloc(softc, &softc->tx_cp_rings[i],
1008		    softc->tx_stats.idi_paddr +
1009		    (sizeof(struct ctx_hw_stats) * i));
1010		if (rc)
1011			goto fail;
1012
1013		/* Allocate the completion ring */
1014		softc->tx_cp_rings[i].cons = UINT32_MAX;
1015		softc->tx_cp_rings[i].v_bit = 1;
1016		bnxt_mark_cpr_invalid(&softc->tx_cp_rings[i]);
1017		rc = bnxt_hwrm_ring_alloc(softc,
1018		    HWRM_RING_ALLOC_INPUT_RING_TYPE_CMPL,
1019		    &softc->tx_cp_rings[i].ring, (uint16_t)HWRM_NA_SIGNATURE,
1020		    HWRM_NA_SIGNATURE, false);
1021		if (rc)
1022			goto fail;
1023
1024		/* Allocate the TX ring */
1025		rc = bnxt_hwrm_ring_alloc(softc,
1026		    HWRM_RING_ALLOC_INPUT_RING_TYPE_TX,
1027		    &softc->tx_rings[i], softc->tx_cp_rings[i].ring.phys_id,
1028		    softc->tx_cp_rings[i].stats_ctx_id, false);
1029		if (rc)
1030			goto fail;
1031		BNXT_TX_DB(&softc->tx_rings[i], 0);
1032		/* TODO: Cumulus+ doesn't need the double doorbell */
1033		BNXT_TX_DB(&softc->tx_rings[i], 0);
1034	}
1035
1036	bnxt_do_enable_intr(&softc->def_cp_ring);
1037	bnxt_media_status(softc->ctx, &ifmr);
1038	return;
1039
1040fail:
1041	bnxt_hwrm_func_reset(softc);
1042	bnxt_clear_ids(softc);
1043	return;
1044}
1045
1046static void
1047bnxt_stop(if_ctx_t ctx)
1048{
1049	struct bnxt_softc *softc = iflib_get_softc(ctx);
1050
1051	bnxt_do_disable_intr(&softc->def_cp_ring);
1052	bnxt_hwrm_func_reset(softc);
1053	bnxt_clear_ids(softc);
1054	return;
1055}
1056
1057static void
1058bnxt_multi_set(if_ctx_t ctx)
1059{
1060	struct bnxt_softc *softc = iflib_get_softc(ctx);
1061	if_t ifp = iflib_get_ifp(ctx);
1062	uint8_t *mta;
1063	int cnt, mcnt;
1064
1065	mcnt = if_multiaddr_count(ifp, -1);
1066
1067	if (mcnt > BNXT_MAX_MC_ADDRS) {
1068		softc->vnic_info.rx_mask |=
1069		    HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
1070		bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info);
1071	}
1072	else {
1073		softc->vnic_info.rx_mask &=
1074		    ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
1075		mta = softc->vnic_info.mc_list.idi_vaddr;
1076		bzero(mta, softc->vnic_info.mc_list.idi_size);
1077		if_multiaddr_array(ifp, mta, &cnt, mcnt);
1078		bus_dmamap_sync(softc->vnic_info.mc_list.idi_tag,
1079		    softc->vnic_info.mc_list.idi_map, BUS_DMASYNC_PREWRITE);
1080		softc->vnic_info.mc_list_count = cnt;
1081		softc->vnic_info.rx_mask |=
1082		    HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_MCAST;
1083		if (bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info))
1084			device_printf(softc->dev,
1085			    "set_multi: rx_mask set failed\n");
1086	}
1087}
1088
1089static int
1090bnxt_mtu_set(if_ctx_t ctx, uint32_t mtu)
1091{
1092	struct bnxt_softc *softc = iflib_get_softc(ctx);
1093
1094	if (mtu > BNXT_MAX_MTU)
1095		return EINVAL;
1096
1097	softc->scctx->isc_max_frame_size = mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
1098	return 0;
1099}
1100
1101static void
1102bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr)
1103{
1104	struct bnxt_softc *softc = iflib_get_softc(ctx);
1105	struct bnxt_link_info *link_info = &softc->link_info;
1106	uint8_t phy_type = get_phy_type(softc);
1107
1108	bnxt_update_link(softc, true);
1109
1110	ifmr->ifm_status = IFM_AVALID;
1111	ifmr->ifm_active = IFM_ETHER;
1112
1113	if (link_info->link_up)
1114		ifmr->ifm_status |= IFM_ACTIVE;
1115	else
1116		ifmr->ifm_status &= ~IFM_ACTIVE;
1117
1118	if (link_info->duplex == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL)
1119		ifmr->ifm_active |= IFM_FDX;
1120	else
1121		ifmr->ifm_active |= IFM_HDX;
1122
1123	switch (link_info->link_speed) {
1124	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB:
1125		ifmr->ifm_active |= IFM_100_T;
1126		break;
1127	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB:
1128		switch (phy_type) {
1129		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
1130			ifmr->ifm_active |= IFM_1000_KX;
1131			break;
1132		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
1133			ifmr->ifm_active |= IFM_1000_T;
1134			break;
1135		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY:
1136			ifmr->ifm_active |= IFM_1000_SGMII;
1137			break;
1138		default:
1139			ifmr->ifm_active |= IFM_UNKNOWN;
1140			break;
1141		}
1142	break;
1143	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB:
1144		switch (phy_type) {
1145		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
1146			ifmr->ifm_active |= IFM_2500_KX;
1147			break;
1148		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
1149			ifmr->ifm_active |= IFM_2500_T;
1150			break;
1151		default:
1152			ifmr->ifm_active |= IFM_UNKNOWN;
1153			break;
1154		}
1155		break;
1156	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB:
1157		switch (phy_type) {
1158		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
1159			ifmr->ifm_active |= IFM_10G_CR1;
1160			break;
1161		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
1162		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
1163		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
1164			ifmr->ifm_active |= IFM_10G_KR;
1165			break;
1166		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
1167			ifmr->ifm_active |= IFM_10G_LR;
1168			break;
1169		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
1170			ifmr->ifm_active |= IFM_10G_SR;
1171			break;
1172		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
1173			ifmr->ifm_active |= IFM_10G_KX4;
1174			break;
1175		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
1176			ifmr->ifm_active |= IFM_10G_T;
1177			break;
1178		default:
1179			ifmr->ifm_active |= IFM_UNKNOWN;
1180			break;
1181		}
1182		break;
1183	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB:
1184		ifmr->ifm_active |= IFM_20G_KR2;
1185		break;
1186	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB:
1187		switch (phy_type) {
1188		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
1189			ifmr->ifm_active |= IFM_25G_CR;
1190			break;
1191		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
1192		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
1193		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
1194			ifmr->ifm_active |= IFM_25G_KR;
1195			break;
1196		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
1197			ifmr->ifm_active |= IFM_25G_SR;
1198			break;
1199		default:
1200			ifmr->ifm_active |= IFM_UNKNOWN;
1201			break;
1202		}
1203		break;
1204	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB:
1205		switch (phy_type) {
1206		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
1207			ifmr->ifm_active |= IFM_40G_CR4;
1208			break;
1209		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
1210		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
1211		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
1212			ifmr->ifm_active |= IFM_40G_KR4;
1213			break;
1214		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
1215			ifmr->ifm_active |= IFM_40G_LR4;
1216			break;
1217		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
1218			ifmr->ifm_active |= IFM_40G_SR4;
1219			break;
1220		default:
1221			ifmr->ifm_active |= IFM_UNKNOWN;
1222			break;
1223		}
1224		break;
1225	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB:
1226		switch (phy_type) {
1227		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
1228			ifmr->ifm_active |= IFM_50G_CR2;
1229			break;
1230		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
1231		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
1232		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
1233			ifmr->ifm_active |= IFM_50G_KR2;
1234			break;
1235		default:
1236			ifmr->ifm_active |= IFM_UNKNOWN;
1237			break;
1238		}
1239		break;
1240	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB:
1241		switch (phy_type) {
1242		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
1243			ifmr->ifm_active |= IFM_100G_CR4;
1244			break;
1245		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
1246		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
1247		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
1248			ifmr->ifm_active |= IFM_100G_KR4;
1249			break;
1250		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
1251			ifmr->ifm_active |= IFM_100G_LR4;
1252			break;
1253		case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
1254			ifmr->ifm_active |= IFM_100G_SR4;
1255			break;
1256		default:
1257			ifmr->ifm_active |= IFM_UNKNOWN;
1258			break;
1259		}
1260	default:
1261		return;
1262	}
1263
1264	if (link_info->pause == (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
1265	    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX))
1266		ifmr->ifm_active |= (IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE);
1267	else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
1268		ifmr->ifm_active |= IFM_ETH_TXPAUSE;
1269	else if (link_info->pause == HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
1270		ifmr->ifm_active |= IFM_ETH_RXPAUSE;
1271
1272	bnxt_report_link(softc);
1273	return;
1274}
1275
1276static int
1277bnxt_media_change(if_ctx_t ctx)
1278{
1279	struct bnxt_softc *softc = iflib_get_softc(ctx);
1280	struct ifmedia *ifm = iflib_get_media(ctx);
1281	struct ifmediareq ifmr;
1282	int rc;
1283
1284	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1285		return EINVAL;
1286
1287	switch (IFM_SUBTYPE(ifm->ifm_media)) {
1288	case IFM_100_T:
1289		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1290		softc->link_info.req_link_speed =
1291		    HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100MB;
1292		break;
1293	case IFM_1000_KX:
1294	case IFM_1000_T:
1295	case IFM_1000_SGMII:
1296		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1297		softc->link_info.req_link_speed =
1298		    HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_1GB;
1299		break;
1300	case IFM_2500_KX:
1301	case IFM_2500_T:
1302		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1303		softc->link_info.req_link_speed =
1304		    HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_2_5GB;
1305		break;
1306	case IFM_10G_CR1:
1307	case IFM_10G_KR:
1308	case IFM_10G_LR:
1309	case IFM_10G_SR:
1310	case IFM_10G_T:
1311		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1312		softc->link_info.req_link_speed =
1313		    HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_10GB;
1314		break;
1315	case IFM_20G_KR2:
1316		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1317		softc->link_info.req_link_speed =
1318		    HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_20GB;
1319		break;
1320	case IFM_25G_CR:
1321	case IFM_25G_KR:
1322	case IFM_25G_SR:
1323		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1324		softc->link_info.req_link_speed =
1325		    HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_25GB;
1326		break;
1327	case IFM_40G_CR4:
1328	case IFM_40G_KR4:
1329	case IFM_40G_LR4:
1330	case IFM_40G_SR4:
1331		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1332		softc->link_info.req_link_speed =
1333		    HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_40GB;
1334		break;
1335	case IFM_50G_CR2:
1336	case IFM_50G_KR2:
1337		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1338		softc->link_info.req_link_speed =
1339		    HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_50GB;
1340		break;
1341	case IFM_100G_CR4:
1342	case IFM_100G_KR4:
1343	case IFM_100G_LR4:
1344	case IFM_100G_SR4:
1345		softc->link_info.autoneg &= ~BNXT_AUTONEG_SPEED;
1346		softc->link_info.req_link_speed =
1347			HWRM_PORT_PHY_CFG_INPUT_FORCE_LINK_SPEED_100GB;
1348		break;
1349	default:
1350		device_printf(softc->dev,
1351		    "Unsupported media type!  Using auto\n");
1352		/* Fall-through */
1353	case IFM_AUTO:
1354		// Auto
1355		softc->link_info.autoneg |= BNXT_AUTONEG_SPEED;
1356		break;
1357	}
1358	rc = bnxt_hwrm_set_link_setting(softc, true, true);
1359	bnxt_media_status(softc->ctx, &ifmr);
1360	return rc;
1361}
1362
1363static int
1364bnxt_promisc_set(if_ctx_t ctx, int flags)
1365{
1366	struct bnxt_softc *softc = iflib_get_softc(ctx);
1367	if_t ifp = iflib_get_ifp(ctx);
1368	int rc;
1369
1370	if (ifp->if_flags & IFF_ALLMULTI ||
1371	    if_multiaddr_count(ifp, -1) > BNXT_MAX_MC_ADDRS)
1372		softc->vnic_info.rx_mask |=
1373		    HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
1374	else
1375		softc->vnic_info.rx_mask &=
1376		    ~HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ALL_MCAST;
1377
1378	if (ifp->if_flags & IFF_PROMISC)
1379		softc->vnic_info.rx_mask |=
1380		    HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS |
1381		    HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN;
1382	else
1383		softc->vnic_info.rx_mask &=
1384		    ~(HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_PROMISCUOUS |
1385		    HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN);
1386
1387	rc = bnxt_hwrm_cfa_l2_set_rx_mask(softc, &softc->vnic_info);
1388
1389	return rc;
1390}
1391
1392static uint64_t
1393bnxt_get_counter(if_ctx_t ctx, ift_counter cnt)
1394{
1395	if_t ifp = iflib_get_ifp(ctx);
1396
1397	if (cnt < IFCOUNTERS)
1398		return if_get_counter_default(ifp, cnt);
1399
1400	return 0;
1401}
1402
1403static void
1404bnxt_update_admin_status(if_ctx_t ctx)
1405{
1406	/* TODO: do we need to do anything here? */
1407	return;
1408}
1409
1410static void inline
1411bnxt_do_enable_intr(struct bnxt_cp_ring *cpr)
1412{
1413	if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE) {
1414		/* First time enabling, do not set index */
1415		if (cpr->cons == UINT32_MAX)
1416			BNXT_CP_ENABLE_DB(&cpr->ring);
1417		else
1418			BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons);
1419	}
1420}
1421
1422static void inline
1423bnxt_do_disable_intr(struct bnxt_cp_ring *cpr)
1424{
1425	if (cpr->ring.phys_id != (uint16_t)HWRM_NA_SIGNATURE)
1426		BNXT_CP_DISABLE_DB(&cpr->ring);
1427}
1428
1429/* Enable all interrupts */
1430static void
1431bnxt_intr_enable(if_ctx_t ctx)
1432{
1433	struct bnxt_softc *softc = iflib_get_softc(ctx);
1434	int i;
1435
1436	bnxt_do_enable_intr(&softc->def_cp_ring);
1437	for (i = 0; i < softc->nrxqsets; i++)
1438		bnxt_do_enable_intr(&softc->rx_cp_rings[i]);
1439
1440	return;
1441}
1442
1443/* Enable interrupt for a single queue */
1444static int
1445bnxt_queue_intr_enable(if_ctx_t ctx, uint16_t qid)
1446{
1447	struct bnxt_softc *softc = iflib_get_softc(ctx);
1448
1449	bnxt_do_enable_intr(&softc->rx_cp_rings[qid]);
1450	return 0;
1451}
1452
1453/* Disable all interrupts */
1454static void
1455bnxt_disable_intr(if_ctx_t ctx)
1456{
1457	struct bnxt_softc *softc = iflib_get_softc(ctx);
1458	int i;
1459
1460	/*
1461	 * NOTE: These TX interrupts should never get enabled, so don't
1462	 * update the index
1463	 */
1464	for (i = 0; i < softc->ntxqsets; i++)
1465		bnxt_do_disable_intr(&softc->tx_cp_rings[i]);
1466	for (i = 0; i < softc->nrxqsets; i++)
1467		bnxt_do_disable_intr(&softc->rx_cp_rings[i]);
1468
1469	return;
1470}
1471
1472static int
1473bnxt_msix_intr_assign(if_ctx_t ctx, int msix)
1474{
1475	struct bnxt_softc *softc = iflib_get_softc(ctx);
1476	int rc;
1477	int i;
1478
1479	rc = iflib_irq_alloc_generic(ctx, &softc->def_cp_ring.irq,
1480	    softc->def_cp_ring.ring.id + 1, IFLIB_INTR_ADMIN,
1481	    bnxt_handle_def_cp, softc, 0, "def_cp");
1482	if (rc) {
1483		device_printf(iflib_get_dev(ctx),
1484		    "Failed to register default completion ring handler\n");
1485		return rc;
1486	}
1487
1488	for (i=0; i<softc->scctx->isc_nrxqsets; i++) {
1489		rc = iflib_irq_alloc_generic(ctx, &softc->rx_cp_rings[i].irq,
1490		    softc->rx_cp_rings[i].ring.id + 1, IFLIB_INTR_RX,
1491		    bnxt_handle_rx_cp, &softc->rx_cp_rings[i], i, "rx_cp");
1492		if (rc) {
1493			device_printf(iflib_get_dev(ctx),
1494			    "Failed to register RX completion ring handler\n");
1495			i--;
1496			goto fail;
1497		}
1498	}
1499
1500	for (i=0; i<softc->scctx->isc_ntxqsets; i++)
1501		iflib_softirq_alloc_generic(ctx, i + 1, IFLIB_INTR_TX, NULL, i,
1502		    "tx_cp");
1503
1504	return rc;
1505
1506fail:
1507	for (; i>=0; i--)
1508		iflib_irq_free(ctx, &softc->rx_cp_rings[i].irq);
1509	iflib_irq_free(ctx, &softc->def_cp_ring.irq);
1510	return rc;
1511}
1512
1513/*
1514 * We're explicitly allowing duplicates here.  They will need to be
1515 * removed as many times as they are added.
1516 */
1517static void
1518bnxt_vlan_register(if_ctx_t ctx, uint16_t vtag)
1519{
1520	struct bnxt_softc *softc = iflib_get_softc(ctx);
1521	struct bnxt_vlan_tag *new_tag;
1522
1523	new_tag = malloc(sizeof(struct bnxt_vlan_tag), M_DEVBUF, M_NOWAIT);
1524	if (new_tag == NULL)
1525		return;
1526	new_tag->tag = vtag;
1527	new_tag->tpid = 8100;
1528	SLIST_INSERT_HEAD(&softc->vnic_info.vlan_tags, new_tag, next);
1529};
1530
1531static void
1532bnxt_vlan_unregister(if_ctx_t ctx, uint16_t vtag)
1533{
1534	struct bnxt_softc *softc = iflib_get_softc(ctx);
1535	struct bnxt_vlan_tag *vlan_tag;
1536
1537	SLIST_FOREACH(vlan_tag, &softc->vnic_info.vlan_tags, next) {
1538		if (vlan_tag->tag == vtag) {
1539			SLIST_REMOVE(&softc->vnic_info.vlan_tags, vlan_tag,
1540			    bnxt_vlan_tag, next);
1541			free(vlan_tag, M_DEVBUF);
1542			break;
1543		}
1544	}
1545}
1546
1547static int
1548bnxt_priv_ioctl(if_ctx_t ctx, u_long command, caddr_t data)
1549{
1550	struct bnxt_softc *softc = iflib_get_softc(ctx);
1551	struct ifreq *ifr = (struct ifreq *)data;
1552	struct ifreq_buffer *ifbuf = &ifr->ifr_ifru.ifru_buffer;
1553	struct bnxt_ioctl_header *ioh =
1554	    (struct bnxt_ioctl_header *)(ifbuf->buffer);
1555	int rc = ENOTSUP;
1556	struct bnxt_ioctl_data *iod = NULL;
1557
1558	switch (command) {
1559	case SIOCGPRIVATE_0:
1560		if ((rc = priv_check(curthread, PRIV_DRIVER)) != 0)
1561			goto exit;
1562
1563		iod = malloc(ifbuf->length, M_DEVBUF, M_NOWAIT | M_ZERO);
1564		if (!iod) {
1565			rc = ENOMEM;
1566			goto exit;
1567		}
1568		copyin(ioh, iod, ifbuf->length);
1569
1570		switch (ioh->type) {
1571		case BNXT_HWRM_NVM_FIND_DIR_ENTRY:
1572		{
1573			struct bnxt_ioctl_hwrm_nvm_find_dir_entry *find =
1574			    &iod->find;
1575
1576			rc = bnxt_hwrm_nvm_find_dir_entry(softc, find->type,
1577			    &find->ordinal, find->ext, &find->index,
1578			    find->use_index, find->search_opt,
1579			    &find->data_length, &find->item_length,
1580			    &find->fw_ver);
1581			if (rc) {
1582				iod->hdr.rc = rc;
1583				copyout(&iod->hdr.rc, &ioh->rc,
1584				    sizeof(ioh->rc));
1585			}
1586			else {
1587				iod->hdr.rc = 0;
1588				copyout(iod, ioh, ifbuf->length);
1589			}
1590
1591			rc = 0;
1592			goto exit;
1593		}
1594		case BNXT_HWRM_NVM_READ:
1595		{
1596			struct bnxt_ioctl_hwrm_nvm_read *rd = &iod->read;
1597			struct iflib_dma_info dma_data;
1598			size_t offset;
1599			size_t remain;
1600			size_t csize;
1601
1602			/*
1603			 * Some HWRM versions can't read more than 0x8000 bytes
1604			 */
1605			rc = iflib_dma_alloc(softc->ctx,
1606			    min(rd->length, 0x8000), &dma_data, BUS_DMA_NOWAIT);
1607			if (rc)
1608				break;
1609			for (remain = rd->length, offset = 0;
1610			    remain && offset < rd->length; offset += 0x8000) {
1611				csize = min(remain, 0x8000);
1612				rc = bnxt_hwrm_nvm_read(softc, rd->index,
1613				    rd->offset + offset, csize, &dma_data);
1614				if (rc) {
1615					iod->hdr.rc = rc;
1616					copyout(&iod->hdr.rc, &ioh->rc,
1617					    sizeof(ioh->rc));
1618					break;
1619				}
1620				else {
1621					copyout(dma_data.idi_vaddr,
1622					    rd->data + offset, csize);
1623					iod->hdr.rc = 0;
1624				}
1625				remain -= csize;
1626			}
1627			if (iod->hdr.rc == 0)
1628				copyout(iod, ioh, ifbuf->length);
1629
1630			iflib_dma_free(&dma_data);
1631			rc = 0;
1632			goto exit;
1633		}
1634		case BNXT_HWRM_FW_RESET:
1635		{
1636			struct bnxt_ioctl_hwrm_fw_reset *rst =
1637			    &iod->reset;
1638
1639			rc = bnxt_hwrm_fw_reset(softc, rst->processor,
1640			    &rst->selfreset);
1641			if (rc) {
1642				iod->hdr.rc = rc;
1643				copyout(&iod->hdr.rc, &ioh->rc,
1644				    sizeof(ioh->rc));
1645			}
1646			else {
1647				iod->hdr.rc = 0;
1648				copyout(iod, ioh, ifbuf->length);
1649			}
1650
1651			rc = 0;
1652			goto exit;
1653		}
1654		case BNXT_HWRM_FW_QSTATUS:
1655		{
1656			struct bnxt_ioctl_hwrm_fw_qstatus *qstat =
1657			    &iod->status;
1658
1659			rc = bnxt_hwrm_fw_qstatus(softc, qstat->processor,
1660			    &qstat->selfreset);
1661			if (rc) {
1662				iod->hdr.rc = rc;
1663				copyout(&iod->hdr.rc, &ioh->rc,
1664				    sizeof(ioh->rc));
1665			}
1666			else {
1667				iod->hdr.rc = 0;
1668				copyout(iod, ioh, ifbuf->length);
1669			}
1670
1671			rc = 0;
1672			goto exit;
1673		}
1674		case BNXT_HWRM_NVM_WRITE:
1675		{
1676			struct bnxt_ioctl_hwrm_nvm_write *wr =
1677			    &iod->write;
1678
1679			rc = bnxt_hwrm_nvm_write(softc, wr->data, true,
1680			    wr->type, wr->ordinal, wr->ext, wr->attr,
1681			    wr->option, wr->data_length, wr->keep,
1682			    &wr->item_length, &wr->index);
1683			if (rc) {
1684				iod->hdr.rc = rc;
1685				copyout(&iod->hdr.rc, &ioh->rc,
1686				    sizeof(ioh->rc));
1687			}
1688			else {
1689				iod->hdr.rc = 0;
1690				copyout(iod, ioh, ifbuf->length);
1691			}
1692
1693			rc = 0;
1694			goto exit;
1695		}
1696		case BNXT_HWRM_NVM_ERASE_DIR_ENTRY:
1697		{
1698			struct bnxt_ioctl_hwrm_nvm_erase_dir_entry *erase =
1699			    &iod->erase;
1700
1701			rc = bnxt_hwrm_nvm_erase_dir_entry(softc, erase->index);
1702			if (rc) {
1703				iod->hdr.rc = rc;
1704				copyout(&iod->hdr.rc, &ioh->rc,
1705				    sizeof(ioh->rc));
1706			}
1707			else {
1708				iod->hdr.rc = 0;
1709				copyout(iod, ioh, ifbuf->length);
1710			}
1711
1712			rc = 0;
1713			goto exit;
1714		}
1715		case BNXT_HWRM_NVM_GET_DIR_INFO:
1716		{
1717			struct bnxt_ioctl_hwrm_nvm_get_dir_info *info =
1718			    &iod->dir_info;
1719
1720			rc = bnxt_hwrm_nvm_get_dir_info(softc, &info->entries,
1721			    &info->entry_length);
1722			if (rc) {
1723				iod->hdr.rc = rc;
1724				copyout(&iod->hdr.rc, &ioh->rc,
1725				    sizeof(ioh->rc));
1726			}
1727			else {
1728				iod->hdr.rc = 0;
1729				copyout(iod, ioh, ifbuf->length);
1730			}
1731
1732			rc = 0;
1733			goto exit;
1734		}
1735		case BNXT_HWRM_NVM_GET_DIR_ENTRIES:
1736		{
1737			struct bnxt_ioctl_hwrm_nvm_get_dir_entries *get =
1738			    &iod->dir_entries;
1739			struct iflib_dma_info dma_data;
1740
1741			rc = iflib_dma_alloc(softc->ctx, get->max_size,
1742			    &dma_data, BUS_DMA_NOWAIT);
1743			if (rc)
1744				break;
1745			rc = bnxt_hwrm_nvm_get_dir_entries(softc, &get->entries,
1746			    &get->entry_length, &dma_data);
1747			if (rc) {
1748				iod->hdr.rc = rc;
1749				copyout(&iod->hdr.rc, &ioh->rc,
1750				    sizeof(ioh->rc));
1751			}
1752			else {
1753				copyout(dma_data.idi_vaddr, get->data,
1754				    get->entry_length * get->entries);
1755				iod->hdr.rc = 0;
1756				copyout(iod, ioh, ifbuf->length);
1757			}
1758			iflib_dma_free(&dma_data);
1759
1760			rc = 0;
1761			goto exit;
1762		}
1763		case BNXT_HWRM_NVM_VERIFY_UPDATE:
1764		{
1765			struct bnxt_ioctl_hwrm_nvm_verify_update *vrfy =
1766			    &iod->verify;
1767
1768			rc = bnxt_hwrm_nvm_verify_update(softc, vrfy->type,
1769			    vrfy->ordinal, vrfy->ext);
1770			if (rc) {
1771				iod->hdr.rc = rc;
1772				copyout(&iod->hdr.rc, &ioh->rc,
1773				    sizeof(ioh->rc));
1774			}
1775			else {
1776				iod->hdr.rc = 0;
1777				copyout(iod, ioh, ifbuf->length);
1778			}
1779
1780			rc = 0;
1781			goto exit;
1782		}
1783		case BNXT_HWRM_NVM_INSTALL_UPDATE:
1784		{
1785			struct bnxt_ioctl_hwrm_nvm_install_update *inst =
1786			    &iod->install;
1787
1788			rc = bnxt_hwrm_nvm_install_update(softc,
1789			    inst->install_type, &inst->installed_items,
1790			    &inst->result, &inst->problem_item,
1791			    &inst->reset_required);
1792			if (rc) {
1793				iod->hdr.rc = rc;
1794				copyout(&iod->hdr.rc, &ioh->rc,
1795				    sizeof(ioh->rc));
1796			}
1797			else {
1798				iod->hdr.rc = 0;
1799				copyout(iod, ioh, ifbuf->length);
1800			}
1801
1802			rc = 0;
1803			goto exit;
1804		}
1805		case BNXT_HWRM_NVM_MODIFY:
1806		{
1807			struct bnxt_ioctl_hwrm_nvm_modify *mod = &iod->modify;
1808
1809			rc = bnxt_hwrm_nvm_modify(softc, mod->index,
1810			    mod->offset, mod->data, true, mod->length);
1811			if (rc) {
1812				iod->hdr.rc = rc;
1813				copyout(&iod->hdr.rc, &ioh->rc,
1814				    sizeof(ioh->rc));
1815			}
1816			else {
1817				iod->hdr.rc = 0;
1818				copyout(iod, ioh, ifbuf->length);
1819			}
1820
1821			rc = 0;
1822			goto exit;
1823		}
1824		case BNXT_HWRM_FW_GET_TIME:
1825		{
1826			struct bnxt_ioctl_hwrm_fw_get_time *gtm =
1827			    &iod->get_time;
1828
1829			rc = bnxt_hwrm_fw_get_time(softc, &gtm->year,
1830			    &gtm->month, &gtm->day, &gtm->hour, &gtm->minute,
1831			    &gtm->second, &gtm->millisecond, &gtm->zone);
1832			if (rc) {
1833				iod->hdr.rc = rc;
1834				copyout(&iod->hdr.rc, &ioh->rc,
1835				    sizeof(ioh->rc));
1836			}
1837			else {
1838				iod->hdr.rc = 0;
1839				copyout(iod, ioh, ifbuf->length);
1840			}
1841
1842			rc = 0;
1843			goto exit;
1844		}
1845		case BNXT_HWRM_FW_SET_TIME:
1846		{
1847			struct bnxt_ioctl_hwrm_fw_set_time *stm =
1848			    &iod->set_time;
1849
1850			rc = bnxt_hwrm_fw_set_time(softc, stm->year,
1851			    stm->month, stm->day, stm->hour, stm->minute,
1852			    stm->second, stm->millisecond, stm->zone);
1853			if (rc) {
1854				iod->hdr.rc = rc;
1855				copyout(&iod->hdr.rc, &ioh->rc,
1856				    sizeof(ioh->rc));
1857			}
1858			else {
1859				iod->hdr.rc = 0;
1860				copyout(iod, ioh, ifbuf->length);
1861			}
1862
1863			rc = 0;
1864			goto exit;
1865		}
1866		}
1867		break;
1868	}
1869
1870exit:
1871	if (iod)
1872		free(iod, M_DEVBUF);
1873	return rc;
1874}
1875
1876/*
1877 * Support functions
1878 */
1879static int
1880bnxt_probe_phy(struct bnxt_softc *softc)
1881{
1882	struct bnxt_link_info *link_info = &softc->link_info;
1883	int rc = 0;
1884
1885	rc = bnxt_update_link(softc, false);
1886	if (rc) {
1887		device_printf(softc->dev,
1888		    "Probe phy can't update link (rc: %x)\n", rc);
1889		return (rc);
1890	}
1891
1892	/*initialize the ethool setting copy with NVM settings */
1893	if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE)
1894		link_info->autoneg |= BNXT_AUTONEG_SPEED;
1895
1896	if (link_info->auto_pause & (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
1897	    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) {
1898		if (link_info->auto_pause == (
1899		    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
1900		    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX))
1901			link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
1902		link_info->req_flow_ctrl = link_info->auto_pause;
1903	} else if (link_info->force_pause & (
1904	    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
1905	    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)) {
1906		link_info->req_flow_ctrl = link_info->force_pause;
1907	}
1908	link_info->req_duplex = link_info->duplex_setting;
1909	if (link_info->autoneg & BNXT_AUTONEG_SPEED)
1910		link_info->req_link_speed = link_info->auto_link_speed;
1911	else
1912		link_info->req_link_speed = link_info->force_link_speed;
1913	return (rc);
1914}
1915
1916static void
1917bnxt_add_media_types(struct bnxt_softc *softc)
1918{
1919	struct bnxt_link_info *link_info = &softc->link_info;
1920	uint16_t supported;
1921	uint8_t phy_type = get_phy_type(softc);
1922
1923	supported = link_info->support_speeds;
1924
1925	/* Auto is always supported */
1926	ifmedia_add(softc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
1927
1928	if (softc->flags & BNXT_FLAG_NPAR)
1929		return;
1930
1931	switch (phy_type) {
1932	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR:
1933		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
1934			ifmedia_add(softc->media, IFM_ETHER | IFM_100G_CR4, 0,
1935			    NULL);
1936		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB)
1937			ifmedia_add(softc->media, IFM_ETHER | IFM_50G_CR2, 0,
1938			    NULL);
1939		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
1940			ifmedia_add(softc->media, IFM_ETHER | IFM_40G_CR4, 0,
1941			    NULL);
1942		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB)
1943			ifmedia_add(softc->media, IFM_ETHER | IFM_25G_CR, 0,
1944			    NULL);
1945		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
1946			ifmedia_add(softc->media, IFM_ETHER | IFM_10G_CR1, 0,
1947			    NULL);
1948		break;
1949	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN:
1950		/* Auto only */
1951		break;
1952	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR4:
1953	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR2:
1954	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR:
1955		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
1956			ifmedia_add(softc->media, IFM_ETHER | IFM_100G_KR4, 0,
1957			    NULL);
1958		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_50GB)
1959			ifmedia_add(softc->media, IFM_ETHER | IFM_50G_KR2, 0,
1960			    NULL);
1961		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
1962			ifmedia_add(softc->media, IFM_ETHER | IFM_40G_KR4, 0,
1963			    NULL);
1964		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB)
1965			ifmedia_add(softc->media, IFM_ETHER | IFM_25G_KR, 0,
1966			    NULL);
1967		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB)
1968			ifmedia_add(softc->media, IFM_ETHER | IFM_20G_KR2, 0,
1969			    NULL);
1970		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
1971			ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KR, 0,
1972			    NULL);
1973		break;
1974	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASELR:
1975		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
1976			ifmedia_add(softc->media, IFM_ETHER | IFM_100G_LR4, 0,
1977			    NULL);
1978		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
1979			ifmedia_add(softc->media, IFM_ETHER | IFM_40G_LR4, 0,
1980			    NULL);
1981		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
1982			ifmedia_add(softc->media, IFM_ETHER | IFM_10G_LR, 0,
1983			    NULL);
1984		break;
1985	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR:
1986		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100GB)
1987			ifmedia_add(softc->media, IFM_ETHER | IFM_100G_SR4, 0,
1988			    NULL);
1989		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_40GB)
1990			ifmedia_add(softc->media, IFM_ETHER | IFM_40G_SR4, 0,
1991			    NULL);
1992		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_25GB)
1993			ifmedia_add(softc->media, IFM_ETHER | IFM_25G_SR, 0,
1994			    NULL);
1995		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
1996			ifmedia_add(softc->media, IFM_ETHER | IFM_10G_SR, 0,
1997			    NULL);
1998		break;
1999	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX:
2000		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
2001			ifmedia_add(softc->media, IFM_ETHER | IFM_10G_KX4, 0,
2002			    NULL);
2003		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB)
2004			ifmedia_add(softc->media, IFM_ETHER | IFM_2500_KX, 0,
2005			    NULL);
2006		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB)
2007			ifmedia_add(softc->media, IFM_ETHER | IFM_1000_KX, 0,
2008			    NULL);
2009		break;
2010	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET:
2011	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASETE:
2012		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10MB)
2013			ifmedia_add(softc->media, IFM_ETHER | IFM_10_T, 0,
2014			    NULL);
2015		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_100MB)
2016			ifmedia_add(softc->media, IFM_ETHER | IFM_100_T, 0,
2017			    NULL);
2018		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB)
2019			ifmedia_add(softc->media, IFM_ETHER | IFM_1000_T, 0,
2020			    NULL);
2021		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB)
2022			ifmedia_add(softc->media, IFM_ETHER | IFM_2500_T, 0,
2023			    NULL);
2024		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_10GB)
2025			ifmedia_add(softc->media, IFM_ETHER | IFM_10G_T, 0,
2026			    NULL);
2027		break;
2028	case HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_SGMIIEXTPHY:
2029		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_1GB)
2030			ifmedia_add(softc->media, IFM_ETHER | IFM_1000_SGMII, 0,
2031			    NULL);
2032		break;
2033	}
2034
2035	return;
2036}
2037
2038static int
2039bnxt_map_bar(struct bnxt_softc *softc, struct bnxt_bar_info *bar, int bar_num, bool shareable)
2040{
2041	uint32_t	flag;
2042
2043	if (bar->res != NULL) {
2044		device_printf(softc->dev, "Bar %d already mapped\n", bar_num);
2045		return EDOOFUS;
2046	}
2047
2048	bar->rid = PCIR_BAR(bar_num);
2049	flag = RF_ACTIVE;
2050	if (shareable)
2051		flag |= RF_SHAREABLE;
2052
2053	if ((bar->res =
2054		bus_alloc_resource_any(softc->dev,
2055			   SYS_RES_MEMORY,
2056			   &bar->rid,
2057			   flag)) == NULL) {
2058		device_printf(softc->dev,
2059		    "PCI BAR%d mapping failure\n", bar_num);
2060		return (ENXIO);
2061	}
2062	bar->tag = rman_get_bustag(bar->res);
2063	bar->handle = rman_get_bushandle(bar->res);
2064	bar->size = rman_get_size(bar->res);
2065
2066	return 0;
2067}
2068
2069static int
2070bnxt_pci_mapping(struct bnxt_softc *softc)
2071{
2072	int rc;
2073
2074	rc = bnxt_map_bar(softc, &softc->hwrm_bar, 0, true);
2075	if (rc)
2076		return rc;
2077
2078	rc = bnxt_map_bar(softc, &softc->doorbell_bar, 2, false);
2079
2080	return rc;
2081}
2082
2083static void
2084bnxt_pci_mapping_free(struct bnxt_softc *softc)
2085{
2086	if (softc->hwrm_bar.res != NULL)
2087		bus_release_resource(softc->dev, SYS_RES_MEMORY,
2088		    softc->hwrm_bar.rid, softc->hwrm_bar.res);
2089	softc->hwrm_bar.res = NULL;
2090
2091	if (softc->doorbell_bar.res != NULL)
2092		bus_release_resource(softc->dev, SYS_RES_MEMORY,
2093		    softc->doorbell_bar.rid, softc->doorbell_bar.res);
2094	softc->doorbell_bar.res = NULL;
2095}
2096
2097static int
2098bnxt_update_link(struct bnxt_softc *softc, bool chng_link_state)
2099{
2100	struct bnxt_link_info *link_info = &softc->link_info;
2101	uint8_t link_up = link_info->link_up;
2102	int rc = 0;
2103
2104	rc = bnxt_hwrm_port_phy_qcfg(softc);
2105	if (rc)
2106		goto exit;
2107
2108	/* TODO: need to add more logic to report VF link */
2109	if (chng_link_state) {
2110		if (link_info->phy_link_status ==
2111		    HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK)
2112			link_info->link_up = 1;
2113		else
2114			link_info->link_up = 0;
2115		if (link_up != link_info->link_up)
2116			bnxt_report_link(softc);
2117	} else {
2118		/* always link down if not require to update link state */
2119		link_info->link_up = 0;
2120	}
2121
2122exit:
2123	return rc;
2124}
2125
2126void
2127bnxt_report_link(struct bnxt_softc *softc)
2128{
2129	const char *duplex = NULL, *flow_ctrl = NULL;
2130
2131	if (softc->link_info.link_up == softc->link_info.last_link_up) {
2132		if (!softc->link_info.link_up)
2133			return;
2134		if (softc->link_info.pause == softc->link_info.last_pause &&
2135		    softc->link_info.duplex == softc->link_info.last_duplex)
2136			return;
2137	}
2138
2139	if (softc->link_info.link_up) {
2140		if (softc->link_info.duplex ==
2141		    HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_FULL)
2142			duplex = "full duplex";
2143		else
2144			duplex = "half duplex";
2145		if (softc->link_info.pause == (
2146		    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX |
2147		    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX))
2148			flow_ctrl = "FC - receive & transmit";
2149		else if (softc->link_info.pause ==
2150		    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_TX)
2151			flow_ctrl = "FC - transmit";
2152		else if (softc->link_info.pause ==
2153		    HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
2154			flow_ctrl = "FC - receive";
2155		else
2156			flow_ctrl = "none";
2157		iflib_link_state_change(softc->ctx, LINK_STATE_UP,
2158		    IF_Gbps(100));
2159		device_printf(softc->dev, "Link is UP %s, %s\n", duplex,
2160		    flow_ctrl);
2161	} else {
2162		iflib_link_state_change(softc->ctx, LINK_STATE_DOWN,
2163		    bnxt_get_baudrate(&softc->link_info));
2164		device_printf(softc->dev, "Link is Down\n");
2165	}
2166
2167	softc->link_info.last_link_up = softc->link_info.link_up;
2168	softc->link_info.last_pause = softc->link_info.pause;
2169	softc->link_info.last_duplex = softc->link_info.duplex;
2170}
2171
2172static int
2173bnxt_handle_rx_cp(void *arg)
2174{
2175	struct bnxt_cp_ring *cpr = arg;
2176
2177	/* Disable further interrupts for this queue */
2178	BNXT_CP_DISABLE_DB(&cpr->ring);
2179	return FILTER_SCHEDULE_THREAD;
2180}
2181
2182static int
2183bnxt_handle_def_cp(void *arg)
2184{
2185	struct bnxt_softc *softc = arg;
2186
2187	BNXT_CP_DISABLE_DB(&softc->def_cp_ring.ring);
2188	GROUPTASK_ENQUEUE(&softc->def_cp_task);
2189	return FILTER_HANDLED;
2190}
2191
2192static void
2193bnxt_clear_ids(struct bnxt_softc *softc)
2194{
2195	int i;
2196
2197	softc->def_cp_ring.stats_ctx_id = HWRM_NA_SIGNATURE;
2198	softc->def_cp_ring.ring.phys_id = (uint16_t)HWRM_NA_SIGNATURE;
2199	for (i = 0; i < softc->ntxqsets; i++) {
2200		softc->tx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE;
2201		softc->tx_cp_rings[i].ring.phys_id =
2202		    (uint16_t)HWRM_NA_SIGNATURE;
2203		softc->tx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
2204	}
2205	for (i = 0; i < softc->nrxqsets; i++) {
2206		softc->rx_cp_rings[i].stats_ctx_id = HWRM_NA_SIGNATURE;
2207		softc->rx_cp_rings[i].ring.phys_id =
2208		    (uint16_t)HWRM_NA_SIGNATURE;
2209		softc->rx_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
2210		softc->ag_rings[i].phys_id = (uint16_t)HWRM_NA_SIGNATURE;
2211		softc->grp_info[i].grp_id = (uint16_t)HWRM_NA_SIGNATURE;
2212	}
2213	softc->vnic_info.filter_id = -1;
2214	softc->vnic_info.id = (uint16_t)HWRM_NA_SIGNATURE;
2215	softc->vnic_info.rss_id = (uint16_t)HWRM_NA_SIGNATURE;
2216	memset(softc->vnic_info.rss_grp_tbl.idi_vaddr, 0xff,
2217	    softc->vnic_info.rss_grp_tbl.idi_size);
2218}
2219
2220static void
2221bnxt_mark_cpr_invalid(struct bnxt_cp_ring *cpr)
2222{
2223	struct cmpl_base *cmp = (void *)cpr->ring.vaddr;
2224	int i;
2225
2226	for (i = 0; i < cpr->ring.ring_size; i++)
2227		cmp[i].info3_v = !cpr->v_bit;
2228}
2229
2230static void
2231bnxt_handle_async_event(struct bnxt_softc *softc, struct cmpl_base *cmpl)
2232{
2233	struct hwrm_async_event_cmpl *ae = (void *)cmpl;
2234	uint16_t async_id = le16toh(ae->event_id);
2235	struct ifmediareq ifmr;
2236
2237	switch (async_id) {
2238	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
2239	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE:
2240	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE:
2241		bnxt_media_status(softc->ctx, &ifmr);
2242		break;
2243	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE:
2244	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE:
2245	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED:
2246	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED:
2247	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD:
2248	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD:
2249	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD:
2250	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD:
2251	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR:
2252	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE:
2253	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE:
2254	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
2255	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR:
2256		device_printf(softc->dev,
2257		    "Unhandled async completion type %u\n", async_id);
2258		break;
2259	default:
2260		device_printf(softc->dev,
2261		    "Unknown async completion type %u\n", async_id);
2262		break;
2263	}
2264}
2265
2266static void
2267bnxt_def_cp_task(void *context)
2268{
2269	if_ctx_t ctx = context;
2270	struct bnxt_softc *softc = iflib_get_softc(ctx);
2271	struct bnxt_cp_ring *cpr = &softc->def_cp_ring;
2272
2273	/* Handle completions on the default completion ring */
2274	struct cmpl_base *cmpl;
2275	uint32_t cons = cpr->cons;
2276	bool v_bit = cpr->v_bit;
2277	bool last_v_bit;
2278	uint32_t last_cons;
2279	uint16_t type;
2280
2281	for (;;) {
2282		last_cons = cons;
2283		last_v_bit = v_bit;
2284		NEXT_CP_CONS_V(&cpr->ring, cons, v_bit);
2285		cmpl = &((struct cmpl_base *)cpr->ring.vaddr)[cons];
2286
2287		if (!CMP_VALID(cmpl, v_bit))
2288			break;
2289
2290		type = le16toh(cmpl->type) & CMPL_BASE_TYPE_MASK;
2291		switch (type) {
2292		case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT:
2293			bnxt_handle_async_event(softc, cmpl);
2294			break;
2295		case CMPL_BASE_TYPE_TX_L2:
2296		case CMPL_BASE_TYPE_RX_L2:
2297		case CMPL_BASE_TYPE_RX_AGG:
2298		case CMPL_BASE_TYPE_RX_TPA_START:
2299		case CMPL_BASE_TYPE_RX_TPA_END:
2300		case CMPL_BASE_TYPE_STAT_EJECT:
2301		case CMPL_BASE_TYPE_HWRM_DONE:
2302		case CMPL_BASE_TYPE_HWRM_FWD_REQ:
2303		case CMPL_BASE_TYPE_HWRM_FWD_RESP:
2304		case CMPL_BASE_TYPE_CQ_NOTIFICATION:
2305		case CMPL_BASE_TYPE_SRQ_EVENT:
2306		case CMPL_BASE_TYPE_DBQ_EVENT:
2307		case CMPL_BASE_TYPE_QP_EVENT:
2308		case CMPL_BASE_TYPE_FUNC_EVENT:
2309			device_printf(softc->dev,
2310			    "Unhandled completion type %u\n", type);
2311			break;
2312		default:
2313			device_printf(softc->dev,
2314			    "Unknown completion type %u\n", type);
2315			break;
2316		}
2317	}
2318
2319	cpr->cons = last_cons;
2320	cpr->v_bit = last_v_bit;
2321	BNXT_CP_IDX_ENABLE_DB(&cpr->ring, cpr->cons);
2322}
2323
2324static uint8_t
2325get_phy_type(struct bnxt_softc *softc)
2326{
2327	struct bnxt_link_info *link_info = &softc->link_info;
2328	uint8_t phy_type = link_info->phy_type;
2329	uint16_t supported;
2330
2331	if (phy_type != HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_UNKNOWN)
2332		return phy_type;
2333
2334	/* Deduce the phy type from the media type and supported speeds */
2335	supported = link_info->support_speeds;
2336
2337	if (link_info->media_type ==
2338	    HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_TP)
2339		return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASET;
2340	if (link_info->media_type ==
2341	    HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_DAC) {
2342		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_2_5GB)
2343			return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKX;
2344		if (supported & HWRM_PORT_PHY_QCFG_OUTPUT_SUPPORT_SPEEDS_20GB)
2345			return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASEKR;
2346		return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASECR;
2347	}
2348	if (link_info->media_type ==
2349	    HWRM_PORT_PHY_QCFG_OUTPUT_MEDIA_TYPE_FIBRE)
2350		return HWRM_PORT_PHY_QCFG_OUTPUT_PHY_TYPE_BASESR;
2351
2352	return phy_type;
2353}
2354
2355bool
2356bnxt_check_hwrm_version(struct bnxt_softc *softc)
2357{
2358	char buf[16];
2359
2360	sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major,
2361	    softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update);
2362	if (softc->ver_info->hwrm_min_major > softc->ver_info->hwrm_if_major) {
2363		device_printf(softc->dev,
2364		    "WARNING: HWRM version %s is too old (older than %s)\n",
2365		    softc->ver_info->hwrm_if_ver, buf);
2366		return false;
2367	}
2368	else if(softc->ver_info->hwrm_min_major ==
2369	    softc->ver_info->hwrm_if_major) {
2370		if (softc->ver_info->hwrm_min_minor >
2371		    softc->ver_info->hwrm_if_minor) {
2372			device_printf(softc->dev,
2373			    "WARNING: HWRM version %s is too old (older than %s)\n",
2374			    softc->ver_info->hwrm_if_ver, buf);
2375			return false;
2376		}
2377		else if (softc->ver_info->hwrm_min_minor ==
2378		    softc->ver_info->hwrm_if_minor) {
2379			if (softc->ver_info->hwrm_min_update >
2380			    softc->ver_info->hwrm_if_update) {
2381				device_printf(softc->dev,
2382				    "WARNING: HWRM version %s is too old (older than %s)\n",
2383				    softc->ver_info->hwrm_if_ver, buf);
2384				return false;
2385			}
2386		}
2387	}
2388	return true;
2389}
2390
2391static uint64_t
2392bnxt_get_baudrate(struct bnxt_link_info *link)
2393{
2394	switch (link->link_speed) {
2395	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100MB:
2396		return IF_Mbps(100);
2397	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_1GB:
2398		return IF_Gbps(1);
2399	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2GB:
2400		return IF_Gbps(2);
2401	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_2_5GB:
2402		return IF_Mbps(2500);
2403	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10GB:
2404		return IF_Gbps(10);
2405	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_20GB:
2406		return IF_Gbps(20);
2407	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_25GB:
2408		return IF_Gbps(25);
2409	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_40GB:
2410		return IF_Gbps(40);
2411	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_50GB:
2412		return IF_Gbps(50);
2413	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_100GB:
2414		return IF_Gbps(100);
2415	case HWRM_PORT_PHY_QCFG_OUTPUT_LINK_SPEED_10MB:
2416		return IF_Mbps(10);
2417	}
2418	return IF_Gbps(100);
2419}
2420