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