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