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