xref: /freebsd/sys/dev/liquidio/lio_sysctl.c (revision f6a3b357e9be4c6423c85eff9a847163a0d307c8)
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2017 Cavium, Inc.. All rights reserved.
5  *   All rights reserved.
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  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Cavium, Inc. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*$FreeBSD$*/
34 
35 #include <sys/types.h>
36 
37 #include "lio_bsd.h"
38 #include "lio_common.h"
39 #include "lio_droq.h"
40 #include "lio_iq.h"
41 #include "lio_response_manager.h"
42 #include "lio_device.h"
43 #include "lio_network.h"
44 #include "lio_ctrl.h"
45 #include "cn23xx_pf_device.h"
46 #include "lio_image.h"
47 #include "lio_main.h"
48 #include "lio_rxtx.h"
49 #include "lio_ioctl.h"
50 
51 #define LIO_OFF_PAUSE	0
52 #define LIO_RX_PAUSE	1
53 #define LIO_TX_PAUSE	2
54 
55 #define LIO_REGDUMP_LEN		4096
56 #define LIO_REGDUMP_LEN_23XX	49248
57 
58 #define LIO_REGDUMP_LEN_XXXX	LIO_REGDUMP_LEN_23XX
59 
60 #define LIO_USE_ADAPTIVE_RX_COALESCE		1
61 #define LIO_USE_ADAPTIVE_TX_COALESCE		2
62 #define LIO_RX_COALESCE_USECS			3
63 #define LIO_RX_MAX_COALESCED_FRAMES		4
64 #define LIO_TX_MAX_COALESCED_FRAMES		8
65 #define LIO_PKT_RATE_LOW			12
66 #define LIO_RX_COALESCE_USECS_LOW		13
67 #define LIO_RX_MAX_COALESCED_FRAMES_LOW		14
68 #define LIO_TX_MAX_COALESCED_FRAMES_LOW		16
69 #define LIO_PKT_RATE_HIGH			17
70 #define LIO_RX_COALESCE_USECS_HIGH		18
71 #define LIO_RX_MAX_COALESCED_FRAMES_HIGH	19
72 #define LIO_TX_MAX_COALESCED_FRAMES_HIGH	21
73 #define LIO_RATE_SAMPLE_INTERVAL		22
74 
75 #define LIO_SET_RING_RX				1
76 #define LIO_SET_RING_TX				2
77 
78 static int	lio_get_eeprom(SYSCTL_HANDLER_ARGS);
79 static int	lio_get_set_pauseparam(SYSCTL_HANDLER_ARGS);
80 static int	lio_get_regs(SYSCTL_HANDLER_ARGS);
81 static int	lio_cn23xx_pf_read_csr_reg(char *s, struct octeon_device *oct);
82 static int	lio_get_set_fwmsglevel(SYSCTL_HANDLER_ARGS);
83 static int	lio_set_stats_interval(SYSCTL_HANDLER_ARGS);
84 static void	lio_get_fw_stats(void *arg);
85 static int	lio_get_set_intr_coalesce(SYSCTL_HANDLER_ARGS);
86 static int	lio_get_intrmod_cfg(struct lio *lio,
87 				    struct octeon_intrmod_cfg *intr_cfg);
88 static int	lio_get_ringparam(SYSCTL_HANDLER_ARGS);
89 static int	lio_set_ringparam(SYSCTL_HANDLER_ARGS);
90 static int	lio_get_channels(SYSCTL_HANDLER_ARGS);
91 static int	lio_set_channels(SYSCTL_HANDLER_ARGS);
92 static int	lio_irq_reallocate_irqs(struct octeon_device *oct,
93 					uint32_t num_ioqs);
94 
95 struct lio_intrmod_context {
96 	int	octeon_id;
97 	volatile int cond;
98 	int	status;
99 };
100 
101 struct lio_intrmod_resp {
102 	uint64_t	rh;
103 	struct octeon_intrmod_cfg intrmod;
104 	uint64_t	status;
105 };
106 
107 static int
108 lio_send_queue_count_update(struct ifnet *ifp, uint32_t num_queues)
109 {
110 	struct lio_ctrl_pkt	nctrl;
111 	struct lio		*lio = if_getsoftc(ifp);
112 	struct octeon_device	*oct = lio->oct_dev;
113 	int ret = 0;
114 
115 	bzero(&nctrl, sizeof(struct lio_ctrl_pkt));
116 
117 	nctrl.ncmd.cmd64 = 0;
118 	nctrl.ncmd.s.cmd = LIO_CMD_QUEUE_COUNT_CTL;
119 	nctrl.ncmd.s.param1 = num_queues;
120 	nctrl.ncmd.s.param2 = num_queues;
121 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
122 	nctrl.wait_time = 100;
123 	nctrl.lio = lio;
124 	nctrl.cb_fn = lio_ctrl_cmd_completion;
125 
126 	ret = lio_send_ctrl_pkt(lio->oct_dev, &nctrl);
127 	if (ret < 0) {
128 		lio_dev_err(oct, "Failed to send Queue reset command (ret: 0x%x)\n",
129 			    ret);
130 		return (-1);
131 	}
132 
133 	return (0);
134 }
135 
136 /* Add sysctl variables to the system, one per statistic. */
137 void
138 lio_add_hw_stats(struct lio *lio)
139 {
140 	struct octeon_device	*oct_dev = lio->oct_dev;
141 	device_t dev = oct_dev->device;
142 
143 	struct sysctl_ctx_list	*ctx = device_get_sysctl_ctx(dev);
144 	struct sysctl_oid	*tree = device_get_sysctl_tree(dev);
145 	struct sysctl_oid_list	*child = SYSCTL_CHILDREN(tree);
146 	struct sysctl_oid	*stat_node, *queue_node, *root_node;
147 	struct sysctl_oid_list	*stat_list, *queue_list, *root_list;
148 #define QUEUE_NAME_LEN 32
149 	char namebuf[QUEUE_NAME_LEN];
150 
151 	callout_reset(&lio->stats_timer, lio_ms_to_ticks(lio->stats_interval),
152 		      lio_get_fw_stats, lio);
153 
154 	SYSCTL_ADD_STRING(ctx, child, OID_AUTO, "fwversion", CTLFLAG_RD,
155 			  oct_dev->fw_info.lio_firmware_version, 0,
156 			  "Firmware version");
157 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "stats_interval",
158 			CTLTYPE_INT | CTLFLAG_RW, lio, 0,
159 			lio_set_stats_interval,	"I",
160 			"Set Stats Updation Timer in milli seconds");
161 	SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "link_state_changes",
162 			 CTLFLAG_RD, &lio->link_changes, "Link Change Counter");
163 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "eeprom-dump",
164 			CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, lio, 0,
165 			lio_get_eeprom, "A", "EEPROM information");
166 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fc",
167 			CTLTYPE_INT | CTLFLAG_RW, lio, 0,
168 			lio_get_set_pauseparam, "I",
169 			"Get and set pause parameters.\n" \
170 			"0 - off\n" \
171 			"1 - rx pause\n" \
172 			"2 - tx pause \n" \
173 			"3 - rx and tx pause");
174 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "register-dump",
175 			CTLTYPE_STRING | CTLFLAG_RD,
176 			lio, 0, lio_get_regs, "A",
177 			"Dump registers in raw format");
178 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "fwmsglevel",
179 			CTLTYPE_INT | CTLFLAG_RW, lio, 0,
180 			lio_get_set_fwmsglevel,
181 			"I", "Get or set firmware message level");
182 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxq_descriptors",
183 			CTLTYPE_INT | CTLFLAG_RW, lio, LIO_SET_RING_RX,
184 			lio_set_ringparam, "I", "Set RX ring parameter");
185 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txq_descriptors",
186 			CTLTYPE_INT | CTLFLAG_RW, lio, LIO_SET_RING_TX,
187 			lio_set_ringparam, "I", "Set TX ring parameter");
188 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "max_rxq_descriptors",
189 			CTLTYPE_INT | CTLFLAG_RD, lio, LIO_SET_RING_RX,
190 			lio_get_ringparam, "I", "Max RX descriptors");
191 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "max_txq_descriptors",
192 			CTLTYPE_INT | CTLFLAG_RD, lio, LIO_SET_RING_TX,
193 			lio_get_ringparam, "I", "Max TX descriptors");
194 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "active_queues",
195 			CTLTYPE_INT | CTLFLAG_RW, lio, 0, lio_set_channels,
196 			"I", "Set channels information");
197 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "max_queues",
198 			CTLTYPE_INT | CTLFLAG_RD, lio, 0, lio_get_channels,
199 			"I", "Get channels information");
200 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_budget",
201 			CTLFLAG_RW, &oct_dev->tx_budget,
202 			0, "TX process pkt budget");
203 	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_budget",
204 			CTLFLAG_RW, &oct_dev->rx_budget,
205 			0, "RX process pkt budget");
206 
207 	/* IRQ Coalescing Parameters */
208 	root_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "coalesce",
209 				    CTLFLAG_RD, NULL, "Get and Set Coalesce");
210 
211 	root_list = SYSCTL_CHILDREN(root_node);
212 
213 	if (lio_get_intrmod_cfg(lio, &lio->intrmod_cfg))
214 		lio_dev_info(oct_dev, "Coalescing driver update failed!\n");
215 
216 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "sample-interval",
217 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
218 			LIO_RATE_SAMPLE_INTERVAL, lio_get_set_intr_coalesce,
219 			"QU", NULL);
220 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "tx-frame-high",
221 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
222 			LIO_TX_MAX_COALESCED_FRAMES_HIGH,
223 			lio_get_set_intr_coalesce, "QU", NULL);
224 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-frame-high",
225 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
226 			LIO_RX_MAX_COALESCED_FRAMES_HIGH,
227 			lio_get_set_intr_coalesce, "QU", NULL);
228 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-usecs-high",
229 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
230 			LIO_RX_COALESCE_USECS_HIGH, lio_get_set_intr_coalesce,
231 			"QU", NULL);
232 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "pkt-rate-high",
233 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
234 			LIO_PKT_RATE_HIGH, lio_get_set_intr_coalesce,
235 			"QU", NULL);
236 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "tx-frame-low",
237 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
238 			LIO_TX_MAX_COALESCED_FRAMES_LOW,
239 			lio_get_set_intr_coalesce, "QU", NULL);
240 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-frame-low",
241 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
242 			LIO_RX_MAX_COALESCED_FRAMES_LOW,
243 			lio_get_set_intr_coalesce, "QU", NULL);
244 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-usecs-low",
245 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
246 			LIO_RX_COALESCE_USECS_LOW, lio_get_set_intr_coalesce,
247 			"QU", NULL);
248 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "pkt-rate-low",
249 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
250 			LIO_PKT_RATE_LOW, lio_get_set_intr_coalesce,
251 			"QU", NULL);
252 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "tx-frames",
253 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
254 			LIO_TX_MAX_COALESCED_FRAMES, lio_get_set_intr_coalesce,
255 			"QU", NULL);
256 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-frames",
257 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
258 			LIO_RX_MAX_COALESCED_FRAMES, lio_get_set_intr_coalesce,
259 			"QU", NULL);
260 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "rx-usecs",
261 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
262 			LIO_RX_COALESCE_USECS, lio_get_set_intr_coalesce,
263 			"QU", NULL);
264 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "adaptive-tx",
265 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
266 			LIO_USE_ADAPTIVE_TX_COALESCE, lio_get_set_intr_coalesce,
267 			"QU", NULL);
268 	SYSCTL_ADD_PROC(ctx, root_list, OID_AUTO, "adaptive-rx",
269 			CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE, lio,
270 			LIO_USE_ADAPTIVE_RX_COALESCE, lio_get_set_intr_coalesce,
271 			"QU", NULL);
272 
273 	/* Root Node of all the Stats */
274 	root_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
275 				    NULL, "Root Node of all the Stats");
276 	root_list = SYSCTL_CHILDREN(root_node);
277 
278 	/* Firmware Tx Stats */
279 	stat_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, "fwtx",CTLFLAG_RD,
280 				    NULL, "Firmware Tx Statistics");
281 	stat_list = SYSCTL_CHILDREN(stat_node);
282 
283 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_total_sent", CTLFLAG_RD,
284 			 &oct_dev->link_stats.fromhost.fw_total_sent,
285 			 "Firmware Total Packets Sent");
286 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_total_fwd", CTLFLAG_RD,
287 			 &oct_dev->link_stats.fromhost.fw_total_fwd,
288 			 "Firmware Total Packets Forwarded");
289 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_total_fwd_bytes",
290 			 CTLFLAG_RD,
291 			 &oct_dev->link_stats.fromhost.fw_total_fwd_bytes,
292 			 "Firmware Total Bytes Forwarded");
293 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_err_pko", CTLFLAG_RD,
294 			 &oct_dev->link_stats.fromhost.fw_err_pko,
295 			 "Firmware Tx PKO Errors");
296 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_err_pki", CTLFLAG_RD,
297 			 &oct_dev->link_stats.fromhost.fw_err_pki,
298 			 "Firmware Tx PKI Errors");
299 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_err_link", CTLFLAG_RD,
300 			 &oct_dev->link_stats.fromhost.fw_err_link,
301 			 "Firmware Tx Link Errors");
302 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_err_drop", CTLFLAG_RD,
303 			 &oct_dev->link_stats.fromhost.fw_err_drop,
304 			 "Firmware Tx Packets Dropped");
305 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "fw_tso", CTLFLAG_RD,
306 			 &oct_dev->link_stats.fromhost.fw_tso,
307 			 "Firmware Tx TSO");
308 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_tso_packets", CTLFLAG_RD,
309 			 &oct_dev->link_stats.fromhost.fw_tso_fwd,
310 			 "Firmware Tx TSO Packets");
311 	//SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_tso_err", CTLFLAG_RD,
312 			   //&oct_dev->link_stats.fromhost.fw_tso_err,
313 			   //"Firmware Tx TSO Errors");
314 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "tx_vxlan", CTLFLAG_RD,
315 			 &oct_dev->link_stats.fromhost.fw_tx_vxlan,
316 			 "Firmware Tx VXLAN");
317 
318 	/* MAC Tx Stats */
319 	stat_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, "mactx",
320 				    CTLFLAG_RD, NULL, "MAC Tx Statistics");
321 	stat_list = SYSCTL_CHILDREN(stat_node);
322 
323 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_total_pkts",
324 			 CTLFLAG_RD,
325 			 &oct_dev->link_stats.fromhost.total_pkts_sent,
326 			 "Link-Level Total Packets Sent");
327 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_total_bytes",
328 			 CTLFLAG_RD,
329 			 &oct_dev->link_stats.fromhost.total_bytes_sent,
330 			 "Link-Level Total Bytes Sent");
331 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_mcast_pkts",
332 			 CTLFLAG_RD,
333 			 &oct_dev->link_stats.fromhost.mcast_pkts_sent,
334 			 "Link-Level Multicast Packets Sent");
335 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_bcast_pkts",
336 			 CTLFLAG_RD,
337 			 &oct_dev->link_stats.fromhost.bcast_pkts_sent,
338 			 "Link-Level Broadcast Packets Sent");
339 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_ctl_packets",
340 			 CTLFLAG_RD,
341 			 &oct_dev->link_stats.fromhost.ctl_sent,
342 			 "Link-Level Control Packets Sent");
343 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_total_collisions",
344 			 CTLFLAG_RD,
345 			 &oct_dev->link_stats.fromhost.total_collisions,
346 			 "Link-Level Tx Total Collisions");
347 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_one_collision",
348 			 CTLFLAG_RD,
349 			 &oct_dev->link_stats.fromhost.one_collision_sent,
350 			 "Link-Level Tx One Collision Sent");
351 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_multi_collison",
352 			 CTLFLAG_RD,
353 			 &oct_dev->link_stats.fromhost.multi_collision_sent,
354 			 "Link-Level Tx Multi-Collision Sent");
355 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_max_collision_fail",
356 			 CTLFLAG_RD,
357 			 &oct_dev->link_stats.fromhost.max_collision_fail,
358 			 "Link-Level Tx Max Collision Failed");
359 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_max_deferal_fail",
360 			 CTLFLAG_RD,
361 			 &oct_dev->link_stats.fromhost.max_deferral_fail,
362 			 "Link-Level Tx Max Deferral Failed");
363 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_fifo_err",
364 			 CTLFLAG_RD,
365 			 &oct_dev->link_stats.fromhost.fifo_err,
366 			 "Link-Level Tx FIFO Errors");
367 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_tx_runts", CTLFLAG_RD,
368 			 &oct_dev->link_stats.fromhost.runts,
369 			 "Link-Level Tx Runts");
370 
371 	/* Firmware Rx Stats */
372 	stat_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, "fwrx",
373 				    CTLFLAG_RD, NULL, "Firmware Rx Statistics");
374 	stat_list = SYSCTL_CHILDREN(stat_node);
375 
376 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_total_rcvd", CTLFLAG_RD,
377 			 &oct_dev->link_stats.fromwire.fw_total_rcvd,
378 			 "Firmware Total Packets Received");
379 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_total_fwd", CTLFLAG_RD,
380 			 &oct_dev->link_stats.fromwire.fw_total_fwd,
381 			 "Firmware Total Packets Forwarded");
382 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_jabber_err", CTLFLAG_RD,
383 			 &oct_dev->link_stats.fromwire.jabber_err,
384 			 "Firmware Rx Jabber Errors");
385 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_l2_err", CTLFLAG_RD,
386 			 &oct_dev->link_stats.fromwire.l2_err,
387 			 "Firmware Rx L2 Errors");
388 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_frame_err", CTLFLAG_RD,
389 			 &oct_dev->link_stats.fromwire.frame_err,
390 			 "Firmware Rx Frame Errors");
391 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_err_pko", CTLFLAG_RD,
392 			 &oct_dev->link_stats.fromwire.fw_err_pko,
393 			 "Firmware Rx PKO Errors");
394 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_err_link", CTLFLAG_RD,
395 			 &oct_dev->link_stats.fromwire.fw_err_link,
396 			 "Firmware Rx Link Errors");
397 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_err_drop", CTLFLAG_RD,
398 			 &oct_dev->link_stats.fromwire.fw_err_drop,
399 			 "Firmware Rx Dropped");
400 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_vxlan", CTLFLAG_RD,
401 			 &oct_dev->link_stats.fromwire.fw_rx_vxlan,
402 			 "Firmware Rx VXLAN");
403 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_vxlan_err", CTLFLAG_RD,
404 			 &oct_dev->link_stats.fromwire.fw_rx_vxlan_err,
405 			 "Firmware Rx VXLAN Errors");
406 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_pkts", CTLFLAG_RD,
407 			 &oct_dev->link_stats.fromwire.fw_lro_pkts,
408 			 "Firmware Rx LRO Packets");
409 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_bytes", CTLFLAG_RD,
410 			 &oct_dev->link_stats.fromwire.fw_lro_octs,
411 			 "Firmware Rx LRO Bytes");
412 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_total_lro", CTLFLAG_RD,
413 			 &oct_dev->link_stats.fromwire.fw_total_lro,
414 			 "Firmware Rx Total LRO");
415 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts", CTLFLAG_RD,
416 			 &oct_dev->link_stats.fromwire.fw_lro_aborts,
417 			 "Firmware Rx LRO Aborts");
418 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts_port",
419 			 CTLFLAG_RD,
420 			 &oct_dev->link_stats.fromwire.fw_lro_aborts_port,
421 			 "Firmware Rx LRO Aborts Port");
422 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts_seq",
423 			 CTLFLAG_RD,
424 			 &oct_dev->link_stats.fromwire.fw_lro_aborts_seq,
425 			 "Firmware Rx LRO Aborts Sequence");
426 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts_tsval",
427 			 CTLFLAG_RD,
428 			 &oct_dev->link_stats.fromwire.fw_lro_aborts_tsval,
429 			 "Firmware Rx LRO Aborts tsval");
430 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_lro_aborts_timer",
431 			 CTLFLAG_RD,
432 			 &oct_dev->link_stats.fromwire.fw_lro_aborts_timer,
433 			 "Firmware Rx LRO Aborts Timer");
434 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "rx_fwd_rate",
435 			 CTLFLAG_RD,
436 			 &oct_dev->link_stats.fromwire.fwd_rate,
437 			 "Firmware Rx Packets Forward Rate");
438 	/* MAC Rx Stats */
439 	stat_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, "macrx",
440 				    CTLFLAG_RD, NULL, "MAC Rx Statistics");
441 	stat_list = SYSCTL_CHILDREN(stat_node);
442 
443 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_total_rcvd",
444 			 CTLFLAG_RD,
445 			 &oct_dev->link_stats.fromwire.total_rcvd,
446 			 "Link-Level Total Packets Received");
447 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_bytes",
448 			 CTLFLAG_RD,
449 			 &oct_dev->link_stats.fromwire.bytes_rcvd,
450 			 "Link-Level Total Bytes Received");
451 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_total_bcst",
452 			 CTLFLAG_RD,
453 			 &oct_dev->link_stats.fromwire.total_bcst,
454 			 "Link-Level Total Broadcast");
455 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_total_mcst",
456 			 CTLFLAG_RD,
457 			 &oct_dev->link_stats.fromwire.total_mcst,
458 			 "Link-Level Total Multicast");
459 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_runts",
460 			 CTLFLAG_RD,
461 			 &oct_dev->link_stats.fromwire.runts,
462 			 "Link-Level Rx Runts");
463 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_ctl_packets",
464 			 CTLFLAG_RD,
465 			 &oct_dev->link_stats.fromwire.ctl_rcvd,
466 			 "Link-Level Rx Control Packets");
467 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_fifo_err",
468 			 CTLFLAG_RD,
469 			 &oct_dev->link_stats.fromwire.fifo_err,
470 			 "Link-Level Rx FIFO Errors");
471 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_dma_drop",
472 			 CTLFLAG_RD,
473 			 &oct_dev->link_stats.fromwire.dmac_drop,
474 			 "Link-Level Rx DMA Dropped");
475 	SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, "mac_rx_fcs_err",
476 			 CTLFLAG_RD,
477 			 &oct_dev->link_stats.fromwire.fcs_err,
478 			 "Link-Level Rx FCS Errors");
479 
480 	/* TX */
481 	for (int i = 0; i < oct_dev->num_iqs; i++) {
482 		if (!(oct_dev->io_qmask.iq & BIT_ULL(i)))
483 			continue;
484 
485 		snprintf(namebuf, QUEUE_NAME_LEN, "tx-%d", i);
486 		queue_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, namebuf,
487 					     CTLFLAG_RD, NULL, "Input Queue Name");
488 		queue_list = SYSCTL_CHILDREN(queue_node);
489 
490 		/* packets to network port */
491 		/* # of packets tx to network */
492 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "packets",
493 				 CTLFLAG_RD,
494 				 &oct_dev->instr_queue[i]->stats.tx_done,
495 				 "Number of Packets Tx to Network");
496 		/* # of bytes tx to network */
497 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "bytes",
498 				 CTLFLAG_RD,
499 				 &oct_dev->instr_queue[i]->stats.tx_tot_bytes,
500 				 "Number of Bytes Tx to Network");
501 		/* # of packets dropped */
502 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped",
503 				 CTLFLAG_RD,
504 				 &oct_dev->instr_queue[i]->stats.tx_dropped,
505 				 "Number of Tx Packets Dropped");
506 		/* # of tx fails due to queue full */
507 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "iq_busy",
508 				 CTLFLAG_RD,
509 				 &oct_dev->instr_queue[i]->stats.tx_iq_busy,
510 				 "Number of Tx Fails Due to Queue Full");
511 		/* scatter gather entries sent */
512 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "sgentry_sent",
513 				 CTLFLAG_RD,
514 				 &oct_dev->instr_queue[i]->stats.sgentry_sent,
515 				 "Scatter Gather Entries Sent");
516 
517 		/* instruction to firmware: data and control */
518 		/* # of instructions to the queue */
519 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_instr_posted",
520 				 CTLFLAG_RD,
521 				 &oct_dev->instr_queue[i]->stats.instr_posted,
522 				 "Number of Instructions to The Queue");
523 		/* # of instructions processed */
524 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO,
525 				 "fw_instr_processed", CTLFLAG_RD,
526 			      &oct_dev->instr_queue[i]->stats.instr_processed,
527 				 "Number of Instructions Processed");
528 		/* # of instructions could not be processed */
529 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_instr_dropped",
530 				 CTLFLAG_RD,
531 				 &oct_dev->instr_queue[i]->stats.instr_dropped,
532 				 "Number of Instructions Dropped");
533 		/* bytes sent through the queue */
534 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_bytes_sent",
535 				 CTLFLAG_RD,
536 				 &oct_dev->instr_queue[i]->stats.bytes_sent,
537 				 "Bytes Sent Through The Queue");
538 		/* tso request */
539 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tso",
540 				 CTLFLAG_RD,
541 				 &oct_dev->instr_queue[i]->stats.tx_gso,
542 				 "TSO Request");
543 		/* vxlan request */
544 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "vxlan",
545 				 CTLFLAG_RD,
546 				 &oct_dev->instr_queue[i]->stats.tx_vxlan,
547 				 "VXLAN Request");
548 		/* txq restart */
549 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "txq_restart",
550 				 CTLFLAG_RD,
551 				 &oct_dev->instr_queue[i]->stats.tx_restart,
552 				 "TxQ Restart");
553 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "tx_dmamap_fail",
554 				 CTLFLAG_RD,
555 			       &oct_dev->instr_queue[i]->stats.tx_dmamap_fail,
556 				 "TxQ DMA Map Failed");
557 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO,
558 				 "mbuf_defrag_failed", CTLFLAG_RD,
559 			   &oct_dev->instr_queue[i]->stats.mbuf_defrag_failed,
560 				 "TxQ defrag Failed");
561 	}
562 
563 	/* RX */
564 	for (int i = 0; i < oct_dev->num_oqs; i++) {
565 		if (!(oct_dev->io_qmask.oq & BIT_ULL(i)))
566 			continue;
567 
568 		snprintf(namebuf, QUEUE_NAME_LEN, "rx-%d", i);
569 		queue_node = SYSCTL_ADD_NODE(ctx, root_list, OID_AUTO, namebuf,
570 					     CTLFLAG_RD, NULL,
571 					     "Output Queue Name");
572 		queue_list = SYSCTL_CHILDREN(queue_node);
573 
574 		/* packets send to TCP/IP network stack */
575 		/* # of packets to network stack */
576 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "packets",
577 				 CTLFLAG_RD,
578 				 &oct_dev->droq[i]->stats.rx_pkts_received,
579 				 "Number of Packets to Network Stack");
580 		/* # of bytes to network stack */
581 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "bytes",
582 				 CTLFLAG_RD,
583 				 &oct_dev->droq[i]->stats.rx_bytes_received,
584 				 "Number of Bytes to Network Stack");
585 		/* # of packets dropped */
586 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped_nomem",
587 				 CTLFLAG_RD,
588 				 &oct_dev->droq[i]->stats.dropped_nomem,
589 				 "Packets Dropped Due to No Memory");
590 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "dropped_toomany",
591 				 CTLFLAG_RD,
592 				 &oct_dev->droq[i]->stats.dropped_toomany,
593 				 "Packets dropped, Too Many Pkts to Process");
594 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_dropped",
595 				 CTLFLAG_RD,
596 				 &oct_dev->droq[i]->stats.rx_dropped,
597 				"Packets Dropped due to Receive path failures");
598 		/* control and data path */
599 		/* # packets  sent to stack from this queue. */
600 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_pkts_received",
601 				 CTLFLAG_RD,
602 				 &oct_dev->droq[i]->stats.pkts_received,
603 				 "Number of Packets Received");
604 		/* # Bytes sent to stack from this queue. */
605 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "fw_bytes_received",
606 				 CTLFLAG_RD,
607 				 &oct_dev->droq[i]->stats.bytes_received,
608 				 "Number of Bytes Received");
609 		/* Packets dropped due to no dispatch function. */
610 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO,
611 				 "fw_dropped_nodispatch", CTLFLAG_RD,
612 				 &oct_dev->droq[i]->stats.dropped_nodispatch,
613 				 "Packets Dropped, No Dispatch Function");
614 		/* Rx VXLAN */
615 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO, "vxlan",
616 				 CTLFLAG_RD,
617 				 &oct_dev->droq[i]->stats.rx_vxlan,
618 				 "Rx VXLAN");
619 		/* # failures of lio_recv_buffer_alloc */
620 		SYSCTL_ADD_UQUAD(ctx, queue_list, OID_AUTO,
621 				 "buffer_alloc_failure", CTLFLAG_RD,
622 				 &oct_dev->droq[i]->stats.rx_alloc_failure,
623 			       "Number of Failures of lio_recv_buffer_alloc");
624 	}
625 }
626 
627 static int
628 lio_get_eeprom(SYSCTL_HANDLER_ARGS)
629 {
630 	struct lio		*lio = (struct lio *)arg1;
631 	struct octeon_device	*oct_dev = lio->oct_dev;
632 	struct lio_board_info	*board_info;
633 	char	buf[512];
634 
635 	board_info = (struct lio_board_info *)(&oct_dev->boardinfo);
636 	if (oct_dev->uboot_len == 0)
637 		sprintf(buf, "boardname:%s serialnum:%s maj:%lld min:%lld",
638 			board_info->name, board_info->serial_number,
639 			LIO_CAST64(board_info->major),
640 		       	LIO_CAST64(board_info->minor));
641 	else {
642 		sprintf(buf, "boardname:%s serialnum:%s maj:%lld min:%lld\n%s",
643 			board_info->name, board_info->serial_number,
644 			LIO_CAST64(board_info->major),
645 		        LIO_CAST64(board_info->minor),
646 			&oct_dev->uboot_version[oct_dev->uboot_sidx]);
647 	}
648 
649 	return (sysctl_handle_string(oidp, buf, strlen(buf), req));
650 }
651 
652 /*
653  * Get and set pause parameters or flow control using sysctl:
654  * 0 - off
655  * 1 - rx pause
656  * 2 - tx pause
657  * 3 - full
658  */
659 static int
660 lio_get_set_pauseparam(SYSCTL_HANDLER_ARGS)
661 {
662 	/* Notes: Not supporting any auto negotiation in these drivers. */
663 	struct lio_ctrl_pkt	nctrl;
664 	struct lio		*lio = (struct lio *)arg1;
665 	struct octeon_device	*oct = lio->oct_dev;
666 	struct octeon_link_info	*linfo = &lio->linfo;
667 
668 	int	err, new_pause = LIO_OFF_PAUSE, old_pause = LIO_OFF_PAUSE;
669 	int	ret = 0;
670 
671 	if (oct->chip_id != LIO_CN23XX_PF_VID)
672 		return (EINVAL);
673 
674 	if (oct->rx_pause)
675 		old_pause |= LIO_RX_PAUSE;
676 
677 	if (oct->tx_pause)
678 		old_pause |= LIO_TX_PAUSE;
679 
680 	new_pause = old_pause;
681 	err = sysctl_handle_int(oidp, &new_pause, 0, req);
682 
683 	if ((err) || (req->newptr == NULL))
684 		return (err);
685 
686 	if (old_pause == new_pause)
687 		return (0);
688 
689 	if (linfo->link.s.duplex == 0) {
690 		/* no flow control for half duplex */
691 		if (new_pause)
692 			return (EINVAL);
693 	}
694 
695 	bzero(&nctrl, sizeof(struct lio_ctrl_pkt));
696 
697 	nctrl.ncmd.cmd64 = 0;
698 	nctrl.ncmd.s.cmd = LIO_CMD_SET_FLOW_CTL;
699 	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
700 	nctrl.wait_time = 100;
701 	nctrl.lio = lio;
702 	nctrl.cb_fn = lio_ctrl_cmd_completion;
703 
704 	if (new_pause & LIO_RX_PAUSE) {
705 		/* enable rx pause */
706 		nctrl.ncmd.s.param1 = 1;
707 	} else {
708 		/* disable rx pause */
709 		nctrl.ncmd.s.param1 = 0;
710 	}
711 
712 	if (new_pause & LIO_TX_PAUSE) {
713 		/* enable tx pause */
714 		nctrl.ncmd.s.param2 = 1;
715 	} else {
716 		/* disable tx pause */
717 		nctrl.ncmd.s.param2 = 0;
718 	}
719 
720 	ret = lio_send_ctrl_pkt(lio->oct_dev, &nctrl);
721 	if (ret < 0) {
722 		lio_dev_err(oct, "Failed to set pause parameter\n");
723 		return (EINVAL);
724 	}
725 
726 	oct->rx_pause = new_pause & LIO_RX_PAUSE;
727 	oct->tx_pause = new_pause & LIO_TX_PAUSE;
728 
729 	return (0);
730 }
731 
732 /*  Return register dump user app.  */
733 static int
734 lio_get_regs(SYSCTL_HANDLER_ARGS)
735 {
736 	struct lio		*lio = (struct lio *)arg1;
737 	struct octeon_device	*oct = lio->oct_dev;
738 	struct ifnet		*ifp = lio->ifp;
739 	char	*regbuf;
740 	int	error = EINVAL, len = 0;
741 
742 	if (!(if_getflags(ifp) & IFF_DEBUG)) {
743 		char debug_info[30] = "Debugging is disabled";
744 
745 		return (sysctl_handle_string(oidp, debug_info,
746 					     strlen(debug_info), req));
747 	}
748 	regbuf = malloc(sizeof(char) * LIO_REGDUMP_LEN_XXXX, M_DEVBUF,
749 			M_WAITOK | M_ZERO);
750 
751 	if (regbuf == NULL)
752 		return (error);
753 
754 	switch (oct->chip_id) {
755 	case LIO_CN23XX_PF_VID:
756 		len += lio_cn23xx_pf_read_csr_reg(regbuf, oct);
757 		break;
758 	default:
759 		len += sprintf(regbuf, "%s Unknown chipid: %d\n",
760 			       __func__, oct->chip_id);
761 	}
762 
763 	error = sysctl_handle_string(oidp, regbuf, len, req);
764 	free(regbuf, M_DEVBUF);
765 
766 	return (error);
767 }
768 
769 static int
770 lio_cn23xx_pf_read_csr_reg(char *s, struct octeon_device *oct)
771 {
772 	uint32_t	reg;
773 	int	i, len = 0;
774 	uint8_t	pf_num = oct->pf_num;
775 
776 	/* PCI  Window Registers */
777 
778 	len += sprintf(s + len, "\t Octeon CSR Registers\n\n");
779 
780 	/* 0x29030 or 0x29040 */
781 	reg = LIO_CN23XX_SLI_PKT_MAC_RINFO64(oct->pcie_port, oct->pf_num);
782 	len += sprintf(s + len, "[%08x] (SLI_PKT_MAC%d_PF%d_RINFO): %016llx\n",
783 		       reg, oct->pcie_port, oct->pf_num,
784 		       LIO_CAST64(lio_read_csr64(oct, reg)));
785 
786 	/* 0x27080 or 0x27090 */
787 	reg = LIO_CN23XX_SLI_MAC_PF_INT_ENB64(oct->pcie_port, oct->pf_num);
788 	len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_INT_ENB): %016llx\n",
789 		       reg, oct->pcie_port, oct->pf_num,
790 		       LIO_CAST64(lio_read_csr64(oct, reg)));
791 
792 	/* 0x27000 or 0x27010 */
793 	reg = LIO_CN23XX_SLI_MAC_PF_INT_SUM64(oct->pcie_port, oct->pf_num);
794 	len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_INT_SUM): %016llx\n",
795 		       reg, oct->pcie_port, oct->pf_num,
796 		       LIO_CAST64(lio_read_csr64(oct, reg)));
797 
798 	/* 0x29120 */
799 	reg = 0x29120;
800 	len += sprintf(s + len, "[%08x] (SLI_PKT_MEM_CTL): %016llx\n", reg,
801 		       LIO_CAST64(lio_read_csr64(oct, reg)));
802 
803 	/* 0x27300 */
804 	reg = 0x27300 + oct->pcie_port * LIO_CN23XX_MAC_INT_OFFSET +
805 	    (oct->pf_num) * LIO_CN23XX_PF_INT_OFFSET;
806 	len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_PKT_VF_INT): %016llx\n",
807 		       reg, oct->pcie_port, oct->pf_num,
808 		       LIO_CAST64(lio_read_csr64(oct, reg)));
809 
810 	/* 0x27200 */
811 	reg = 0x27200 + oct->pcie_port * LIO_CN23XX_MAC_INT_OFFSET +
812 	    (oct->pf_num) * LIO_CN23XX_PF_INT_OFFSET;
813 	len += sprintf(s + len, "[%08x] (SLI_MAC%d_PF%d_PP_VF_INT): %016llx\n",
814 		       reg, oct->pcie_port, oct->pf_num,
815 		       LIO_CAST64(lio_read_csr64(oct, reg)));
816 
817 	/* 29130 */
818 	reg = LIO_CN23XX_SLI_PKT_CNT_INT;
819 	len += sprintf(s + len, "[%08x] (SLI_PKT_CNT_INT): %016llx\n", reg,
820 		       LIO_CAST64(lio_read_csr64(oct, reg)));
821 
822 	/* 0x29140 */
823 	reg = LIO_CN23XX_SLI_PKT_TIME_INT;
824 	len += sprintf(s + len, "[%08x] (SLI_PKT_TIME_INT): %016llx\n", reg,
825 		       LIO_CAST64(lio_read_csr64(oct, reg)));
826 
827 	/* 0x29160 */
828 	reg = 0x29160;
829 	len += sprintf(s + len, "[%08x] (SLI_PKT_INT): %016llx\n", reg,
830 		       LIO_CAST64(lio_read_csr64(oct, reg)));
831 
832 	/* 0x29180 */
833 	reg = LIO_CN23XX_SLI_OQ_WMARK;
834 	len += sprintf(s + len, "[%08x] (SLI_PKT_OUTPUT_WMARK): %016llx\n",
835 		       reg, LIO_CAST64(lio_read_csr64(oct, reg)));
836 
837 	/* 0x291E0 */
838 	reg = LIO_CN23XX_SLI_PKT_IOQ_RING_RST;
839 	len += sprintf(s + len, "[%08x] (SLI_PKT_RING_RST): %016llx\n", reg,
840 		       LIO_CAST64(lio_read_csr64(oct, reg)));
841 
842 	/* 0x29210 */
843 	reg = LIO_CN23XX_SLI_GBL_CONTROL;
844 	len += sprintf(s + len, "[%08x] (SLI_PKT_GBL_CONTROL): %016llx\n", reg,
845 		       LIO_CAST64(lio_read_csr64(oct, reg)));
846 
847 	/* 0x29220 */
848 	reg = 0x29220;
849 	len += sprintf(s + len, "[%08x] (SLI_PKT_BIST_STATUS): %016llx\n",
850 		       reg, LIO_CAST64(lio_read_csr64(oct, reg)));
851 
852 	/* PF only */
853 	if (pf_num == 0) {
854 		/* 0x29260 */
855 		reg = LIO_CN23XX_SLI_OUT_BP_EN_W1S;
856 		len += sprintf(s + len, "[%08x] (SLI_PKT_OUT_BP_EN_W1S):  %016llx\n",
857 			       reg, LIO_CAST64(lio_read_csr64(oct, reg)));
858 	} else if (pf_num == 1) {
859 		/* 0x29270 */
860 		reg = LIO_CN23XX_SLI_OUT_BP_EN2_W1S;
861 		len += sprintf(s + len, "[%08x] (SLI_PKT_OUT_BP_EN2_W1S): %016llx\n",
862 			       reg, LIO_CAST64(lio_read_csr64(oct, reg)));
863 	}
864 
865 	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
866 		reg = LIO_CN23XX_SLI_OQ_BUFF_INFO_SIZE(i);
867 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_OUT_SIZE): %016llx\n",
868 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
869 	}
870 
871 	/* 0x10040 */
872 	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
873 		reg = LIO_CN23XX_SLI_IQ_INSTR_COUNT64(i);
874 		len += sprintf(s + len, "[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
875 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
876 	}
877 
878 	/* 0x10080 */
879 	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
880 		reg = LIO_CN23XX_SLI_OQ_PKTS_CREDIT(i);
881 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_BAOFF_DBELL): %016llx\n",
882 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
883 	}
884 
885 	/* 0x10090 */
886 	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
887 		reg = LIO_CN23XX_SLI_OQ_SIZE(i);
888 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_FIFO_RSIZE): %016llx\n",
889 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
890 	}
891 
892 	/* 0x10050 */
893 	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
894 		reg = LIO_CN23XX_SLI_OQ_PKT_CONTROL(i);
895 		len += sprintf(s + len, "[%08x] (SLI_PKT%d__OUTPUT_CONTROL): %016llx\n",
896 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
897 	}
898 
899 	/* 0x10070 */
900 	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
901 		reg = LIO_CN23XX_SLI_OQ_BASE_ADDR64(i);
902 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_SLIST_BADDR): %016llx\n",
903 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
904 	}
905 
906 	/* 0x100a0 */
907 	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
908 		reg = LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(i);
909 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INT_LEVELS): %016llx\n",
910 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
911 	}
912 
913 	/* 0x100b0 */
914 	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
915 		reg = LIO_CN23XX_SLI_OQ_PKTS_SENT(i);
916 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_CNTS): %016llx\n",
917 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
918 	}
919 
920 	/* 0x100c0 */
921 	for (i = 0; i < LIO_CN23XX_PF_MAX_OUTPUT_QUEUES; i++) {
922 		reg = 0x100c0 + i * LIO_CN23XX_OQ_OFFSET;
923 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_ERROR_INFO): %016llx\n",
924 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
925 	}
926 
927 	/* 0x10000 */
928 	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
929 		reg = LIO_CN23XX_SLI_IQ_PKT_CONTROL64(i);
930 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INPUT_CONTROL): %016llx\n",
931 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
932 	}
933 
934 	/* 0x10010 */
935 	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
936 		reg = LIO_CN23XX_SLI_IQ_BASE_ADDR64(i);
937 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_BADDR): %016llx\n",
938 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
939 	}
940 
941 	/* 0x10020 */
942 	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
943 		reg = LIO_CN23XX_SLI_IQ_DOORBELL(i);
944 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_BAOFF_DBELL): %016llx\n",
945 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
946 	}
947 
948 	/* 0x10030 */
949 	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++) {
950 		reg = LIO_CN23XX_SLI_IQ_SIZE(i);
951 		len += sprintf(s + len, "[%08x] (SLI_PKT%d_INSTR_FIFO_RSIZE): %016llx\n",
952 			       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
953 	}
954 
955 	/* 0x10040 */
956 	for (i = 0; i < LIO_CN23XX_PF_MAX_INPUT_QUEUES; i++)
957 		reg = LIO_CN23XX_SLI_IQ_INSTR_COUNT64(i);
958 	len += sprintf(s + len, "[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
959 		       reg, i, LIO_CAST64(lio_read_csr64(oct, reg)));
960 
961 	return (len);
962 }
963 
964 static int
965 lio_get_ringparam(SYSCTL_HANDLER_ARGS)
966 {
967 	struct lio		*lio = (struct lio *)arg1;
968 	struct octeon_device	*oct = lio->oct_dev;
969 	uint32_t		rx_max_pending = 0, tx_max_pending = 0;
970 	int	err;
971 
972 	if (LIO_CN23XX_PF(oct)) {
973 		tx_max_pending = LIO_CN23XX_MAX_IQ_DESCRIPTORS;
974 		rx_max_pending = LIO_CN23XX_MAX_OQ_DESCRIPTORS;
975 	}
976 
977 	switch (arg2) {
978 	case LIO_SET_RING_RX:
979 		err = sysctl_handle_int(oidp, &rx_max_pending, 0, req);
980 		break;
981 	case LIO_SET_RING_TX:
982 		err = sysctl_handle_int(oidp, &tx_max_pending, 0, req);
983 		break;
984 	}
985 
986 	return (err);
987 }
988 
989 static int
990 lio_reset_queues(struct ifnet *ifp, uint32_t num_qs)
991 {
992 	struct lio		*lio = if_getsoftc(ifp);
993 	struct octeon_device	*oct = lio->oct_dev;
994 	int	i, update = 0;
995 
996 	if (lio_wait_for_pending_requests(oct))
997 		lio_dev_err(oct, "There were pending requests\n");
998 
999 	if (lio_wait_for_instr_fetch(oct))
1000 		lio_dev_err(oct, "IQ had pending instructions\n");
1001 
1002 
1003 	/*
1004 	 * Disable the input and output queues now. No more packets will
1005 	 * arrive from Octeon.
1006 	 */
1007 	oct->fn_list.disable_io_queues(oct);
1008 
1009 	if (num_qs != oct->num_iqs)
1010 		update = 1;
1011 
1012 	for (i = 0; i < LIO_MAX_OUTPUT_QUEUES(oct); i++) {
1013 		if (!(oct->io_qmask.oq & BIT_ULL(i)))
1014 			continue;
1015 
1016 		lio_delete_droq(oct, i);
1017 	}
1018 
1019 	for (i = 0; i < LIO_MAX_INSTR_QUEUES(oct); i++) {
1020 		if (!(oct->io_qmask.iq & BIT_ULL(i)))
1021 			continue;
1022 
1023 		lio_delete_instr_queue(oct, i);
1024 	}
1025 
1026 	if (oct->fn_list.setup_device_regs(oct)) {
1027 		lio_dev_err(oct, "Failed to configure device registers\n");
1028 		return (-1);
1029 	}
1030 
1031 	if (lio_setup_io_queues(oct, 0, num_qs, num_qs)) {
1032 		lio_dev_err(oct, "IO queues initialization failed\n");
1033 		return (-1);
1034 	}
1035 
1036 	if (update && lio_send_queue_count_update(ifp, num_qs))
1037 		return (-1);
1038 
1039 	return (0);
1040 }
1041 
1042 static int
1043 lio_set_ringparam(SYSCTL_HANDLER_ARGS)
1044 {
1045 	struct lio		*lio = (struct lio *)arg1;
1046 	struct octeon_device	*oct = lio->oct_dev;
1047 	uint32_t		rx_count, rx_count_old, tx_count, tx_count_old;
1048 	int	err, stopped = 0;
1049 
1050 	if (!LIO_CN23XX_PF(oct))
1051 		return (EINVAL);
1052 
1053 	switch (arg2) {
1054 	case LIO_SET_RING_RX:
1055 		rx_count = rx_count_old = oct->droq[0]->max_count;
1056 		err = sysctl_handle_int(oidp, &rx_count, 0, req);
1057 
1058 		if ((err) || (req->newptr == NULL))
1059 			return (err);
1060 
1061 		rx_count = min(max(rx_count, LIO_CN23XX_MIN_OQ_DESCRIPTORS),
1062 			       LIO_CN23XX_MAX_OQ_DESCRIPTORS);
1063 
1064 		if (rx_count == rx_count_old)
1065 			return (0);
1066 
1067 		lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1068 
1069 		if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1070 			lio_stop(lio->ifp);
1071 			stopped = 1;
1072 		}
1073 
1074 		/* Change RX DESCS  count */
1075 		LIO_SET_NUM_RX_DESCS_NIC_IF(lio_get_conf(oct),
1076 					    lio->ifidx, rx_count);
1077 		break;
1078 	case LIO_SET_RING_TX:
1079 		tx_count = tx_count_old = oct->instr_queue[0]->max_count;
1080 		err = sysctl_handle_int(oidp, &tx_count, 0, req);
1081 
1082 		if ((err) || (req->newptr == NULL))
1083 			return (err);
1084 
1085 		tx_count = min(max(tx_count, LIO_CN23XX_MIN_IQ_DESCRIPTORS),
1086 			       LIO_CN23XX_MAX_IQ_DESCRIPTORS);
1087 
1088 		if (tx_count == tx_count_old)
1089 			return (0);
1090 
1091 		lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1092 
1093 		if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1094 			lio_stop(lio->ifp);
1095 			stopped = 1;
1096 		}
1097 
1098 		/* Change TX DESCS  count */
1099 		LIO_SET_NUM_TX_DESCS_NIC_IF(lio_get_conf(oct),
1100 					    lio->ifidx, tx_count);
1101 		break;
1102 	}
1103 
1104 	if (lio_reset_queues(lio->ifp, lio->linfo.num_txpciq))
1105 		goto err_lio_reset_queues;
1106 
1107 	lio_irq_reallocate_irqs(oct, lio->linfo.num_txpciq);
1108 	if (stopped)
1109 		lio_open(lio);
1110 
1111 	lio_ifstate_reset(lio, LIO_IFSTATE_RESETTING);
1112 
1113 	return (0);
1114 
1115 err_lio_reset_queues:
1116 	if (arg2 == LIO_SET_RING_RX && rx_count != rx_count_old)
1117 		LIO_SET_NUM_RX_DESCS_NIC_IF(lio_get_conf(oct), lio->ifidx,
1118 					    rx_count_old);
1119 
1120 	if (arg2 == LIO_SET_RING_TX && tx_count != tx_count_old)
1121 		LIO_SET_NUM_TX_DESCS_NIC_IF(lio_get_conf(oct), lio->ifidx,
1122 					    tx_count_old);
1123 
1124 	return (EINVAL);
1125 }
1126 
1127 static int
1128 lio_get_channels(SYSCTL_HANDLER_ARGS)
1129 {
1130 	struct lio		*lio = (struct lio *)arg1;
1131 	struct octeon_device	*oct = lio->oct_dev;
1132 	uint32_t	max_combined = 0;
1133 
1134 		if (LIO_CN23XX_PF(oct))
1135 			max_combined = lio->linfo.num_txpciq;
1136 	return (sysctl_handle_int(oidp, &max_combined, 0, req));
1137 }
1138 
1139 static int
1140 lio_irq_reallocate_irqs(struct octeon_device *oct, uint32_t num_ioqs)
1141 {
1142 	int	i, num_msix_irqs = 0;
1143 
1144 	if (!oct->msix_on)
1145 		return (0);
1146 
1147 	/*
1148 	 * Disable the input and output queues now. No more packets will
1149 	 * arrive from Octeon.
1150 	 */
1151 	oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
1152 
1153 	if (oct->msix_on) {
1154 		if (LIO_CN23XX_PF(oct))
1155 			num_msix_irqs = oct->num_msix_irqs - 1;
1156 
1157 		for (i = 0; i < num_msix_irqs; i++) {
1158 			if (oct->ioq_vector[i].tag != NULL) {
1159 				bus_teardown_intr(oct->device,
1160 						  oct->ioq_vector[i].msix_res,
1161 						  oct->ioq_vector[i].tag);
1162 				oct->ioq_vector[i].tag = NULL;
1163 			}
1164 
1165 			if (oct->ioq_vector[i].msix_res != NULL) {
1166 				bus_release_resource(oct->device, SYS_RES_IRQ,
1167 						     oct->ioq_vector[i].vector,
1168 						 oct->ioq_vector[i].msix_res);
1169 				oct->ioq_vector[i].msix_res = NULL;
1170 			}
1171 		}
1172 
1173 
1174 		if (oct->tag != NULL) {
1175 			bus_teardown_intr(oct->device, oct->msix_res, oct->tag);
1176 			oct->tag = NULL;
1177 		}
1178 
1179 		if (oct->msix_res != NULL) {
1180 			bus_release_resource(oct->device, SYS_RES_IRQ,
1181 					     oct->aux_vector,
1182 					     oct->msix_res);
1183 			oct->msix_res = NULL;
1184 		}
1185 
1186 		pci_release_msi(oct->device);
1187 
1188 	}
1189 
1190 	if (lio_setup_interrupt(oct, num_ioqs)) {
1191 		lio_dev_info(oct, "Setup interuupt failed\n");
1192 		return (1);
1193 	}
1194 
1195 	/* Enable Octeon device interrupts */
1196 	oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
1197 
1198 	return (0);
1199 }
1200 
1201 static int
1202 lio_set_channels(SYSCTL_HANDLER_ARGS)
1203 {
1204 	struct lio		*lio = (struct lio *)arg1;
1205 	struct octeon_device	*oct = lio->oct_dev;
1206 	uint32_t		combined_count, max_combined;
1207 	int	err, stopped = 0;
1208 
1209 	if (strcmp(oct->fw_info.lio_firmware_version, "1.6.1") < 0) {
1210 		lio_dev_err(oct,
1211 			    "Minimum firmware version required is 1.6.1\n");
1212 		return (EINVAL);
1213 	}
1214 
1215 	combined_count = oct->num_iqs;
1216 	err = sysctl_handle_int(oidp, &combined_count, 0, req);
1217 
1218 	if ((err) || (req->newptr == NULL))
1219 		return (err);
1220 
1221 	if (!combined_count)
1222 		return (EINVAL);
1223 
1224 	if (LIO_CN23XX_PF(oct)) {
1225 		max_combined = lio->linfo.num_txpciq;
1226 	} else {
1227 		return (EINVAL);
1228 	}
1229 
1230 	if ((combined_count > max_combined) || (combined_count < 1))
1231 		return (EINVAL);
1232 
1233 	if (combined_count == oct->num_iqs)
1234 		return (0);
1235 
1236 	lio_ifstate_set(lio, LIO_IFSTATE_RESETTING);
1237 
1238 	if (if_getdrvflags(lio->ifp) & IFF_DRV_RUNNING) {
1239 		lio_stop(lio->ifp);
1240 		stopped = 1;
1241 	}
1242 
1243 	if (lio_reset_queues(lio->ifp, combined_count))
1244 		return (EINVAL);
1245 
1246 	lio_irq_reallocate_irqs(oct, combined_count);
1247 	if (stopped)
1248 		lio_open(lio);
1249 
1250 	lio_ifstate_reset(lio, LIO_IFSTATE_RESETTING);
1251 
1252 	return (0);
1253 }
1254 
1255 
1256 static int
1257 lio_get_set_fwmsglevel(SYSCTL_HANDLER_ARGS)
1258 {
1259 	struct lio	*lio = (struct lio *)arg1;
1260 	struct ifnet	*ifp = lio->ifp;
1261 	int	err, new_msglvl = 0, old_msglvl = 0;
1262 
1263 	if (lio_ifstate_check(lio, LIO_IFSTATE_RESETTING))
1264 		return (ENXIO);
1265 
1266 	old_msglvl = new_msglvl = lio->msg_enable;
1267 	err = sysctl_handle_int(oidp, &new_msglvl, 0, req);
1268 
1269 	if ((err) || (req->newptr == NULL))
1270 		return (err);
1271 
1272 	if (old_msglvl == new_msglvl)
1273 		return (0);
1274 
1275 	if (new_msglvl ^ lio->msg_enable) {
1276 		if (new_msglvl)
1277 			err = lio_set_feature(ifp, LIO_CMD_VERBOSE_ENABLE, 0);
1278 		else
1279 			err = lio_set_feature(ifp, LIO_CMD_VERBOSE_DISABLE, 0);
1280 	}
1281 
1282 	lio->msg_enable = new_msglvl;
1283 
1284 	return ((err) ? EINVAL : 0);
1285 }
1286 
1287 static int
1288 lio_set_stats_interval(SYSCTL_HANDLER_ARGS)
1289 {
1290 	struct lio	*lio = (struct lio *)arg1;
1291 	int	err, new_time = 0, old_time = 0;
1292 
1293 	old_time = new_time = lio->stats_interval;
1294 	err = sysctl_handle_int(oidp, &new_time, 0, req);
1295 
1296 	if ((err) || (req->newptr == NULL))
1297 		return (err);
1298 
1299 	if (old_time == new_time)
1300 		return (0);
1301 
1302 	lio->stats_interval = new_time;
1303 
1304 	return (0);
1305 }
1306 
1307 static void
1308 lio_fw_stats_callback(struct octeon_device *oct_dev, uint32_t status, void *ptr)
1309 {
1310 	struct lio_soft_command	*sc = (struct lio_soft_command *)ptr;
1311 	struct lio_fw_stats_resp *resp =
1312 		(struct lio_fw_stats_resp *)sc->virtrptr;
1313 	struct octeon_rx_stats	*rsp_rstats = &resp->stats.fromwire;
1314 	struct octeon_tx_stats	*rsp_tstats = &resp->stats.fromhost;
1315 	struct octeon_rx_stats	*rstats = &oct_dev->link_stats.fromwire;
1316 	struct octeon_tx_stats	*tstats = &oct_dev->link_stats.fromhost;
1317 	struct ifnet		*ifp = oct_dev->props.ifp;
1318 	struct lio		*lio = if_getsoftc(ifp);
1319 
1320 	if ((status != LIO_REQUEST_TIMEOUT) && !resp->status) {
1321 		lio_swap_8B_data((uint64_t *)&resp->stats,
1322 				 (sizeof(struct octeon_link_stats)) >> 3);
1323 
1324 		/* RX link-level stats */
1325 		rstats->total_rcvd = rsp_rstats->total_rcvd;
1326 		rstats->bytes_rcvd = rsp_rstats->bytes_rcvd;
1327 		rstats->total_bcst = rsp_rstats->total_bcst;
1328 		rstats->total_mcst = rsp_rstats->total_mcst;
1329 		rstats->runts = rsp_rstats->runts;
1330 		rstats->ctl_rcvd = rsp_rstats->ctl_rcvd;
1331 		/* Accounts for over/under-run of buffers */
1332 		rstats->fifo_err = rsp_rstats->fifo_err;
1333 		rstats->dmac_drop = rsp_rstats->dmac_drop;
1334 		rstats->fcs_err = rsp_rstats->fcs_err;
1335 		rstats->jabber_err = rsp_rstats->jabber_err;
1336 		rstats->l2_err = rsp_rstats->l2_err;
1337 		rstats->frame_err = rsp_rstats->frame_err;
1338 
1339 		/* RX firmware stats */
1340 		rstats->fw_total_rcvd = rsp_rstats->fw_total_rcvd;
1341 		rstats->fw_total_fwd = rsp_rstats->fw_total_fwd;
1342 		rstats->fw_err_pko = rsp_rstats->fw_err_pko;
1343 		rstats->fw_err_link = rsp_rstats->fw_err_link;
1344 		rstats->fw_err_drop = rsp_rstats->fw_err_drop;
1345 		rstats->fw_rx_vxlan = rsp_rstats->fw_rx_vxlan;
1346 		rstats->fw_rx_vxlan_err = rsp_rstats->fw_rx_vxlan_err;
1347 
1348 		/* Number of packets that are LROed      */
1349 		rstats->fw_lro_pkts = rsp_rstats->fw_lro_pkts;
1350 		/* Number of octets that are LROed       */
1351 		rstats->fw_lro_octs = rsp_rstats->fw_lro_octs;
1352 		/* Number of LRO packets formed          */
1353 		rstats->fw_total_lro = rsp_rstats->fw_total_lro;
1354 		/* Number of times lRO of packet aborted */
1355 		rstats->fw_lro_aborts = rsp_rstats->fw_lro_aborts;
1356 		rstats->fw_lro_aborts_port = rsp_rstats->fw_lro_aborts_port;
1357 		rstats->fw_lro_aborts_seq = rsp_rstats->fw_lro_aborts_seq;
1358 		rstats->fw_lro_aborts_tsval = rsp_rstats->fw_lro_aborts_tsval;
1359 		rstats->fw_lro_aborts_timer = rsp_rstats->fw_lro_aborts_timer;
1360 		/* intrmod: packet forward rate */
1361 		rstats->fwd_rate = rsp_rstats->fwd_rate;
1362 
1363 		/* TX link-level stats */
1364 		tstats->total_pkts_sent = rsp_tstats->total_pkts_sent;
1365 		tstats->total_bytes_sent = rsp_tstats->total_bytes_sent;
1366 		tstats->mcast_pkts_sent = rsp_tstats->mcast_pkts_sent;
1367 		tstats->bcast_pkts_sent = rsp_tstats->bcast_pkts_sent;
1368 		tstats->ctl_sent = rsp_tstats->ctl_sent;
1369 		/* Packets sent after one collision */
1370 		tstats->one_collision_sent = rsp_tstats->one_collision_sent;
1371 		/* Packets sent after multiple collision */
1372 		tstats->multi_collision_sent = rsp_tstats->multi_collision_sent;
1373 		/* Packets not sent due to max collisions */
1374 		tstats->max_collision_fail = rsp_tstats->max_collision_fail;
1375 		/* Packets not sent due to max deferrals */
1376 		tstats->max_deferral_fail = rsp_tstats->max_deferral_fail;
1377 		/* Accounts for over/under-run of buffers */
1378 		tstats->fifo_err = rsp_tstats->fifo_err;
1379 		tstats->runts = rsp_tstats->runts;
1380 		/* Total number of collisions detected */
1381 		tstats->total_collisions = rsp_tstats->total_collisions;
1382 
1383 		/* firmware stats */
1384 		tstats->fw_total_sent = rsp_tstats->fw_total_sent;
1385 		tstats->fw_total_fwd = rsp_tstats->fw_total_fwd;
1386 		tstats->fw_err_pko = rsp_tstats->fw_err_pko;
1387 		tstats->fw_err_pki = rsp_tstats->fw_err_pki;
1388 		tstats->fw_err_link = rsp_tstats->fw_err_link;
1389 		tstats->fw_err_drop = rsp_tstats->fw_err_drop;
1390 		tstats->fw_tso = rsp_tstats->fw_tso;
1391 		tstats->fw_tso_fwd = rsp_tstats->fw_tso_fwd;
1392 		tstats->fw_err_tso = rsp_tstats->fw_err_tso;
1393 		tstats->fw_tx_vxlan = rsp_tstats->fw_tx_vxlan;
1394 	}
1395 	lio_free_soft_command(oct_dev, sc);
1396 	callout_schedule(&lio->stats_timer,
1397 			 lio_ms_to_ticks(lio->stats_interval));
1398 }
1399 
1400 /*  Configure interrupt moderation parameters */
1401 static void
1402 lio_get_fw_stats(void *arg)
1403 {
1404 	struct lio		*lio = arg;
1405 	struct octeon_device	*oct_dev = lio->oct_dev;
1406 	struct lio_soft_command	*sc;
1407 	struct lio_fw_stats_resp *resp;
1408 	int	retval;
1409 
1410 	if (callout_pending(&lio->stats_timer) ||
1411 	    callout_active(&lio->stats_timer) == 0)
1412 		return;
1413 
1414 	/* Alloc soft command */
1415 	sc = lio_alloc_soft_command(oct_dev, 0,
1416 				    sizeof(struct lio_fw_stats_resp), 0);
1417 
1418 	if (sc == NULL)
1419 		goto alloc_sc_failed;
1420 
1421 	resp = (struct lio_fw_stats_resp *)sc->virtrptr;
1422 	bzero(resp, sizeof(struct lio_fw_stats_resp));
1423 
1424 	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1425 
1426 	lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1427 				 LIO_OPCODE_NIC_PORT_STATS, 0, 0, 0);
1428 
1429 	sc->callback = lio_fw_stats_callback;
1430 	sc->callback_arg = sc;
1431 	sc->wait_time = 500;		/* in milli seconds */
1432 
1433 	retval = lio_send_soft_command(oct_dev, sc);
1434 	if (retval == LIO_IQ_SEND_FAILED)
1435 		goto send_sc_failed;
1436 
1437 	return;
1438 
1439 send_sc_failed:
1440 	lio_free_soft_command(oct_dev, sc);
1441 alloc_sc_failed:
1442 	callout_schedule(&lio->stats_timer,
1443 			 lio_ms_to_ticks(lio->stats_interval));
1444 }
1445 
1446 /* Callback function for intrmod */
1447 static void
1448 lio_get_intrmod_callback(struct octeon_device *oct_dev, uint32_t status,
1449 			 void *ptr)
1450 {
1451 	struct lio_soft_command	*sc = (struct lio_soft_command *)ptr;
1452 	struct ifnet		*ifp = oct_dev->props.ifp;
1453 	struct lio		*lio = if_getsoftc(ifp);
1454 	struct lio_intrmod_resp	*resp;
1455 
1456 	if (status) {
1457 		lio_dev_err(oct_dev, "Failed to get intrmod\n");
1458 	} else {
1459 		resp = (struct lio_intrmod_resp *)sc->virtrptr;
1460 		lio_swap_8B_data((uint64_t *)&resp->intrmod,
1461 				 (sizeof(struct octeon_intrmod_cfg)) / 8);
1462 		memcpy(&lio->intrmod_cfg, &resp->intrmod,
1463 		       sizeof(struct octeon_intrmod_cfg));
1464 	}
1465 
1466 	lio_free_soft_command(oct_dev, sc);
1467 }
1468 
1469 /*  get interrupt moderation parameters */
1470 static int
1471 lio_get_intrmod_cfg(struct lio *lio, struct octeon_intrmod_cfg *intr_cfg)
1472 {
1473 	struct lio_soft_command	*sc;
1474 	struct lio_intrmod_resp	*resp;
1475 	struct octeon_device	*oct_dev = lio->oct_dev;
1476 	int	retval;
1477 
1478 	/* Alloc soft command */
1479 	sc = lio_alloc_soft_command(oct_dev, 0, sizeof(struct lio_intrmod_resp),
1480 				    0);
1481 
1482 	if (sc == NULL)
1483 		return (ENOMEM);
1484 
1485 	resp = (struct lio_intrmod_resp *)sc->virtrptr;
1486 	bzero(resp, sizeof(struct lio_intrmod_resp));
1487 	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1488 
1489 	lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1490 				 LIO_OPCODE_NIC_INTRMOD_PARAMS, 0, 0, 0);
1491 
1492 	sc->callback = lio_get_intrmod_callback;
1493 	sc->callback_arg = sc;
1494 	sc->wait_time = 1000;
1495 
1496 	retval = lio_send_soft_command(oct_dev, sc);
1497 	if (retval == LIO_IQ_SEND_FAILED) {
1498 		lio_free_soft_command(oct_dev, sc);
1499 		return (EINVAL);
1500 	}
1501 
1502 	return (0);
1503 }
1504 
1505 static void
1506 lio_set_intrmod_callback(struct octeon_device *oct_dev, uint32_t status,
1507 			 void *ptr)
1508 {
1509 	struct lio_soft_command		*sc = (struct lio_soft_command *)ptr;
1510 	struct lio_intrmod_context	*ctx;
1511 
1512 	ctx = (struct lio_intrmod_context *)sc->ctxptr;
1513 
1514 	ctx->status = status;
1515 
1516 	ctx->cond = 1;
1517 
1518 	/*
1519 	 * This barrier is required to be sure that the response has been
1520 	 * written fully before waking up the handler
1521 	 */
1522 	wmb();
1523 }
1524 
1525 /*  Configure interrupt moderation parameters */
1526 static int
1527 lio_set_intrmod_cfg(struct lio *lio, struct octeon_intrmod_cfg *intr_cfg)
1528 {
1529 	struct lio_soft_command		*sc;
1530 	struct lio_intrmod_context	*ctx;
1531 	struct octeon_intrmod_cfg	*cfg;
1532 	struct octeon_device		*oct_dev = lio->oct_dev;
1533 	int	retval;
1534 
1535 	/* Alloc soft command */
1536 	sc = lio_alloc_soft_command(oct_dev, sizeof(struct octeon_intrmod_cfg),
1537 				    0, sizeof(struct lio_intrmod_context));
1538 
1539 	if (sc == NULL)
1540 		return (ENOMEM);
1541 
1542 	ctx = (struct lio_intrmod_context *)sc->ctxptr;
1543 
1544 	ctx->cond = 0;
1545 	ctx->octeon_id = lio_get_device_id(oct_dev);
1546 
1547 	cfg = (struct octeon_intrmod_cfg *)sc->virtdptr;
1548 
1549 	memcpy(cfg, intr_cfg, sizeof(struct octeon_intrmod_cfg));
1550 	lio_swap_8B_data((uint64_t *)cfg,
1551 			 (sizeof(struct octeon_intrmod_cfg)) / 8);
1552 
1553 	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
1554 
1555 	lio_prepare_soft_command(oct_dev, sc, LIO_OPCODE_NIC,
1556 				 LIO_OPCODE_NIC_INTRMOD_CFG, 0, 0, 0);
1557 
1558 	sc->callback = lio_set_intrmod_callback;
1559 	sc->callback_arg = sc;
1560 	sc->wait_time = 1000;
1561 
1562 	retval = lio_send_soft_command(oct_dev, sc);
1563 	if (retval == LIO_IQ_SEND_FAILED) {
1564 		lio_free_soft_command(oct_dev, sc);
1565 		return (EINVAL);
1566 	}
1567 
1568 	/*
1569 	 * Sleep on a wait queue till the cond flag indicates that the
1570 	 * response arrived or timed-out.
1571 	 */
1572 	lio_sleep_cond(oct_dev, &ctx->cond);
1573 
1574 	retval = ctx->status;
1575 	if (retval)
1576 		lio_dev_err(oct_dev, "intrmod config failed. Status: %llx\n",
1577 			    LIO_CAST64(retval));
1578 	else
1579 		lio_dev_info(oct_dev, "Rx-Adaptive Interrupt moderation enabled:%llx\n",
1580 			     LIO_CAST64(intr_cfg->rx_enable));
1581 
1582 	lio_free_soft_command(oct_dev, sc);
1583 
1584 	return ((retval) ? ETIMEDOUT : 0);
1585 }
1586 
1587 static int
1588 lio_intrmod_cfg_rx_intrcnt(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1589 			   uint32_t rx_max_frames)
1590 {
1591 	struct octeon_device	*oct = lio->oct_dev;
1592 	uint32_t		rx_max_coalesced_frames;
1593 
1594 	/* Config Cnt based interrupt values */
1595 	switch (oct->chip_id) {
1596 	case LIO_CN23XX_PF_VID:{
1597 			int	q_no;
1598 
1599 			if (!rx_max_frames)
1600 				rx_max_coalesced_frames = intrmod->rx_frames;
1601 			else
1602 				rx_max_coalesced_frames = rx_max_frames;
1603 
1604 			for (q_no = 0; q_no < oct->num_oqs; q_no++) {
1605 				q_no += oct->sriov_info.pf_srn;
1606 				lio_write_csr64(oct,
1607 					LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
1608 						(lio_read_csr64(oct,
1609 				     LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no)) &
1610 						 (0x3fffff00000000UL)) |
1611 						(rx_max_coalesced_frames - 1));
1612 				/* consider setting resend bit */
1613 			}
1614 
1615 			intrmod->rx_frames = rx_max_coalesced_frames;
1616 			oct->rx_max_coalesced_frames = rx_max_coalesced_frames;
1617 			break;
1618 		}
1619 	default:
1620 		return (EINVAL);
1621 	}
1622 	return (0);
1623 }
1624 
1625 static int
1626 lio_intrmod_cfg_rx_intrtime(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1627 			    uint32_t rx_usecs)
1628 {
1629 	struct octeon_device	*oct = lio->oct_dev;
1630 	uint32_t		rx_coalesce_usecs;
1631 
1632 	/* Config Time based interrupt values */
1633 	switch (oct->chip_id) {
1634 	case LIO_CN23XX_PF_VID:{
1635 			uint64_t	time_threshold;
1636 			int	q_no;
1637 
1638 			if (!rx_usecs)
1639 				rx_coalesce_usecs = intrmod->rx_usecs;
1640 			else
1641 				rx_coalesce_usecs = rx_usecs;
1642 
1643 			time_threshold =
1644 			    lio_cn23xx_pf_get_oq_ticks(oct, rx_coalesce_usecs);
1645 			for (q_no = 0; q_no < oct->num_oqs; q_no++) {
1646 				q_no += oct->sriov_info.pf_srn;
1647 				lio_write_csr64(oct,
1648 				       LIO_CN23XX_SLI_OQ_PKT_INT_LEVELS(q_no),
1649 						(intrmod->rx_frames |
1650 					   ((uint64_t)time_threshold << 32)));
1651 				/* consider writing to resend bit here */
1652 			}
1653 
1654 			intrmod->rx_usecs = rx_coalesce_usecs;
1655 			oct->rx_coalesce_usecs = rx_coalesce_usecs;
1656 			break;
1657 		}
1658 	default:
1659 		return (EINVAL);
1660 	}
1661 
1662 	return (0);
1663 }
1664 
1665 static int
1666 lio_intrmod_cfg_tx_intrcnt(struct lio *lio, struct octeon_intrmod_cfg *intrmod,
1667 			   uint32_t tx_max_frames)
1668 {
1669 	struct octeon_device	*oct = lio->oct_dev;
1670 	uint64_t	val;
1671 	uint32_t	iq_intr_pkt;
1672 	uint32_t	inst_cnt_reg;
1673 
1674 	/* Config Cnt based interrupt values */
1675 	switch (oct->chip_id) {
1676 	case LIO_CN23XX_PF_VID:{
1677 			int	q_no;
1678 
1679 			if (!tx_max_frames)
1680 				iq_intr_pkt = LIO_CN23XX_DEF_IQ_INTR_THRESHOLD &
1681 				    LIO_CN23XX_PKT_IN_DONE_WMARK_MASK;
1682 			else
1683 				iq_intr_pkt = tx_max_frames &
1684 				    LIO_CN23XX_PKT_IN_DONE_WMARK_MASK;
1685 			for (q_no = 0; q_no < oct->num_iqs; q_no++) {
1686 				inst_cnt_reg =
1687 					(oct->instr_queue[q_no])->inst_cnt_reg;
1688 				val = lio_read_csr64(oct, inst_cnt_reg);
1689 				/*
1690 				 * clear wmark and count.dont want to write
1691 				 * count back
1692 				 */
1693 				val = (val & 0xFFFF000000000000ULL) |
1694 				    ((uint64_t)(iq_intr_pkt - 1)
1695 				     << LIO_CN23XX_PKT_IN_DONE_WMARK_BIT_POS);
1696 				lio_write_csr64(oct, inst_cnt_reg, val);
1697 				/* consider setting resend bit */
1698 			}
1699 
1700 			intrmod->tx_frames = iq_intr_pkt;
1701 			oct->tx_max_coalesced_frames = iq_intr_pkt;
1702 			break;
1703 		}
1704 	default:
1705 		return (-EINVAL);
1706 	}
1707 	return (0);
1708 }
1709 
1710 static int
1711 lio_get_set_intr_coalesce(SYSCTL_HANDLER_ARGS)
1712 {
1713 	struct lio		*lio = (struct lio *)arg1;
1714 	struct octeon_device	*oct = lio->oct_dev;
1715 	uint64_t	new_val = 0, old_val = 0;
1716 	uint32_t	rx_coalesce_usecs = 0;
1717 	uint32_t	rx_max_coalesced_frames = 0;
1718 	uint32_t	tx_coalesce_usecs = 0;
1719 	int		err, ret;
1720 
1721 	switch (arg2) {
1722 	case LIO_USE_ADAPTIVE_RX_COALESCE:
1723 		if (lio->intrmod_cfg.rx_enable)
1724 			new_val = old_val = lio->intrmod_cfg.rx_enable;
1725 
1726 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1727 		if ((err) || (req->newptr == NULL))
1728 			return (err);
1729 
1730 		if (old_val == new_val)
1731 			return (0);
1732 
1733 		lio->intrmod_cfg.rx_enable = new_val ? 1 : 0;
1734 		break;
1735 
1736 	case LIO_USE_ADAPTIVE_TX_COALESCE:
1737 		if (lio->intrmod_cfg.tx_enable)
1738 			new_val = old_val = lio->intrmod_cfg.tx_enable;
1739 
1740 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1741 		if ((err) || (req->newptr == NULL))
1742 			return (err);
1743 
1744 		if (old_val == new_val)
1745 			return (0);
1746 
1747 		lio->intrmod_cfg.tx_enable = new_val ? 1 : 0;
1748 		break;
1749 
1750 	case LIO_RX_COALESCE_USECS:
1751 		if (!lio->intrmod_cfg.rx_enable)
1752 			new_val = old_val = oct->rx_coalesce_usecs;
1753 
1754 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1755 		if ((err) || (req->newptr == NULL))
1756 			return (err);
1757 
1758 		if (old_val == new_val)
1759 			return (0);
1760 
1761 		rx_coalesce_usecs = new_val;
1762 		break;
1763 
1764 	case LIO_RX_MAX_COALESCED_FRAMES:
1765 		if (!lio->intrmod_cfg.rx_enable)
1766 			new_val = old_val = oct->rx_max_coalesced_frames;
1767 
1768 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1769 		if ((err) || (req->newptr == NULL))
1770 			return (err);
1771 
1772 		if (old_val == new_val)
1773 			return (0);
1774 
1775 		rx_max_coalesced_frames = new_val;
1776 		break;
1777 
1778 	case LIO_TX_MAX_COALESCED_FRAMES:
1779 		if (!lio->intrmod_cfg.tx_enable)
1780 			new_val = old_val = oct->tx_max_coalesced_frames;
1781 
1782 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1783 		if ((err) || (req->newptr == NULL))
1784 			return (err);
1785 
1786 		if (old_val == new_val)
1787 			return (0);
1788 
1789 		tx_coalesce_usecs = new_val;
1790 		break;
1791 
1792 	case LIO_PKT_RATE_LOW:
1793 		if (lio->intrmod_cfg.rx_enable)
1794 			new_val = old_val = lio->intrmod_cfg.minpkt_ratethr;
1795 
1796 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1797 		if ((err) || (req->newptr == NULL))
1798 			return (err);
1799 
1800 		if (old_val == new_val)
1801 			return (0);
1802 
1803 		if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1804 			lio->intrmod_cfg.minpkt_ratethr = new_val;
1805 		break;
1806 
1807 	case LIO_RX_COALESCE_USECS_LOW:
1808 		if (lio->intrmod_cfg.rx_enable)
1809 			new_val = old_val = lio->intrmod_cfg.rx_mintmr_trigger;
1810 
1811 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1812 		if ((err) || (req->newptr == NULL))
1813 			return (err);
1814 
1815 		if (old_val == new_val)
1816 			return (0);
1817 
1818 		if (lio->intrmod_cfg.rx_enable)
1819 			lio->intrmod_cfg.rx_mintmr_trigger = new_val;
1820 		break;
1821 
1822 	case LIO_RX_MAX_COALESCED_FRAMES_LOW:
1823 		if (lio->intrmod_cfg.rx_enable)
1824 			new_val = old_val = lio->intrmod_cfg.rx_mincnt_trigger;
1825 
1826 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1827 		if ((err) || (req->newptr == NULL))
1828 			return (err);
1829 
1830 		if (old_val == new_val)
1831 			return (0);
1832 
1833 		if (lio->intrmod_cfg.rx_enable)
1834 			lio->intrmod_cfg.rx_mincnt_trigger = new_val;
1835 		break;
1836 
1837 	case LIO_TX_MAX_COALESCED_FRAMES_LOW:
1838 		if (lio->intrmod_cfg.tx_enable)
1839 			new_val = old_val = lio->intrmod_cfg.tx_mincnt_trigger;
1840 
1841 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1842 		if ((err) || (req->newptr == NULL))
1843 			return (err);
1844 
1845 		if (old_val == new_val)
1846 			return (0);
1847 
1848 		if (lio->intrmod_cfg.tx_enable)
1849 			lio->intrmod_cfg.tx_mincnt_trigger = new_val;
1850 		break;
1851 
1852 	case LIO_PKT_RATE_HIGH:
1853 		if (lio->intrmod_cfg.rx_enable)
1854 			new_val = old_val = lio->intrmod_cfg.maxpkt_ratethr;
1855 
1856 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1857 		if ((err) || (req->newptr == NULL))
1858 			return (err);
1859 
1860 		if (old_val == new_val)
1861 			return (0);
1862 
1863 		if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1864 			lio->intrmod_cfg.maxpkt_ratethr = new_val;
1865 		break;
1866 
1867 	case LIO_RX_COALESCE_USECS_HIGH:
1868 		if (lio->intrmod_cfg.rx_enable)
1869 			new_val = old_val = lio->intrmod_cfg.rx_maxtmr_trigger;
1870 
1871 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1872 		if ((err) || (req->newptr == NULL))
1873 			return (err);
1874 
1875 		if (old_val == new_val)
1876 			return (0);
1877 
1878 		if (lio->intrmod_cfg.rx_enable)
1879 			lio->intrmod_cfg.rx_maxtmr_trigger = new_val;
1880 		break;
1881 
1882 	case LIO_RX_MAX_COALESCED_FRAMES_HIGH:
1883 		if (lio->intrmod_cfg.rx_enable)
1884 			new_val = old_val = lio->intrmod_cfg.rx_maxcnt_trigger;
1885 
1886 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1887 		if ((err) || (req->newptr == NULL))
1888 			return (err);
1889 
1890 		if (old_val == new_val)
1891 			return (0);
1892 
1893 		if (lio->intrmod_cfg.rx_enable)
1894 			lio->intrmod_cfg.rx_maxcnt_trigger = new_val;
1895 		break;
1896 
1897 	case LIO_TX_MAX_COALESCED_FRAMES_HIGH:
1898 		if (lio->intrmod_cfg.tx_enable)
1899 			new_val = old_val = lio->intrmod_cfg.tx_maxcnt_trigger;
1900 
1901 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1902 		if ((err) || (req->newptr == NULL))
1903 			return (err);
1904 
1905 		if (old_val == new_val)
1906 			return (0);
1907 
1908 		if (lio->intrmod_cfg.tx_enable)
1909 			lio->intrmod_cfg.tx_maxcnt_trigger = new_val;
1910 		break;
1911 
1912 	case LIO_RATE_SAMPLE_INTERVAL:
1913 		if (lio->intrmod_cfg.rx_enable)
1914 			new_val = old_val = lio->intrmod_cfg.check_intrvl;
1915 
1916 		err = sysctl_handle_64(oidp, &new_val, 0, req);
1917 		if ((err) || (req->newptr == NULL))
1918 			return (err);
1919 
1920 		if (old_val == new_val)
1921 			return (0);
1922 
1923 		if (lio->intrmod_cfg.rx_enable || lio->intrmod_cfg.tx_enable)
1924 			lio->intrmod_cfg.check_intrvl = new_val;
1925 		break;
1926 
1927 	default:
1928 		return (EINVAL);
1929 	}
1930 
1931 	lio->intrmod_cfg.rx_usecs = LIO_GET_OQ_INTR_TIME_CFG(lio_get_conf(oct));
1932 	lio->intrmod_cfg.rx_frames = LIO_GET_OQ_INTR_PKT_CFG(lio_get_conf(oct));
1933 	lio->intrmod_cfg.tx_frames = LIO_GET_IQ_INTR_PKT_CFG(lio_get_conf(oct));
1934 
1935 	ret = lio_set_intrmod_cfg(lio, &lio->intrmod_cfg);
1936 	if (ret)
1937 		lio_dev_err(oct, "Interrupt coalescing updation to Firmware failed!\n");
1938 
1939 	if (!lio->intrmod_cfg.rx_enable) {
1940 		if (!rx_coalesce_usecs)
1941 			rx_coalesce_usecs = oct->rx_coalesce_usecs;
1942 
1943 		if (!rx_max_coalesced_frames)
1944 			rx_max_coalesced_frames = oct->rx_max_coalesced_frames;
1945 
1946 		ret = lio_intrmod_cfg_rx_intrtime(lio, &lio->intrmod_cfg,
1947 						  rx_coalesce_usecs);
1948 		if (ret)
1949 			return (ret);
1950 
1951 		ret = lio_intrmod_cfg_rx_intrcnt(lio, &lio->intrmod_cfg,
1952 						 rx_max_coalesced_frames);
1953 		if (ret)
1954 			return (ret);
1955 	} else {
1956 		oct->rx_coalesce_usecs =
1957 		    LIO_GET_OQ_INTR_TIME_CFG(lio_get_conf(oct));
1958 		oct->rx_max_coalesced_frames =
1959 		    LIO_GET_OQ_INTR_PKT_CFG(lio_get_conf(oct));
1960 	}
1961 
1962 	if (!lio->intrmod_cfg.tx_enable) {
1963 		if (!tx_coalesce_usecs)
1964 			tx_coalesce_usecs = oct->tx_max_coalesced_frames;
1965 
1966 		ret = lio_intrmod_cfg_tx_intrcnt(lio, &lio->intrmod_cfg,
1967 						 tx_coalesce_usecs);
1968 		if (ret)
1969 			return (ret);
1970 	} else {
1971 		oct->tx_max_coalesced_frames =
1972 			LIO_GET_IQ_INTR_PKT_CFG(lio_get_conf(oct));
1973 	}
1974 
1975 	return (0);
1976 }
1977