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