1 /*
2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2019 aQuantia Corporation. All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * (1) Redistributions of source code must retain the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer.
12 *
13 * (2) Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * (3)The name of the author may not be used to endorse or promote
19 * products derived from this software without specific prior
20 * written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include "opt_inet.h"
39 #include "opt_inet6.h"
40 #include "opt_rss.h"
41
42 #include <sys/param.h>
43 #include <sys/bitstring.h>
44 #include <sys/bus.h>
45 #include <sys/endian.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
48 #include <sys/module.h>
49 #include <sys/priv.h>
50 #include <sys/rman.h>
51 #include <sys/sbuf.h>
52 #include <sys/socket.h>
53 #include <sys/sockio.h>
54 #include <sys/sysctl.h>
55
56 #include <machine/bus.h>
57 #include <machine/resource.h>
58
59 #include <dev/pci/pcireg.h>
60 #include <dev/pci/pcivar.h>
61
62 #include <net/ethernet.h>
63 #include <net/if.h>
64 #include <net/if_dl.h>
65 #include <net/if_media.h>
66 #include <net/if_var.h>
67 #include <net/iflib.h>
68 #include <net/rss_config.h>
69
70 #include "ifdi_if.h"
71
72 #include "aq_device.h"
73 #include "aq_fw.h"
74 #include "aq_hw.h"
75 #include "aq_hw_llh.h"
76 #include "aq_ring.h"
77 #include "aq_dbg.h"
78
79
80 #define AQ_XXX_UNIMPLEMENTED_FUNCTION do { \
81 printf("atlantic: unimplemented function: %s@%s:%d\n", __func__, \
82 __FILE__, __LINE__); \
83 } while (0)
84
85 MALLOC_DEFINE(M_AQ, "aq", "Aquantia");
86
87 char aq_driver_version[] = AQ_VER;
88
89 #define AQUANTIA_VENDOR_ID 0x1D6A
90
91 #define AQ_DEVICE_ID_0001 0x0001
92 #define AQ_DEVICE_ID_D100 0xD100
93 #define AQ_DEVICE_ID_D107 0xD107
94 #define AQ_DEVICE_ID_D108 0xD108
95 #define AQ_DEVICE_ID_D109 0xD109
96
97 #define AQ_DEVICE_ID_AQC100 0x00B1
98 #define AQ_DEVICE_ID_AQC107 0x07B1
99 #define AQ_DEVICE_ID_AQC108 0x08B1
100 #define AQ_DEVICE_ID_AQC109 0x09B1
101 #define AQ_DEVICE_ID_AQC111 0x11B1
102 #define AQ_DEVICE_ID_AQC112 0x12B1
103
104 #define AQ_DEVICE_ID_AQC100S 0x80B1
105 #define AQ_DEVICE_ID_AQC107S 0x87B1
106 #define AQ_DEVICE_ID_AQC108S 0x88B1
107 #define AQ_DEVICE_ID_AQC109S 0x89B1
108 #define AQ_DEVICE_ID_AQC111S 0x91B1
109 #define AQ_DEVICE_ID_AQC112S 0x92B1
110
111 static pci_vendor_info_t aq_vendor_info_array[] = {
112 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_0001,
113 "Aquantia AQtion 10Gbit Network Adapter"),
114 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_D107,
115 "Aquantia AQtion 10Gbit Network Adapter"),
116 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_D108,
117 "Aquantia AQtion 5Gbit Network Adapter"),
118 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_D109,
119 "Aquantia AQtion 2.5Gbit Network Adapter"),
120
121 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC107,
122 "Aquantia AQtion 10Gbit Network Adapter"),
123 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC108,
124 "Aquantia AQtion 5Gbit Network Adapter"),
125 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC109,
126 "Aquantia AQtion 2.5Gbit Network Adapter"),
127 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC100,
128 "Aquantia AQtion 10Gbit Network Adapter"),
129
130 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC107S,
131 "Aquantia AQtion 10Gbit Network Adapter"),
132 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC108S,
133 "Aquantia AQtion 5Gbit Network Adapter"),
134 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC109S,
135 "Aquantia AQtion 2.5Gbit Network Adapter"),
136 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC100S,
137 "Aquantia AQtion 10Gbit Network Adapter"),
138
139 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC111,
140 "Aquantia AQtion 5Gbit Network Adapter"),
141 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC112,
142 "Aquantia AQtion 2.5Gbit Network Adapter"),
143 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC111S,
144 "Aquantia AQtion 5Gbit Network Adapter"),
145 PVID(AQUANTIA_VENDOR_ID, AQ_DEVICE_ID_AQC112S,
146 "Aquantia AQtion 2.5Gbit Network Adapter"),
147
148 PVID_END
149 };
150
151
152 /* Device setup, teardown, etc */
153 static void *aq_register(device_t dev);
154 static int aq_if_attach_pre(if_ctx_t ctx);
155 static int aq_if_attach_post(if_ctx_t ctx);
156 static int aq_if_detach(if_ctx_t ctx);
157 static int aq_if_shutdown(if_ctx_t ctx);
158 static int aq_if_suspend(if_ctx_t ctx);
159 static int aq_if_resume(if_ctx_t ctx);
160
161 /* Soft queue setup and teardown */
162 static int aq_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
163 uint64_t *paddrs, int ntxqs, int ntxqsets);
164 static int aq_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs,
165 uint64_t *paddrs, int nrxqs, int nrxqsets);
166 static void aq_if_queues_free(if_ctx_t ctx);
167
168 /* Device configuration */
169 static void aq_if_init(if_ctx_t ctx);
170 static void aq_if_stop(if_ctx_t ctx);
171 static void aq_if_multi_set(if_ctx_t ctx);
172 static int aq_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
173 static void aq_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr);
174 static int aq_if_media_change(if_ctx_t ctx);
175 static int aq_if_promisc_set(if_ctx_t ctx, int flags);
176 static uint64_t aq_if_get_counter(if_ctx_t ctx, ift_counter cnt);
177 static void aq_if_timer(if_ctx_t ctx, uint16_t qid);
178 static int aq_hw_capabilities(struct aq_dev *softc);
179 static void aq_add_stats_sysctls(struct aq_dev *softc);
180
181 /* Interrupt enable / disable */
182 static void aq_if_enable_intr(if_ctx_t ctx);
183 static void aq_if_disable_intr(if_ctx_t ctx);
184 static int aq_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid);
185 static int aq_if_msix_intr_assign(if_ctx_t ctx, int msix);
186
187 /* VLAN support */
188 static bool aq_is_vlan_promisc_required(struct aq_dev *softc);
189 static void aq_update_vlan_filters(struct aq_dev *softc);
190 static void aq_if_vlan_register(if_ctx_t ctx, uint16_t vtag);
191 static void aq_if_vlan_unregister(if_ctx_t ctx, uint16_t vtag);
192
193 /* Informational/diagnostic */
194 static void aq_if_led_func(if_ctx_t ctx, int onoff);
195
196 static device_method_t aq_methods[] = {
197 DEVMETHOD(device_register, aq_register),
198 DEVMETHOD(device_probe, iflib_device_probe),
199 DEVMETHOD(device_attach, iflib_device_attach),
200 DEVMETHOD(device_detach, iflib_device_detach),
201 DEVMETHOD(device_shutdown, iflib_device_shutdown),
202 DEVMETHOD(device_suspend, iflib_device_suspend),
203 DEVMETHOD(device_resume, iflib_device_resume),
204
205 DEVMETHOD_END
206 };
207
208 static driver_t aq_driver = {
209 "aq", aq_methods, sizeof(struct aq_dev),
210 };
211
212 #if __FreeBSD_version >= 1400058
213 DRIVER_MODULE(atlantic, pci, aq_driver, 0, 0);
214 #else
215 static devclass_t aq_devclass;
216 DRIVER_MODULE(atlantic, pci, aq_driver, aq_devclass, 0, 0);
217 #endif
218
219 MODULE_DEPEND(atlantic, pci, 1, 1, 1);
220 MODULE_DEPEND(atlantic, ether, 1, 1, 1);
221 MODULE_DEPEND(atlantic, iflib, 1, 1, 1);
222
223 IFLIB_PNP_INFO(pci, atlantic, aq_vendor_info_array);
224
225 static device_method_t aq_if_methods[] = {
226 /* Device setup, teardown, etc */
227 DEVMETHOD(ifdi_attach_pre, aq_if_attach_pre),
228 DEVMETHOD(ifdi_attach_post, aq_if_attach_post),
229 DEVMETHOD(ifdi_detach, aq_if_detach),
230
231 DEVMETHOD(ifdi_shutdown, aq_if_shutdown),
232 DEVMETHOD(ifdi_suspend, aq_if_suspend),
233 DEVMETHOD(ifdi_resume, aq_if_resume),
234
235 /* Soft queue setup and teardown */
236 DEVMETHOD(ifdi_tx_queues_alloc, aq_if_tx_queues_alloc),
237 DEVMETHOD(ifdi_rx_queues_alloc, aq_if_rx_queues_alloc),
238 DEVMETHOD(ifdi_queues_free, aq_if_queues_free),
239
240 /* Device configuration */
241 DEVMETHOD(ifdi_init, aq_if_init),
242 DEVMETHOD(ifdi_stop, aq_if_stop),
243 DEVMETHOD(ifdi_multi_set, aq_if_multi_set),
244 DEVMETHOD(ifdi_mtu_set, aq_if_mtu_set),
245 DEVMETHOD(ifdi_media_status, aq_if_media_status),
246 DEVMETHOD(ifdi_media_change, aq_if_media_change),
247 DEVMETHOD(ifdi_promisc_set, aq_if_promisc_set),
248 DEVMETHOD(ifdi_get_counter, aq_if_get_counter),
249 DEVMETHOD(ifdi_update_admin_status, aq_if_update_admin_status),
250 DEVMETHOD(ifdi_timer, aq_if_timer),
251
252 /* Interrupt enable / disable */
253 DEVMETHOD(ifdi_intr_enable, aq_if_enable_intr),
254 DEVMETHOD(ifdi_intr_disable, aq_if_disable_intr),
255 DEVMETHOD(ifdi_rx_queue_intr_enable, aq_if_rx_queue_intr_enable),
256 DEVMETHOD(ifdi_tx_queue_intr_enable, aq_if_rx_queue_intr_enable),
257 DEVMETHOD(ifdi_msix_intr_assign, aq_if_msix_intr_assign),
258
259 /* VLAN support */
260 DEVMETHOD(ifdi_vlan_register, aq_if_vlan_register),
261 DEVMETHOD(ifdi_vlan_unregister, aq_if_vlan_unregister),
262
263 /* Informational/diagnostic */
264 DEVMETHOD(ifdi_led_func, aq_if_led_func),
265
266 DEVMETHOD_END
267 };
268
269 static driver_t aq_if_driver = {
270 "aq_if", aq_if_methods, sizeof(struct aq_dev)
271 };
272
273 static struct if_shared_ctx aq_sctx_init = {
274 .isc_magic = IFLIB_MAGIC,
275 .isc_q_align = PAGE_SIZE,
276 .isc_tx_maxsize = HW_ATL_B0_TSO_SIZE,
277 .isc_tx_maxsegsize = HW_ATL_B0_MTU_JUMBO,
278 #if __FreeBSD__ >= 12
279 .isc_tso_maxsize = HW_ATL_B0_TSO_SIZE,
280 .isc_tso_maxsegsize = HW_ATL_B0_MTU_JUMBO,
281 #endif
282 .isc_rx_maxsize = HW_ATL_B0_MTU_JUMBO,
283 .isc_rx_nsegments = 16,
284 .isc_rx_maxsegsize = PAGE_SIZE,
285 .isc_nfl = 1,
286 .isc_nrxqs = 1,
287 .isc_ntxqs = 1,
288 .isc_admin_intrcnt = 1,
289 .isc_vendor_info = aq_vendor_info_array,
290 .isc_driver_version = aq_driver_version,
291 .isc_driver = &aq_if_driver,
292 .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP |
293 IFLIB_NEED_ZERO_CSUM,
294
295 .isc_nrxd_min = {HW_ATL_B0_MIN_RXD},
296 .isc_ntxd_min = {HW_ATL_B0_MIN_TXD},
297 .isc_nrxd_max = {HW_ATL_B0_MAX_RXD},
298 .isc_ntxd_max = {HW_ATL_B0_MAX_TXD},
299 .isc_nrxd_default = {PAGE_SIZE / sizeof(aq_txc_desc_t) * 4},
300 .isc_ntxd_default = {PAGE_SIZE / sizeof(aq_txc_desc_t) * 4},
301 };
302
303 /*
304 * TUNEABLE PARAMETERS:
305 */
306
307 static SYSCTL_NODE(_hw, OID_AUTO, aq, CTLFLAG_RD, 0, "Atlantic driver parameters");
308 /* UDP Receive-Side Scaling */
309 static int aq_enable_rss_udp = 1;
310 SYSCTL_INT(_hw_aq, OID_AUTO, enable_rss_udp, CTLFLAG_RDTUN, &aq_enable_rss_udp,
311 0, "Enable Receive-Side Scaling (RSS) for UDP");
312
313
314 /*
315 * Device Methods
316 */
317 static void *
aq_register(device_t dev)318 aq_register(device_t dev)
319 {
320 return (&aq_sctx_init);
321 }
322
323 static int
aq_if_attach_pre(if_ctx_t ctx)324 aq_if_attach_pre(if_ctx_t ctx)
325 {
326 struct aq_dev *softc;
327 struct aq_hw *hw;
328 if_softc_ctx_t scctx;
329 int rc;
330
331 AQ_DBG_ENTER();
332 softc = iflib_get_softc(ctx);
333 rc = 0;
334
335 softc->ctx = ctx;
336 softc->dev = iflib_get_dev(ctx);
337 softc->media = iflib_get_media(ctx);
338 softc->scctx = iflib_get_softc_ctx(ctx);
339 softc->sctx = iflib_get_sctx(ctx);
340 scctx = softc->scctx;
341
342 softc->mmio_rid = PCIR_BAR(0);
343 softc->mmio_res = bus_alloc_resource_any(softc->dev, SYS_RES_MEMORY,
344 &softc->mmio_rid, RF_ACTIVE|RF_SHAREABLE);
345 if (softc->mmio_res == NULL) {
346 device_printf(softc->dev,
347 "failed to allocate MMIO resources\n");
348 rc = ENXIO;
349 goto fail;
350 }
351
352 softc->mmio_tag = rman_get_bustag(softc->mmio_res);
353 softc->mmio_handle = rman_get_bushandle(softc->mmio_res);
354 softc->mmio_size = rman_get_size(softc->mmio_res);
355 softc->hw.hw_addr = (uint8_t*) softc->mmio_handle;
356 hw = &softc->hw;
357 hw->link_rate = aq_fw_speed_auto;
358 hw->itr = -1;
359 hw->fc.fc_rx = 1;
360 hw->fc.fc_tx = 1;
361 softc->linkup = 0U;
362
363 /* Look up ops and caps. */
364 rc = aq_hw_mpi_create(hw);
365 if (rc < 0) {
366 AQ_DBG_ERROR(" %s: aq_hw_mpi_create fail err=%d", __func__, rc);
367 goto fail;
368 }
369
370 if (hw->fast_start_enabled) {
371 if (hw->fw_ops && hw->fw_ops->reset)
372 hw->fw_ops->reset(hw);
373 } else
374 aq_hw_reset(&softc->hw);
375 aq_hw_capabilities(softc);
376
377 if (aq_hw_get_mac_permanent(hw, hw->mac_addr) < 0) {
378 AQ_DBG_ERROR("Unable to get mac addr from hw");
379 goto fail;
380 };
381
382 softc->admin_ticks = 0;
383
384 iflib_set_mac(ctx, hw->mac_addr);
385 #if __FreeBSD__ < 13
386 /* since FreeBSD13 deadlock due to calling iflib_led_func() under CTX_LOCK() */
387 iflib_led_create(ctx);
388 #endif
389 scctx->isc_tx_csum_flags = CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO;
390 #if __FreeBSD__ >= 12
391 scctx->isc_capabilities = IFCAP_RXCSUM | IFCAP_TXCSUM | IFCAP_HWCSUM |
392 IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_VLAN_HWFILTER | IFCAP_VLAN_MTU |
393 IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM;
394 scctx->isc_capenable = scctx->isc_capabilities;
395 #else
396 if_t ifp;
397 ifp = iflib_get_ifp(ctx);
398 if_setcapenable(ifp, IFCAP_RXCSUM | IFCAP_TXCSUM | IFCAP_HWCSUM |
399 IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_VLAN_HWFILTER | IFCAP_VLAN_MTU |
400 IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM;
401 #endif
402 scctx->isc_tx_nsegments = 31,
403 scctx->isc_tx_tso_segments_max = 31;
404 scctx->isc_tx_tso_size_max =
405 HW_ATL_B0_TSO_SIZE - sizeof(struct ether_vlan_header);
406 scctx->isc_tx_tso_segsize_max = HW_ATL_B0_MTU_JUMBO;
407 scctx->isc_min_frame_size = 52;
408 scctx->isc_txrx = &aq_txrx;
409
410 scctx->isc_txqsizes[0] = sizeof(aq_tx_desc_t) * scctx->isc_ntxd[0];
411 scctx->isc_rxqsizes[0] = sizeof(aq_rx_desc_t) * scctx->isc_nrxd[0];
412
413 scctx->isc_ntxqsets_max = HW_ATL_B0_RINGS_MAX;
414 scctx->isc_nrxqsets_max = HW_ATL_B0_RINGS_MAX;
415
416 /* iflib will map and release this bar */
417 scctx->isc_msix_bar = pci_msix_table_bar(softc->dev);
418
419 softc->vlan_tags = bit_alloc(4096, M_AQ, M_NOWAIT);
420
421 AQ_DBG_EXIT(rc);
422 return (rc);
423
424 fail:
425 if (softc->mmio_res != NULL)
426 bus_release_resource(softc->dev, SYS_RES_MEMORY,
427 softc->mmio_rid, softc->mmio_res);
428
429 AQ_DBG_EXIT(rc);
430 return (ENXIO);
431 }
432
433
434 static int
435 aq_if_attach_post(if_ctx_t ctx)
436 {
437 struct aq_dev *softc;
438 int rc;
439
440 AQ_DBG_ENTER();
441
442 softc = iflib_get_softc(ctx);
443 rc = 0;
444
445 aq_update_hw_stats(softc);
446
447 aq_initmedia(softc);
448
449
450 switch (softc->scctx->isc_intr) {
451 case IFLIB_INTR_LEGACY:
452 rc = EOPNOTSUPP;
453 goto exit;
454 goto exit;
455 break;
456 case IFLIB_INTR_MSI:
457 break;
458 case IFLIB_INTR_MSIX:
459 break;
460 default:
461 device_printf(softc->dev, "unknown interrupt mode\n");
462 rc = EOPNOTSUPP;
463 goto exit;
464 }
465
466 aq_add_stats_sysctls(softc);
467 /* RSS */
468 arc4rand(softc->rss_key, HW_ATL_RSS_HASHKEY_SIZE, 0);
469 for (int i = ARRAY_SIZE(softc->rss_table); i--;){
470 softc->rss_table[i] = i & (softc->rx_rings_count - 1);
471 }
472 exit:
473 AQ_DBG_EXIT(rc);
474 return (rc);
475 }
476
477
478 static int
479 aq_if_detach(if_ctx_t ctx)
480 {
481 struct aq_dev *softc;
482 int i;
483
484 AQ_DBG_ENTER();
485 softc = iflib_get_softc(ctx);
486
487 aq_hw_deinit(&softc->hw);
488
489 for (i = 0; i < softc->scctx->isc_nrxqsets; i++)
490 iflib_irq_free(ctx, &softc->rx_rings[i]->irq);
491 iflib_irq_free(ctx, &softc->irq);
492
493
494 if (softc->mmio_res != NULL)
495 bus_release_resource(softc->dev, SYS_RES_MEMORY,
496 softc->mmio_rid, softc->mmio_res);
497
498 free(softc->vlan_tags, M_AQ);
499
500 AQ_DBG_EXIT(0);
501 return (0);
502 }
503
504 static int
505 aq_if_shutdown(if_ctx_t ctx)
506 {
507
508 AQ_DBG_ENTER();
509
510 AQ_XXX_UNIMPLEMENTED_FUNCTION;
511
512 AQ_DBG_EXIT(0);
513 return (0);
514 }
515
516 static int
517 aq_if_suspend(if_ctx_t ctx)
518 {
519 AQ_DBG_ENTER();
520
521 AQ_XXX_UNIMPLEMENTED_FUNCTION;
522
523 AQ_DBG_EXIT(0);
524 return (0);
525 }
526
527 static int
528 aq_if_resume(if_ctx_t ctx)
529 {
530 AQ_DBG_ENTER();
531
532 AQ_XXX_UNIMPLEMENTED_FUNCTION;
533
534 AQ_DBG_EXIT(0);
535 return (0);
536 }
537
538 /* Soft queue setup and teardown */
539 static int
540 aq_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
541 int ntxqs, int ntxqsets)
542 {
543 struct aq_dev *softc;
544 struct aq_ring *ring;
545 int rc = 0, i;
546
547 AQ_DBG_ENTERA("ntxqs=%d, ntxqsets=%d", ntxqs, ntxqsets);
548 softc = iflib_get_softc(ctx);
549 AQ_DBG_PRINT("tx descriptors number %d", softc->scctx->isc_ntxd[0]);
550
551 for (i = 0; i < ntxqsets; i++) {
552 ring = softc->tx_rings[i] = malloc(sizeof(struct aq_ring),
553 M_AQ, M_NOWAIT | M_ZERO);
554 if (!ring){
555 rc = ENOMEM;
556 device_printf(softc->dev, "atlantic: tx_ring malloc fail\n");
557 goto fail;
558 }
559 ring->tx_descs = (aq_tx_desc_t*)vaddrs[i];
560 ring->tx_size = softc->scctx->isc_ntxd[0];
561 ring->tx_descs_phys = paddrs[i];
562 ring->tx_head = ring->tx_tail = 0;
563 ring->index = i;
564 ring->dev = softc;
565
566 softc->tx_rings_count++;
567 }
568
569 AQ_DBG_EXIT(rc);
570 return (rc);
571
572 fail:
573 aq_if_queues_free(ctx);
574 AQ_DBG_EXIT(rc);
575 return (rc);
576 }
577
578 static int
579 aq_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs,
580 int nrxqs, int nrxqsets)
581 {
582 struct aq_dev *softc;
583 struct aq_ring *ring;
584 int rc = 0, i;
585
586 AQ_DBG_ENTERA("nrxqs=%d, nrxqsets=%d", nrxqs, nrxqsets);
587 softc = iflib_get_softc(ctx);
588
589 for (i = 0; i < nrxqsets; i++) {
590 ring = softc->rx_rings[i] = malloc(sizeof(struct aq_ring),
591 M_AQ, M_NOWAIT | M_ZERO);
592 if (!ring){
593 rc = ENOMEM;
594 device_printf(softc->dev,
595 "atlantic: rx_ring malloc fail\n");
596 goto fail;
597 }
598
599 ring->rx_descs = (aq_rx_desc_t*)vaddrs[i];
600 ring->rx_descs_phys = paddrs[i];
601 ring->rx_size = softc->scctx->isc_nrxd[0];
602 ring->index = i;
603 ring->dev = softc;
604
605 switch (MCLBYTES) {
606 case (4 * 1024):
607 case (8 * 1024):
608 case (16 * 1024):
609 ring->rx_max_frame_size = MCLBYTES;
610 break;
611 default:
612 ring->rx_max_frame_size = 2048;
613 break;
614 }
615
616 softc->rx_rings_count++;
617 }
618
619 AQ_DBG_EXIT(rc);
620 return (rc);
621
622 fail:
623 aq_if_queues_free(ctx);
624 AQ_DBG_EXIT(rc);
625 return (rc);
626 }
627
628 static void
629 aq_if_queues_free(if_ctx_t ctx)
630 {
631 struct aq_dev *softc;
632 int i;
633
634 AQ_DBG_ENTER();
635 softc = iflib_get_softc(ctx);
636
637 for (i = 0; i < softc->tx_rings_count; i++) {
638 if (softc->tx_rings[i]) {
639 free(softc->tx_rings[i], M_AQ);
640 softc->tx_rings[i] = NULL;
641 }
642 }
643 softc->tx_rings_count = 0;
644 for (i = 0; i < softc->rx_rings_count; i++) {
645 if (softc->rx_rings[i]){
646 free(softc->rx_rings[i], M_AQ);
647 softc->rx_rings[i] = NULL;
648 }
649 }
650 softc->rx_rings_count = 0;
651
652 AQ_DBG_EXIT(0);
653 return;
654 }
655
656 /* Device configuration */
657 static void
658 aq_if_init(if_ctx_t ctx)
659 {
660 struct aq_dev *softc;
661 struct aq_hw *hw;
662 struct ifmediareq ifmr;
663 int i, err;
664
665 AQ_DBG_ENTER();
666 softc = iflib_get_softc(ctx);
667 hw = &softc->hw;
668
669 err = aq_hw_init(&softc->hw, softc->hw.mac_addr, softc->msix,
670 softc->scctx->isc_intr == IFLIB_INTR_MSIX);
671 if (err != EOK) {
672 device_printf(softc->dev, "atlantic: aq_hw_init: %d", err);
673 }
674
675 aq_if_media_status(ctx, &ifmr);
676
677 aq_update_vlan_filters(softc);
678
679 for (i = 0; i < softc->tx_rings_count; i++) {
680 struct aq_ring *ring = softc->tx_rings[i];
681 err = aq_ring_tx_init(&softc->hw, ring);
682 if (err) {
683 device_printf(softc->dev,
684 "atlantic: aq_ring_tx_init: %d", err);
685 }
686 err = aq_ring_tx_start(hw, ring);
687 if (err != EOK) {
688 device_printf(softc->dev,
689 "atlantic: aq_ring_tx_start: %d", err);
690 }
691 }
692 for (i = 0; i < softc->rx_rings_count; i++) {
693 struct aq_ring *ring = softc->rx_rings[i];
694 err = aq_ring_rx_init(&softc->hw, ring);
695 if (err) {
696 device_printf(softc->dev,
697 "atlantic: aq_ring_rx_init: %d", err);
698 }
699 err = aq_ring_rx_start(hw, ring);
700 if (err != EOK) {
701 device_printf(softc->dev,
702 "atlantic: aq_ring_rx_start: %d", err);
703 }
704 aq_if_rx_queue_intr_enable(ctx, i);
705 }
706
707 aq_hw_start(hw);
708 aq_if_enable_intr(ctx);
709 aq_hw_rss_hash_set(&softc->hw, softc->rss_key);
710 aq_hw_rss_set(&softc->hw, softc->rss_table);
711 aq_hw_udp_rss_enable(hw, aq_enable_rss_udp);
712 aq_hw_set_link_speed(hw, hw->link_rate);
713
714 AQ_DBG_EXIT(0);
715 }
716
717
718 static void
719 aq_if_stop(if_ctx_t ctx)
720 {
721 struct aq_dev *softc;
722 struct aq_hw *hw;
723 int i;
724
725 AQ_DBG_ENTER();
726
727 softc = iflib_get_softc(ctx);
728 hw = &softc->hw;
729
730 /* disable interrupt */
731 aq_if_disable_intr(ctx);
732
733 for (i = 0; i < softc->tx_rings_count; i++) {
734 aq_ring_tx_stop(hw, softc->tx_rings[i]);
735 softc->tx_rings[i]->tx_head = 0;
736 softc->tx_rings[i]->tx_tail = 0;
737 }
738 for (i = 0; i < softc->rx_rings_count; i++) {
739 aq_ring_rx_stop(hw, softc->rx_rings[i]);
740 }
741
742 aq_hw_reset(&softc->hw);
743 memset(&softc->last_stats, 0, sizeof(softc->last_stats));
744 softc->linkup = false;
745 aq_if_update_admin_status(ctx);
746 AQ_DBG_EXIT(0);
747 }
748
749 static uint64_t
750 aq_if_get_counter(if_ctx_t ctx, ift_counter cnt)
751 {
752 struct aq_dev *softc = iflib_get_softc(ctx);
753 if_t ifp = iflib_get_ifp(ctx);
754
755 switch (cnt) {
756 case IFCOUNTER_IERRORS:
757 return (softc->curr_stats.erpr);
758 case IFCOUNTER_IQDROPS:
759 return (softc->curr_stats.dpc);
760 case IFCOUNTER_OERRORS:
761 return (softc->curr_stats.erpt);
762 default:
763 return (if_get_counter_default(ifp, cnt));
764 }
765 }
766
767 #if __FreeBSD_version >= 1300054
768 static u_int
769 aq_mc_filter_apply(void *arg, struct sockaddr_dl *dl, u_int count)
770 {
771 struct aq_dev *softc = arg;
772 struct aq_hw *hw = &softc->hw;
773 uint8_t *mac_addr = NULL;
774
775 if (count == AQ_HW_MAC_MAX)
776 return (0);
777
778 mac_addr = LLADDR(dl);
779 aq_hw_mac_addr_set(hw, mac_addr, count + 1);
780
781 aq_log_detail("set %d mc address %6D", count + 1, mac_addr, ":");
782 return (1);
783 }
784 #else
785 static int
786 aq_mc_filter_apply(void *arg, struct ifmultiaddr *ifma, int count)
787 {
788 struct aq_dev *softc = arg;
789 struct aq_hw *hw = &softc->hw;
790 uint8_t *mac_addr = NULL;
791
792 if (ifma->ifma_addr->sa_family != AF_LINK)
793 return (0);
794 if (count == AQ_HW_MAC_MAX)
795 return (0);
796
797 mac_addr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
798 aq_hw_mac_addr_set(hw, mac_addr, count + 1);
799
800 aq_log_detail("set %d mc address %6D", count + 1, mac_addr, ":");
801 return (1);
802 }
803 #endif
804
805 static bool
806 aq_is_mc_promisc_required(struct aq_dev *softc)
807 {
808 return (softc->mcnt >= AQ_HW_MAC_MAX);
809 }
810
811 static void
812 aq_if_multi_set(if_ctx_t ctx)
813 {
814 struct aq_dev *softc = iflib_get_softc(ctx);
815 if_t ifp = iflib_get_ifp(ctx);
816 struct aq_hw *hw = &softc->hw;
817 AQ_DBG_ENTER();
818 #if __FreeBSD_version >= 1300054
819 softc->mcnt = if_llmaddr_count(iflib_get_ifp(ctx));
820 #else
821 softc->mcnt = if_multiaddr_count(iflib_get_ifp(ctx), AQ_HW_MAC_MAX);
822 #endif
823 if (softc->mcnt >= AQ_HW_MAC_MAX) {
824 aq_hw_set_promisc(hw, !!(if_getflags(ifp) & IFF_PROMISC),
825 aq_is_vlan_promisc_required(softc),
826 !!(if_getflags(ifp) & IFF_ALLMULTI) || aq_is_mc_promisc_required(softc));
827 } else {
828 #if __FreeBSD_version >= 1300054
829 if_foreach_llmaddr(iflib_get_ifp(ctx), &aq_mc_filter_apply, softc);
830 #else
831 if_multi_apply(iflib_get_ifp(ctx), aq_mc_filter_apply, softc);
832 #endif
833 }
834 AQ_DBG_EXIT(0);
835 }
836
837 static int
838 aq_if_mtu_set(if_ctx_t ctx, uint32_t mtu)
839 {
840 int err = 0;
841 AQ_DBG_ENTER();
842
843 AQ_DBG_EXIT(err);
844 return (err);
845 }
846
847 static void
848 aq_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr)
849 {
850 if_t ifp;
851
852 AQ_DBG_ENTER();
853
854 ifp = iflib_get_ifp(ctx);
855
856 aq_mediastatus(ifp, ifmr);
857
858 AQ_DBG_EXIT(0);
859 }
860
861 static int
862 aq_if_media_change(if_ctx_t ctx)
863 {
864 struct aq_dev *softc = iflib_get_softc(ctx);
865 if_t ifp = iflib_get_ifp(ctx);
866 int rc = 0;
867
868 AQ_DBG_ENTER();
869
870 /* Not allowd in UP state, since causes unsync of rings */
871 if ((if_getflags(ifp) & IFF_UP)){
872 rc = EPERM;
873 goto exit;
874 }
875
876 ifp = iflib_get_ifp(softc->ctx);
877
878 rc = aq_mediachange(ifp);
879
880 exit:
881 AQ_DBG_EXIT(rc);
882 return (rc);
883 }
884
885 static int
886 aq_if_promisc_set(if_ctx_t ctx, int flags)
887 {
888 struct aq_dev *softc;
889
890 AQ_DBG_ENTER();
891
892 softc = iflib_get_softc(ctx);
893
894 aq_hw_set_promisc(&softc->hw, !!(flags & IFF_PROMISC),
895 aq_is_vlan_promisc_required(softc),
896 !!(flags & IFF_ALLMULTI) || aq_is_mc_promisc_required(softc));
897
898 AQ_DBG_EXIT(0);
899 return (0);
900 }
901
902 static void
903 aq_if_timer(if_ctx_t ctx, uint16_t qid)
904 {
905 struct aq_dev *softc;
906 uint64_t ticks_now;
907
908 // AQ_DBG_ENTER();
909
910 softc = iflib_get_softc(ctx);
911 ticks_now = ticks;
912
913 /* Schedule aqc_if_update_admin_status() once per sec */
914 if (ticks_now - softc->admin_ticks >= hz) {
915 softc->admin_ticks = ticks_now;
916 iflib_admin_intr_deferred(ctx);
917 }
918
919 // AQ_DBG_EXIT(0);
920 return;
921
922 }
923
924 /* Interrupt enable / disable */
925 static void
926 aq_if_enable_intr(if_ctx_t ctx)
927 {
928 struct aq_dev *softc = iflib_get_softc(ctx);
929 struct aq_hw *hw = &softc->hw;
930
931 AQ_DBG_ENTER();
932
933 /* Enable interrupts */
934 itr_irq_msk_setlsw_set(hw, BIT(softc->msix + 1) - 1);
935
936 AQ_DBG_EXIT(0);
937 }
938
939 static void
940 aq_if_disable_intr(if_ctx_t ctx)
941 {
942 struct aq_dev *softc = iflib_get_softc(ctx);
943 struct aq_hw *hw = &softc->hw;
944
945 AQ_DBG_ENTER();
946
947 /* Disable interrupts */
948 itr_irq_msk_clearlsw_set(hw, BIT(softc->msix + 1) - 1);
949
950 AQ_DBG_EXIT(0);
951 }
952
953 static int
954 aq_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid)
955 {
956 struct aq_dev *softc = iflib_get_softc(ctx);
957 struct aq_hw *hw = &softc->hw;
958
959 AQ_DBG_ENTER();
960
961 itr_irq_msk_setlsw_set(hw, BIT(softc->rx_rings[rxqid]->msix));
962
963 AQ_DBG_EXIT(0);
964 return (0);
965 }
966
967 static int
968 aq_if_msix_intr_assign(if_ctx_t ctx, int msix)
969 {
970 struct aq_dev *softc;
971 int i, vector = 0, rc;
972 char irq_name[16];
973 int rx_vectors;
974
975 AQ_DBG_ENTER();
976 softc = iflib_get_softc(ctx);
977
978 for (i = 0; i < softc->rx_rings_count; i++, vector++) {
979 snprintf(irq_name, sizeof(irq_name), "rxq%d", i);
980 rc = iflib_irq_alloc_generic(ctx, &softc->rx_rings[i]->irq,
981 vector + 1, IFLIB_INTR_RX, aq_isr_rx, softc->rx_rings[i],
982 softc->rx_rings[i]->index, irq_name);
983 device_printf(softc->dev, "Assign IRQ %u to rx ring %u\n",
984 vector, softc->rx_rings[i]->index);
985
986 if (rc) {
987 device_printf(softc->dev, "failed to set up RX handler\n");
988 i--;
989 goto fail;
990 }
991
992 softc->rx_rings[i]->msix = vector;
993 }
994
995 rx_vectors = vector;
996
997 for (i = 0; i < softc->tx_rings_count; i++, vector++) {
998 snprintf(irq_name, sizeof(irq_name), "txq%d", i);
999 iflib_softirq_alloc_generic(ctx, &softc->rx_rings[i]->irq,
1000 IFLIB_INTR_TX, softc->tx_rings[i], i, irq_name);
1001
1002 softc->tx_rings[i]->msix = (vector % softc->rx_rings_count);
1003 device_printf(softc->dev, "Assign IRQ %u to tx ring %u\n",
1004 softc->tx_rings[i]->msix, softc->tx_rings[i]->index);
1005 }
1006
1007 rc = iflib_irq_alloc_generic(ctx, &softc->irq, rx_vectors + 1,
1008 IFLIB_INTR_ADMIN, aq_linkstat_isr, softc, 0, "aq");
1009 softc->msix = rx_vectors;
1010 device_printf(softc->dev, "Assign IRQ %u to admin proc \n",
1011 rx_vectors);
1012 if (rc) {
1013 device_printf(iflib_get_dev(ctx),
1014 "Failed to register admin handler");
1015 i = softc->rx_rings_count;
1016 goto fail;
1017 }
1018 AQ_DBG_EXIT(0);
1019 return (0);
1020
1021 fail:
1022 for (; i >= 0; i--)
1023 iflib_irq_free(ctx, &softc->rx_rings[i]->irq);
1024 AQ_DBG_EXIT(rc);
1025 return (rc);
1026 }
1027
1028 static bool
1029 aq_is_vlan_promisc_required(struct aq_dev *softc)
1030 {
1031 int vlan_tag_count;
1032
1033 bit_count(softc->vlan_tags, 0, 4096, &vlan_tag_count);
1034
1035 if (vlan_tag_count <= AQ_HW_VLAN_MAX_FILTERS)
1036 return (false);
1037 else
1038 return (true);
1039
1040 }
1041
1042 static void
1043 aq_update_vlan_filters(struct aq_dev *softc)
1044 {
1045 struct aq_rx_filter_vlan aq_vlans[AQ_HW_VLAN_MAX_FILTERS];
1046 struct aq_hw *hw = &softc->hw;
1047 int bit_pos = 0;
1048 int vlan_tag = -1;
1049 int i;
1050
1051 hw_atl_b0_hw_vlan_promisc_set(hw, true);
1052 for (i = 0; i < AQ_HW_VLAN_MAX_FILTERS; i++) {
1053 bit_ffs_at(softc->vlan_tags, bit_pos, 4096, &vlan_tag);
1054 if (vlan_tag != -1) {
1055 aq_vlans[i].enable = true;
1056 aq_vlans[i].location = i;
1057 aq_vlans[i].queue = 0xFF;
1058 aq_vlans[i].vlan_id = vlan_tag;
1059 bit_pos = vlan_tag;
1060 } else {
1061 aq_vlans[i].enable = false;
1062 }
1063 }
1064
1065 hw_atl_b0_hw_vlan_set(hw, aq_vlans);
1066 hw_atl_b0_hw_vlan_promisc_set(hw, aq_is_vlan_promisc_required(softc));
1067 }
1068
1069 /* VLAN support */
1070 static void
1071 aq_if_vlan_register(if_ctx_t ctx, uint16_t vtag)
1072 {
1073 struct aq_dev *softc = iflib_get_softc(ctx);
1074
1075 AQ_DBG_ENTERA("%d", vtag);
1076
1077 bit_set(softc->vlan_tags, vtag);
1078
1079 aq_update_vlan_filters(softc);
1080
1081 AQ_DBG_EXIT(0);
1082 }
1083
1084 static void
1085 aq_if_vlan_unregister(if_ctx_t ctx, uint16_t vtag)
1086 {
1087 struct aq_dev *softc = iflib_get_softc(ctx);
1088
1089 AQ_DBG_ENTERA("%d", vtag);
1090
1091 bit_clear(softc->vlan_tags, vtag);
1092
1093 aq_update_vlan_filters(softc);
1094
1095 AQ_DBG_EXIT(0);
1096 }
1097
1098 static void
1099 aq_if_led_func(if_ctx_t ctx, int onoff)
1100 {
1101 struct aq_dev *softc = iflib_get_softc(ctx);
1102 struct aq_hw *hw = &softc->hw;
1103
1104 AQ_DBG_ENTERA("%d", onoff);
1105 if (hw->fw_ops && hw->fw_ops->led_control)
1106 hw->fw_ops->led_control(hw, onoff);
1107
1108 AQ_DBG_EXIT(0);
1109 }
1110
1111 static int
1112 aq_hw_capabilities(struct aq_dev *softc)
1113 {
1114
1115 if (pci_get_vendor(softc->dev) != AQUANTIA_VENDOR_ID)
1116 return (ENXIO);
1117
1118 switch (pci_get_device(softc->dev)) {
1119 case AQ_DEVICE_ID_D100:
1120 case AQ_DEVICE_ID_AQC100:
1121 case AQ_DEVICE_ID_AQC100S:
1122 softc->media_type = AQ_MEDIA_TYPE_FIBRE;
1123 softc->link_speeds = AQ_LINK_ALL & ~AQ_LINK_10G;
1124 break;
1125
1126 case AQ_DEVICE_ID_0001:
1127 case AQ_DEVICE_ID_D107:
1128 case AQ_DEVICE_ID_AQC107:
1129 case AQ_DEVICE_ID_AQC107S:
1130 softc->media_type = AQ_MEDIA_TYPE_TP;
1131 softc->link_speeds = AQ_LINK_ALL;
1132 break;
1133
1134 case AQ_DEVICE_ID_D108:
1135 case AQ_DEVICE_ID_AQC108:
1136 case AQ_DEVICE_ID_AQC108S:
1137 case AQ_DEVICE_ID_AQC111:
1138 case AQ_DEVICE_ID_AQC111S:
1139 softc->media_type = AQ_MEDIA_TYPE_TP;
1140 softc->link_speeds = AQ_LINK_ALL & ~AQ_LINK_10G;
1141 break;
1142
1143 case AQ_DEVICE_ID_D109:
1144 case AQ_DEVICE_ID_AQC109:
1145 case AQ_DEVICE_ID_AQC109S:
1146 case AQ_DEVICE_ID_AQC112:
1147 case AQ_DEVICE_ID_AQC112S:
1148 softc->media_type = AQ_MEDIA_TYPE_TP;
1149 softc->link_speeds = AQ_LINK_ALL & ~(AQ_LINK_10G | AQ_LINK_5G);
1150 break;
1151
1152 default:
1153 return (ENXIO);
1154 }
1155
1156 return (0);
1157 }
1158
1159 static int
1160 aq_sysctl_print_rss_config(SYSCTL_HANDLER_ARGS)
1161 {
1162 struct aq_dev *softc = (struct aq_dev *)arg1;
1163 device_t dev = softc->dev;
1164 struct sbuf *buf;
1165 int error = 0;
1166
1167 buf = sbuf_new_for_sysctl(NULL, NULL, 256, req);
1168 if (!buf) {
1169 device_printf(dev, "Could not allocate sbuf for output.\n");
1170 return (ENOMEM);
1171 }
1172
1173 /* Print out the redirection table */
1174 sbuf_cat(buf, "\nRSS Indirection table:\n");
1175 for (int i = 0; i < HW_ATL_RSS_INDIRECTION_TABLE_MAX; i++) {
1176 sbuf_printf(buf, "%d ", softc->rss_table[i]);
1177 if ((i+1) % 10 == 0)
1178 sbuf_printf(buf, "\n");
1179 }
1180
1181 sbuf_cat(buf, "\nRSS Key:\n");
1182 for (int i = 0; i < HW_ATL_RSS_HASHKEY_SIZE; i++) {
1183 sbuf_printf(buf, "0x%02x ", softc->rss_key[i]);
1184 }
1185 sbuf_printf(buf, "\n");
1186
1187 error = sbuf_finish(buf);
1188 if (error)
1189 device_printf(dev, "Error finishing sbuf: %d\n", error);
1190
1191 sbuf_delete(buf);
1192
1193 return (0);
1194 }
1195
1196 static int
1197 aq_sysctl_print_tx_head(SYSCTL_HANDLER_ARGS)
1198 {
1199 struct aq_ring *ring = arg1;
1200 int error = 0;
1201 unsigned int val;
1202
1203 if (!ring)
1204 return (0);
1205
1206 val = tdm_tx_desc_head_ptr_get(&ring->dev->hw, ring->index);
1207
1208 error = sysctl_handle_int(oidp, &val, 0, req);
1209 if (error || !req->newptr)
1210 return (error);
1211
1212 return (0);
1213 }
1214
1215 static int
1216 aq_sysctl_print_tx_tail(SYSCTL_HANDLER_ARGS)
1217 {
1218 struct aq_ring *ring = arg1;
1219 int error = 0;
1220 unsigned int val;
1221
1222 if (!ring)
1223 return (0);
1224
1225 val = reg_tx_dma_desc_tail_ptr_get(&ring->dev->hw, ring->index);
1226
1227 error = sysctl_handle_int(oidp, &val, 0, req);
1228 if (error || !req->newptr)
1229 return (error);
1230
1231 return (0);
1232 }
1233
1234 static int
1235 aq_sysctl_print_rx_head(SYSCTL_HANDLER_ARGS)
1236 {
1237 struct aq_ring *ring = arg1;
1238 int error = 0;
1239 unsigned int val;
1240
1241 if (!ring)
1242 return (0);
1243
1244 val = rdm_rx_desc_head_ptr_get(&ring->dev->hw, ring->index);
1245
1246 error = sysctl_handle_int(oidp, &val, 0, req);
1247 if (error || !req->newptr)
1248 return (error);
1249
1250 return (0);
1251 }
1252
1253 static int
1254 aq_sysctl_print_rx_tail(SYSCTL_HANDLER_ARGS)
1255 {
1256 struct aq_ring *ring = arg1;
1257 int error = 0;
1258 unsigned int val;
1259
1260 if (!ring)
1261 return (0);
1262
1263 val = reg_rx_dma_desc_tail_ptr_get(&ring->dev->hw, ring->index);
1264
1265 error = sysctl_handle_int(oidp, &val, 0, req);
1266 if (error || !req->newptr)
1267 return (error);
1268
1269 return (0);
1270 }
1271
1272 static void
1273 aq_add_stats_sysctls(struct aq_dev *softc)
1274 {
1275 device_t dev = softc->dev;
1276 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
1277 struct sysctl_oid *tree = device_get_sysctl_tree(dev);
1278 struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree);
1279 struct aq_stats_s *stats = &softc->curr_stats;
1280 struct sysctl_oid *stat_node, *queue_node;
1281 struct sysctl_oid_list *stat_list, *queue_list;
1282
1283 #define QUEUE_NAME_LEN 32
1284 char namebuf[QUEUE_NAME_LEN];
1285 /* RSS configuration */
1286 SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "print_rss_config",
1287 CTLTYPE_STRING | CTLFLAG_RD, softc, 0,
1288 aq_sysctl_print_rss_config, "A", "Prints RSS Configuration");
1289
1290 /* Driver Statistics */
1291 for (int i = 0; i < softc->tx_rings_count; i++) {
1292 struct aq_ring *ring = softc->tx_rings[i];
1293 snprintf(namebuf, QUEUE_NAME_LEN, "tx_queue%d", i);
1294 queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
1295 CTLFLAG_RD, NULL, "Queue Name");
1296 queue_list = SYSCTL_CHILDREN(queue_node);
1297
1298 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_pkts",
1299 CTLFLAG_RD, &(ring->stats.tx_pkts), "TX Packets");
1300 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_bytes",
1301 CTLFLAG_RD, &(ring->stats.tx_bytes), "TX Octets");
1302 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_drops",
1303 CTLFLAG_RD, &(ring->stats.tx_drops), "TX Drops");
1304 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_queue_full",
1305 CTLFLAG_RD, &(ring->stats.tx_queue_full), "TX Queue Full");
1306 SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "tx_head",
1307 CTLTYPE_UINT | CTLFLAG_RD, ring, 0,
1308 aq_sysctl_print_tx_head, "IU", "ring head pointer");
1309 SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "tx_tail",
1310 CTLTYPE_UINT | CTLFLAG_RD, ring, 0,
1311 aq_sysctl_print_tx_tail, "IU", "ring tail pointer");
1312 }
1313
1314 for (int i = 0; i < softc->rx_rings_count; i++) {
1315 struct aq_ring *ring = softc->rx_rings[i];
1316 snprintf(namebuf, QUEUE_NAME_LEN, "rx_queue%d", i);
1317 queue_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, namebuf,
1318 CTLFLAG_RD, NULL, "Queue Name");
1319 queue_list = SYSCTL_CHILDREN(queue_node);
1320
1321 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_pkts",
1322 CTLFLAG_RD, &(ring->stats.rx_pkts), "RX Packets");
1323 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_bytes",
1324 CTLFLAG_RD, &(ring->stats.rx_bytes), "TX Octets");
1325 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "jumbo_pkts",
1326 CTLFLAG_RD, &(ring->stats.jumbo_pkts), "Jumbo Packets");
1327 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "rx_err",
1328 CTLFLAG_RD, &(ring->stats.rx_err), "RX Errors");
1329 SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "irq",
1330 CTLFLAG_RD, &(ring->stats.irq), "RX interrupts");
1331 SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rx_head",
1332 CTLTYPE_UINT | CTLFLAG_RD, ring, 0,
1333 aq_sysctl_print_rx_head, "IU", "ring head pointer");
1334 SYSCTL_ADD_PROC(ctx, queue_list, OID_AUTO, "rx_tail",
1335 CTLTYPE_UINT | CTLFLAG_RD, ring, 0,
1336 aq_sysctl_print_rx_tail, "IU", " ring tail pointer");
1337 }
1338
1339 stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac",
1340 CTLFLAG_RD, NULL, "Statistics (read from HW registers)");
1341 stat_list = SYSCTL_CHILDREN(stat_node);
1342
1343 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_rcvd",
1344 CTLFLAG_RD, &stats->prc, "Good Packets Received");
1345 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ucast_pkts_rcvd",
1346 CTLFLAG_RD, &stats->uprc, "Unicast Packets Received");
1347 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_rcvd",
1348 CTLFLAG_RD, &stats->mprc, "Multicast Packets Received");
1349 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_rcvd",
1350 CTLFLAG_RD, &stats->bprc, "Broadcast Packets Received");
1351 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rsc_pkts_rcvd",
1352 CTLFLAG_RD, &stats->cprc, "Coalesced Packets Received");
1353 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "err_pkts_rcvd",
1354 CTLFLAG_RD, &stats->erpr, "Errors of Packet Receive");
1355 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "drop_pkts_dma",
1356 CTLFLAG_RD, &stats->dpc, "Dropped Packets in DMA");
1357 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_rcvd",
1358 CTLFLAG_RD, &stats->brc, "Good Octets Received");
1359 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ucast_octets_rcvd",
1360 CTLFLAG_RD, &stats->ubrc, "Unicast Octets Received");
1361 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_octets_rcvd",
1362 CTLFLAG_RD, &stats->mbrc, "Multicast Octets Received");
1363 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_octets_rcvd",
1364 CTLFLAG_RD, &stats->bbrc, "Broadcast Octets Received");
1365
1366 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_pkts_txd",
1367 CTLFLAG_RD, &stats->ptc, "Good Packets Transmitted");
1368 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ucast_pkts_txd",
1369 CTLFLAG_RD, &stats->uptc, "Unicast Packets Transmitted");
1370 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_pkts_txd",
1371 CTLFLAG_RD, &stats->mptc, "Multicast Packets Transmitted");
1372 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_pkts_txd",
1373 CTLFLAG_RD, &stats->bptc, "Broadcast Packets Transmitted");
1374
1375 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "err_pkts_txd",
1376 CTLFLAG_RD, &stats->erpt, "Errors of Packet Transmit");
1377 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "good_octets_txd",
1378 CTLFLAG_RD, &stats->btc, "Good Octets Transmitted");
1379 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "ucast_octets_txd",
1380 CTLFLAG_RD, &stats->ubtc, "Unicast Octets Transmitted");
1381 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mcast_octets_txd",
1382 CTLFLAG_RD, &stats->mbtc, "Multicast Octets Transmitted");
1383 SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "bcast_octets_txd",
1384 CTLFLAG_RD, &stats->bbtc, "Broadcast Octets Transmitted");
1385 }
1386