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