xref: /freebsd/sys/dev/bnxt/bnxt_en/bnxt_sysctl.c (revision c4fde87a3236b500246d4fce76dbca2a3d64f73a)
1 /*-
2  * Broadcom NetXtreme-C/E network driver.
3  *
4  * Copyright (c) 2016 Broadcom, All Rights Reserved.
5  * The term Broadcom refers to Broadcom Limited and/or its subsidiaries
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <sys/sysctl.h>
31 #include <sys/ctype.h>
32 
33 #include "bnxt.h"
34 #include "bnxt_hwrm.h"
35 #include "bnxt_sysctl.h"
36 #include "bnxt_ktls.h"
37 
38 struct bnxt_ktls_counters_list {
39 	enum bnxt_ktls_counters id;
40 	const char *label;
41 	const char *desc;
42 };
43 static const struct bnxt_ktls_counters_list ktls_counters[] = {
44 	{ BNXT_KTLS_TX_ADD,			"add_tx_session",		"KTLS sessions add count" },
45 	{ BNXT_KTLS_TX_DEL,			"delete_tx_session",		"KTLS sessions delete count" },
46 	{ BNXT_KTLS_TX_HW_PKT,			"hw_tx_pkts",			"HW KTLS TX count" },
47 	{ BNXT_KTLS_TX_FAILED,			"failed_tx_pkts",		"SW KTLS TX count" },
48 	{ BNXT_KTLS_TX_OOO,			"ooo_tx_pkts",			"OOO KTLS TX count" },
49 	{ BNXT_KTLS_TX_RETRANS,			"retrans_tx_pkts",		"Retransmitted KTLS TX count" },
50 	{ BNXT_KTLS_TX_REPLAY,			"replay_tx_pkts",		"Replay KTLS TX count" },
51 	{ BNXT_KTLS_TX_SEQ_FWD,			"seq_fwd_tx_pkts",		"Seq forward KTLS Tx count" },
52 	{ BNXT_KTLS_TX_SEQ_FWD_TLS_HDR,		"seq_fwd_tx_tls_hdr_pkts",	"Seq forward Tx packets with TLS header" },
53 	{ BNXT_KTLS_TX_SEQ_FWD_SILENT_DROPS,	"seq_fwd_tx_silent_drops_pkts",	"Silently dropped seq forward packets" },
54 	{ BNXT_KTLS_TX_SEQ_FWD_REPLAY,		"seq_fwd_tx_replay_pkts",	"Replayed Seq forward packets" },
55 	{ BNXT_KTLS_TX_MBUF_ALLOCS,		"mbuf_allocs",			"Alloc mbufs count" },
56 	{ BNXT_KTLS_TX_MBUF_FREES,		"mbuf_frees",			"Free mbufs count" },
57 	{ BNXT_KTLS_TX_MBUF_ERRORS,		"mbuf_errors",			"Error mbufs count" },
58 };
59 static const int ktls_counters_count = sizeof(ktls_counters) / sizeof(ktls_counters[0]);
60 
61 struct bnxt_ktls_err_counters_list {
62 	enum bnxt_ktls_err_counters id;
63 	const char *label;
64 	const char *desc;
65 };
66 static const struct bnxt_ktls_err_counters_list ktls_err_counters[] = {
67 	{ BNXT_KTLS_TX_DEV_ADD_FAILED,	    "add_tx_session_failure",	"Tx KTLS device add failure count" },
68 	{ BNXT_KTLS_TX_MPC_TIMEOUT,	    "mpc_cmd_timeout",		"Timeout MPC commands count" },
69 	{ BNXT_KTLS_TX_UNINITIALIZED,	    "ktls_tx_uninit",		"snd_tag alloc failure due to ktls not initialized" },
70 	{ BNXT_KTLS_TX_CTX_ALLOC_FAILED,    "ctx_alloc_failures",	"snd_tag alloc failure due to ctx alloc failed" },
71 	{ BNXT_KTLS_TX_MPC_FAILED,	    "mpc_failures",		"MPC command failures count" },
72 	{ BNXT_KTLS_TX_TCE_NOT_READY,	    "tce_not_ready",		"Tx crypto engine(TCE) is not ready" },
73 	{ BNXT_KTLS_TX_TCE_READY_DELAYED,   "tce_ready_delayed",	"TCE getting ready with delay" },
74 	{ BNXT_KTLS_TX_TCE_BAD,	    	    "tce_bad",			"TCE is in bad state" },
75 	{ BNXT_KTLS_TX_UNSUPPORTED_TLS_HDR, "unsupported_tls_hdr",	"snd_tag alloc failure due to unsupported TLS header" },
76 	{ BNXT_KTLS_TX_INVALID_TAG, 	    "invalid_tag",		"Invalid snd_tag" },
77 	{ BNXT_KTLS_TX_ZERO_TCP_PAYLEN,     "zero_payload",		"Packet/s with zero TCP payload" },
78 	{ BNXT_KTLS_TX_INVALID_REC_SN,      "invalid_rec_sn",		"Invalid Record" },
79 	{ BNXT_KTLS_TX_TCE_FREE,	    "tce_free",        		"Packets received when crypto delete is ongoing"},
80 	{ BNXT_KTLS_TX_MPC_RING_BUSY,	    "mpc_ring_busy",		"MPC ring full on crypto add/delete xmit, retry count"},
81 };
82 
83 static const int ktls_err_counters_count = sizeof(ktls_err_counters) / sizeof(ktls_err_counters[0]);
84 
85 struct bnxt_mpc_cmp_time_counters_list {
86 	enum bnxt_mpc_cmp_time_counters id;
87 	const char *label;
88 	const char *desc;
89 };
90 static const struct bnxt_mpc_cmp_time_counters_list mpc_cmp_counters[] = {
91 	{ BNXT_MPC_CMP_TIME_1US,		"<=1us",	"MPC command completion <= 1us" },
92 	{ BNXT_MPC_CMP_TIME_1_5US,		"1-5us",	"MPC command completion between 1-5us" },
93 	{ BNXT_MPC_CMP_TIME_5_10US,		"5-10us",	"MPC command completion between 5-10us" },
94 	{ BNXT_MPC_CMP_TIME_10_15US,		"10-15us",	"MPC command completion between 10-15us" },
95 	{ BNXT_MPC_CMP_TIME_15_20US,		"15-20us",	"MPC command completion between 15-20us" },
96 	{ BNXT_MPC_CMP_TIME_20_25US,		"20-25us",	"MPC command completion between 20-25us" },
97 	{ BNXT_MPC_CMP_TIME_25_50US,		"25-50us",	"MPC command completion between 25-50us" },
98 	{ BNXT_MPC_CMP_TIME_50_100US,		"50-100us",	"MPC command completion between 50-100us" },
99 	{ BNXT_MPC_CMP_TIME_100_200US,		"100-200us",	"MPC command completion between 100-200us" },
100 	{ BNXT_MPC_CMP_TIME_200_500US,		"200-500us",	"MPC command completion between 200-500us" },
101 	{ BNXT_MPC_CMP_TIME_500_1000US,		"500-1000us",	"MPC command completion between 500-1000us" },
102 	{ BNXT_MPC_CMP_TIME_1000_1500US,	"1000-1500us",	"MPC command completion between 1000-1500us" },
103 	{ BNXT_MPC_CMP_TIME_1500_2000US,	"1500-2000us",	"MPC command completion between 1500-2000us" },
104 	{ BNXT_MPC_CMP_TIME_2000_2500US,	"2000-2500us",	"MPC command completion between 2000-2500us" },
105 	{ BNXT_MPC_CMP_TIME_2500_3000US,	"2500-3000us",	"MPC command completion between 2500-3000us" },
106 	{ BNXT_MPC_CMP_TIME_3000_3500US,	"3000-3500us",	"MPC command completion between 3000-3500us" },
107 	{ BNXT_MPC_CMP_TIME_3500_4000US,	"3500-4000us",	"MPC command completion between 3500-4000us" },
108 	{ BNXT_MPC_CMP_TIME_4000_4500US,	"4000-4500us",	"MPC command completion between 4000-4500us" },
109 	{ BNXT_MPC_CMP_TIME_4500_5000US,	"4500-5000us",	"MPC command completion between 4500-5000us" },
110 	{ BNXT_MPC_CMP_TIME_5000_PLUS_US,	"5000+us",	"MPC command completion >= 5000us" },
111 };
112 static const int mpc_cmp_counters_count = sizeof(mpc_cmp_counters) / sizeof(mpc_cmp_counters[0]);
113 
114 extern void bnxt_fw_reset(struct bnxt_softc *bp);
115 extern void bnxt_queue_sp_work(struct bnxt_softc *bp);
116 extern bool
117 process_nq(struct bnxt_softc *softc, uint16_t nqid);
118 /*
119  * We want to create:
120  * dev.bnxt.0.hwstats.txq0
121  * dev.bnxt.0.hwstats.txq0.txmbufs
122  * dev.bnxt.0.hwstats.rxq0
123  * dev.bnxt.0.hwstats.txq0.rxmbufs
124  * so the hwstats ctx list needs to be created in attach_post and populated
125  * during init.
126  *
127  * Then, it needs to be cleaned up in stop.
128  */
129 
130 int
131 bnxt_init_sysctl_ctx(struct bnxt_softc *softc)
132 {
133 	struct sysctl_ctx_list *ctx;
134 
135 	sysctl_ctx_init(&softc->hw_stats);
136 	ctx = device_get_sysctl_ctx(softc->dev);
137 	softc->hw_stats_oid = SYSCTL_ADD_NODE(ctx,
138 	    SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
139 	    "hwstats", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "hardware statistics");
140 	if (!softc->hw_stats_oid) {
141 		sysctl_ctx_free(&softc->hw_stats);
142 		return ENOMEM;
143 	}
144 
145 	sysctl_ctx_init(&softc->ver_info->ver_ctx);
146 	ctx = device_get_sysctl_ctx(softc->dev);
147 	softc->ver_info->ver_oid = SYSCTL_ADD_NODE(ctx,
148 	    SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
149 	    "ver", CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
150 	    "hardware/firmware version information");
151 	if (!softc->ver_info->ver_oid) {
152 		sysctl_ctx_free(&softc->ver_info->ver_ctx);
153 		return ENOMEM;
154 	}
155 
156 	if (BNXT_PF(softc)) {
157 		sysctl_ctx_init(&softc->nvm_info->nvm_ctx);
158 		ctx = device_get_sysctl_ctx(softc->dev);
159 		softc->nvm_info->nvm_oid = SYSCTL_ADD_NODE(ctx,
160 		    SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
161 		    "nvram", CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
162 		    "nvram information");
163 		if (!softc->nvm_info->nvm_oid) {
164 			sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
165 			return ENOMEM;
166 		}
167 	}
168 
169 	sysctl_ctx_init(&softc->hw_lro_ctx);
170 	ctx = device_get_sysctl_ctx(softc->dev);
171 	softc->hw_lro_oid = SYSCTL_ADD_NODE(ctx,
172 	    SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
173 	    "hw_lro", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "hardware lro");
174 	if (!softc->hw_lro_oid) {
175 		sysctl_ctx_free(&softc->hw_lro_ctx);
176 		return ENOMEM;
177 	}
178 
179 	sysctl_ctx_init(&softc->flow_ctrl_ctx);
180 	ctx = device_get_sysctl_ctx(softc->dev);
181 	softc->flow_ctrl_oid = SYSCTL_ADD_NODE(ctx,
182 	    SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
183 	    "fc", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "flow ctrl");
184 	if (!softc->flow_ctrl_oid) {
185 		sysctl_ctx_free(&softc->flow_ctrl_ctx);
186 		return ENOMEM;
187 	}
188 
189 	sysctl_ctx_init(&softc->dcb_ctx);
190 	ctx = device_get_sysctl_ctx(softc->dev);
191 	softc->dcb_oid = SYSCTL_ADD_NODE(ctx,
192 	    SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
193 	    "dcb", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Data Center Bridging");
194 	if (!softc->dcb_oid) {
195 		sysctl_ctx_free(&softc->dcb_ctx);
196 		return ENOMEM;
197 	}
198 
199 	sysctl_ctx_init(&softc->ktls_stats);
200 	ctx = device_get_sysctl_ctx(softc->dev);
201 	softc->ktls_stats_oid = SYSCTL_ADD_NODE(ctx,
202 	    SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
203 	    "ktls_stats", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "kTLS statistics");
204 	if (!softc->ktls_stats_oid) {
205 		sysctl_ctx_free(&softc->ktls_stats);
206 		return ENOMEM;
207 	}
208 
209 	sysctl_ctx_init(&softc->mpc_cmp_time_stats);
210 	ctx = device_get_sysctl_ctx(softc->dev);
211 	softc->mpc_cmp_time_stats_oid = SYSCTL_ADD_NODE(ctx,
212 	    SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev)), OID_AUTO,
213 	    "mpc_cmp_time_stats", CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
214 	    "MPC completion time statistics");
215 	if (!softc->mpc_cmp_time_stats_oid) {
216 		sysctl_ctx_free(&softc->mpc_cmp_time_stats);
217 		return ENOMEM;
218 	}
219 
220 	return 0;
221 }
222 
223 int
224 bnxt_free_sysctl_ctx(struct bnxt_softc *softc)
225 {
226 	int orc;
227 	int rc = 0;
228 
229 	if (softc->hw_stats_oid != NULL) {
230 		orc = sysctl_ctx_free(&softc->hw_stats);
231 		if (orc)
232 			rc = orc;
233 		else
234 			softc->hw_stats_oid = NULL;
235 	}
236 	if (softc->ver_info->ver_oid != NULL) {
237 		orc = sysctl_ctx_free(&softc->ver_info->ver_ctx);
238 		if (orc)
239 			rc = orc;
240 		else
241 			softc->ver_info->ver_oid = NULL;
242 	}
243 	if (BNXT_PF(softc) && softc->nvm_info->nvm_oid != NULL) {
244 		orc = sysctl_ctx_free(&softc->nvm_info->nvm_ctx);
245 		if (orc)
246 			rc = orc;
247 		else
248 			softc->nvm_info->nvm_oid = NULL;
249 	}
250 	if (softc->hw_lro_oid != NULL) {
251 		orc = sysctl_ctx_free(&softc->hw_lro_ctx);
252 		if (orc)
253 			rc = orc;
254 		else
255 			softc->hw_lro_oid = NULL;
256 	}
257 
258 	if (softc->flow_ctrl_oid != NULL) {
259 		orc = sysctl_ctx_free(&softc->flow_ctrl_ctx);
260 		if (orc)
261 			rc = orc;
262 		else
263 			softc->flow_ctrl_oid = NULL;
264 	}
265 
266 	if (softc->dcb_oid != NULL) {
267 		orc = sysctl_ctx_free(&softc->dcb_ctx);
268 		if (orc)
269 			rc = orc;
270 		else
271 			softc->dcb_oid = NULL;
272 	}
273 
274 	if (softc->ktls_stats_oid != NULL) {
275 		orc = sysctl_ctx_free(&softc->ktls_stats);
276 		if (orc)
277 			rc = orc;
278 		else
279 			softc->ktls_stats_oid = NULL;
280 	}
281 
282 	if (softc->mpc_cmp_time_stats_oid != NULL) {
283 		orc = sysctl_ctx_free(&softc->mpc_cmp_time_stats);
284 		if (orc)
285 			rc = orc;
286 		else
287 			softc->mpc_cmp_time_stats_oid = NULL;
288 	}
289 
290 	return rc;
291 }
292 
293 int
294 bnxt_create_tx_sysctls(struct bnxt_softc *softc, int txr)
295 {
296 	struct sysctl_oid *oid;
297 	struct ctx_hw_stats *tx_stats = (void *)softc->tx_stats[txr].idi_vaddr;
298 	char	name[32];
299 	char	desc[64];
300 
301 	sprintf(name, "txq%d", txr);
302 	sprintf(desc, "transmit queue %d", txr);
303 	oid = SYSCTL_ADD_NODE(&softc->hw_stats,
304 	    SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name,
305 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, desc);
306 	if (!oid)
307 		return ENOMEM;
308 
309 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
310 	    "ucast_pkts", CTLFLAG_RD, &tx_stats->tx_ucast_pkts,
311 	    "unicast packets sent");
312 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
313 	    "mcast_pkts", CTLFLAG_RD, &tx_stats->tx_mcast_pkts,
314 	    "multicast packets sent");
315 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
316 	    "bcast_pkts", CTLFLAG_RD, &tx_stats->tx_bcast_pkts,
317 	    "broadcast packets sent");
318 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
319 	    "discard_pkts", CTLFLAG_RD,
320 	    &tx_stats->tx_discard_pkts, "discarded transmit packets");
321 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
322 	    "error_pkts", CTLFLAG_RD, &tx_stats->tx_error_pkts,
323 	    "Error transmit packets");
324 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
325 	    "ucast_bytes", CTLFLAG_RD, &tx_stats->tx_ucast_bytes,
326 	    "unicast bytes sent");
327 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
328 	    "mcast_bytes", CTLFLAG_RD, &tx_stats->tx_mcast_bytes,
329 	    "multicast bytes sent");
330 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
331 	    "bcast_bytes", CTLFLAG_RD, &tx_stats->tx_bcast_bytes,
332 	    "broadcast bytes sent");
333 
334 	return 0;
335 }
336 
337 int
338 bnxt_create_generic_stats_sysctls(struct bnxt_softc *softc)
339 {
340 	struct sysctl_oid *oid;
341 	char	name[32];
342 	char	desc[64];
343 
344 	sprintf(name, "generic_stats");
345 	sprintf(desc, "Generic Stats");
346 	oid = SYSCTL_ADD_NODE(&softc->hw_stats,
347 	    SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name,
348 		CTLFLAG_RD | CTLFLAG_MPSAFE, 0, desc);
349 	if (!oid)
350 		return ENOMEM;
351 
352 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
353 	    "pcie_statistics_tx_tlp", CTLFLAG_RD,
354 	    &softc->generic_stats->pcie_statistics_tx_tlp, "pcie_statistics_tx_tlp");
355 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
356 	    "pcie_statistics_rx_tlp", CTLFLAG_RD,
357 	    &softc->generic_stats->pcie_statistics_rx_tlp, "pcie_statistics_rx_tlp");
358 
359 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
360 	    "pcie_credit_fc_hdr_posted", CTLFLAG_RD,
361 	    &softc->generic_stats->pcie_credit_fc_hdr_posted, "pcie_credit_fc_hdr_posted");
362 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
363 	    "pcie_credit_fc_hdr_nonposted", CTLFLAG_RD,
364 	    &softc->generic_stats->pcie_credit_fc_hdr_nonposted, "pcie_credit_fc_hdr_nonposted");
365 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
366 	    "pcie_credit_fc_hdr_cmpl", CTLFLAG_RD,
367 	    &softc->generic_stats->pcie_credit_fc_hdr_cmpl, "pcie_credit_fc_hdr_cmpl");
368 
369 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
370 	    "pcie_credit_fc_data_posted", CTLFLAG_RD,
371 	    &softc->generic_stats->pcie_credit_fc_data_posted, "pcie_credit_fc_data_posted");
372 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
373 	    "pcie_credit_fc_data_nonposted", CTLFLAG_RD,
374 	    &softc->generic_stats->pcie_credit_fc_data_nonposted, "pcie_credit_fc_data_nonposted");
375 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
376 	    "pcie_credit_fc_data_cmpl", CTLFLAG_RD,
377 	    &softc->generic_stats->pcie_credit_fc_data_cmpl, "pcie_credit_fc_data_cmpl");
378 
379 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
380 	    "pcie_credit_fc_tgt_nonposted", CTLFLAG_RD,
381 	    &softc->generic_stats->pcie_credit_fc_tgt_nonposted, "pcie_credit_fc_tgt_nonposted");
382 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
383 	    "pcie_credit_fc_tgt_data_posted", CTLFLAG_RD,
384 	    &softc->generic_stats->pcie_credit_fc_tgt_data_posted, "pcie_credit_fc_tgt_data_posted");
385 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
386 	    "pcie_credit_fc_tgt_hdr_posted", CTLFLAG_RD,
387 	    &softc->generic_stats->pcie_credit_fc_tgt_hdr_posted, "pcie_credit_fc_tgt_hdr_posted");
388 
389 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
390 	    "pcie_credit_fc_cmpl_hdr_posted", CTLFLAG_RD,
391 	    &softc->generic_stats->pcie_credit_fc_cmpl_hdr_posted, "pcie_credit_fc_cmpl_hdr_posted");
392 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
393 	    "pcie_credit_fc_cmpl_data_posted", CTLFLAG_RD,
394 	    &softc->generic_stats->pcie_credit_fc_cmpl_data_posted, "pcie_credit_fc_cmpl_data_posted");
395 
396 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
397 	    "pcie_cmpl_longest", CTLFLAG_RD,
398 	    &softc->generic_stats->pcie_cmpl_longest, "pcie_cmpl_longest");
399 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
400 	    "pcie_cmpl_shortest", CTLFLAG_RD,
401 	    &softc->generic_stats->pcie_cmpl_shortest, "pcie_cmpl_shortest");
402 
403 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
404 	    "cache_miss_count_cfcq", CTLFLAG_RD,
405 	    &softc->generic_stats->cache_miss_count_cfcq, "cache_miss_count_cfcq");
406 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
407 	    "cache_miss_count_cfcs", CTLFLAG_RD,
408 	    &softc->generic_stats->cache_miss_count_cfcs, "cache_miss_count_cfcs");
409 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
410 	    "cache_miss_count_cfcc", CTLFLAG_RD,
411 	    &softc->generic_stats->cache_miss_count_cfcc, "cache_miss_count_cfcc");
412 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
413 	    "cache_miss_count_cfcm", CTLFLAG_RD,
414 	    &softc->generic_stats->cache_miss_count_cfcm, "cache_miss_count_cfcm");
415 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
416 	    "hw_db_recov_dbs_dropped", CTLFLAG_RD,
417 	    &softc->generic_stats->hw_db_recov_dbs_dropped, "hw_db_recov_dbs_dropped");
418 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
419 	    "hw_db_recov_drops_serviced", CTLFLAG_RD,
420 	    &softc->generic_stats->hw_db_recov_drops_serviced, "hw_db_recov_drops_serviced");
421 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
422 	    "hw_db_recov_dbs_recovered", CTLFLAG_RD,
423 	    &softc->generic_stats->hw_db_recov_dbs_recovered, "hw_db_recov_dbs_recovered");
424 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
425 	    "hw_db_recov_oo_drop_count", CTLFLAG_RD,
426 	    &softc->generic_stats->hw_db_recov_oo_drop_count, "hw_db_recov_oo_drop_count");
427 
428 	return 0;
429 }
430 
431 int
432 bnxt_create_port_stats_sysctls(struct bnxt_softc *softc)
433 {
434 	struct sysctl_oid *oid;
435 	char	name[32];
436 	char	desc[64];
437 
438 	sprintf(name, "port_stats");
439 	sprintf(desc, "Port Stats");
440 	oid = SYSCTL_ADD_NODE(&softc->hw_stats,
441 	    SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name,
442 	        CTLFLAG_RD | CTLFLAG_MPSAFE, 0, desc);
443 	if (!oid)
444 		return ENOMEM;
445 
446 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
447 	    "tx_64b_frames", CTLFLAG_RD,
448 	    &softc->tx_port_stats->tx_64b_frames, "Transmitted 64b frames");
449 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
450 	    "tx_65b_127b_frames", CTLFLAG_RD,
451 	    &softc->tx_port_stats->tx_65b_127b_frames,
452 	    "Transmitted 65b 127b frames");
453 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
454 	    "tx_128b_255b_frames", CTLFLAG_RD,
455 	    &softc->tx_port_stats->tx_128b_255b_frames,
456 	    "Transmitted 128b 255b frames");
457 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
458 	    "tx_256b_511b_frames", CTLFLAG_RD,
459 	    &softc->tx_port_stats->tx_256b_511b_frames,
460 	    "Transmitted 256b 511b frames");
461 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
462 	    "tx_512b_1023b_frames", CTLFLAG_RD,
463 	    &softc->tx_port_stats->tx_512b_1023b_frames,
464 	    "Transmitted 512b 1023b frames");
465 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
466 	    "tx_1024b_1518b_frames", CTLFLAG_RD,
467 	    &softc->tx_port_stats->tx_1024b_1518b_frames,
468 	    "Transmitted 1024b 1518b frames");
469 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
470 	    "tx_good_vlan_frames", CTLFLAG_RD,
471 	    &softc->tx_port_stats->tx_good_vlan_frames,
472 	    "Transmitted good vlan frames");
473 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
474 	    "tx_1519b_2047b_frames", CTLFLAG_RD,
475 	    &softc->tx_port_stats->tx_1519b_2047b_frames,
476 	    "Transmitted 1519b 2047b frames");
477 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
478 	    "tx_2048b_4095b_frames", CTLFLAG_RD,
479 	    &softc->tx_port_stats->tx_2048b_4095b_frames,
480 	    "Transmitted 2048b 4095b frames");
481 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
482 	    "tx_4096b_9216b_frames", CTLFLAG_RD,
483 	    &softc->tx_port_stats->tx_4096b_9216b_frames,
484 	    "Transmitted 4096b 9216b frames");
485 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
486 	    "tx_9217b_16383b_frames", CTLFLAG_RD,
487 	    &softc->tx_port_stats->tx_9217b_16383b_frames,
488 	    "Transmitted 9217b 16383b frames");
489 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
490 	    "tx_good_frames", CTLFLAG_RD,
491 	    &softc->tx_port_stats->tx_good_frames, "Transmitted good frames");
492 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
493 	    "tx_total_frames", CTLFLAG_RD,
494 	    &softc->tx_port_stats->tx_total_frames, "Transmitted total frames");
495 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
496 	    "tx_ucast_frames", CTLFLAG_RD,
497 	    &softc->tx_port_stats->tx_ucast_frames, "Transmitted ucast frames");
498 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
499 	    "tx_mcast_frames", CTLFLAG_RD,
500 	    &softc->tx_port_stats->tx_mcast_frames, "Transmitted mcast frames");
501 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
502 	    "tx_bcast_frames", CTLFLAG_RD,
503 	    &softc->tx_port_stats->tx_bcast_frames, "Transmitted bcast frames");
504 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
505 	    "tx_pause_frames", CTLFLAG_RD,
506 	    &softc->tx_port_stats->tx_pause_frames, "Transmitted pause frames");
507 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
508 	    "tx_pfc_frames", CTLFLAG_RD,
509 	    &softc->tx_port_stats->tx_pfc_frames, "Transmitted pfc frames");
510 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
511 	    "tx_jabber_frames", CTLFLAG_RD,
512 	    &softc->tx_port_stats->tx_jabber_frames, "Transmitted jabber frames");
513 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
514 	    "tx_fcs_err_frames", CTLFLAG_RD,
515 	    &softc->tx_port_stats->tx_fcs_err_frames,
516 	    "Transmitted fcs err frames");
517 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
518 	    "tx_err", CTLFLAG_RD,
519 	    &softc->tx_port_stats->tx_err, "Transmitted err");
520 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
521 	    "tx_fifo_underruns", CTLFLAG_RD,
522 	    &softc->tx_port_stats->tx_fifo_underruns,
523 	    "Transmitted fifo underruns");
524 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
525 	    "tx_pfc_ena_frames_pri0", CTLFLAG_RD,
526 	    &softc->tx_port_stats->tx_pfc_ena_frames_pri0,
527 	    "Transmitted pfc ena frames pri0");
528 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
529 	    "tx_pfc_ena_frames_pri1", CTLFLAG_RD,
530 	    &softc->tx_port_stats->tx_pfc_ena_frames_pri1,
531 	    "Transmitted pfc ena frames pri1");
532 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
533 	    "tx_pfc_ena_frames_pri2", CTLFLAG_RD,
534 	    &softc->tx_port_stats->tx_pfc_ena_frames_pri2,
535 	    "Transmitted pfc ena frames pri2");
536 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
537 	    "tx_pfc_ena_frames_pri3", CTLFLAG_RD,
538 	    &softc->tx_port_stats->tx_pfc_ena_frames_pri3,
539 	    "Transmitted pfc ena frames pri3");
540 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
541 	    "tx_pfc_ena_frames_pri4", CTLFLAG_RD,
542 	    &softc->tx_port_stats->tx_pfc_ena_frames_pri4,
543 	    "Transmitted pfc ena frames pri4");
544 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
545 	    "tx_pfc_ena_frames_pri5", CTLFLAG_RD,
546 	    &softc->tx_port_stats->tx_pfc_ena_frames_pri5,
547 	    "Transmitted pfc ena frames pri5");
548 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
549 	    "tx_pfc_ena_frames_pri6", CTLFLAG_RD,
550 	    &softc->tx_port_stats->tx_pfc_ena_frames_pri6,
551 	    "Transmitted pfc ena frames pri6");
552 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
553 	    "tx_pfc_ena_frames_pri7", CTLFLAG_RD,
554 	    &softc->tx_port_stats->tx_pfc_ena_frames_pri7,
555 	    "Transmitted pfc ena frames pri7");
556 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
557 	    "tx_eee_lpi_events", CTLFLAG_RD,
558 	    &softc->tx_port_stats->tx_eee_lpi_events,
559 	    "Transmitted eee lpi events");
560 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
561 	    "tx_eee_lpi_duration", CTLFLAG_RD,
562 	    &softc->tx_port_stats->tx_eee_lpi_duration,
563 	    "Transmitted eee lpi duration");
564 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
565 	    "tx_llfc_logical_msgs", CTLFLAG_RD,
566 	    &softc->tx_port_stats->tx_llfc_logical_msgs,
567 	    "Transmitted llfc logical msgs");
568 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
569 	    "tx_hcfc_msgs", CTLFLAG_RD,
570 	    &softc->tx_port_stats->tx_hcfc_msgs, "Transmitted hcfc msgs");
571 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
572 	    "tx_total_collisions", CTLFLAG_RD,
573 	    &softc->tx_port_stats->tx_total_collisions,
574 	    "Transmitted total collisions");
575 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
576 	    "tx_bytes", CTLFLAG_RD,
577 	    &softc->tx_port_stats->tx_bytes, "Transmitted bytes");
578 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
579 	    "tx_xthol_frames", CTLFLAG_RD,
580 	    &softc->tx_port_stats->tx_xthol_frames, "Transmitted xthol frames");
581 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
582 	    "tx_stat_discard", CTLFLAG_RD,
583 	    &softc->tx_port_stats->tx_stat_discard, "Transmitted stat discard");
584 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
585 	    "tx_stat_error", CTLFLAG_RD,
586 	    &softc->tx_port_stats->tx_stat_error, "Transmitted stat error");
587 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
588 	    "rx_64b_frames", CTLFLAG_RD,
589 	    &softc->rx_port_stats->rx_64b_frames, "Received 64b frames");
590 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
591 	    "rx_65b_127b_frames", CTLFLAG_RD,
592 	    &softc->rx_port_stats->rx_65b_127b_frames, "Received 65b 127b frames");
593 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
594 	    "rx_128b_255b_frames", CTLFLAG_RD,
595 	    &softc->rx_port_stats->rx_128b_255b_frames,
596 	    "Received 128b 255b frames");
597 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
598 	    "rx_256b_511b_frames", CTLFLAG_RD,
599 	    &softc->rx_port_stats->rx_256b_511b_frames,
600 	    "Received 256b 511b frames");
601 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
602 	    "rx_512b_1023b_frames", CTLFLAG_RD,
603 	    &softc->rx_port_stats->rx_512b_1023b_frames,
604 	    "Received 512b 1023b frames");
605 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
606 	    "rx_1024b_1518b_frames", CTLFLAG_RD,
607 	    &softc->rx_port_stats->rx_1024b_1518b_frames,
608 	    "Received 1024b 1518 frames");
609 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
610 	    "rx_good_vlan_frames", CTLFLAG_RD,
611 	    &softc->rx_port_stats->rx_good_vlan_frames,
612 	    "Received good vlan frames");
613 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
614 	    "rx_1519b_2047b_frames", CTLFLAG_RD,
615 	    &softc->rx_port_stats->rx_1519b_2047b_frames,
616 	    "Received 1519b 2047b frames");
617 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
618 	    "rx_2048b_4095b_frames", CTLFLAG_RD,
619 	    &softc->rx_port_stats->rx_2048b_4095b_frames,
620 	    "Received 2048b 4095b frames");
621 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
622 	    "rx_4096b_9216b_frames", CTLFLAG_RD,
623 	    &softc->rx_port_stats->rx_4096b_9216b_frames,
624 	    "Received 4096b 9216b frames");
625 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
626 	    "rx_9217b_16383b_frames", CTLFLAG_RD,
627 	    &softc->rx_port_stats->rx_9217b_16383b_frames,
628 	    "Received 9217b 16383b frames");
629 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
630 	    "rx_total_frames", CTLFLAG_RD,
631 	    &softc->rx_port_stats->rx_total_frames, "Received total frames");
632 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
633 	    "rx_ucast_frames", CTLFLAG_RD,
634 	    &softc->rx_port_stats->rx_ucast_frames, "Received ucast frames");
635 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
636 	    "rx_mcast_frames", CTLFLAG_RD,
637 	    &softc->rx_port_stats->rx_mcast_frames, "Received mcast frames");
638 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
639 	    "rx_bcast_frames", CTLFLAG_RD,
640 	    &softc->rx_port_stats->rx_bcast_frames, "Received bcast frames");
641 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
642 	    "rx_fcs_err_frames", CTLFLAG_RD,
643 	    &softc->rx_port_stats->rx_fcs_err_frames, "Received fcs err frames");
644 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
645 	    "rx_ctrl_frames", CTLFLAG_RD,
646 	    &softc->rx_port_stats->rx_ctrl_frames, "Received ctrl frames");
647 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
648 	    "rx_pause_frames", CTLFLAG_RD,
649 	    &softc->rx_port_stats->rx_pause_frames, "Received pause frames");
650 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
651 	    "rx_pfc_frames", CTLFLAG_RD,
652 	    &softc->rx_port_stats->rx_pfc_frames, "Received pfc frames");
653 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
654 	    "rx_align_err_frames", CTLFLAG_RD,
655 	    &softc->rx_port_stats->rx_align_err_frames,
656 	    "Received align err frames");
657 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
658 	    "rx_ovrsz_frames", CTLFLAG_RD,
659 	    &softc->rx_port_stats->rx_ovrsz_frames,
660 	    "Received ovrsz frames");
661 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
662 	    "rx_jbr_frames", CTLFLAG_RD,
663 	    &softc->rx_port_stats->rx_jbr_frames,
664 	    "Received jbr frames");
665 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
666 	    "rx_mtu_err_frames", CTLFLAG_RD,
667 	    &softc->rx_port_stats->rx_mtu_err_frames,
668 	    "Received mtu err frames");
669 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
670 	    "rx_tagged_frames", CTLFLAG_RD,
671 	    &softc->rx_port_stats->rx_tagged_frames,
672 	    "Received tagged frames");
673 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
674 	    "rx_double_tagged_frames", CTLFLAG_RD,
675 	    &softc->rx_port_stats->rx_double_tagged_frames,
676 	    "Received double tagged frames");
677 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
678 	    "rx_good_frames", CTLFLAG_RD,
679 	    &softc->rx_port_stats->rx_good_frames,
680 	    "Received good frames");
681 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
682 	    "rx_pfc_ena_frames_pri0", CTLFLAG_RD,
683 	    &softc->rx_port_stats->rx_pfc_ena_frames_pri0,
684 	    "Received pfc ena frames pri0");
685 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
686 	    "rx_pfc_ena_frames_pri1", CTLFLAG_RD,
687 	    &softc->rx_port_stats->rx_pfc_ena_frames_pri1,
688 	    "Received pfc ena frames pri1");
689 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
690 	    "rx_pfc_ena_frames_pri2", CTLFLAG_RD,
691 	    &softc->rx_port_stats->rx_pfc_ena_frames_pri2,
692 	    "Received pfc ena frames pri2");
693 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
694 	    "rx_pfc_ena_frames_pri3", CTLFLAG_RD,
695 	    &softc->rx_port_stats->rx_pfc_ena_frames_pri3,
696 	    "Received pfc ena frames pri3");
697 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
698 	    "rx_pfc_ena_frames_pri4", CTLFLAG_RD,
699 	    &softc->rx_port_stats->rx_pfc_ena_frames_pri4,
700 	    "Received pfc ena frames pri4");
701 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
702 	    "rx_pfc_ena_frames_pri5", CTLFLAG_RD,
703 	    &softc->rx_port_stats->rx_pfc_ena_frames_pri5,
704 	    "Received pfc ena frames pri5");
705 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
706 	    "rx_pfc_ena_frames_pri6", CTLFLAG_RD,
707 	    &softc->rx_port_stats->rx_pfc_ena_frames_pri6,
708 	    "Received pfc ena frames pri6");
709 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
710 	    "rx_pfc_ena_frames_pri7", CTLFLAG_RD,
711 	    &softc->rx_port_stats->rx_pfc_ena_frames_pri7,
712 	    "Received pfc ena frames pri7");
713 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
714 	    "rx_sch_crc_err_frames", CTLFLAG_RD,
715 	    &softc->rx_port_stats->rx_sch_crc_err_frames,
716 	    "Received sch crc err frames");
717 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
718 	    "rx_undrsz_frames", CTLFLAG_RD,
719 	    &softc->rx_port_stats->rx_undrsz_frames, "Received undrsz frames");
720 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
721 	    "rx_eee_lpi_events", CTLFLAG_RD,
722 	    &softc->rx_port_stats->rx_eee_lpi_events, "Received eee lpi events");
723 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
724 	    "rx_eee_lpi_duration", CTLFLAG_RD,
725 	    &softc->rx_port_stats->rx_eee_lpi_duration,
726 	    "Received eee lpi duration");
727 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
728 	    "rx_llfc_physical_msgs", CTLFLAG_RD,
729 	    &softc->rx_port_stats->rx_llfc_physical_msgs,
730 	    "Received llfc physical msgs");
731 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
732 	    "rx_llfc_logical_msgs", CTLFLAG_RD,
733 	    &softc->rx_port_stats->rx_llfc_logical_msgs,
734 	    "Received llfc logical msgs");
735 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
736 	    "rx_llfc_msgs_with_crc_err", CTLFLAG_RD,
737 	    &softc->rx_port_stats->rx_llfc_msgs_with_crc_err,
738 	    "Received llfc msgs with crc err");
739 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
740 	    "rx_hcfc_msgs", CTLFLAG_RD,
741 	    &softc->rx_port_stats->rx_hcfc_msgs, "Received hcfc msgs");
742 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
743 	    "rx_hcfc_msgs_with_crc_err", CTLFLAG_RD,
744 	    &softc->rx_port_stats->rx_hcfc_msgs_with_crc_err,
745 	    "Received hcfc msgs with crc err");
746 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
747 	    "rx_bytes", CTLFLAG_RD,
748 	    &softc->rx_port_stats->rx_bytes, "Received bytes");
749 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
750 	    "rx_runt_bytes", CTLFLAG_RD,
751 	    &softc->rx_port_stats->rx_runt_bytes, "Received runt bytes");
752 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
753 	    "rx_runt_frames", CTLFLAG_RD,
754 	    &softc->rx_port_stats->rx_runt_frames, "Received runt frames");
755 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
756 	    "rx_stat_discard", CTLFLAG_RD,
757 	    &softc->rx_port_stats->rx_stat_discard, "Received stat discard");
758 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
759 	    "rx_stat_err", CTLFLAG_RD,
760 	    &softc->rx_port_stats->rx_stat_err, "Received stat err");
761 
762 	if (BNXT_CHIP_P5_PLUS(softc) &&
763 	    (softc->flags & BNXT_FLAG_FW_CAP_EXT_STATS)) {
764 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
765 		    "tx_bytes_cos0", CTLFLAG_RD,
766 		    &softc->tx_port_stats_ext->tx_bytes_cos0, "Transmitted bytes count cos0");
767 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
768 		    "tx_packets_cos0", CTLFLAG_RD,
769 		    &softc->tx_port_stats_ext->tx_packets_cos0, "Transmitted packets count cos0");
770 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
771 		    "tx_bytes_cos1", CTLFLAG_RD,
772 		    &softc->tx_port_stats_ext->tx_bytes_cos1, "Transmitted bytes count cos1");
773 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
774 		    "tx_packets_cos1", CTLFLAG_RD,
775 		    &softc->tx_port_stats_ext->tx_packets_cos1, "Transmitted packets count cos1");
776 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
777 		    "tx_bytes_cos2", CTLFLAG_RD,
778 		    &softc->tx_port_stats_ext->tx_bytes_cos2, "Transmitted bytes count cos2");
779 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
780 		    "tx_packets_cos2", CTLFLAG_RD,
781 		    &softc->tx_port_stats_ext->tx_packets_cos2, "Transmitted packets count cos2");
782 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
783 		    "tx_bytes_cos3", CTLFLAG_RD,
784 		    &softc->tx_port_stats_ext->tx_bytes_cos3, "Transmitted bytes count cos3");
785 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
786 		    "tx_packets_cos3", CTLFLAG_RD,
787 		    &softc->tx_port_stats_ext->tx_packets_cos3, "Transmitted packets count cos3");
788 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
789 		    "tx_bytes_cos4", CTLFLAG_RD,
790 		    &softc->tx_port_stats_ext->tx_bytes_cos4, "Transmitted bytes count cos4");
791 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
792 		    "tx_packets_cos4", CTLFLAG_RD,
793 		    &softc->tx_port_stats_ext->tx_packets_cos4, "Transmitted packets count cos4");
794 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
795 		    "tx_bytes_cos5", CTLFLAG_RD,
796 		    &softc->tx_port_stats_ext->tx_bytes_cos5, "Transmitted bytes count cos5");
797 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
798 		    "tx_packets_cos5", CTLFLAG_RD,
799 		    &softc->tx_port_stats_ext->tx_packets_cos5, "Transmitted packets count cos5");
800 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
801 		    "tx_bytes_cos6", CTLFLAG_RD,
802 		    &softc->tx_port_stats_ext->tx_bytes_cos6, "Transmitted bytes count cos6");
803 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
804 		    "tx_packets_cos6", CTLFLAG_RD,
805 		    &softc->tx_port_stats_ext->tx_packets_cos6, "Transmitted packets count cos6");
806 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
807 		    "tx_bytes_cos7", CTLFLAG_RD,
808 		    &softc->tx_port_stats_ext->tx_bytes_cos7, "Transmitted bytes count cos7");
809 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
810 		    "tx_packets_cos7", CTLFLAG_RD,
811 		    &softc->tx_port_stats_ext->tx_packets_cos7, "Transmitted packets count cos7");
812 
813 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
814 		    "tx_bytes_pri0", CTLFLAG_RD,
815 		    &softc->tx_bytes_pri[0], "Transmitted bytes count pri0");
816 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
817 		    "tx_packets_pri0", CTLFLAG_RD,
818 		    &softc->tx_packets_pri[0], "Transmitted packets count pri0");
819 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
820 		    "tx_bytes_pri1", CTLFLAG_RD,
821 		    &softc->tx_bytes_pri[1], "Transmitted bytes count pri1");
822 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
823 		    "tx_packets_pri1", CTLFLAG_RD,
824 		    &softc->tx_packets_pri[1], "Transmitted packets count pri1");
825 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
826 		    "tx_bytes_pri2", CTLFLAG_RD,
827 		    &softc->tx_bytes_pri[2], "Transmitted bytes count pri2");
828 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
829 		    "tx_packets_pri2", CTLFLAG_RD,
830 		    &softc->tx_packets_pri[2], "Transmitted packets count pri2");
831 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
832 		    "tx_bytes_pri3", CTLFLAG_RD,
833 		    &softc->tx_bytes_pri[3], "Transmitted bytes count pri3");
834 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
835 		    "tx_packets_pri3", CTLFLAG_RD,
836 		    &softc->tx_packets_pri[3], "Transmitted packets count pri3");
837 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
838 		    "tx_bytes_pri4", CTLFLAG_RD,
839 		    &softc->tx_bytes_pri[4], "Transmitted bytes count pri4");
840 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
841 		    "tx_packets_pri4", CTLFLAG_RD,
842 		    &softc->tx_packets_pri[4], "Transmitted packets count pri4");
843 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
844 		    "tx_bytes_pri5", CTLFLAG_RD,
845 		    &softc->tx_bytes_pri[5], "Transmitted bytes count pri5");
846 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
847 		    "tx_packets_pri5", CTLFLAG_RD,
848 		    &softc->tx_packets_pri[5], "Transmitted packets count pri5");
849 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
850 		    "tx_bytes_pri6", CTLFLAG_RD,
851 		    &softc->tx_bytes_pri[6], "Transmitted bytes count pri6");
852 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
853 		    "tx_packets_pri6", CTLFLAG_RD,
854 		    &softc->tx_packets_pri[6], "Transmitted packets count pri6");
855 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
856 		    "tx_bytes_pri7", CTLFLAG_RD,
857 		    &softc->tx_bytes_pri[7], "Transmitted bytes count pri7");
858 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
859 		    "tx_packets_pri7", CTLFLAG_RD,
860 		    &softc->tx_packets_pri[7], "Transmitted packets count pri7");
861 
862 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
863 		    "pfc_pri0_tx_duration_us", CTLFLAG_RD,
864 		    &softc->tx_port_stats_ext->pfc_pri0_tx_duration_us, "Time duration between"
865 		    "XON to XOFF and XOFF to XON for pri0");
866 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
867 		    "pfc_pri0_tx_transitions", CTLFLAG_RD,
868 		    &softc->tx_port_stats_ext->pfc_pri0_tx_transitions, "Num times transition"
869 		    "between XON to XOFF and XOFF to XON for pri0");
870 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
871 		    "pfc_pri1_tx_duration_us", CTLFLAG_RD,
872 		    &softc->tx_port_stats_ext->pfc_pri1_tx_duration_us, "Time duration between"
873 		    "XON to XOFF and XOFF to XON for pri1");
874 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
875 		    "pfc_pri1_tx_transitions", CTLFLAG_RD,
876 		    &softc->tx_port_stats_ext->pfc_pri1_tx_transitions, "Num times transition"
877 		    "between XON to XOFF and XOFF to XON for pri1");
878 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
879 		    "pfc_pri2_tx_duration_us", CTLFLAG_RD,
880 		    &softc->tx_port_stats_ext->pfc_pri2_tx_duration_us, "Time duration between"
881 		    "XON to XOFF and XOFF to XON for pri2");
882 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
883 		    "pfc_pri2_tx_transitions", CTLFLAG_RD,
884 		    &softc->tx_port_stats_ext->pfc_pri2_tx_transitions, "Num times transition"
885 		    "between XON to XOFF and XOFF to XON for pri2");
886 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
887 		    "pfc_pri3_tx_duration_us", CTLFLAG_RD,
888 		    &softc->tx_port_stats_ext->pfc_pri3_tx_duration_us, "Time duration between"
889 		    "XON to XOFF and XOFF to XON for pri3");
890 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
891 		    "pfc_pri3_tx_transitions", CTLFLAG_RD,
892 		    &softc->tx_port_stats_ext->pfc_pri3_tx_transitions, "Num times transition"
893 		    "between XON to XOFF and XOFF to XON for pri3");
894 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
895 		    "pfc_pri4_tx_duration_us", CTLFLAG_RD,
896 		    &softc->tx_port_stats_ext->pfc_pri4_tx_duration_us, "Time duration between"
897 		    "XON to XOFF and XOFF to XON for pri4");
898 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
899 		    "pfc_pri4_tx_transitions", CTLFLAG_RD,
900 		    &softc->tx_port_stats_ext->pfc_pri4_tx_transitions, "Num times transition"
901 		    "between XON to XOFF and XOFF to XON for pri4");
902 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
903 		    "pfc_pri5_tx_duration_us", CTLFLAG_RD,
904 		    &softc->tx_port_stats_ext->pfc_pri5_tx_duration_us, "Time duration between"
905 		    "XON to XOFF and XOFF to XON for pri5");
906 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
907 		    "pfc_pri5_tx_transitions", CTLFLAG_RD,
908 		    &softc->tx_port_stats_ext->pfc_pri5_tx_transitions, "Num times transition"
909 		    "between XON to XOFF and XOFF to XON for pri5");
910 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
911 		    "pfc_pri6_tx_duration_us", CTLFLAG_RD,
912 		    &softc->tx_port_stats_ext->pfc_pri6_tx_duration_us, "Time duration between"
913 		    "XON to XOFF and XOFF to XON for pri6");
914 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
915 		    "pfc_pri6_tx_transitions", CTLFLAG_RD,
916 		    &softc->tx_port_stats_ext->pfc_pri6_tx_transitions, "Num times transition"
917 		    "between XON to XOFF and XOFF to XON for pri6");
918 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
919 		    "pfc_pri7_tx_duration_us", CTLFLAG_RD,
920 		    &softc->tx_port_stats_ext->pfc_pri7_tx_duration_us, "Time duration between"
921 		    "XON to XOFF and XOFF to XON for pri7");
922 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
923 		    "pfc_pri7_tx_transitions", CTLFLAG_RD,
924 		    &softc->tx_port_stats_ext->pfc_pri7_tx_transitions, "Num times transition"
925 		    "between XON to XOFF and XOFF to XON for pri7");
926 
927 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
928 		    "link_down_events", CTLFLAG_RD,
929 		    &softc->rx_port_stats_ext->link_down_events, "Num times link states down");
930 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
931 		    "continuous_pause_events", CTLFLAG_RD,
932 		    &softc->rx_port_stats_ext->continuous_pause_events, "Num times pause events");
933 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
934 		    "resume_pause_events", CTLFLAG_RD,
935 		    &softc->rx_port_stats_ext->resume_pause_events, "Num times pause events"
936 		    "resumes");
937 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
938 		    "continuous_roce_pause_events", CTLFLAG_RD,
939 		    &softc->rx_port_stats_ext->continuous_roce_pause_events, "Num times roce"
940 		    "pause events");
941 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
942 		    "resume_roce_pause_events", CTLFLAG_RD,
943 		    &softc->rx_port_stats_ext->resume_roce_pause_events, "Num times roce pause"
944 		    "events resumes");
945 
946 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
947 		    "rx_bytes_cos0", CTLFLAG_RD,
948 		    &softc->rx_port_stats_ext->rx_bytes_cos0, "Received bytes count cos0");
949 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
950 		    "rx_packets_cos0", CTLFLAG_RD,
951 		    &softc->rx_port_stats_ext->rx_packets_cos0, "Received packets count cos0");
952 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
953 		    "rx_bytes_cos1", CTLFLAG_RD,
954 		    &softc->rx_port_stats_ext->rx_bytes_cos1, "Received bytes count cos1");
955 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
956 		    "rx_packets_cos1", CTLFLAG_RD,
957 		    &softc->rx_port_stats_ext->rx_packets_cos1, "Received packets count cos1");
958 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
959 		    "rx_bytes_cos2", CTLFLAG_RD,
960 		    &softc->rx_port_stats_ext->rx_bytes_cos2, "Received bytes count cos2");
961 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
962 		    "rx_packets_cos2", CTLFLAG_RD,
963 		    &softc->rx_port_stats_ext->rx_packets_cos2, "Received packets count cos2");
964 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
965 		    "rx_bytes_cos3", CTLFLAG_RD,
966 		    &softc->rx_port_stats_ext->rx_bytes_cos3, "Received bytes count cos3");
967 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
968 		    "rx_packets_cos3", CTLFLAG_RD,
969 		    &softc->rx_port_stats_ext->rx_packets_cos3, "Received packets count cos3");
970 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
971 		    "rx_bytes_cos4", CTLFLAG_RD,
972 		    &softc->rx_port_stats_ext->rx_bytes_cos4, "Received bytes count cos4");
973 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
974 		    "rx_packets_cos4", CTLFLAG_RD,
975 		    &softc->rx_port_stats_ext->rx_packets_cos4, "Received packets count cos4");
976 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
977 		    "rx_bytes_cos5", CTLFLAG_RD,
978 		    &softc->rx_port_stats_ext->rx_bytes_cos5, "Received bytes count cos5");
979 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
980 		    "rx_packets_cos5", CTLFLAG_RD,
981 		    &softc->rx_port_stats_ext->rx_packets_cos5, "Received packets count cos5");
982 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
983 		    "rx_bytes_cos6", CTLFLAG_RD,
984 		    &softc->rx_port_stats_ext->rx_bytes_cos6, "Received bytes count cos6");
985 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
986 		    "rx_packets_cos6", CTLFLAG_RD,
987 		    &softc->rx_port_stats_ext->rx_packets_cos6, "Received packets count cos6");
988 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
989 		    "rx_bytes_cos7", CTLFLAG_RD,
990 		    &softc->rx_port_stats_ext->rx_bytes_cos7, "Received bytes count cos7");
991 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
992 		    "rx_packets_cos7", CTLFLAG_RD,
993 		    &softc->rx_port_stats_ext->rx_packets_cos7, "Received packets count cos7");
994 
995 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
996 		    "rx_bytes_pri0", CTLFLAG_RD,
997 		    &softc->rx_bytes_pri[0], "Received bytes count pri0");
998 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
999 		    "rx_packets_pri0", CTLFLAG_RD,
1000 		    &softc->rx_packets_pri[0], "Received packets count pri0");
1001 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1002 		    "rx_bytes_pri1", CTLFLAG_RD,
1003 		    &softc->rx_bytes_pri[1], "Received bytes count pri1");
1004 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1005 		    "rx_packets_pri1", CTLFLAG_RD,
1006 		    &softc->rx_packets_pri[1], "Received packets count pri1");
1007 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1008 		    "rx_bytes_pri2", CTLFLAG_RD,
1009 		    &softc->rx_bytes_pri[2], "Received bytes count pri2");
1010 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1011 		    "rx_packets_pri2", CTLFLAG_RD,
1012 		    &softc->rx_packets_pri[2], "Received packets count pri2");
1013 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1014 		    "rx_bytes_pri3", CTLFLAG_RD,
1015 		    &softc->rx_bytes_pri[3], "Received bytes count pri3");
1016 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1017 		    "rx_packets_pri3", CTLFLAG_RD,
1018 		    &softc->rx_packets_pri[3], "Received packets count pri3");
1019 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1020 		    "rx_bytes_pri4", CTLFLAG_RD,
1021 		    &softc->rx_bytes_pri[4], "Received bytes count pri4");
1022 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1023 		    "rx_packets_pri4", CTLFLAG_RD,
1024 		    &softc->rx_packets_pri[4], "Received packets count pri4");
1025 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1026 		    "rx_bytes_pri5", CTLFLAG_RD,
1027 		    &softc->rx_bytes_pri[5], "Received bytes count pri5");
1028 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1029 		    "rx_packets_pri5", CTLFLAG_RD,
1030 		    &softc->rx_packets_pri[5], "Received packets count pri5");
1031 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1032 		    "rx_bytes_pri6", CTLFLAG_RD,
1033 		    &softc->rx_bytes_pri[6], "Received bytes count pri6");
1034 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1035 		    "rx_packets_pri6", CTLFLAG_RD,
1036 		    &softc->rx_packets_pri[6], "Received packets count pri6");
1037 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1038 		    "rx_bytes_pri7", CTLFLAG_RD,
1039 		    &softc->rx_bytes_pri[7], "Received bytes count pri7");
1040 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1041 		    "rx_packets_pri7", CTLFLAG_RD,
1042 		    &softc->rx_packets_pri[7], "Received packets count pri7");
1043 
1044 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1045 		    "pfc_pri0_rx_duration_us", CTLFLAG_RD,
1046 		    &softc->rx_port_stats_ext->pfc_pri0_rx_duration_us, "Time duration in receiving"
1047 		    "between XON to XOFF and XOFF to XON for pri0");
1048 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1049 		    "pfc_pri0_rx_transitions", CTLFLAG_RD,
1050 		    &softc->rx_port_stats_ext->pfc_pri0_rx_transitions, "Num times rx transition"
1051 		    "between XON to XOFF and XOFF to XON for pri0");
1052 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1053 		    "pfc_pri1_rx_duration_us", CTLFLAG_RD,
1054 		    &softc->rx_port_stats_ext->pfc_pri1_rx_duration_us, "Time duration in receiving"
1055 		    "between XON to XOFF and XOFF to XON for pri1");
1056 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1057 		    "pfc_pri1_rx_transitions", CTLFLAG_RD,
1058 		    &softc->rx_port_stats_ext->pfc_pri1_rx_transitions, "Num times rx transition"
1059 		    "between XON to XOFF and XOFF to XON for pri1");
1060 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1061 		    "pfc_pri2_rx_duration_us", CTLFLAG_RD,
1062 		    &softc->rx_port_stats_ext->pfc_pri2_rx_duration_us, "Time duration in receiving"
1063 		    "between XON to XOFF and XOFF to XON for pri2");
1064 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1065 		    "pfc_pri2_rx_transitions", CTLFLAG_RD,
1066 		    &softc->rx_port_stats_ext->pfc_pri2_rx_transitions, "Num times rx transition"
1067 		    "between XON to XOFF and XOFF to XON for pri2");
1068 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1069 		    "pfc_pri3_rx_duration_us", CTLFLAG_RD,
1070 		    &softc->rx_port_stats_ext->pfc_pri3_rx_duration_us, "Time duration in receiving"
1071 		    "between XON to XOFF and XOFF to XON for pri3");
1072 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1073 		    "pfc_pri3_rx_transitions", CTLFLAG_RD,
1074 		    &softc->rx_port_stats_ext->pfc_pri3_rx_transitions, "Num times rx transition"
1075 		    "between XON to XOFF and XOFF to XON for pri3");
1076 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1077 		    "pfc_pri4_rx_duration_us", CTLFLAG_RD,
1078 		    &softc->rx_port_stats_ext->pfc_pri4_rx_duration_us, "Time duration in receiving"
1079 		    "between XON to XOFF and XOFF to XON for pri4");
1080 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1081 		    "pfc_pri4_rx_transitions", CTLFLAG_RD,
1082 		    &softc->rx_port_stats_ext->pfc_pri4_rx_transitions, "Num times rx transition"
1083 		    "between XON to XOFF and XOFF to XON for pri4");
1084 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1085 		    "pfc_pri5_rx_duration_us", CTLFLAG_RD,
1086 		    &softc->rx_port_stats_ext->pfc_pri5_rx_duration_us, "Time duration in receiving"
1087 		    "between XON to XOFF and XOFF to XON for pri5");
1088 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1089 		    "pfc_pri5_rx_transitions", CTLFLAG_RD,
1090 		    &softc->rx_port_stats_ext->pfc_pri5_rx_transitions, "Num times rx transition"
1091 		    "between XON to XOFF and XOFF to XON for pri5");
1092 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1093 		    "pfc_pri6_rx_duration_us", CTLFLAG_RD,
1094 		    &softc->rx_port_stats_ext->pfc_pri6_rx_duration_us, "Time duration in receiving"
1095 		    "between XON to XOFF and XOFF to XON for pri6");
1096 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1097 		    "pfc_pri6_rx_transitions", CTLFLAG_RD,
1098 		    &softc->rx_port_stats_ext->pfc_pri6_rx_transitions, "Num times rx transition"
1099 		    "between XON to XOFF and XOFF to XON for pri6");
1100 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1101 		    "pfc_pri7_rx_duration_us", CTLFLAG_RD,
1102 		    &softc->rx_port_stats_ext->pfc_pri7_rx_duration_us, "Time duration in receiving"
1103 		    "between XON to XOFF and XOFF to XON for pri7");
1104 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1105 		    "pfc_pri7_rx_transitions", CTLFLAG_RD,
1106 		    &softc->rx_port_stats_ext->pfc_pri7_rx_transitions, "Num times rx transition"
1107 		    "between XON to XOFF and XOFF to XON for pri7");
1108 
1109 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1110 		    "rx_bits", CTLFLAG_RD,
1111 		    &softc->rx_port_stats_ext->rx_bits, "total number of received bits");
1112 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1113 		    "rx_buffer_passed_threshold", CTLFLAG_RD,
1114 		    &softc->rx_port_stats_ext->rx_buffer_passed_threshold, "num of events port"
1115 		    "buffer"
1116 		    "was over 85%");
1117 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1118 		    "rx_pcs_symbol_err", CTLFLAG_RD,
1119 		    &softc->rx_port_stats_ext->rx_pcs_symbol_err, "num of symbol errors wasn't"
1120 		    "corrected by FEC");
1121 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1122 		    "rx_corrected_bits", CTLFLAG_RD,
1123 		    &softc->rx_port_stats_ext->rx_corrected_bits, "num of bits corrected by FEC");
1124 
1125 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1126 		    "rx_discard_bytes_cos0", CTLFLAG_RD,
1127 		    &softc->rx_port_stats_ext->rx_discard_bytes_cos0, "num of rx discard bytes"
1128 		    "count on cos0");
1129 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1130 		    "rx_discard_packets_cos0", CTLFLAG_RD,
1131 		    &softc->rx_port_stats_ext->rx_discard_packets_cos0, "num of rx discard packets"
1132 		    "count on cos0");
1133 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1134 		    "rx_discard_bytes_cos1", CTLFLAG_RD,
1135 		    &softc->rx_port_stats_ext->rx_discard_bytes_cos1, "num of rx discard bytes"
1136 		    "count on cos1");
1137 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1138 		    "rx_discard_packets_cos1", CTLFLAG_RD,
1139 		    &softc->rx_port_stats_ext->rx_discard_packets_cos1, "num of rx discard packets"
1140 		    "count on cos1");
1141 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1142 		    "rx_discard_bytes_cos2", CTLFLAG_RD,
1143 		    &softc->rx_port_stats_ext->rx_discard_bytes_cos2, "num of rx discard bytes"
1144 		    "count on cos2");
1145 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1146 		    "rx_discard_packets_cos2", CTLFLAG_RD,
1147 		    &softc->rx_port_stats_ext->rx_discard_packets_cos2, "num of rx discard packets"
1148 		    "count on cos2");
1149 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1150 		    "rx_discard_bytes_cos3", CTLFLAG_RD,
1151 		    &softc->rx_port_stats_ext->rx_discard_bytes_cos3, "num of rx discard bytes"
1152 		    "count on cos3");
1153 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1154 		    "rx_discard_packets_cos3", CTLFLAG_RD,
1155 		    &softc->rx_port_stats_ext->rx_discard_packets_cos3, "num of rx discard packets"
1156 		    "count on cos3");
1157 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1158 		    "rx_discard_bytes_cos4", CTLFLAG_RD,
1159 		    &softc->rx_port_stats_ext->rx_discard_bytes_cos4, "num of rx discard bytes"
1160 		    "count on cos4");
1161 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1162 		    "rx_discard_packets_cos4", CTLFLAG_RD,
1163 		    &softc->rx_port_stats_ext->rx_discard_packets_cos4, "num of rx discard packets"
1164 		    "count on cos4");
1165 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1166 		    "rx_discard_bytes_cos5", CTLFLAG_RD,
1167 		    &softc->rx_port_stats_ext->rx_discard_bytes_cos5, "num of rx discard bytes"
1168 		    "count on cos5");
1169 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1170 		    "rx_discard_packets_cos5", CTLFLAG_RD,
1171 		    &softc->rx_port_stats_ext->rx_discard_packets_cos5, "num of rx discard packets"
1172 		    "count on cos5");
1173 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1174 		    "rx_discard_bytes_cos6", CTLFLAG_RD,
1175 		    &softc->rx_port_stats_ext->rx_discard_bytes_cos6, "num of rx discard bytes"
1176 		    "count on cos6");
1177 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1178 		    "rx_discard_packets_cos6", CTLFLAG_RD,
1179 		    &softc->rx_port_stats_ext->rx_discard_packets_cos6, "num of rx discard packets"
1180 		    "count on cos6");
1181 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1182 		    "rx_discard_bytes_cos7", CTLFLAG_RD,
1183 		    &softc->rx_port_stats_ext->rx_discard_bytes_cos7, "num of rx discard bytes"
1184 		    "count on cos7");
1185 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1186 		    "rx_discard_packets_cos7", CTLFLAG_RD,
1187 		    &softc->rx_port_stats_ext->rx_discard_packets_cos7, "num of rx discard packets"
1188 		    "count on cos7");
1189 	}
1190 
1191 
1192 	return 0;
1193 }
1194 
1195 int
1196 bnxt_create_rx_sysctls(struct bnxt_softc *softc, int rxr)
1197 {
1198 	struct sysctl_oid *oid;
1199 	struct ctx_hw_stats *rx_stats = (void *)softc->rx_stats[rxr].idi_vaddr;
1200 	char	name[32];
1201 	char	desc[64];
1202 
1203 	sprintf(name, "rxq%d", rxr);
1204 	sprintf(desc, "receive queue %d", rxr);
1205 	oid = SYSCTL_ADD_NODE(&softc->hw_stats,
1206 	    SYSCTL_CHILDREN(softc->hw_stats_oid), OID_AUTO, name,
1207 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, desc);
1208 	if (!oid)
1209 		return ENOMEM;
1210 
1211 	if (BNXT_CHIP_P5_PLUS(softc))
1212 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1213 		    "nq_num_ints", CTLFLAG_RD, &softc->nq_rings[rxr].int_count,
1214 		    "Num Interrupts");
1215 	else
1216 		SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1217 		    "rq_num_ints", CTLFLAG_RD, &softc->rx_cp_rings[rxr].int_count,
1218 		    "Num Interrupts");
1219 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1220 	    "ucast_pkts", CTLFLAG_RD, &rx_stats->rx_ucast_pkts,
1221 	    "unicast packets received");
1222 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1223 	    "mcast_pkts", CTLFLAG_RD, &rx_stats->rx_mcast_pkts,
1224 	    "multicast packets received");
1225 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1226 	    "bcast_pkts", CTLFLAG_RD, &rx_stats->rx_bcast_pkts,
1227 	    "broadcast packets received");
1228 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1229 	    "discard_pkts", CTLFLAG_RD,
1230 	    &rx_stats->rx_discard_pkts, "discarded receive packets");
1231 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1232 	    "error_pkts", CTLFLAG_RD, &rx_stats->rx_error_pkts,
1233 	    "Error receive packets");
1234 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1235 	    "ucast_bytes", CTLFLAG_RD, &rx_stats->rx_ucast_bytes,
1236 	    "unicast bytes received");
1237 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1238 	    "mcast_bytes", CTLFLAG_RD, &rx_stats->rx_mcast_bytes,
1239 	    "multicast bytes received");
1240 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1241 	    "bcast_bytes", CTLFLAG_RD, &rx_stats->rx_bcast_bytes,
1242 	    "broadcast bytes received");
1243 
1244 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1245 	    "tpa_pkts", CTLFLAG_RD, &rx_stats->tpa_pkts,
1246 	    "TPA packets");
1247 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1248 	    "tpa_bytes", CTLFLAG_RD, &rx_stats->tpa_bytes,
1249 	    "TPA bytes");
1250 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1251 	    "tpa_events", CTLFLAG_RD, &rx_stats->tpa_events,
1252 	    "TPA events");
1253 	SYSCTL_ADD_QUAD(&softc->hw_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
1254 	    "tpa_aborts", CTLFLAG_RD, &rx_stats->tpa_aborts,
1255 	    "TPA aborts");
1256 
1257 	return 0;
1258 }
1259 
1260 static char *bnxt_chip_type[] = {
1261 	"ASIC",
1262 	"FPGA",
1263 	"Palladium",
1264 	"Unknown"
1265 };
1266 #define MAX_CHIP_TYPE 3
1267 
1268 static char *bnxt_parse_pkglog(int desired_field, uint8_t *data, size_t datalen)
1269 {
1270 	char    *retval = NULL;
1271 	char    *p;
1272 	char    *value;
1273 	int     field = 0;
1274 
1275 	if (datalen < 1)
1276 		return NULL;
1277 	/* null-terminate the log data (removing last '\n'): */
1278 	data[datalen - 1] = 0;
1279 	for (p = data; *p != 0; p++) {
1280 		field = 0;
1281 		retval = NULL;
1282 		while (*p != 0 && *p != '\n') {
1283 			value = p;
1284 			while (*p != 0 && *p != '\t' && *p != '\n')
1285 				p++;
1286 			if (field == desired_field)
1287 				retval = value;
1288 			if (*p != '\t')
1289 				break;
1290 			*p = 0;
1291 			field++;
1292 			p++;
1293 		}
1294 		if (*p == 0)
1295 			break;
1296 		*p = 0;
1297 	}
1298 	return retval;
1299 }
1300 
1301 static int
1302 bnxt_package_ver_sysctl(SYSCTL_HANDLER_ARGS)
1303 {
1304 	struct bnxt_softc *softc = arg1;
1305 	struct iflib_dma_info dma_data;
1306 	char *pkglog = NULL;
1307 	char *p;
1308 	char unk[] = "<unknown>";
1309 	char *buf = unk;
1310 	int rc;
1311 	uint16_t ordinal = BNX_DIR_ORDINAL_FIRST;
1312 	uint16_t index;
1313 	uint32_t data_len;
1314 
1315 	rc = bnxt_hwrm_nvm_find_dir_entry(softc, BNX_DIR_TYPE_PKG_LOG,
1316 	    &ordinal, BNX_DIR_EXT_NONE, &index, false,
1317 	    HWRM_NVM_FIND_DIR_ENTRY_INPUT_OPT_ORDINAL_EQ,
1318 	    &data_len, NULL, NULL);
1319 	dma_data.idi_vaddr = NULL;
1320 	if (rc == 0 && data_len) {
1321 		rc = iflib_dma_alloc(softc->ctx, data_len, &dma_data,
1322 		    BUS_DMA_NOWAIT);
1323 		if (rc == 0) {
1324 			rc = bnxt_hwrm_nvm_read(softc, index, 0, data_len,
1325 			    &dma_data);
1326 			if (rc == 0) {
1327 				pkglog = dma_data.idi_vaddr;
1328 				p = bnxt_parse_pkglog(BNX_PKG_LOG_FIELD_IDX_PKG_VERSION, pkglog, data_len);
1329 				if (p && *p != 0 && isdigit(*p))
1330 					buf = p;
1331 			}
1332 		} else
1333 			dma_data.idi_vaddr = NULL;
1334 	}
1335 
1336 	rc = sysctl_handle_string(oidp, buf, 0, req);
1337 	if (dma_data.idi_vaddr)
1338 		iflib_dma_free(&dma_data);
1339 	return rc;
1340 }
1341 
1342 static int
1343 bnxt_hwrm_min_ver_sysctl(SYSCTL_HANDLER_ARGS)
1344 {
1345 	struct bnxt_softc *softc = arg1;
1346 	char buf[16];
1347 	uint8_t	newver[3];
1348 	int rc;
1349 
1350 	sprintf(buf, "%hhu.%hhu.%hhu", softc->ver_info->hwrm_min_major,
1351 	    softc->ver_info->hwrm_min_minor, softc->ver_info->hwrm_min_update);
1352 
1353 	rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
1354 	if (rc || req->newptr == NULL)
1355 		return rc;
1356 	if (sscanf(buf, "%hhu.%hhu.%hhu%*c", &newver[0], &newver[1],
1357 	    &newver[2]) != 3)
1358 		return EINVAL;
1359 	softc->ver_info->hwrm_min_major = newver[0];
1360 	softc->ver_info->hwrm_min_minor = newver[1];
1361 	softc->ver_info->hwrm_min_update = newver[2];
1362 	bnxt_check_hwrm_version(softc);
1363 
1364 	return rc;
1365 }
1366 
1367 int
1368 bnxt_create_ver_sysctls(struct bnxt_softc *softc)
1369 {
1370 	struct bnxt_ver_info *vi = softc->ver_info;
1371 	struct sysctl_oid *oid = vi->ver_oid;
1372 
1373 	if (!oid)
1374 		return ENOMEM;
1375 
1376 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1377 	    "hwrm_if", CTLFLAG_RD, vi->hwrm_if_ver, 0,
1378 	    "HWRM interface version");
1379 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1380 	    "driver_hwrm_if", CTLFLAG_RD, vi->driver_hwrm_if_ver, 0,
1381 	    "HWRM firmware version");
1382 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1383 	    "mgmt_fw", CTLFLAG_RD, vi->mgmt_fw_ver, 0,
1384 	    "management firmware version");
1385 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1386 	    "netctrl_fw", CTLFLAG_RD, vi->netctrl_fw_ver, 0,
1387 	    "network control firmware version");
1388 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1389 	    "roce_fw", CTLFLAG_RD, vi->roce_fw_ver, 0,
1390 	    "RoCE firmware version");
1391 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1392 	    "fw_ver", CTLFLAG_RD, vi->fw_ver_str, 0,
1393 	    "Firmware version");
1394 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1395 	    "phy", CTLFLAG_RD, vi->phy_ver, 0,
1396 	    "PHY version");
1397 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1398 	    "hwrm_fw_name", CTLFLAG_RD, vi->hwrm_fw_name, 0,
1399 	    "HWRM firmware name");
1400 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1401 	    "mgmt_fw_name", CTLFLAG_RD, vi->mgmt_fw_name, 0,
1402 	    "management firmware name");
1403 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1404 	    "netctrl_fw_name", CTLFLAG_RD, vi->netctrl_fw_name, 0,
1405 	    "network control firmware name");
1406 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1407 	    "roce_fw_name", CTLFLAG_RD, vi->roce_fw_name, 0,
1408 	    "RoCE firmware name");
1409 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1410 	    "phy_vendor", CTLFLAG_RD, vi->phy_vendor, 0,
1411 	    "PHY vendor name");
1412 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1413 	    "phy_partnumber", CTLFLAG_RD, vi->phy_partnumber, 0,
1414 	    "PHY vendor part number");
1415 	SYSCTL_ADD_U16(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1416 	    "chip_num", CTLFLAG_RD, &vi->chip_num, 0, "chip number");
1417 	SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1418 	    "chip_rev", CTLFLAG_RD, &vi->chip_rev, 0, "chip revision");
1419 	SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1420 	    "chip_metal", CTLFLAG_RD, &vi->chip_metal, 0, "chip metal number");
1421 	SYSCTL_ADD_U8(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1422 	    "chip_bond_id", CTLFLAG_RD, &vi->chip_bond_id, 0,
1423 	    "chip bond id");
1424 	SYSCTL_ADD_STRING(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1425 	    "chip_type", CTLFLAG_RD, vi->chip_type > MAX_CHIP_TYPE ?
1426 	    bnxt_chip_type[MAX_CHIP_TYPE] : bnxt_chip_type[vi->chip_type], 0,
1427 	    "RoCE firmware name");
1428 	if (!BNXT_VF(softc))
1429 		SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1430 		    "package_ver", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
1431 		    softc, 0, bnxt_package_ver_sysctl, "A",
1432 		    "currently installed package version");
1433 	SYSCTL_ADD_PROC(&vi->ver_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1434 	    "hwrm_min_ver", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1435 	    softc, 0, bnxt_hwrm_min_ver_sysctl, "A",
1436 	    "minimum hwrm API vesion to support");
1437 
1438 	return 0;
1439 }
1440 
1441 int
1442 bnxt_create_nvram_sysctls(struct bnxt_nvram_info *ni)
1443 {
1444 	struct sysctl_oid *oid = ni->nvm_oid;
1445 
1446 	if (!oid)
1447 		return ENOMEM;
1448 
1449 	SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1450 	    "mfg_id", CTLFLAG_RD, &ni->mfg_id, 0, "manufacturer id");
1451 	SYSCTL_ADD_U16(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1452 	    "device_id", CTLFLAG_RD, &ni->device_id, 0, "device id");
1453 	SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1454 	    "sector_size", CTLFLAG_RD, &ni->sector_size, 0, "sector size");
1455 	SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1456 	    "size", CTLFLAG_RD, &ni->size, 0, "nvram total size");
1457 	SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1458 	    "reserved_size", CTLFLAG_RD, &ni->reserved_size, 0,
1459 	    "total reserved space");
1460 	SYSCTL_ADD_U32(&ni->nvm_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
1461 	    "available_size", CTLFLAG_RD, &ni->available_size, 0,
1462 	    "total available space");
1463 
1464 	return 0;
1465 }
1466 
1467 static int
1468 bnxt_rss_key_sysctl(SYSCTL_HANDLER_ARGS)
1469 {
1470 	struct bnxt_softc *softc = arg1;
1471 	char buf[HW_HASH_KEY_SIZE*2+1] = {0};
1472 	char *p;
1473 	int i;
1474 	int rc;
1475 
1476 	for (p = buf, i=0; i<HW_HASH_KEY_SIZE; i++)
1477 		p += sprintf(p, "%02x", softc->vnic_info.rss_hash_key[i]);
1478 
1479 	rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
1480 	if (rc || req->newptr == NULL)
1481 		return rc;
1482 
1483 	if (strspn(buf, "0123456789abcdefABCDEF") != (HW_HASH_KEY_SIZE * 2))
1484 		return EINVAL;
1485 
1486 	for (p = buf, i=0; i<HW_HASH_KEY_SIZE; i++) {
1487 		if (sscanf(p, "%02hhx", &softc->vnic_info.rss_hash_key[i]) != 1)
1488 			return EINVAL;
1489 		p += 2;
1490 	}
1491 
1492 	if (iflib_is_running(softc->ctx))
1493 		bnxt_hwrm_rss_cfg(softc, &softc->vnic_info,
1494 		    softc->vnic_info.rss_hash_type);
1495 
1496 	return rc;
1497 }
1498 
1499 static const char *bnxt_hash_types[] = {"ipv4", "tcp_ipv4", "udp_ipv4", "ipv6",
1500     "tcp_ipv6", "udp_ipv6", NULL};
1501 
1502 static int bnxt_get_rss_type_str_bit(char *str)
1503 {
1504 	int i;
1505 
1506 	for (i=0; bnxt_hash_types[i]; i++)
1507 		if (strcmp(bnxt_hash_types[i], str) == 0)
1508 			return i;
1509 
1510 	return -1;
1511 }
1512 
1513 static int
1514 bnxt_rss_type_sysctl(SYSCTL_HANDLER_ARGS)
1515 {
1516 	struct bnxt_softc *softc = arg1;
1517 	char buf[256] = {0};
1518 	char *p;
1519 	char *next;
1520 	int rc;
1521 	int type;
1522 	int bit;
1523 
1524 	for (type = softc->vnic_info.rss_hash_type; type;
1525 	    type &= ~(1<<bit)) {
1526 		bit = ffs(type) - 1;
1527 		if (bit >= sizeof(bnxt_hash_types) / sizeof(const char *))
1528 			continue;
1529 		if (type != softc->vnic_info.rss_hash_type)
1530 			strcat(buf, ",");
1531 		strcat(buf, bnxt_hash_types[bit]);
1532 	}
1533 
1534 	rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
1535 	if (rc || req->newptr == NULL)
1536 		return rc;
1537 
1538 	for (type = 0, next = buf, p = strsep(&next, " ,"); p;
1539 	    p = strsep(&next, " ,")) {
1540 		bit = bnxt_get_rss_type_str_bit(p);
1541 		if (bit == -1)
1542 			return EINVAL;
1543 		type |= 1<<bit;
1544 	}
1545 	if (type != softc->vnic_info.rss_hash_type) {
1546 		softc->vnic_info.rss_hash_type = type;
1547 		if (iflib_is_running(softc->ctx))
1548 			bnxt_hwrm_rss_cfg(softc, &softc->vnic_info,
1549 			    softc->vnic_info.rss_hash_type);
1550 	}
1551 
1552 	return rc;
1553 }
1554 
1555 static int
1556 bnxt_rx_stall_sysctl(SYSCTL_HANDLER_ARGS) {
1557 	struct bnxt_softc *softc = arg1;
1558 	int rc;
1559 	int val;
1560 
1561 	if (softc == NULL)
1562 		return EBUSY;
1563 
1564 	val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_BD_STALL);
1565 	rc = sysctl_handle_int(oidp, &val, 0, req);
1566 	if (rc || !req->newptr)
1567 		return rc;
1568 
1569 	if (val)
1570 		softc->vnic_info.flags |= BNXT_VNIC_FLAG_BD_STALL;
1571 	else
1572 		softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_BD_STALL;
1573 
1574 	if (iflib_is_running(softc->ctx))
1575 		rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info);
1576 
1577 	return rc;
1578 }
1579 
1580 static int
1581 bnxt_vlan_strip_sysctl(SYSCTL_HANDLER_ARGS) {
1582 	struct bnxt_softc *softc = arg1;
1583 	int rc;
1584 	int val;
1585 
1586 	if (softc == NULL)
1587 		return EBUSY;
1588 
1589 	val = (bool)(softc->vnic_info.flags & BNXT_VNIC_FLAG_VLAN_STRIP);
1590 	rc = sysctl_handle_int(oidp, &val, 0, req);
1591 	if (rc || !req->newptr)
1592 		return rc;
1593 
1594 	if (val)
1595 		softc->vnic_info.flags |= BNXT_VNIC_FLAG_VLAN_STRIP;
1596 	else
1597 		softc->vnic_info.flags &= ~BNXT_VNIC_FLAG_VLAN_STRIP;
1598 
1599 	if (iflib_is_running(softc->ctx))
1600 		rc = bnxt_hwrm_vnic_cfg(softc, &softc->vnic_info);
1601 
1602 	return rc;
1603 }
1604 
1605 /*
1606  * sysctl_handle_int() allows any int-sized value; reject anything that
1607  * would truncate/overflow when narrowed into the uint16_t coal field.
1608  */
1609 static int
1610 bnxt_sysctl_check_u16_range(struct bnxt_softc *softc, const char *what,
1611     int val, uint16_t mult)
1612 {
1613 	int max = mult ? (UINT16_MAX / mult) : UINT16_MAX;
1614 
1615 	if (val < 0 || val > max) {
1616 		device_printf(softc->dev,
1617 		    "%s: value %d out of range [0, %d]\n", what, val, max);
1618 		return EINVAL;
1619 	}
1620 	return 0;
1621 }
1622 
1623 static int
1624 bnxt_set_coal_rx_usecs(SYSCTL_HANDLER_ARGS) {
1625 	struct bnxt_softc *softc = arg1;
1626 	struct bnxt_coal *hw_coal;
1627 	int rc;
1628 	int val;
1629 
1630 	if (softc == NULL)
1631 		return EBUSY;
1632 
1633 	hw_coal = &softc->rx_coal;
1634 	val = hw_coal->coal_ticks;
1635 
1636 	rc = sysctl_handle_int(oidp, &val, 0, req);
1637 	if (rc || !req->newptr)
1638 		return rc;
1639 
1640 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, 0);
1641 	if (rc)
1642 		return rc;
1643 
1644 	hw_coal->coal_ticks = val;
1645 	rc = bnxt_hwrm_set_coal(softc);
1646 
1647 	return rc;
1648 }
1649 
1650 static int
1651 bnxt_set_coal_rx_frames(SYSCTL_HANDLER_ARGS) {
1652 	struct bnxt_softc *softc = arg1;
1653 	struct bnxt_coal *hw_coal;
1654 	uint16_t mult;
1655 	int rc;
1656 	int val;
1657 
1658 	if (softc == NULL)
1659 		return EBUSY;
1660 
1661 	hw_coal = &softc->rx_coal;
1662 	mult = hw_coal->bufs_per_record;
1663 	if (!mult) {
1664 		device_printf(softc->dev,
1665 		    "%s: bufs_per_record is zero which is invalid\n", __func__);
1666 		return EINVAL;
1667 	}
1668 
1669 	val = hw_coal->coal_bufs / mult;
1670 
1671 	rc = sysctl_handle_int(oidp, &val, 0, req);
1672 	if (rc || !req->newptr)
1673 		return rc;
1674 
1675 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, mult);
1676 	if (rc)
1677 		return rc;
1678 
1679 	hw_coal->coal_bufs = val * mult;
1680 	rc = bnxt_hwrm_set_coal(softc);
1681 
1682 	return rc;
1683 }
1684 
1685 static int
1686 bnxt_set_coal_rx_usecs_irq(SYSCTL_HANDLER_ARGS) {
1687 	struct bnxt_softc *softc = arg1;
1688 	struct bnxt_coal *hw_coal;
1689 	int rc;
1690 	int val;
1691 
1692 	if (softc == NULL)
1693 		return EBUSY;
1694 
1695 	hw_coal = &softc->rx_coal;
1696 	val = hw_coal->coal_ticks_irq;
1697 
1698 	rc = sysctl_handle_int(oidp, &val, 0, req);
1699 	if (rc || !req->newptr)
1700 		return rc;
1701 
1702 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, 0);
1703 	if (rc)
1704 		return rc;
1705 
1706 	hw_coal->coal_ticks_irq = val;
1707 	rc = bnxt_hwrm_set_coal(softc);
1708 
1709 	return rc;
1710 }
1711 
1712 static int
1713 bnxt_set_coal_rx_frames_irq(SYSCTL_HANDLER_ARGS) {
1714 	struct bnxt_softc *softc = arg1;
1715 	struct bnxt_coal *hw_coal;
1716 	uint16_t mult;
1717 	int rc;
1718 	int val;
1719 
1720 	if (softc == NULL)
1721 		return EBUSY;
1722 
1723 	hw_coal = &softc->rx_coal;
1724 	mult = hw_coal->bufs_per_record;
1725 	if (!mult) {
1726 		device_printf(softc->dev,
1727 		    "%s: bufs_per_record is zero which is invalid\n", __func__);
1728 		return EINVAL;
1729 	}
1730 
1731 	val = hw_coal->coal_bufs_irq / mult;
1732 
1733 	rc = sysctl_handle_int(oidp, &val, 0, req);
1734 	if (rc || !req->newptr)
1735 		return rc;
1736 
1737 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, mult);
1738 	if (rc)
1739 		return rc;
1740 
1741 	hw_coal->coal_bufs_irq = val * mult;
1742 	rc = bnxt_hwrm_set_coal(softc);
1743 
1744 	return rc;
1745 }
1746 
1747 static int
1748 bnxt_set_rx_coalesce_mode(SYSCTL_HANDLER_ARGS) {
1749 	struct bnxt_softc *softc = arg1;
1750 	struct bnxt_coal_cap *coal_cap;
1751 	struct bnxt_coal *hw_coal;
1752 	uint16_t flags;
1753 	int val;
1754 	int rc;
1755 
1756 	if (softc == NULL)
1757 		return EBUSY;
1758 
1759 	coal_cap = &softc->coal_cap;
1760 
1761 	if (coal_cap->cmpl_params &
1762 	    HWRM_RING_AGGINT_QCAPS_OUTPUT_CMPL_PARAMS_TIMER_RESET) {
1763 		hw_coal = &softc->rx_coal;
1764 		flags = hw_coal->flags;
1765 
1766 		val = flags & HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1767 		rc = sysctl_handle_int(oidp, &val, 0, req);
1768 		if (rc || !req->newptr)
1769 			return rc;
1770 
1771 		if (val)
1772 			flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1773 		else
1774 			flags &= ~HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
1775 
1776 		hw_coal->flags = flags;
1777 		rc = bnxt_hwrm_set_coal(softc);
1778 		return rc;
1779 	}
1780 
1781 	if (coal_cap->cmpl_params &
1782 	    HWRM_RING_AGGINT_QCAPS_OUTPUT_CMPL_PARAMS_TMR_RESET_ON_ALLOC) {
1783 		hw_coal = &softc->rx_coal;
1784 		val = hw_coal->timer_reset_during_ring_alloc;
1785 		rc = sysctl_handle_int(oidp, &val, 0, req);
1786 		if (rc || !req->newptr)
1787 			return rc;
1788 
1789 		/* Takes effect on next ring (re)alloc, so no bnxt_hwrm_set_coal() call needed here. */
1790 		hw_coal->timer_reset_during_ring_alloc = val ? 1 : 0;
1791 
1792 		return rc;
1793 	}
1794 
1795 	return EOPNOTSUPP;
1796 }
1797 
1798 static int
1799 bnxt_set_coal_tx_usecs(SYSCTL_HANDLER_ARGS) {
1800 	struct bnxt_softc *softc = arg1;
1801 	struct bnxt_coal *hw_coal;
1802 	int rc;
1803 	int val;
1804 
1805 	if (softc == NULL)
1806 		return EBUSY;
1807 
1808 	hw_coal = &softc->tx_coal;
1809 	val = hw_coal->coal_ticks;
1810 
1811 	rc = sysctl_handle_int(oidp, &val, 0, req);
1812 	if (rc || !req->newptr)
1813 		return rc;
1814 
1815 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, 0);
1816 	if (rc)
1817 		return rc;
1818 
1819 	hw_coal->coal_ticks = val;
1820 	rc = bnxt_hwrm_set_coal(softc);
1821 
1822 	return rc;
1823 }
1824 
1825 static int
1826 bnxt_set_coal_tx_frames(SYSCTL_HANDLER_ARGS) {
1827 	struct bnxt_softc *softc = arg1;
1828 	struct bnxt_coal *hw_coal;
1829 	uint16_t mult;
1830 	int rc;
1831 	int val;
1832 
1833 	if (softc == NULL)
1834 		return EBUSY;
1835 
1836 	hw_coal = &softc->tx_coal;
1837 	mult = hw_coal->bufs_per_record;
1838 	if (!mult) {
1839 		device_printf(softc->dev,
1840 		    "%s: bufs_per_record is zero which is invalid\n", __func__);
1841 		return EINVAL;
1842 	}
1843 
1844 	val = hw_coal->coal_bufs / mult;
1845 
1846 	rc = sysctl_handle_int(oidp, &val, 0, req);
1847 	if (rc || !req->newptr)
1848 		return rc;
1849 
1850 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, mult);
1851 	if (rc)
1852 		return rc;
1853 
1854 	hw_coal->coal_bufs = val * mult;
1855 	rc = bnxt_hwrm_set_coal(softc);
1856 
1857 	return rc;
1858 }
1859 
1860 static int
1861 bnxt_set_coal_tx_usecs_irq(SYSCTL_HANDLER_ARGS) {
1862 	struct bnxt_softc *softc = arg1;
1863 	struct bnxt_coal *hw_coal;
1864 	int rc;
1865 	int val;
1866 
1867 	if (softc == NULL)
1868 		return EBUSY;
1869 
1870 	hw_coal = &softc->tx_coal;
1871 	val = hw_coal->coal_ticks_irq;
1872 
1873 	rc = sysctl_handle_int(oidp, &val, 0, req);
1874 	if (rc || !req->newptr)
1875 		return rc;
1876 
1877 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, 0);
1878 	if (rc)
1879 		return rc;
1880 
1881 	hw_coal->coal_ticks_irq = val;
1882 	rc = bnxt_hwrm_set_coal(softc);
1883 
1884 	return rc;
1885 }
1886 
1887 static int
1888 bnxt_set_coal_tx_frames_irq(SYSCTL_HANDLER_ARGS) {
1889 	struct bnxt_softc *softc = arg1;
1890 	struct bnxt_coal *hw_coal;
1891 	uint16_t mult;
1892 	int rc;
1893 	int val;
1894 
1895 	if (softc == NULL)
1896 		return EBUSY;
1897 
1898 	hw_coal = &softc->tx_coal;
1899 	mult = hw_coal->bufs_per_record;
1900 	if (!mult) {
1901 		device_printf(softc->dev,
1902 		    "%s: bufs_per_record is zero which is invalid\n", __func__);
1903 		return EINVAL;
1904 	}
1905 
1906 	val = hw_coal->coal_bufs_irq / mult;
1907 
1908 	rc = sysctl_handle_int(oidp, &val, 0, req);
1909 	if (rc || !req->newptr)
1910 		return rc;
1911 
1912 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, mult);
1913 	if (rc)
1914 		return rc;
1915 
1916 	hw_coal->coal_bufs_irq = val * mult;
1917 	rc = bnxt_hwrm_set_coal(softc);
1918 
1919 	return rc;
1920 }
1921 
1922 static int
1923 bnxt_set_stats_coal_ticks(SYSCTL_HANDLER_ARGS) {
1924 	struct bnxt_softc *softc = arg1;
1925 	int rc;
1926 	int val;
1927 
1928 	if (softc == NULL)
1929 		return EBUSY;
1930 
1931 	val = softc->stats_coal_ticks;
1932 
1933 	rc = sysctl_handle_int(oidp, &val, 0, req);
1934 	if (rc || !req->newptr)
1935 		return rc;
1936 
1937 	softc->stats_coal_ticks = val;
1938 	/*
1939 	 * Stats DMA period is set once at HWRM_STAT_CTX_ALLOC time; there's no
1940 	 * HWRM_STAT_CTX_CFG to reprogram it, so nothing to apply this to yet.
1941 	 */
1942 
1943 	return 0;
1944 }
1945 
1946 static int
1947 bnxt_set_cagr_tick_res(SYSCTL_HANDLER_ARGS) {
1948 	struct bnxt_softc *softc = arg1;
1949 	int rc;
1950 	int val;
1951 
1952 	if (softc == NULL)
1953 		return EBUSY;
1954 
1955 	val = softc->cagr_tick_res;
1956 
1957 	rc = sysctl_handle_int(oidp, &val, 0, req);
1958 	if (rc || !req->newptr)
1959 		return rc;
1960 
1961 	if (val < BNXT_CAGR_TICK_RES_MIN ||
1962 	    val > BNXT_CAGR_TICK_RES_MAX)
1963 		return EINVAL;
1964 
1965 	softc->cagr_tick_res = val;
1966 
1967 	return rc;
1968 }
1969 
1970 static int
1971 bnxt_set_rx_coal_budget(SYSCTL_HANDLER_ARGS) {
1972 	struct bnxt_softc *softc = arg1;
1973 	struct bnxt_coal *hw_coal;
1974 	int rc;
1975 	int val;
1976 
1977 	if (softc == NULL)
1978 		return EBUSY;
1979 
1980 	hw_coal = &softc->rx_coal;
1981 
1982 	val = hw_coal->budget;
1983 
1984 	rc = sysctl_handle_int(oidp, &val, 0, req);
1985 	if (rc || !req->newptr)
1986 		return rc;
1987 
1988 	rc = bnxt_sysctl_check_u16_range(softc, __func__, val, 0);
1989 	if (rc)
1990 		return rc;
1991 
1992 	hw_coal->budget = val;
1993 	rc = bnxt_hwrm_set_coal(softc);
1994 
1995 	return rc;
1996 }
1997 
1998 static int
1999 bnxt_set_tx_host_coal_bds(SYSCTL_HANDLER_ARGS)
2000 {
2001 	struct bnxt_softc *softc = arg1;
2002 	uint32_t val;
2003 	int rc;
2004 
2005 	if (softc == NULL)
2006 		return EBUSY;
2007 
2008 	val = softc->tx_host_coal_bds;
2009 
2010 	rc = sysctl_handle_int(oidp, (int *)&val, 0, req);
2011 	if (rc || !req->newptr)
2012 		return rc;
2013 
2014 	if (val < BNXT_TX_HOST_COAL_BDS_MIN || val > softc->tx_ring_size)
2015 		return EINVAL;
2016 
2017 	softc->tx_host_coal_bds = val;
2018 
2019 	return 0;
2020 }
2021 
2022 static int
2023 bnxt_set_tx_hw_coal_cnt(SYSCTL_HANDLER_ARGS)
2024 {
2025 	struct bnxt_softc *softc = arg1;
2026 	uint32_t val;
2027 	int rc;
2028 
2029 	if (softc == NULL)
2030 		return EBUSY;
2031 
2032 	val = softc->tx_hw_coal_cnt;
2033 
2034 	rc = sysctl_handle_int(oidp, (int *)&val, 0, req);
2035 	if (rc || !req->newptr)
2036 		return rc;
2037 
2038 	if (val > HWRM_RING_ALLOC_INPUT_CMPL_COAL_CNT_LAST)
2039 		return EINVAL;
2040 
2041 	softc->tx_hw_coal_cnt = (uint8_t)val;
2042 
2043 	return 0;
2044 }
2045 
2046 static
2047 void simulate_reset(struct bnxt_softc *bp, char *fwcli_string)
2048 {
2049 	struct hwrm_dbg_fw_cli_input req = {0};
2050 	int rc = 0;
2051 
2052 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_DBG_FW_CLI);
2053 	req.cmpl_ring = -1;
2054 	req.target_id = -1;
2055 	req.cli_cmd_len = strlen(fwcli_string);
2056 	req.host_buf_len = 64 * 1024;
2057 	strcpy((char *)req.cli_cmd, fwcli_string);
2058 
2059 	BNXT_HWRM_LOCK(bp);
2060 	rc = _hwrm_send_message(bp, &req, sizeof(req));
2061 	if (rc) {
2062 		device_printf(bp->dev, " Manual FW fault failed, rc:%x\n", rc);
2063 	}
2064 	BNXT_HWRM_UNLOCK(bp);
2065 }
2066 
2067 static int
2068 bnxt_reset_ctrl(SYSCTL_HANDLER_ARGS) {
2069 	struct bnxt_softc *softc = arg1;
2070 	int rc = 0;
2071 	char buf[50] = {0};
2072 
2073 	if (softc == NULL)
2074 		return EBUSY;
2075 
2076 	rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
2077 	if (rc || req->newptr == NULL)
2078 		return rc;
2079 
2080 	if (BNXT_CHIP_P5_PLUS(softc))
2081 		simulate_reset(softc, buf);
2082 
2083 	return rc;
2084 }
2085 
2086 int
2087 bnxt_create_config_sysctls_pre(struct bnxt_softc *softc)
2088 {
2089 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(softc->dev);
2090 	struct sysctl_oid_list *children;
2091 
2092 	children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));
2093 
2094 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_key",
2095 	    CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2096 	    bnxt_rss_key_sysctl, "A", "RSS key");
2097 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rss_type",
2098 	    CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2099 	    bnxt_rss_type_sysctl, "A", "RSS type bits");
2100 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_stall",
2101 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2102 	    bnxt_rx_stall_sysctl, "I",
2103 	    "buffer rx packets in hardware until the host posts new buffers");
2104 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "vlan_strip",
2105 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2106 	    bnxt_vlan_strip_sysctl, "I", "strip VLAN tag in the RX path");
2107 	SYSCTL_ADD_CONST_STRING(ctx, children, OID_AUTO, "if_name", CTLFLAG_RD,
2108 		if_name(iflib_get_ifp(softc->ctx)), "interface name");
2109 
2110 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs",
2111 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2112 	    bnxt_set_coal_rx_usecs, "I", "interrupt coalescing Rx Usecs");
2113 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames",
2114 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2115 	    bnxt_set_coal_rx_frames, "I", "interrupt coalescing Rx Frames");
2116 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs_irq",
2117 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2118 	    bnxt_set_coal_rx_usecs_irq, "I",
2119 	    "interrupt coalescing Rx Usecs IRQ");
2120 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames_irq",
2121 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2122 	    bnxt_set_coal_rx_frames_irq, "I",
2123 	    "interrupt coalescing Rx Frames IRQ");
2124 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_coalesce_mode",
2125 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2126 	    bnxt_set_rx_coalesce_mode, "I",
2127 	    "set rx_coalesce_mode 0/1");
2128 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs",
2129 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2130 	    bnxt_set_coal_tx_usecs, "I", "interrupt coalescing Tx Usces");
2131 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames",
2132 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2133 	    bnxt_set_coal_tx_frames, "I", "interrupt coalescing Tx Frames");
2134 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs_irq",
2135 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2136 	    bnxt_set_coal_tx_usecs_irq, "I",
2137 	    "interrupt coalescing Tx Usecs IRQ");
2138 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames_irq",
2139 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2140 	    bnxt_set_coal_tx_frames_irq, "I",
2141 	    "interrupt coalescing Tx Frames IRQ");
2142 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_stats_coal_ticks",
2143 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2144 	    bnxt_set_stats_coal_ticks, "I",
2145 	    "interrupt coalescing stats coal ticks");
2146 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cagr_tick_res",
2147 	    CTLTYPE_INT | CTLFLAG_RDTUN | CTLFLAG_MPSAFE, softc, 0,
2148 	    bnxt_set_cagr_tick_res, "I", "CAGR tick resolution");
2149 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_rx_coal_budget",
2150 	    CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2151 	    bnxt_set_rx_coal_budget, "I",
2152 	    "Rx interrupt coalescing budget");
2153 
2154 	/*
2155 	 * Default coal_bds to half the Tx ring depth, clamped between
2156 	 * BNXT_TX_HOST_COAL_BDS_MIN and DEFAULT; disable below the floor to
2157 	 * avoid uint underflow in (coal_bds - (BNXT_MAX_NUM_SEGS+1)).
2158 	 */
2159 	softc->tx_host_coal_bds = min(softc->tx_ring_size,
2160 	    max(BNXT_TX_HOST_COAL_BDS_MIN,
2161 		min(BNXT_TX_HOST_COAL_BDS_DEFAULT, softc->tx_ring_size / 2)));
2162 	softc->tx_host_coal_enable =
2163 	    (softc->tx_ring_size >= BNXT_TX_HOST_COAL_BDS_MIN);
2164 	softc->tx_hw_coal_cnt = BNXT_TX_HW_COAL_CNT_DEFAULT;
2165 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_host_coal_bds",
2166 	    CTLTYPE_INT | CTLFLAG_RDTUN | CTLFLAG_MPSAFE, softc, 0,
2167 	    bnxt_set_tx_host_coal_bds, "I",
2168 	    "host-driven TX coalescing: max BDs before forcing completion "
2169 	    "(33 to Tx ring size, default max(33, min(256, ring_size/2)) "
2170 	    "clamped to ring_size; feature auto-disabled if ring_size < 33)");
2171 	SYSCTL_ADD_BOOL(ctx, children, OID_AUTO, "tx_host_coal_enable", CTLFLAG_RDTUN,
2172 	    &softc->tx_host_coal_enable, 0,
2173 	    "enable host-driven TX coalescing via NO_CMPL/COAL_NOW BD flags "
2174 	    "(default enabled)");
2175 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_hw_coal_cnt",
2176 	    CTLTYPE_INT | CTLFLAG_RDTUN | CTLFLAG_MPSAFE, softc, 0,
2177 	    bnxt_set_tx_hw_coal_cnt, "I",
2178 	    "HW-driven TX coalesced-completion packet count code for ring_alloc "
2179 	    "(0=off 1=4 2=8 3=12 4=16 5=24 6=32 7=48 8=64[default] "
2180 	    "9=96 10=128 11=192 12=256 13=320 14=384 15=MAX; "
2181 	    "requires BNXT_FLAG_TX_COAL_CMPL firmware capability)");
2182 	SYSCTL_ADD_U32(ctx, children, OID_AUTO, "flags", CTLFLAG_RD,
2183 		&softc->flags, 0, "flags");
2184 	SYSCTL_ADD_U64(ctx, children, OID_AUTO, "fw_cap", CTLFLAG_RD,
2185 		&softc->fw_cap, 0, "FW caps");
2186 
2187 	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
2188 	    "reset_ctrl", CTLTYPE_STRING | CTLFLAG_RWTUN, softc,
2189 	    0, bnxt_reset_ctrl, "A",
2190 	    "Issue controller reset: 0 / 1");
2191 	return 0;
2192 }
2193 
2194 #define BNXT_HW_LRO_FN(fn_name, arg)			                   \
2195 static int						                   \
2196 fn_name(SYSCTL_HANDLER_ARGS) {				                   \
2197 	struct bnxt_softc *softc = arg1;		                   \
2198 	int rc;						                   \
2199 	int val;					                   \
2200 							                   \
2201 	if (softc == NULL)				                   \
2202 		return EBUSY;				                   \
2203 							                   \
2204 	val = softc->hw_lro.arg;			                   \
2205 	rc = sysctl_handle_int(oidp, &val, 0, req);	                   \
2206 	if (rc || !req->newptr)				                   \
2207 		return rc;				                   \
2208 							                   \
2209 	if (iflib_is_running(softc->ctx)) \
2210 		return EBUSY;				                   \
2211 							                   \
2212 	if (!(softc->flags & BNXT_FLAG_TPA))				   \
2213 		return EINVAL;						   \
2214 							                   \
2215 	softc->hw_lro.arg = val;			                   \
2216 	bnxt_validate_hw_lro_settings(softc);		                   \
2217 	rc = bnxt_hwrm_vnic_tpa_cfg(softc);		                   \
2218 							                   \
2219 	return rc;					                   \
2220 }
2221 
2222 BNXT_HW_LRO_FN(bnxt_hw_lro_enable_disable, enable)
2223 BNXT_HW_LRO_FN(bnxt_hw_lro_set_mode, is_mode_gro)
2224 BNXT_HW_LRO_FN(bnxt_hw_lro_set_max_agg_segs, max_agg_segs)
2225 BNXT_HW_LRO_FN(bnxt_hw_lro_set_max_aggs, max_aggs)
2226 BNXT_HW_LRO_FN(bnxt_hw_lro_set_min_agg_len, min_agg_len)
2227 
2228 #define BNXT_FLOW_CTRL_FN(fn_name, arg)			                   \
2229 static int						                   \
2230 fn_name(SYSCTL_HANDLER_ARGS) {				                   \
2231 	struct bnxt_softc *softc = arg1;		                   \
2232 	int rc;						                   \
2233 	int val;					                   \
2234 							                   \
2235 	if (softc == NULL)				                   \
2236 		return EBUSY;				                   \
2237 							                   \
2238 	val = softc->link_info.flow_ctrl.arg;			           \
2239 	rc = sysctl_handle_int(oidp, &val, 0, req);	                   \
2240 	if (rc || !req->newptr)				                   \
2241 		return rc;				                   \
2242 							                   \
2243 	if (val)					                   \
2244 	   	val = 1; 				                   \
2245 	        					                   \
2246 	if (softc->link_info.flow_ctrl.arg != val) {		           \
2247 		softc->link_info.flow_ctrl.arg = val;		           \
2248 		rc = bnxt_hwrm_set_link_setting(softc, true, false, false);\
2249 		rc = bnxt_hwrm_port_phy_qcfg(softc);			   \
2250 	}						                   \
2251 							                   \
2252 	return rc;					                   \
2253 }
2254 
2255 BNXT_FLOW_CTRL_FN(bnxt_flow_ctrl_tx, tx)
2256 BNXT_FLOW_CTRL_FN(bnxt_flow_ctrl_rx, rx)
2257 BNXT_FLOW_CTRL_FN(bnxt_flow_ctrl_autoneg, autoneg)
2258 int
2259 bnxt_create_pause_fc_sysctls(struct bnxt_softc *softc)
2260 {
2261 	struct sysctl_oid *oid = softc->flow_ctrl_oid;
2262 
2263 	if (!oid)
2264 		return ENOMEM;
2265 
2266 	SYSCTL_ADD_PROC(&softc->flow_ctrl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2267 	    "tx", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2268 	    bnxt_flow_ctrl_tx, "A", "Enable or Disable Tx Flow Ctrl: 0 / 1");
2269 
2270 	SYSCTL_ADD_PROC(&softc->flow_ctrl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2271 	    "rx", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc, 0,
2272 	    bnxt_flow_ctrl_rx, "A", "Enable or Disable Tx Flow Ctrl: 0 / 1");
2273 
2274 	SYSCTL_ADD_PROC(&softc->flow_ctrl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2275 	    "autoneg", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc,
2276 	    0, bnxt_flow_ctrl_autoneg, "A",
2277 	    "Enable or Disable Autoneg Flow Ctrl: 0 / 1");
2278 
2279 	return 0;
2280 }
2281 
2282 int
2283 bnxt_create_hw_lro_sysctls(struct bnxt_softc *softc)
2284 {
2285 	struct sysctl_oid *oid = softc->hw_lro_oid;
2286 
2287 	if (!oid)
2288 		return ENOMEM;
2289 
2290 	SYSCTL_ADD_PROC(&softc->hw_lro_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2291 	    "enable", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc,
2292 	    0, bnxt_hw_lro_enable_disable, "A",
2293 	    "Enable or Disable HW LRO: 0 / 1");
2294 
2295 	SYSCTL_ADD_PROC(&softc->hw_lro_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2296 	    "gro_mode", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, softc,
2297 	    0, bnxt_hw_lro_set_mode, "A",
2298 	    "Set mode: 1 = GRO mode, 0 = RSC mode");
2299 
2300 	SYSCTL_ADD_PROC(&softc->hw_lro_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2301 	    "max_agg_segs", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2302 	    softc, 0, bnxt_hw_lro_set_max_agg_segs, "A",
2303 	    "Set Max Agg Seg Value (unit is Log2): "
2304 	    "0 (= 1 seg) / 1 (= 2 segs) /  ... / 31 (= 2^31 segs)");
2305 
2306         SYSCTL_ADD_PROC(&softc->hw_lro_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2307 	    "max_aggs", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2308 	    softc, 0, bnxt_hw_lro_set_max_aggs, "A",
2309 	    "Set Max Aggs Value (unit is Log2): "
2310 	    "0 (= 1 agg) / 1 (= 2 aggs) /  ... / 7 (= 2^7 segs)");
2311 
2312 	SYSCTL_ADD_PROC(&softc->hw_lro_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2313 	    "min_agg_len", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2314 	    softc, 0, bnxt_hw_lro_set_min_agg_len, "A",
2315 	    "Min Agg Len: 1 to 9000");
2316 
2317 	return 0;
2318 }
2319 
2320 static int
2321 bnxt_dcb_dcbx_cap(SYSCTL_HANDLER_ARGS)
2322 {
2323 	struct bnxt_softc *softc = arg1;
2324 	int val;
2325 	int rc;
2326 
2327 	val = bnxt_dcb_getdcbx(softc);
2328 	rc = sysctl_handle_int(oidp, &val, 0, req);
2329 	if (rc || !req->newptr)
2330 		return rc;
2331 
2332 	bnxt_dcb_setdcbx(softc, val);
2333 
2334 	return rc;
2335 }
2336 
2337 static char
2338 bnxt_ets_tsa_to_str(struct bnxt_softc *softc, uint32_t tc)
2339 {
2340 	switch (softc->ieee_ets->tc_tsa[tc]) {
2341 	case BNXT_IEEE_8021QAZ_TSA_STRICT:
2342 		return 's';
2343 	case BNXT_IEEE_8021QAZ_TSA_ETS:
2344 		return 'e';
2345 	default:
2346 		return 'X';
2347 
2348 	}
2349 }
2350 
2351 static uint32_t
2352 bnxt_ets_str_to_tsa(char tsa_str)
2353 {
2354 	switch (tsa_str) {
2355 	case 's':
2356 		return BNXT_IEEE_8021QAZ_TSA_STRICT;
2357 	case 'e':
2358 		return BNXT_IEEE_8021QAZ_TSA_ETS;
2359 	default:
2360 		return -1;
2361 	}
2362 }
2363 
2364 static int
2365 bnxt_ets_get_val(struct bnxt_softc *softc, uint32_t type, uint32_t tc)
2366 {
2367 	switch (type) {
2368 	case BNXT_TYPE_ETS_TSA:
2369 		if (softc->ieee_ets)
2370 			return softc->ieee_ets->tc_tsa[tc];
2371 		break;
2372 	case BNXT_TYPE_ETS_PRI2TC:
2373 		if (softc->ieee_ets)
2374 			return softc->ieee_ets->prio_tc[tc];
2375 		break;
2376 	case BNXT_TYPE_ETS_TCBW:
2377 		if (softc->ieee_ets)
2378 			return softc->ieee_ets->tc_tx_bw[tc];
2379 		break;
2380 	default:
2381 		break;
2382 	}
2383 
2384 	return -1;
2385 }
2386 
2387 static void
2388 bnxt_pfc_get_string(struct bnxt_softc *softc, char *buf, struct bnxt_ieee_pfc *pfc)
2389 {
2390 	uint32_t i;
2391 	bool found = false;
2392 
2393 	for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) {
2394 		if (pfc->pfc_en & (1 << i)) {
2395 			if (found)
2396 				buf += sprintf(buf, ", ");
2397 			buf += sprintf(buf, "%d", i);
2398 			found = true;
2399 		}
2400 	}
2401 
2402 	if (!found)
2403 		buf += sprintf(buf, "none");
2404 }
2405 
2406 static const char *bnxt_get_tlv_selector_str(uint8_t selector)
2407 {
2408 	switch (selector) {
2409 	case BNXT_IEEE_8021QAZ_APP_SEL_ETHERTYPE:
2410 		return "Ethertype";
2411 	case BNXT_IEEE_8021QAZ_APP_SEL_DGRAM:
2412 		return "UDP or DCCP";
2413 	case BNXT_IEEE_8021QAZ_APP_SEL_DSCP:
2414 		return "DSCP";
2415 	default:
2416 		return "Unknown";
2417 	}
2418 }
2419 
2420 static void
2421 bnxt_app_tlv_get_string(struct sbuf *sb, struct bnxt_dcb_app *app, int num)
2422 {
2423 	int i;
2424 
2425 	if (num == 0) {
2426 		sbuf_printf(sb, " None");
2427 		return;
2428 	}
2429 
2430 	sbuf_putc(sb, '\n');
2431 	for (i = 0; i < num; i++) {
2432 		sbuf_printf(sb, "\tAPP#%0d:\tpri: %d,\tSel: %d,\t%s: %d\n",
2433 		    i,
2434 		    app[i].priority,
2435 		    app[i].selector,
2436 		    bnxt_get_tlv_selector_str(app[i].selector),
2437 		    app[i].protocol);
2438 	}
2439 }
2440 
2441 static void
2442 bnxt_ets_get_string(struct bnxt_softc *softc, char *buf)
2443 {
2444 	uint32_t type, i;
2445 
2446 	type = BNXT_TYPE_ETS_TSA;
2447 	for (type = 0; type < BNXT_TYPE_ETS_MAX; type++) {
2448 		for (i = 0; i < BNXT_IEEE_8021QAZ_MAX_TCS; i++) {
2449 			if (i == 0)
2450 				buf += sprintf(buf, "%s:", BNXT_ETS_TYPE_STR[type]);
2451 
2452 			if (!softc->ieee_ets)
2453 				buf += sprintf(buf, "x");
2454 			else if (type == BNXT_TYPE_ETS_TSA)
2455 				buf += sprintf(buf, "%c", bnxt_ets_tsa_to_str(softc, i));
2456 			else
2457 				buf += sprintf(buf, "%d", bnxt_ets_get_val(softc, type, i));
2458 
2459 			if (i != BNXT_IEEE_8021QAZ_MAX_TCS - 1)
2460 				buf += sprintf(buf, ",");
2461 		}
2462 		if (type != BNXT_TYPE_ETS_MAX - 1)
2463 			buf += sprintf(buf, "#");
2464 	}
2465 }
2466 
2467 static int
2468 bnxt_dcb_list_app(SYSCTL_HANDLER_ARGS)
2469 {
2470 	struct sbuf sb;
2471 	struct bnxt_dcb_app app[128] = {0};
2472 	struct bnxt_softc *softc = arg1;
2473 	int rc, num_inputs = 0;
2474 
2475 	sbuf_new_for_sysctl(&sb, NULL, 128, req);
2476 	bnxt_dcb_ieee_listapp(softc, app, nitems(app), &num_inputs);
2477 	bnxt_app_tlv_get_string(&sb, app, num_inputs);
2478 	rc = sbuf_finish(&sb);
2479 	sbuf_delete(&sb);
2480 	return rc;
2481 }
2482 
2483 static int
2484 bnxt_dcb_del_app(SYSCTL_HANDLER_ARGS)
2485 {
2486 	struct bnxt_softc *softc = arg1;
2487 	struct bnxt_dcb_app app = {0};
2488 	char buf[256] = {0};
2489 	int rc, num_inputs;
2490 
2491 	rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
2492 	if (rc || req->newptr == NULL)
2493 		return rc;
2494 
2495 	num_inputs = sscanf(buf, "%hhu,%hhu,%hd", &app.priority, &app.selector, &app.protocol);
2496 
2497 	if (num_inputs != 3) {
2498 		device_printf(softc->dev,
2499 			      "Invalid app tlv syntax, inputs = %d\n", num_inputs);
2500 		return EINVAL;
2501 	}
2502 
2503 	bnxt_dcb_ieee_delapp(softc, &app);
2504 
2505 	return rc;
2506 }
2507 static int
2508 bnxt_dcb_set_app(SYSCTL_HANDLER_ARGS)
2509 {
2510 	struct bnxt_softc *softc = arg1;
2511 	struct bnxt_dcb_app app = {0};
2512 	char buf[256] = {0};
2513 	int rc, num_inputs;
2514 
2515 	rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
2516 	if (rc || req->newptr == NULL)
2517 		return rc;
2518 
2519 	num_inputs = sscanf(buf, "%hhu,%hhu,%hd", &app.priority, &app.selector, &app.protocol);
2520 
2521 	if (num_inputs != 3) {
2522 		device_printf(softc->dev,
2523 			      "Invalid app tlv syntax, inputs = %d\n", num_inputs);
2524 		return EINVAL;
2525 	}
2526 
2527 	bnxt_dcb_ieee_setapp(softc, &app);
2528 
2529 	return rc;
2530 }
2531 
2532 static int
2533 bnxt_dcb_pfc(SYSCTL_HANDLER_ARGS)
2534 {
2535 	struct bnxt_softc *softc = arg1;
2536 	struct bnxt_ieee_pfc pfc = {0};
2537 	int rc, i, num_inputs;
2538 	char buf[256] = {0};
2539 	int pri_mask = 0;
2540 	char pri[8];
2541 
2542 	rc = bnxt_dcb_ieee_getpfc(softc, &pfc);
2543 	if (!rc)
2544 		bnxt_pfc_get_string(softc, buf, &pfc);
2545 	else
2546 		sprintf(buf, "## getpfc failed with error %d ##", rc);
2547 
2548 	rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
2549 	if (rc || req->newptr == NULL)
2550 		return rc;
2551 
2552 	/* Check for 'none' string first */
2553 	if (sscanf(buf,  "%s", buf) == 1) {
2554 		if (strncmp(buf, "none", 8) == 0) {
2555 			goto configure;
2556 		}
2557 	}
2558 	num_inputs = sscanf(buf, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",
2559 			    &pri[0], &pri[1], &pri[2], &pri[3], &pri[4],
2560 			    &pri[5], &pri[6], &pri[7]);
2561 
2562 	if (num_inputs < 1 || num_inputs > 8) {
2563 		device_printf(softc->dev,
2564 			      "Invalid pfc syntax, inputs = %d\n", num_inputs);
2565 		return EINVAL;
2566 	}
2567 
2568 	for (i = 0; i < num_inputs; i++) {
2569 		if (pri[i] > 7 || pri[i] < 0) {
2570 			device_printf(softc->dev,
2571 				      "Invalid priority %d. Valid priorties are "
2572 				      "from 0 to 7 and string \"none\".\n", pri[i]);
2573 			return EINVAL;
2574 		}
2575 
2576 		pri_mask |= (1 << pri[i]) & 0xFF;
2577 	}
2578 
2579 configure:
2580 	pfc.pfc_en = pri_mask;
2581 	rc = bnxt_dcb_ieee_setpfc(softc, &pfc);
2582 	if (rc)
2583 		device_printf(softc->dev,
2584 			      "setpfc failed with status %d\n", rc);
2585 	return rc;
2586 }
2587 
2588 static int
2589 bnxt_dcb_ets(SYSCTL_HANDLER_ARGS)
2590 {
2591 	struct bnxt_softc *softc = arg1;
2592 	struct bnxt_ieee_ets ets = {0};
2593 	int rc = 0, i, num_inputs;
2594 	char buf[256] = {0};
2595 	char tsa[8];
2596 
2597 	rc = bnxt_dcb_ieee_getets(softc, &ets);
2598 	if (!rc)
2599 		bnxt_ets_get_string(softc, buf);
2600 	else
2601 		sprintf(buf, "## getets failed with error %d ##", rc);
2602 
2603 	rc = sysctl_handle_string(oidp, buf, sizeof(buf), req);
2604 	if (rc || req->newptr == NULL)
2605 		return rc;
2606 
2607 	num_inputs = sscanf(buf,  "tsa:%c,%c,%c,%c,%c,%c,%c,%c#"
2608 			    "pri2tc:%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu#"
2609 			    "tcbw:%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",
2610 			    &tsa[0], &tsa[1], &tsa[2], &tsa[3], &tsa[4], &tsa[5], &tsa[6], &tsa[7],
2611 			    &ets.prio_tc[0], &ets.prio_tc[1], &ets.prio_tc[2], &ets.prio_tc[3],
2612 			    &ets.prio_tc[4], &ets.prio_tc[5], &ets.prio_tc[6], &ets.prio_tc[7],
2613 			    &ets.tc_tx_bw[0], &ets.tc_tx_bw[1], &ets.tc_tx_bw[2], &ets.tc_tx_bw[3],
2614 			    &ets.tc_tx_bw[4], &ets.tc_tx_bw[5], &ets.tc_tx_bw[6], &ets.tc_tx_bw[7]);
2615 
2616 	if (num_inputs != 24)
2617 		return EINVAL;
2618 
2619 	for ( i= 0; i < 8; i++)
2620 		ets.tc_tsa[i] = bnxt_ets_str_to_tsa(tsa[i]);
2621 
2622 	rc = bnxt_dcb_ieee_setets(softc, &ets);
2623 
2624 	return rc;
2625 }
2626 
2627 int
2628 bnxt_create_dcb_sysctls(struct bnxt_softc *softc)
2629 {
2630 	struct sysctl_oid *oid = softc->dcb_oid;
2631 
2632 	if (!oid)
2633 		return ENOMEM;
2634 
2635 	SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
2636 	    "dcbx_cap", CTLTYPE_INT | CTLFLAG_RWTUN, softc,
2637 	    0, bnxt_dcb_dcbx_cap, "A",
2638 	    "Enable DCB Capability Exchange Protocol (DCBX) capabilities");
2639 
2640 	SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "ets",
2641 	    CTLTYPE_STRING | CTLFLAG_RWTUN, softc, 0,
2642 	    bnxt_dcb_ets, "A", "Enhanced Transmission Selection (ETS)");
2643 
2644 	SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "pfc",
2645 	    CTLTYPE_STRING | CTLFLAG_RWTUN, softc, 0,
2646 	    bnxt_dcb_pfc, "A", "Enhanced Transmission Selection (ETS)");
2647 
2648 	SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "set_apptlv",
2649 	    CTLTYPE_STRING | CTLFLAG_WR, softc, 0,
2650 	    bnxt_dcb_set_app, "A", "Set App TLV");
2651 
2652 	SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "del_apptlv",
2653 	    CTLTYPE_STRING | CTLFLAG_WR, softc, 0,
2654 	    bnxt_dcb_del_app, "A", "Delete App TLV");
2655 
2656 	SYSCTL_ADD_PROC(&softc->dcb_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "list_apptlv",
2657 	    CTLTYPE_STRING | CTLFLAG_RD, softc, 0,
2658 	    bnxt_dcb_list_app, "A", "List all App TLVs");
2659 
2660 	return 0;
2661 }
2662 
2663 int
2664 bnxt_create_config_sysctls_post(struct bnxt_softc *softc)
2665 {
2666 	/* Nothing for now, meant for future expansion */
2667 	return 0;
2668 }
2669 
2670 static int
2671 sysctl_counter_u64_handler(SYSCTL_HANDLER_ARGS)
2672 {
2673 	counter_u64_t *counter = (counter_u64_t *)arg1;
2674 	uint64_t val = counter_u64_fetch(*counter);
2675 
2676 	return sysctl_handle_64(oidp, &val, 0, req);
2677 }
2678 
2679 int
2680 bnxt_create_ktls_sysctls(struct bnxt_softc *softc)
2681 {
2682 	struct bnxt_tls_info *ktls = softc->ktls_info;
2683 	struct sysctl_oid *oid;
2684 
2685 	if (!ktls)
2686 		return 0;
2687 
2688 	oid = SYSCTL_ADD_NODE(&softc->ktls_stats,
2689 			      SYSCTL_CHILDREN(softc->ktls_stats_oid), OID_AUTO,
2690 			      "ktls_stats", CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
2691 			      "In-kernel TLS statistics");
2692 	if (!oid)
2693 		return ENOMEM;
2694 
2695 	for (int i = 0; i < ktls_counters_count; i++) {
2696 		const struct bnxt_ktls_counters_list *counters = &ktls_counters[i];
2697 
2698 		SYSCTL_ADD_PROC(&softc->ktls_stats,
2699 				SYSCTL_CHILDREN(oid), OID_AUTO,
2700 				counters->label,
2701 				CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
2702 				&ktls->counters[counters->id],
2703 				0,
2704 				sysctl_counter_u64_handler,
2705 				"Q",
2706 				counters->desc);
2707 	}
2708 
2709 	for (int i = 0; i < ktls_err_counters_count; i++) {
2710 		const struct bnxt_ktls_err_counters_list *err_counters = &ktls_err_counters[i];
2711 
2712 		SYSCTL_ADD_PROC(&softc->ktls_stats, SYSCTL_CHILDREN(oid), OID_AUTO,
2713 				err_counters->label,
2714 				CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
2715 				&ktls->err_counters[err_counters->id], 0,
2716 				sysctl_counter_u64_handler, "Q",
2717 				err_counters->desc);
2718 	}
2719 
2720 	return 0;
2721 }
2722 
2723 int
2724 bnxt_ktls_sysctls(struct bnxt_softc *softc)
2725 {
2726 	struct sysctl_ctx_list *ctx;
2727 	struct sysctl_oid_list *children;
2728 	struct sysctl_oid *oid;
2729 
2730 	ctx = device_get_sysctl_ctx(softc->dev);
2731 	children = SYSCTL_CHILDREN(device_get_sysctl_tree(softc->dev));
2732 
2733 	oid = SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "max_ktls_entries",
2734 			      CTLFLAG_RDTUN, &softc->max_ktls_entries, 0,
2735 			      "Maximum number of TLS offload entries to preallocate (default: 102400, max: 512000)");
2736 	if (!oid)
2737 		return ENOMEM;
2738 
2739 	return 0;
2740 }
2741 
2742 int
2743 bnxt_create_mpc_cmp_time_sysctls(struct bnxt_softc *softc)
2744 {
2745 	struct bnxt_tls_info *ktls = softc->ktls_info;
2746 	struct sysctl_oid *oid;
2747 
2748 	if (!ktls)
2749 		return 0;
2750 
2751 	oid = SYSCTL_ADD_NODE(&softc->mpc_cmp_time_stats,
2752 			      SYSCTL_CHILDREN(softc->mpc_cmp_time_stats_oid), OID_AUTO,
2753 			      "mpc_cmp_stats", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "MPC CMP time statistics");
2754 	if (!oid)
2755 		return ENOMEM;
2756 
2757 	for (int i = 0; i < mpc_cmp_counters_count; i++) {
2758 		const struct bnxt_mpc_cmp_time_counters_list *mpc_counters = &mpc_cmp_counters[i];
2759 
2760 		SYSCTL_ADD_PROC(&softc->mpc_cmp_time_stats,
2761 				SYSCTL_CHILDREN(oid), OID_AUTO,
2762 				mpc_counters->label,
2763 				CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE,
2764 				&ktls->mpc_cmp_time[mpc_counters->id],
2765 				0,
2766 				sysctl_counter_u64_handler,
2767 				"Q",
2768 				mpc_counters->desc);
2769 	}
2770 
2771 	return 0;
2772 }
2773