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